#!/usr/bin/python2.6 # # The Qubes OS Project, http://www.qubes-os.org # # Copyright (C) 2010 Joanna Rutkowska # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # 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 License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # from qubes.qubes import QubesVmCollection from qubes.qubes import QubesException from optparse import OptionParser fields = { "qid": {"func": "vm.qid"}, "name": {"func": "('=>' if qvm_collection.get_default_template_vm() is not None\ and vm.qid == qvm_collection.get_default_template_vm().qid else '')\ + ('[' if vm.is_templete() else '')\ + ('<' if vm.is_disposablevm() else '')\ + ('{' if vm.is_netvm() else '')\ + vm.name \ + (']' if vm.is_templete() else '')\ + ('>' if vm.is_disposablevm() else '')\ + ('}' if vm.is_netvm() else '')"}, "type": {"func": "'Tpl' if vm.is_templete() else \ (' Net' if vm.is_netvm() else '')"}, "updbl" : {"func": "'Yes' if vm.is_updateable() else ''"}, "template": {"func": "'n/a' if vm.is_templete() or vm.is_netvm() else\ qvm_collection[vm.template_vm.qid].name"}, "netvm": {"func": "'n/a' if vm.is_netvm() else\ ('*' if vm.uses_default_netvm else '') +\ qvm_collection[vm.netvm_vm.qid].name\ if vm.netvm_vm is not None else '-'"}, "ip" : {"func": "vm.ip"}, "netmask" : {"func": "vm.netmask"}, "gateway" : {"func": "vm.gateway"}, "xid" : {"func" : "vm.get_xid() if vm.is_running() else '-'"}, "mem" : {"func" : "(str(vm.get_mem()/1024/1024) + ' MB') if vm.is_running() else '-'"}, "cpu" : {"func" : "round (vm.get_cpu_total_load(), 1) if vm.is_running() else '-'"}, "disk": {"func" : "str(vm.get_disk_utilization()/(1024*1024)) + ' MB'"}, "state": {"func" : "vm.get_power_state()"}, "priv-curr": {"func" : "str(vm.get_disk_utilization_private_img()/(1024*1024)) + ' MB'"}, "priv-max": {"func" : "str(vm.get_private_img_sz()/(1024*1024)) + ' MB'"}, "priv-util": {"func" : "str(vm.get_disk_utilization_private_img()*100/vm.get_private_img_sz()) + '%' if vm.get_private_img_sz() != 0 else '-'"}, "root-curr": {"func" : "str(vm.get_disk_utilization_root_img()/(1024*1024)) + ' MB'"}, "root-max": {"func" : "str(vm.get_root_img_sz()/(1024*1024)) + ' MB'"}, "root-util": {"func" : "str(vm.get_disk_utilization_root_img()*100/vm.get_root_img_sz()) + '%' if vm.get_root_img_sz() != 0 else '-'"}, "label" : {"func" : "vm.label.name"}, "on" : {"func" : "'*' if vm.is_running() else ''"} } def main(): usage = "usage: %prog [options] " parser = OptionParser (usage) parser.add_option ("-n", "--network", dest="network", action="store_true", default=False, help="Show network addresses assigned to VMs") parser.add_option ("-c", "--cpu", dest="cpu", action="store_true", default=False, help="Show CPU load") parser.add_option ("-m", "--mem", dest="mem", action="store_true", default=False, help="Show memory usage") parser.add_option ("-d", "--disk", dest="disk", action="store_true", default=False, help="Show VM disk utilization statistics") parser.add_option ("-i", "--ids", dest="ids", action="store_true", default=False, help="Show Qubes and Xen id#s") (options, args) = parser.parse_args () qvm_collection = QubesVmCollection() qvm_collection.lock_db_for_reading() qvm_collection.load() qvm_collection.unlock_db() fields_to_display = ["name", "on", "state", "updbl", "type", "template", "netvm", "label" ] if (options.ids): fields_to_display += ["qid", "xid"] if (options.cpu): fields_to_display += ["cpu"] if (options.mem): fields_to_display += ["mem"] if (options.network): fields_to_display.remove ("template") fields_to_display += ["ip", "netmask", "gateway"] if (options.disk): fields_to_display.remove ("template") fields_to_display.remove ("netvm") fields_to_display += ["priv-curr", "priv-max", "root-curr", "root-max", "disk" ] vms_list = [vm for vm in qvm_collection.values()] no_vms = len (vms_list) vms_to_display = [] # Frist, the NetVMs... for netvm in vms_list: if netvm.is_netvm(): vms_to_display.append (netvm) # Now, the template, and all its AppVMs... for tvm in vms_list: if tvm.is_templete(): vms_to_display.append (tvm) for vm in vms_list: if (vm.is_appvm() or vm.is_disposablevm()) and vm.template_vm.qid == tvm.qid: vms_to_display.append(vm) assert len(vms_to_display) == no_vms # First calculate the maximum width of each field we want to display total_width = 0; for f in fields_to_display: fields[f]["max_width"] = len(f) for vm in vms_to_display: l = len(str(eval(fields[f]["func"]))) if l > fields[f]["max_width"]: fields[f]["max_width"] = l total_width += fields[f]["max_width"] # Display the header s = "" for f in fields_to_display: fmt="{{0:-^{0}}}-+".format(fields[f]["max_width"] + 1) s += fmt.format('-') print s s = "" for f in fields_to_display: fmt="{{0:>{0}}} |".format(fields[f]["max_width"] + 1) s += fmt.format(f) print s s = "" for f in fields_to_display: fmt="{{0:-^{0}}}-+".format(fields[f]["max_width"] + 1) s += fmt.format('-') print s # ... and the actual data for vm in vms_to_display: s = "" for f in fields_to_display: fmt="{{0:>{0}}} |".format(fields[f]["max_width"] + 1) s += fmt.format(eval(fields[f]["func"])) print s try: vm.verify_files() except QubesException as err: print "WARNING: VM '{0}' has corrupted files!".format(vm.name) main()