qvm-ls 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #!/usr/bin/python2.6
  2. #
  3. # The Qubes OS Project, http://www.qubes-os.org
  4. #
  5. # Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
  6. #
  7. # This program is free software; you can redistribute it and/or
  8. # modify it under the terms of the GNU General Public License
  9. # as published by the Free Software Foundation; either version 2
  10. # of the License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20. #
  21. #
  22. from qubes.qubes import QubesVmCollection
  23. from qubes.qubes import QubesException
  24. from optparse import OptionParser
  25. fields = {
  26. "qid": {"func": "vm.qid"},
  27. "name": {"func": "('=>' if qvm_collection.get_default_template_vm() is not None\
  28. and vm.qid == qvm_collection.get_default_template_vm().qid else '')\
  29. + ('[' if vm.is_templete() else '')\
  30. + ('<' if vm.is_disposablevm() else '')\
  31. + ('{' if vm.is_netvm() else '')\
  32. + vm.name \
  33. + (']' if vm.is_templete() else '')\
  34. + ('>' if vm.is_disposablevm() else '')\
  35. + ('}' if vm.is_netvm() else '')"},
  36. "type": {"func": "'Tpl' if vm.is_templete() else \
  37. (' Net' if vm.is_netvm() else '')"},
  38. "updbl" : {"func": "'Yes' if vm.is_updateable() else ''"},
  39. "template": {"func": "'n/a' if vm.is_templete() or vm.is_netvm() else\
  40. qvm_collection[vm.template_vm.qid].name"},
  41. "netvm": {"func": "'n/a' if vm.is_netvm() else\
  42. ('*' if vm.uses_default_netvm else '') +\
  43. qvm_collection[vm.netvm_vm.qid].name\
  44. if vm.netvm_vm is not None else '-'"},
  45. "ip" : {"func": "vm.ip"},
  46. "netmask" : {"func": "vm.netmask"},
  47. "gateway" : {"func": "vm.gateway"},
  48. "xid" : {"func" : "vm.get_xid() if vm.is_running() else '-'"},
  49. "mem" : {"func" : "(str(vm.get_mem()/1024/1024) + ' MB') if vm.is_running() else '-'"},
  50. "cpu" : {"func" : "round (vm.get_cpu_total_load(), 1) if vm.is_running() else '-'"},
  51. "disk": {"func" : "str(vm.get_disk_utilization()/(1024*1024)) + ' MB'"},
  52. "state": {"func" : "vm.get_power_state()"},
  53. "priv-curr": {"func" : "str(vm.get_disk_utilization_private_img()/(1024*1024)) + ' MB'"},
  54. "priv-max": {"func" : "str(vm.get_private_img_sz()/(1024*1024)) + ' MB'"},
  55. "priv-util": {"func" : "str(vm.get_disk_utilization_private_img()*100/vm.get_private_img_sz()) + '%' if vm.get_private_img_sz() != 0 else '-'"},
  56. "root-curr": {"func" : "str(vm.get_disk_utilization_root_img()/(1024*1024)) + ' MB'"},
  57. "root-max": {"func" : "str(vm.get_root_img_sz()/(1024*1024)) + ' MB'"},
  58. "root-util": {"func" : "str(vm.get_disk_utilization_root_img()*100/vm.get_root_img_sz()) + '%' if vm.get_root_img_sz() != 0 else '-'"},
  59. "label" : {"func" : "vm.label.name"},
  60. "on" : {"func" : "'*' if vm.is_running() else ''"}
  61. }
  62. def main():
  63. usage = "usage: %prog [options] <vm-name>"
  64. parser = OptionParser (usage)
  65. parser.add_option ("-n", "--network", dest="network",
  66. action="store_true", default=False,
  67. help="Show network addresses assigned to VMs")
  68. parser.add_option ("-c", "--cpu", dest="cpu",
  69. action="store_true", default=False,
  70. help="Show CPU load")
  71. parser.add_option ("-m", "--mem", dest="mem",
  72. action="store_true", default=False,
  73. help="Show memory usage")
  74. parser.add_option ("-d", "--disk", dest="disk",
  75. action="store_true", default=False,
  76. help="Show VM disk utilization statistics")
  77. parser.add_option ("-i", "--ids", dest="ids",
  78. action="store_true", default=False,
  79. help="Show Qubes and Xen id#s")
  80. (options, args) = parser.parse_args ()
  81. qvm_collection = QubesVmCollection()
  82. qvm_collection.lock_db_for_reading()
  83. qvm_collection.load()
  84. qvm_collection.unlock_db()
  85. fields_to_display = ["name", "on", "state", "updbl", "type", "template", "netvm", "label" ]
  86. if (options.ids):
  87. fields_to_display += ["qid", "xid"]
  88. if (options.cpu):
  89. fields_to_display += ["cpu"]
  90. if (options.mem):
  91. fields_to_display += ["mem"]
  92. if (options.network):
  93. fields_to_display.remove ("template")
  94. fields_to_display += ["ip", "netmask", "gateway"]
  95. if (options.disk):
  96. fields_to_display.remove ("template")
  97. fields_to_display.remove ("netvm")
  98. fields_to_display += ["priv-curr", "priv-max", "root-curr", "root-max", "disk" ]
  99. vms_list = [vm for vm in qvm_collection.values()]
  100. no_vms = len (vms_list)
  101. vms_to_display = []
  102. # Frist, the NetVMs...
  103. for netvm in vms_list:
  104. if netvm.is_netvm():
  105. vms_to_display.append (netvm)
  106. # Now, the template, and all its AppVMs...
  107. for tvm in vms_list:
  108. if tvm.is_templete():
  109. vms_to_display.append (tvm)
  110. for vm in vms_list:
  111. if (vm.is_appvm() or vm.is_disposablevm()) and vm.template_vm.qid == tvm.qid:
  112. vms_to_display.append(vm)
  113. assert len(vms_to_display) == no_vms
  114. # First calculate the maximum width of each field we want to display
  115. total_width = 0;
  116. for f in fields_to_display:
  117. fields[f]["max_width"] = len(f)
  118. for vm in vms_to_display:
  119. l = len(str(eval(fields[f]["func"])))
  120. if l > fields[f]["max_width"]:
  121. fields[f]["max_width"] = l
  122. total_width += fields[f]["max_width"]
  123. # Display the header
  124. s = ""
  125. for f in fields_to_display:
  126. fmt="{{0:-^{0}}}-+".format(fields[f]["max_width"] + 1)
  127. s += fmt.format('-')
  128. print s
  129. s = ""
  130. for f in fields_to_display:
  131. fmt="{{0:>{0}}} |".format(fields[f]["max_width"] + 1)
  132. s += fmt.format(f)
  133. print s
  134. s = ""
  135. for f in fields_to_display:
  136. fmt="{{0:-^{0}}}-+".format(fields[f]["max_width"] + 1)
  137. s += fmt.format('-')
  138. print s
  139. # ... and the actual data
  140. for vm in vms_to_display:
  141. s = ""
  142. for f in fields_to_display:
  143. fmt="{{0:>{0}}} |".format(fields[f]["max_width"] + 1)
  144. s += fmt.format(eval(fields[f]["func"]))
  145. print s
  146. try:
  147. vm.verify_files()
  148. except QubesException as err:
  149. print "WARNING: VM '{0}' has corrupted files!".format(vm.name)
  150. main()