From: David Howells Date: Mon, 6 Jul 2020 22:13:50 +0000 (+0100) Subject: Implement "vos examine" X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=95f7a217f6f1f8885c124b029b25ac847c46aa05;p=users%2Fdhowells%2Fkafs-utils.git Implement "vos examine" Signed-off-by: David Howells --- diff --git a/kafs/Makefile b/kafs/Makefile index 5dcad56..bde79f6 100644 --- a/kafs/Makefile +++ b/kafs/Makefile @@ -32,6 +32,7 @@ PTS_SRCS := \ VOS_SRCS := \ vos.C \ + vos_examine.C \ vos_help.C \ vos_listvldb.C \ vos_status.C diff --git a/kafs/display.H b/kafs/display.H index e76b9af..8be7e61 100644 --- a/kafs/display.H +++ b/kafs/display.H @@ -18,6 +18,7 @@ namespace kafs { struct Vldb_entry; struct Vldb_site; +struct Volume_info; /* * display.C @@ -40,6 +41,16 @@ extern bool kafs_display_error(Context *); extern std::string sprint_site(Context *, Vldb_site &); extern void display_vldb_site_list(Context *, Vldb_entry *, const char *); +extern void display_vol_information(Context *, FS_site *, + Partition_spec &, Volume_info &); +extern void display_vol_statistics(Context *, Volume_info &); +extern void display_vol_mp_basic_information(Context *, FS_site *, + Partition_spec &, Volume_info &); +extern void display_vol_mp_information(Context *, FS_site *, + Partition_spec &, Volume_info &); +extern void display_vol_oneline_summary(Context *, FS_site *, + Partition_spec &, Volume_info &); + } /* end namespace kafs */ #endif /* DISPLAY_H */ diff --git a/kafs/display_vol.C b/kafs/display_vol.C index d38c059..1825ac7 100644 --- a/kafs/display_vol.C +++ b/kafs/display_vol.C @@ -13,11 +13,60 @@ #include #include "kafs.H" #include "vlservice.H" +#include "volservice.H" #include "afs_xg.H" #include "display.H" using rxrpc::ref; +static const char *const statistics_time_ranges[] = { + "0-60 sec ", + "1-10 min ", + "10min-1hr", + "1hr-1day ", + "1day-1wk ", + "> 1wk " +}; + +static std::string vol_type(const kafs::Volume_info &vi) +{ + switch (vi.type) { + case 0: return "RW"; + case 1: return "RO"; + case 2: return "BK"; + default: return fmt::format("0x{:02x}", vi.type); + } +} + +static const char *vol_state(const kafs::Volume_info &vi) +{ + if (!vi.needs_salvage) { + if (vi.in_use) + return "On-line"; + else + return "Off-line"; + } else { + if (vi.in_use) + return "On-line**needs salvage**"; + else + return "Off-line**needs salvage**"; + } +} + +static const char *vol_status(const kafs::Volume_info &vi) +{ + switch (vi.status) { + case kafs::afs::VOK: return "OK"; + case kafs::afs::VBUSY: return "BUSY"; + default: return "UNATTACHABLE"; + } +} + +static const char *yes_or_no(bool x) +{ + return x ? "Y" : "N"; +} + /* * Convert a volume site into a textual representation, possibly resolving it * to a DNS hostname. @@ -94,3 +143,273 @@ void kafs::display_vldb_site_list(Context *ctx, std::cout << indent << "Volume is locked for a dump/restore operation\n"; } } + +/* + * Display a one-line volume summary + * + * proj.foo 536870957 RW 40475760 K On-line + * + */ +void kafs::display_vol_oneline_summary(Context *ctx, + FS_site *server, + Partition_spec &partition, + Volume_info &vi) +{ + fmt::print("{:<32s} {:10d} {:<2s} {:10d} K {}\n", + vi.name, + vi.volid, + vol_type(vi), + vi.size, + vol_state(vi)); +} + +/* + * Display a volume information timestamp. + */ +static void display_vol_timestamp(const char *key, kafs::Time &t) +{ + fmt::print("{}{}\n", key, kafs::sprint_time_or_never(t)); +} + +/* + * Display volume information + * + * proj.foo 536870957 RW 40475760 K On-line + * 204.29.154.47 /vicepa + * RWrite 536870957 ROnly 536870958 Backup 0 + * MaxQuota 0 K + * Creation Sat Aug 22 06:22:27 2009 + * Copy Tue Oct 26 00:40:32 2010 + * Backup Never + * Last Access Tue Jan 28 23:20:37 2014 + * Last Update Mon Aug 05 21:15:32 2013 + * 0 accesses in the past day (i.e., vnode references) + * + * + */ +void kafs::display_vol_information(Context *ctx, + FS_site *site, + Partition_spec &partition, + Volume_info &vi) +{ + std::string addr = kafs::sprint_address(ctx, site->vs_addrs[0]); + std::string part = kafs::sprint_partition(partition); + + display_vol_oneline_summary(ctx, site, partition, vi); + fmt::print(" {} {}\n", addr, part); + fmt::print(" RWrite {:10d} ROnly {:10d} Backup {:10d}\n", + vi.parent_id, vi.clone_id, vi.backup_id); + fmt::print(" MaxQuota {:10d} K\n", vi.max_quota); + + display_vol_timestamp(" Creation ", vi.creation_date); + display_vol_timestamp(" Copy ", vi.copy_date); + display_vol_timestamp(" Backup ", vi.backup_date); + display_vol_timestamp(" Last Access ", vi.access_date); + display_vol_timestamp(" Last Update ", vi.update_date); + fmt::print(" {:d} accesses in the past day (i.e., vnode references)\n", + vi.day_use); + fmt::print("\n"); +} + +/* + * Display volume access statistics + * + * Raw Read/Write Stats + * |-------------------------------------------| + * | Same Network | Diff Network | + * |----------|----------|----------|----------| + * | Total | Auth | Total | Auth | + * |----------|----------|----------|----------| + * Reads | 0 | 0 | 0 | 0 | + * Writes | 0 | 0 | 0 | 0 | + * |-------------------------------------------| + * + * Writes Affecting Authorship + * |-------------------------------------------| + * | File Authorship | Directory Authorship| + * |----------|----------|----------|----------| + * | Same | Diff | Same | Diff | + * |----------|----------|----------|----------| + * 0-60 sec | 0 | 0 | 0 | 0 | + * 1-10 min | 0 | 0 | 0 | 0 | + * 10min-1hr | 0 | 0 | 0 | 0 | + * 1hr-1day | 0 | 0 | 0 | 0 | + * 1day-1wk | 0 | 0 | 0 | 0 | + * > 1wk | 0 | 0 | 0 | 0 | + * |-------------------------------------------| + * + */ +void kafs::display_vol_statistics(Context *ctx, + Volume_info &vi) +{ + int i; + + printf(" Raw Read/Write Stats\n"); + printf(" |-------------------------------------------|\n"); + printf(" | Same Network | Diff Network |\n"); + printf(" |----------|----------|----------|----------|\n"); + printf(" | Total | Auth | Total | Auth |\n"); + printf(" |----------|----------|----------|----------|\n"); + printf("Reads |%9u |%9u |%9u |%9u |\n", + vi.stat_reads[0], + vi.stat_reads[1], + vi.stat_reads[2], + vi.stat_reads[3]); + printf("Writes |%9u |%9u |%9u |%9u |\n", + vi.stat_writes[0], + vi.stat_writes[1], + vi.stat_writes[2], + vi.stat_writes[3]); + printf(" |-------------------------------------------|\n"); + + printf("\n"); + printf(" Writes Affecting Authorship\n"); + printf(" |-------------------------------------------|\n"); + printf(" | File Authorship | Directory Authorship|\n"); + printf(" |----------|----------|----------|----------|\n"); + printf(" | Same | Diff | Same | Diff |\n"); + printf(" |----------|----------|----------|----------|\n"); + + for (i = 0; i < 5; i++) { + printf("%s |%9u |%9u |%9u |%9u |\n", + statistics_time_ranges[i], + vi.stat_fileSameAuthor[i], + vi.stat_fileDiffAuthor[i], + vi.stat_dirSameAuthor[i], + vi.stat_dirDiffAuthor[i]); + printf(" |-------------------------------------------|\n"); + } +} + +/* + * Display machine-parseable form of volume record, but excluding certain info + * + * name proj.foo + * id 536870957 + * serv 111.22.33.44 foo.abc.com + * part /vicepa + * status OK + * backupID 0 + * parentID 536870957 + * cloneID 536870958 + * inUse Y + * needsSalvaged N + * destroyMe N + * type RW + * creationDate 1250918547 Sat Aug 22 06:22:27 2009 + * accessDate 1390951237 Tue Jan 28 23:20:37 2014 + * updateDate 1375733732 Mon Aug 5 21:15:32 2013 + * backupDate 0 Thu Jan 1 01:00:00 1970 + * copyDate 1288050032 Tue Oct 26 00:40:32 2010 + * flags 0 (Optional) + * diskused 40475760 + * maxquota 0 + * minquota 0 (Optional) + * filecount 327 + * dayUse 0 + * + */ +void kafs::display_vol_mp_basic_information(Context *ctx, + FS_site *site, + Partition_spec &partition, + Volume_info &vi) +{ + char abuf[20]; + unsigned int i; + + abuf[0] = 0; + for (i = 0; i < site->vs_addrs.size(); i++) { + if (site->vs_addrs[i].transport.family != AF_INET) + continue; + if (inet_ntop(AF_INET, &site->vs_addrs[i].transport.sin.sin_addr, + abuf, sizeof(abuf))) + break; + } + + if (!abuf[0]) + strcpy(abuf, "0.0.0.0"); + + std::string addr = kafs::sprint_address(ctx, site->vs_addrs[0]); + std::string part = kafs::sprint_partition(partition); + + fmt::print("BEGIN_OF_ENTRY\n"); + fmt::print("name\t\t{:s}\n", vi.name); + fmt::print("id\t\t{:d}\n", vi.volid); + fmt::print("serv\t\t{:<15s}\t{:s}\n", site->name, addr); + fmt::print("part\t\t{:s}\n", part); + fmt::print("status\t\t{:s}\n", vol_status(vi)); + fmt::print("backupID\t{:d}\n", vi.backup_id); + fmt::print("parentID\t{:d}\n", vi.parent_id); + fmt::print("cloneID\t\t{:d}\n", vi.clone_id); + fmt::print("inUse\t\t{:s}\n", yes_or_no(vi.in_use)); + if (vi.has_need_salvage) { + fmt::print("needsSalvaged\t{:s}\n", yes_or_no(vi.needs_salvage)); + fmt::print("destroyMe\t{:s}\n", yes_or_no(vi.destroy_me)); + } + fmt::print("type\t\t{:s}\n", vol_type(vi)); + fmt::print("creationDate\t{:<10d}\t{:s}\n", + vi.creation_date.seconds(), kafs::sprint_time(vi.creation_date)); + fmt::print("accessDate\t{:<10d}\t{:s}\n", + vi.access_date.seconds(), kafs::sprint_time(vi.access_date)); + fmt::print("updateDate\t{:<10d}\t{:s}\n", + vi.update_date.seconds(), kafs::sprint_time(vi.update_date)); + fmt::print("backupData\t{:<10d}\t{:s}\n", + vi.backup_date.seconds(), kafs::sprint_time(vi.backup_date)); + fmt::print("copyDate\t{:<10d}\t{:s}\n", + vi.copy_date.seconds(), kafs::sprint_time(vi.copy_date)); + if (vi.has_flags) + fmt::print("flags\t\t{:<7d}\t(Optional)\n", vi.flags); + fmt::print("diskused\t{:d}\n", vi.size); + fmt::print("maxquota\t{:d}\n", vi.max_quota); + if (vi.has_min_quota) + fmt::print("minquota\t{:<7d}\t(Optional)\n", vi.min_quota); + fmt::print("filecount\t{:d}\n", vi.file_count); + fmt::print("dayUse\t\t{:d}\n", vi.day_use); +} + +/* + * + * Display machine parseable form of volume record + * + * name proj.foo + * id 536870957 + * serv 111.22.33.44 foo.abc.com + * part /vicepa + * status OK + * backupID 0 + * parentID 536870957 + * cloneID 536870958 + * inUse Y + * needsSalvaged N + * destroyMe N + * type RW + * creationDate 1250918547 Sat Aug 22 06:22:27 2009 + * accessDate 1390951237 Tue Jan 28 23:20:37 2014 + * updateDate 1375733732 Mon Aug 5 21:15:32 2013 + * backupDate 0 Thu Jan 1 01:00:00 1970 + * copyDate 1288050032 Tue Oct 26 00:40:32 2010 + * flags 0 (Optional) + * diskused 40475760 + * maxquota 0 + * minquota 0 (Optional) + * filecount 327 + * dayUse 0 + * weekUse 0 (Optional) + * spare2 21775 (Optional) + * spare3 0 (Optional) + * + */ +void kafs::display_vol_mp_information(Context *ctx, + FS_site *site, + Partition_spec &partition, + Volume_info &vi) +{ + display_vol_mp_basic_information(ctx, site, partition, vi); + + if (vi.nr_week_use > 0) + fmt::print("weekUse\t\t{:<7u}\t(Optional)\n", vi.week_use[0]); + if (vi.has_spare2) + fmt::print("spare2\t\t{:<7u}\t(Optional)\n", vi.spare2); + if (vi.has_spare3) + fmt::print("spare3\t\t{:<7u}\t(Optional)\n", vi.spare3); +} diff --git a/kafs/vos_examine.C b/kafs/vos_examine.C new file mode 100644 index 0000000..51030ed --- /dev/null +++ b/kafs/vos_examine.C @@ -0,0 +1,144 @@ +/* The "vos examine" 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 "kafs.H" +#include "vlservice.H" +#include "volservice.H" +#include "afs_xg.H" +#include "display.H" + +using rxrpc::ref; +using kafs::afs::RWVOL; +using kafs::afs::ROVOL; +using kafs::afs::BACKVOL; +using kafs::afs::VLSF_RWVOL; +using kafs::afs::VLSF_ROVOL; +using kafs::afs::VLSF_BACKVOL; + +static void display_vldb(kafs::Context *ctx, + kafs::Vldb_entry *vldb) +{ + if (vldb->volume_id[RWVOL] != 0) + fmt::print(" RWrite: {:<10d}", vldb->volume_id[RWVOL]); + if (vldb->volume_id[ROVOL] != 0) + fmt::print(" ROnly: {:<10d}", vldb->volume_id[ROVOL]); + if (vldb->volume_id[BACKVOL] != 0) + fmt::print(" Backup: {:<10d}", vldb->volume_id[BACKVOL]); + fmt::print("\n"); + + kafs::display_vldb_site_list(ctx, vldb, " "); +} + +/*** + * COMMAND: vos examine - Show volume header and VLDB entry information for a volume + * ARG: "-id " + * ARG: "[-extended]" + * ARG: "[-format]" + * ARG: "[-cell ]" + * ARG: "[-noauth]" - Auth + * ARG: "[-localauth]" - Auth + * ARG: "[-verbose]" + * ARG: "[-encrypt]" - Auth + * ARG: "[-noresolve]" + * + * Show volume header and VLDB entry information for a volume + */ +void COMMAND_vos_examine( + kafs::Context *ctx, + kafs::Volume_spec &a_id, + bool a_extended, + bool a_format, + bool a_verbose, + bool a_noresolve) +{ + kafs::Vldb_entry_list vlist; + kafs::Volume_id volid; + unsigned int servflag = 0, i; + + _enter(""); + + ctx->no_resolve = a_noresolve; + + ref vlservice = new kafs::VL_service(ctx); + + vlservice->look_up_volume_by_name(a_id, vlist); + + kafs::Vldb_entry *vldb = vlist[0]; + if (a_id.is_numeric) { + volid = a_id.number; + if (volid == vldb->volume_id[RWVOL]) + servflag = VLSF_RWVOL; + else if (volid == vldb->volume_id[ROVOL]) + servflag = VLSF_ROVOL; + else if (volid == vldb->volume_id[BACKVOL]) + servflag = VLSF_BACKVOL; + else + throw std::runtime_error("Requested volume ID not in record for volume ID"); + } else { + for (i = 0; i < vldb->sites.size(); i++) + servflag |= vldb->sites[i].flags; + if (servflag & VLSF_RWVOL) { + servflag = VLSF_RWVOL; + volid = vldb->volume_id[RWVOL]; + } else if (servflag & VLSF_ROVOL) { + servflag = VLSF_ROVOL; + volid = vldb->volume_id[ROVOL]; + } else if (servflag & VLSF_BACKVOL) { + servflag = VLSF_BACKVOL; + volid = vldb->volume_id[BACKVOL]; + } else { + throw std::runtime_error("Requested volume does not exist on any server"); + } + } + + if (vldb->sites.size() == 0) + throw std::runtime_error("Couldn't examine requested volume"); + + for (i = 0; i < vldb->sites.size(); i++) { + kafs::Volume_info_list vi; + kafs::Vldb_site &site = vldb->sites[i]; + kafs::FS_site *fs_site = site.fs_site; + + if (!(site.flags & servflag)) + continue; + + try { + ref server = new kafs::Volserver(ctx, fs_site); + server->query_volume_state(site.partition, volid, a_extended, vi); + } catch (const rxrpc::rx_abort &a) { + std::cout << "aborted: " << a.what() << "\n"; + continue; + } catch (const std::system_error &e) { + std::cout << "error: " << e.what() << "\n"; + continue; + } catch (const std::runtime_error &e) { + std::cout << "error: " << e.what() << "\n"; + continue; + } catch (...) { + continue; + } + + if (vi.size()) { + if (a_format && !a_extended) { + display_vol_mp_information(ctx, fs_site, site.partition, vi[0]); + fmt::print("\n"); + } else { + display_vol_information(ctx, fs_site, site.partition, vi[0]); + if (a_extended) + display_vol_statistics(ctx, vi[0]); + } + } + } + + display_vldb(ctx, vldb); +}