#include <fmt/format.h>
#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.
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)
+ * <blank>
+ *
+ */
+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 |
+ * |-------------------------------------------|
+ * <blank>
+ * 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);
+}
--- /dev/null
+/* 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 <iostream>
+#include <fmt/core.h>
+#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 <volume name or ID>"
+ * ARG: "[-extended]"
+ * ARG: "[-format]"
+ * ARG: "[-cell <cell name>]"
+ * 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<kafs::VL_service> 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<kafs::Volserver> 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);
+}