From: David Howells Date: Fri, 10 Jul 2020 07:40:08 +0000 (+0100) Subject: Implement "vos listvol" X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=f5c2f2c6c98c76005ae883df234c544a3b68a610;p=users%2Fdhowells%2Fkafs-utils.git Implement "vos listvol" Signed-off-by: David Howells --- diff --git a/kafs/Makefile b/kafs/Makefile index 504b93b..6c0d392 100644 --- a/kafs/Makefile +++ b/kafs/Makefile @@ -36,6 +36,7 @@ VOS_SRCS := \ vos_help.C \ vos_listaddrs.C \ vos_listvldb.C \ + vos_listvol.C \ vos_status.C CORE_OBJS := $(patsubst %.C,%.o,$(CORE_SRCS)) diff --git a/kafs/vol_query.C b/kafs/vol_query.C index 21d6277..1ab4750 100644 --- a/kafs/vol_query.C +++ b/kafs/vol_query.C @@ -18,6 +18,8 @@ using kafs::Volserver; namespace kafs { static void volintinfo_to_volume_info(afs::volintInfo &info, Volume_info_list &vilist); static void xvolintinfo_to_volume_info(afs::xvolintInfo &xinfo, Volume_info_list &vilist); +static void volintInfo64_to_volume_info(afs::volintInfo64 &info, afs::volintStats64 &stats, + Volume_info_list &vilist); } /** @@ -152,6 +154,59 @@ static void kafs::xvolintinfo_to_volume_info(afs::xvolintInfo &xinfo, vi.nr_week_use = 0; } +/* + * Convert an xvolintInfo64 struct to a kafs_volume_info record. + */ +static void kafs::volintInfo64_to_volume_info(afs::volintInfo64 &info, + afs::volintStats64 &stats, + Volume_info_list &vilist) +{ + unsigned int index = vilist.size(); + vilist.resize(index + 1); + Volume_info &vi = vilist[index]; + int i; + + vi.name = info.name; + vi.offline_msg = info.offlineMessage; + vi.volid = info.volId; + vi.type = info.type; + vi.backup_id = info.backupId; + vi.parent_id = info.parentId; + vi.clone_id = info.cloneId; + vi.status = info.status; + vi.flags = info.flags; + vi.owner = info.owner; + + vi.creation_date = info.creationDate; + vi.access_date = info.accessDate; + vi.update_date = info.updateDate; + vi.expiration_date = info.expirationDate; + vi.backup_date = info.backupDate; + vi.copy_date = info.copyDate; + + vi.max_quota = info.maxquota; + vi.min_quota = info.minquota; + vi.max_files = info.maxfiles; + vi.disk_used = info.diskused; + vi.file_count = info.filecount; + vi.vol_update_counter = info.volUpdateCounter; + + vi.day_use_date = info.dayUseDate; + vi.day_use = info.dayUse; + for (i = 0; i < 7; i++) + vi.week_use[i] = info.weekUse[i]; + + vi.has_day_use_date = true; + vi.has_disk_used = true; + vi.has_expiration_date = true; + vi.has_flags = true; + vi.has_max_files = true; + vi.has_min_quota = true; + vi.has_owner = true; + vi.has_vol_update_counter = true; + vi.nr_week_use = 7; +} + /** * Volserver::VOLSER_ListOneVolume - Get the ordinary state of an instance of a volume * @partition: The partition on which the volume resides @@ -196,6 +251,27 @@ void Volserver::VOLSER_XListOneVolume(Partition_spec &partition, xvolintinfo_to_volume_info(xinfos[0], vi); } +/** + * Volserver::YFSVOL_FetchVolumeInfo64 - Get the state of an instance of a volume + * @partition: The partition on which the volume resides + * @volid: The ID of the volume to query + * @vi: The record to load with the information retrieved + * + * Query the extended state of a volume on a volume server. The information is + * stored into the supplied record. + */ +void Volserver::YFSVOL_FetchVolumeInfo64(Partition_spec &partition, + Volume_id volid, + Volume_info_list &vi) +{ + afs::volintInfo64 result_entry; + afs::volintStats64 result_stats; + + afs::YFSVOL::FetchVolumeInfo64(&vs_params, partition.id, volid, + 1, 1, result_entry, result_stats); + volintInfo64_to_volume_info(result_entry, result_stats, vi); +} + /** * Volserver::query_volume_state - Query the state of an instance of a volume * @partition: The partition on which the volume resides @@ -217,6 +293,61 @@ void Volserver::query_volume_state(Partition_spec &partition, VOLSER_ListOneVolume(partition, volid, vi); } +/** + * Volserver::VOLSER_ListVolumes - Get the ordinary states of volume instances on a partition + * @ctx: The cell and authentication context + * @server: The volume server to contact + * @partition: The partition on which the volumes reside + * @vilist: The record to load with the information retrieved + * + * Query the ordinary state of a volume on a volume server. The information is + * stored into the supplied record. + */ +void Volserver::VOLSER_ListVolumes(Partition_spec &partition, + Volume_info_list &vilist) +{ + std::vector infos; + + afs::VOLSER::ListVolumes(&vs_params, partition.id, 1, infos); + if (infos.size() == 0) + throw std::runtime_error("No volume information results returned"); + volintinfo_to_volume_info(infos[0], vilist); +} + +/* + * Query the extended state of a volume. + */ +void Volserver::VOLSER_XListVolumes(Partition_spec &partition, + Volume_info_list &vilist) +{ + std::vector xinfos; + + afs::VOLSER::XListVolumes(&vs_params, partition.id, 1, xinfos); + if (xinfos.size() == 0) + throw std::runtime_error("No volume information results returned"); + xvolintinfo_to_volume_info(xinfos[0], vilist); +} + +/** + * Volserver::query_volume_states - Query the state of the volumes on a partition + * @partition: The partition to search + * @extended: Whether extended info is required + * @vilist: The list to add the returned record to + * + * Query the state of a volume residing in a particular partition on a + * particular volume server. If successful, a record is allocated and + * added to the list. + */ +void Volserver::query_volume_states(Partition_spec &partition, + bool extended, + Volume_info_list &vilist) +{ + if (extended) + VOLSER_XListVolumes(partition, vilist); + else + VOLSER_ListVolumes(partition, vilist); +} + /** * Volserver::list_partitions - Get a list of partitions on a server. * @partitions: Where to store the list of partitions. diff --git a/kafs/volservice.H b/kafs/volservice.H index 4eaf7dc..2412c1f 100644 --- a/kafs/volservice.H +++ b/kafs/volservice.H @@ -144,10 +144,18 @@ public: void VOLSER_XListOneVolume(Partition_spec &partition, Volume_id volid, Volume_info_list &vi); + void YFSVOL_FetchVolumeInfo64(Partition_spec &partition, + Volume_id volid, + Volume_info_list &vi); + void VOLSER_ListVolumes(Partition_spec &partition, + Volume_info_list &vilist); + void VOLSER_XListVolumes(Partition_spec &partition, + Volume_info_list &vilist); void vol_monitor_transaction(Vol_transaction_info_list &); void list_partitions(Partition_list &); void query_volume_state(Partition_spec &, Volume_id, bool, Volume_info_list &); + void query_volume_states(Partition_spec &, bool, Volume_info_list &); }; } /* end namespace kafs */ diff --git a/kafs/vos_listvol.C b/kafs/vos_listvol.C new file mode 100644 index 0000000..7e92779 --- /dev/null +++ b/kafs/vos_listvol.C @@ -0,0 +1,227 @@ +/* The "vos listvol" command + * + * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include +#include +#include "kafs.H" +#include "volservice.H" +#include "arg_parse.H" +#include "display.H" +#include "afs_xg.H" + +using rxrpc::ref; +using kafs::afs::VOK; +using kafs::afs::VBUSY; + +static void display_fast(kafs::Context *ctx, + kafs::FS_site *site, + kafs::Partition_spec &part, + kafs::Volume_info &vi) +{ + fmt::print("{:d}\n", vi.volid); +} + +static void display_extended(kafs::Context *ctx, + kafs::FS_site *site, + kafs::Partition_spec &part, + kafs::Volume_info &vi) +{ + kafs::display_vol_information(ctx, site, part, vi); + kafs::display_vol_statistics(ctx, vi); +} + +static void display_format_normal(kafs::Context *ctx, + kafs::FS_site *site, + kafs::Partition_spec &part, + kafs::Volume_info &vi) +{ + kafs::display_vol_mp_information(ctx, site, part, vi); + fmt::print("END_OF_ENTRY\n"); +} + +static const char *const reads_labels[] = { + "reads_same_net", + "reads_same_net_auth", + "reads_diff_net", + "reads_diff_net_auth", +}; + +static const char *const writes_labels[] = { + "writes_same_net", + "writes_same_net_auth", + "writes_diff_net", + "writes_diff_net_auth", +}; + +static void display_format_extended(kafs::Context *ctx, + kafs::FS_site *site, + kafs::Partition_spec &part, + kafs::Volume_info &vi) +{ + int i; + + if (vi.status != VOK) { + if (vi.status == VBUSY) + fmt::print("VOLUME_BUSY\t{:d}\n", vi.volid); + else + fmt::print("COULD_NOT_ATTACH_VOLUME\t{:d}\n", vi.volid); + return; + } + + display_vol_mp_basic_information(ctx, site, part, vi); + + for (i = 0; i < 4; i++) + fmt::print("{}\t{:8d}\n", reads_labels[i], vi.stat_reads[i]); + for (i = 0; i < 4; i++) + fmt::print("{}\t{:8d}\n", writes_labels[i], vi.stat_writes[i]); + for (i = 0; i < 6; i++) { + fmt::print("file_same_author_idx_{:d}\t{:8d}\n", i, vi.stat_fileSameAuthor[i]); + fmt::print("file_diff_author_idx_{:d}\t{:8d}\n", i, vi.stat_fileDiffAuthor[i]); + fmt::print("dir_same_author_idx_{:d}\t{:8d}\n", i, vi.stat_dirSameAuthor[i]); + fmt::print("dir_dif_author_idx_{:d}\t{:8d}\n", i, vi.stat_dirDiffAuthor[i]); + } + + fmt::print("END_OF_ENTRY"); +} + +static bool compare_entries(const kafs::Volume_info &a, const kafs::Volume_info &b) +{ + return a.name.compare(b.name) < 0; //strcmp(a->name, b->name) < 0; +} + +/* + * Display the records for a single partition in the appropriate format + */ +static void display_one_partition(kafs::Context *ctx, + kafs::FS_site *site, + kafs::Volserver *server, + kafs::Partition_spec &partition, + bool a_fast, + bool a_long, + bool a_quiet, + bool a_extended, + bool a_format) +{ + kafs::Volume_info_list vilist; + unsigned int n_online = 0, n_offline = 0, n_busy = 0, i; + + void (*display_func)(kafs::Context *ctx, + kafs::FS_site *site, + kafs::Partition_spec &part, + kafs::Volume_info &vi); + + server->query_volume_states(partition, a_extended, vilist); + + if (!a_quiet) + fmt::print("Total number of volumes on server {} partition {}: {:d}\n", + site->name, kafs::sprint_partition(partition), vilist.size()); + + display_func = kafs::display_vol_oneline_summary; + if (a_fast) + display_func = display_fast; + else if (a_format && a_extended) + display_func = display_format_extended; + else if (a_format) + display_func = display_format_normal; + else if (a_extended) + display_func = display_extended; + else if (a_long) + display_func = kafs::display_vol_information; + + std::sort(vilist.begin(), vilist.end(), compare_entries); + + for (i = 0; i < vilist.size(); i++) { + kafs::Volume_info &vi = vilist[i]; + if (vi.in_use) + n_online += 1; + if (vi.status == VBUSY) + n_busy += 1; + display_func(ctx, site, partition, vi); + } + + if (!a_quiet) { + fmt::print("\n"); + if (!a_fast && !a_format) { + fmt::print("Total volumes onLine {:d}; Total volumes offLine {:d}; Total busy {:d}\n", + n_online, n_offline, n_busy); + fmt::print("\n"); + } else if (a_format && a_extended) { + fmt::print("VOLUMES_ONLINE {:d}\n", n_online); + fmt::print("VOLUMES_OFFLINE {:d}\n", n_offline); + fmt::print("VOLUMES_BUSY {:d}\n", n_busy); + } + } +} + +/*** + * COMMAND: vos listvol - Display information from a volume header + * ARG: "-server " + * ARG: "[-partition ]" + * ARG: "[-fast]" + * ARG: "[-long]" + * ARG: "[-quiet]" + * ARG: "[-extended]" + * ARG: "[-format]" + * ARG: "[-cell ]" + * ARG: "[-noauth]" - Auth + * ARG: "[-localauth]" - Auth + * ARG: "[-verbose]" + * ARG: "[-encrypt]" - Auth + * ARG: "[-noresolve]" + * NOCOMBINE: fast, extended + * + * Display information from a volume header. + */ +void COMMAND_vos_listvol( + kafs::Context *ctx, + kafs::Volserver_spec &a_server, + kafs::Partition_spec &a_partition, + bool a_fast, + bool a_long, + bool a_quiet, + bool a_extended, + bool a_format, + bool a_verbose, + bool a_noresolve) +{ + kafs::Partition_list partitions; + ref server; + ref site; + unsigned int i; + + _enter(""); + + ctx->no_resolve = a_noresolve; + + site = kafs::resolve_server_spec(ctx, a_server); + server = new kafs::Volserver(ctx, site); + + if (a_partition.specified) { + std::string part = kafs::sprint_partition(a_partition); + try { + display_one_partition(ctx, site, server, a_partition, + a_fast, a_long, a_quiet, a_extended, + a_format); + } catch (const kafs::afs::VOLSER::AbortVOLSERILLEGAL_PARTITION &a) { + throw std::runtime_error( + fmt::format("vos : partition {} does not exist on the server", + part)); + } + } else { + server->list_partitions(partitions); + + for (i = 0; i < partitions.size(); i++) + display_one_partition(ctx, site, server, partitions[i], + a_fast, a_long, a_quiet, a_extended, + a_format); + } +}