--- /dev/null
+#
+# AFS Volume management toolkit: Volume location database info
+# -*- coding: utf-8 -*-
+#
+
+__copyright__ = """
+Copyright (C) 2014 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 version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+from afs.argparse import *
+from afs.lib.debug import debug
+from afs.lib.partition import id2part
+import afs.lib.addrcache as addrcache
+import kafs
+import sys
+import datetime
+
+help = "Display information from a volume header"
+
+command_arguments = [
+ [ "server", get_volserver, "rs", "<machine name>" ],
+ [ "partition", get_partition_id, "os", "<partition name>" ],
+ [ "fast", get_dummy, "fn" ],
+ [ "long", get_dummy, "fn" ],
+ [ "quiet", get_dummy, "fn" ],
+ [ "extended", get_dummy, "fn" ],
+ [ "format", get_dummy, "fn" ],
+ [ "cell", get_cell, "os", "<cell name>" ],
+ [ "noauth", get_auth, "fn" ],
+ [ "localauth", get_auth, "fn" ],
+ [ "verbose", get_dummy, "fn" ],
+ [ "encrypt", get_dummy, "fn" ],
+ [ "noresolve", get_dummy, "fn" ],
+]
+
+cant_combine_arguments = [
+ ( "cell", "localauth" ),
+ ( "noauth", "localauth" ),
+ ( "fast", "extended" ),
+]
+
+description = r"""
+Display information from a volume header
+"""
+
+def vol_type(vol):
+ if vol.type == 0:
+ return "RW"
+ if vol.type == 1:
+ return "RO"
+ if vol.type == 2:
+ return "BK"
+ return "0x{:02x}".format(vol.type)
+
+def vol_state(vol):
+ if vol.inUse:
+ s = "On-line"
+ else:
+ s = "Off-line"
+ try:
+ # This isn't available in struct xvolintInfo
+ if vol.needsSalvaged:
+ s += "**needs salvage**"
+ except AttributeError:
+ pass
+ return s
+
+def vol_status(vol):
+ if vol.status == kafs.VOK:
+ return "OK"
+ if vol.status == kafs.VBUSY:
+ return "BUSY"
+ return "UNATTACHABLE"
+
+def vol_date(d, never = False):
+ if d == 0 and never:
+ return "Never"
+ t = datetime.datetime.fromtimestamp(d)
+ return t.strftime("%a %b %d %H:%M:%S %Y")
+
+def yes_or_no(n):
+ if (n):
+ return "Y"
+ return "N"
+
+def display_normal(params, vol):
+ print("{:32s} {:10d} {:2s} {:10d} K {:s}".format(vol.name,
+ vol.volid,
+ vol_type(vol),
+ vol.size,
+ vol_state(vol)))
+
+def display_fast(params, vol):
+ print(vol.volid)
+
+def display_long(params, vol):
+ display_normal(params, vol)
+ print(" ", params["server"], params["_partname"])
+ print(" ", "RWrite {:10d} ROnly {:10d} Backup {:10d}".format(vol.parentID,
+ vol.cloneID,
+ vol.backupID))
+ print(" ", "MaxQuota {:10d} K".format(vol.maxquota))
+ print(" ", "Creation ", vol_date(vol.creationDate, True))
+ print(" ", "Copy ", vol_date(vol.copyDate, True))
+ print(" ", "Backup ", vol_date(vol.backupDate, True))
+ print(" ", "Last Access", vol_date(vol.accessDate, True))
+ print(" ", "Last Update", vol_date(vol.updateDate, True))
+ print(" ", vol.dayUse, "accesses in the past day (i.e., vnode references)")
+ print()
+
+def display_extended(params, vol):
+ display_long(params, vol)
+ print(" Raw Read/Write Stats")
+ print(" |-------------------------------------------|")
+ print(" | Same Network | Diff Network |")
+ print(" |----------|----------|----------|----------|")
+ print(" | Total | Auth | Total | Auth |")
+ print(" |----------|----------|----------|----------|")
+ print("Reads |{:9d} |{:9d} |{:9d} |{:9d} |".format(vol.stat_reads[0],
+ vol.stat_reads[1],
+ vol.stat_reads[2],
+ vol.stat_reads[3]))
+ print("Writes |{:9d} |{:9d} |{:9d} |{:9d} |".format(vol.stat_writes[0],
+ vol.stat_writes[1],
+ vol.stat_writes[2],
+ vol.stat_writes[3]))
+ print(" |-------------------------------------------|")
+
+ print()
+ print(" Writes Affecting Authorship")
+ print(" |-------------------------------------------|")
+ print(" | File Authorship | Directory Authorship|")
+ print(" |----------|----------|----------|----------|")
+ print(" | Same | Diff | Same | Diff |")
+ print(" |----------|----------|----------|----------|")
+
+ ranges = [
+ "0-60 sec ",
+ "1-10 min ",
+ "10min-1hr",
+ "1hr-1day ",
+ "1day-1wk ",
+ "> 1wk "
+ ]
+
+ for i in range(0, 5):
+ print("{:s} |{:9d} |{:9d} |{:9d} |{:9d} |".format(ranges[i],
+ vol.stat_fileSameAuthor[i],
+ vol.stat_fileDiffAuthor[i],
+ vol.stat_dirSameAuthor[i],
+ vol.stat_dirDiffAuthor[i]))
+ print(" |-------------------------------------------|")
+ print()
+
+def display_format_basic(params, vol):
+ server = params["server"]
+ print("BEGIN_OF_ENTRY")
+ print("name\t\t{:s}".format(vol.name))
+ print("id\t\t{:d}".format(vol.volid))
+ print("serv\t\t{:<15s}\t{:s}".format(str(server), server.addr()))
+ print("part\t\t{:s}".format(params["_partname"]))
+ print("status\t\t{:s}".format(vol_status(vol)))
+ print("backupID\t{:d}".format(vol.backupID))
+ print("parentID\t{:d}".format(vol.parentID))
+ print("cloneID\t\t{:d}".format(vol.cloneID))
+ print("inUse\t\t{:s}".format(yes_or_no(vol.inUse)))
+ try:
+ print("needsSalvaged\t{:s}".format(yes_or_no(vol.needsSalvaged)))
+ print("destroyMe\t{:s}".format(yes_or_no(vol.destroyMe)))
+ except AttributeError:
+ pass
+ print("type\t\t{:s}".format(vol_type(vol)))
+ print("creationDate\t{:<10d}\t{:s}".format(vol.creationDate, vol_date(vol.creationDate)))
+ print("accessDate\t{:<10d}\t{:s}".format(vol.accessDate, vol_date(vol.accessDate)))
+ print("updateDate\t{:<10d}\t{:s}".format(vol.updateDate, vol_date(vol.updateDate)))
+ print("backupData\t{:<10d}\t{:s}".format(vol.backupDate, vol_date(vol.backupDate)))
+ print("copyDate\t{:<10d}\t{:s}".format(vol.copyDate, vol_date(vol.copyDate)))
+ try:
+ print("flags\t\t{:<7d}\t(Optional)".format(vol.flags))
+ except AttributeError:
+ pass
+ print("diskused\t{:d}".format(vol.size))
+ print("maxquota\t{:d}".format(vol.maxquota))
+ try:
+ print("minquota\t{:<7d}\t(Optional)".format(vol.spare0))
+ except AttributeError:
+ pass
+ print("filecount\t{:d}".format(vol.filecount))
+ print("dayUse\t\t{:d}".format(vol.dayUse))
+
+def display_format_normal(params, vol):
+ display_format_basic(params, vol)
+ print("weekUse\t\t{:<7d}\t(Optional)".format(vol.spare1))
+ print("spare2\t\t{:<7d}\t(Optional)".format(vol.spare2))
+ print("spare3\t\t{:<7d}\t(Optional)".format(vol.spare3))
+ print("END_OF_ENTRY")
+
+reads_labels = [ "reads_same_net", "reads_same_net_auth",
+ "reads_diff_net", "reads_diff_net_auth" ]
+
+writes_labels = [ "writes_same_net", "writes_same_net_auth",
+ "writes_diff_net", "writes_diff_net_auth" ]
+
+def display_format_extended(params, vol):
+ if vol.status == kafs.VBUSY:
+ print("VOLUME_BUSY\t{:d}\n", vol.volid)
+ return
+ elif vol.status != kafs.VOK:
+ print("COULD_NOT_ATTACH_VOLUME\t{:d}\n", vol.volid)
+ return
+
+ display_format_basic(params, vol)
+
+ for i in range(0, 4):
+ print("{:s}\t{:8d}".format(reads_labels[i], vol.stat_reads[i]))
+ for i in range(0, 4):
+ print("{:s}\t{:8d}".format(writes_labels[i], vol.stat_writes[i]))
+ for i in range(0, 6):
+ print("file_same_author_idx_{:d}\t{:8d}".format(i, vol.stat_fileSameAuthor[i]))
+ print("file_diff_author_idx_{:d}\t{:8d}".format(i, vol.stat_fileDiffAuthor[i]))
+ print("dir_same_author_idx_{:d}\t{:8d}".format(i, vol.stat_dirSameAuthor[i]))
+ print("dir_dif_author_idx_{:d}\t{:8d}".format(i, vol.stat_dirDiffAuthor[i]))
+
+ print("END_OF_ENTRY")
+
+###############################################################################
+#
+# Display the records for a single partition in the appropriate format
+#
+###############################################################################
+def display_one_partition(params, vol_conn, partition):
+ if "extended" in params:
+ ret = kafs.VOLSER_AFSVolXListVolumes(vol_conn, partition, 1)
+ else:
+ ret = kafs.VOLSER_AFSVolListVolumes(vol_conn, partition, 1)
+
+ params["_partname"] = partname = id2part(partition)
+ if "quiet" not in params:
+ print("Total number of volumes on server", params["server"], "partition",
+ partname + ":", len(ret.resultEntries))
+
+ display_func = display_normal
+ if "fast" in params:
+ display_func = display_fast
+ elif "format" in params and "extended" in params:
+ display_func = display_format_extended
+ elif "format" in params:
+ display_func = display_format_normal
+ elif "extended" in params:
+ display_func = display_extended
+ elif "long" in params:
+ display_func = display_long
+
+ n_online = 0
+ n_offline = 0
+ n_busy = 0
+ volumes = ret.resultEntries
+ volumes.sort(key=lambda vol: vol.name)
+ for vol in volumes:
+ if vol.inUse:
+ n_online += 1
+ if vol.status == kafs.VBUSY:
+ n_busy += 1
+ display_func(params, vol)
+
+ if "quiet" not in params:
+ print()
+ if "fast" not in params and "format" not in params:
+ print("Total volumes onLine", n_online, "; Total volumes offLine", n_offline,
+ "; Total busy", n_busy)
+ print()
+ elif "format" in params and "extended" in params:
+ print("VOLUMES_ONLINE ", n_online)
+ print("VOLUMES_OFFLINE", n_offline)
+ print("VOLUMES_BUSY ", n_busy)
+
+def main(params):
+ cell = params["cell"]
+ vol_conn = cell.open_volume_server(params["server"], params)
+
+ if "partition" in params:
+ try:
+ display_one_partition(params, vol_conn, params["partition"])
+ except kafs.AbortVOLSERILLEGAL_PARTITION:
+ print("vos : partition", params["raw.partition"][0],
+ "does not exist on the server", file=sys.stderr)
+ sys.exit(2)
+
+ else:
+ ret = kafs.VOLSER_AFSVolXListPartitions(vol_conn)
+ for p in ret.ent:
+ one_partition(params, vol_conn, p)