Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: client/tests/kvm/kvm_vm.py

Issue 6883035: Merge remote branch 'autotest-upstream/master' into autotest-merge (Closed) Base URL: ssh://gitrw.chromium.org:9222/autotest.git@master
Patch Set: patch Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 """ 2 """
3 Utility classes and functions to handle Virtual Machine creation using qemu. 3 Utility classes and functions to handle Virtual Machine creation using qemu.
4 4
5 @copyright: 2008-2009 Red Hat Inc. 5 @copyright: 2008-2009 Red Hat Inc.
6 """ 6 """
7 7
8 import time, os, logging, fcntl, re, commands, glob 8 import time, os, logging, fcntl, re, commands, glob
9 import kvm_utils, kvm_subprocess, kvm_monitor 9 import kvm_utils, kvm_subprocess, kvm_monitor
10 from autotest_lib.client.common_lib import error 10 from autotest_lib.client.common_lib import error
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 def __init__(self, status, output): 98 def __init__(self, status, output):
99 VMError.__init__(self, status, output) 99 VMError.__init__(self, status, output)
100 self.status = status 100 self.status = status
101 self.output = output 101 self.output = output
102 102
103 def __str__(self): 103 def __str__(self):
104 return ("VM process is dead (status: %s, output: %r)" % 104 return ("VM process is dead (status: %s, output: %r)" %
105 (self.status, self.output)) 105 (self.status, self.output))
106 106
107 107
108 class VMDeadKernelCrashError(VMError):
109 def __init__(self, kernel_crash):
110 VMError.__init__(self, kernel_crash)
111 self.kernel_crash = kernel_crash
112
113 def __str__(self):
114 return ("VM is dead due to a kernel crash:\n%s" % self.kernel_crash)
115
116
108 class VMAddressError(VMError): 117 class VMAddressError(VMError):
109 pass 118 pass
110 119
111 120
112 class VMPortNotRedirectedError(VMAddressError): 121 class VMPortNotRedirectedError(VMAddressError):
113 def __init__(self, port): 122 def __init__(self, port):
114 VMAddressError.__init__(self, port) 123 VMAddressError.__init__(self, port)
115 self.port = port 124 self.port = port
116 125
117 def __str__(self): 126 def __str__(self):
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 if not "info" in q_output: 287 if not "info" in q_output:
279 logging.error("qemu-img does not support 'info', " 288 logging.error("qemu-img does not support 'info', "
280 "skipping check...") 289 "skipping check...")
281 check_img = False 290 check_img = False
282 if check_img: 291 if check_img:
283 try: 292 try:
284 utils.system("%s info %s" % (qemu_img_cmd, image_filename)) 293 utils.system("%s info %s" % (qemu_img_cmd, image_filename))
285 except error.CmdError: 294 except error.CmdError:
286 logging.error("Error getting info from image %s", 295 logging.error("Error getting info from image %s",
287 image_filename) 296 image_filename)
288 try: 297
289 utils.system("%s check %s" % (qemu_img_cmd, image_filename)) 298 cmd_result = utils.run("%s check %s" %
290 except error.CmdError: 299 (qemu_img_cmd, image_filename),
300 ignore_status=True)
301 # Error check, large chances of a non-fatal problem.
302 # There are chances that bad data was skipped though
303 if cmd_result.exit_status == 1:
304 for e_line in cmd_result.stdout.splitlines():
305 logging.error("[stdout] %s", e_line)
306 for e_line in cmd_result.stderr.splitlines():
307 logging.error("[stderr] %s", e_line)
308 raise error.TestWarn("qemu-img check error. Some bad data in "
309 "the image may have gone unnoticed")
310 # Exit status 2 is data corruption for sure, so fail the test
311 elif cmd_result.exit_status == 2:
312 for e_line in cmd_result.stdout.splitlines():
313 logging.error("[stdout] %s", e_line)
314 for e_line in cmd_result.stderr.splitlines():
315 logging.error("[stderr] %s", e_line)
291 raise VMImageCheckError(image_filename) 316 raise VMImageCheckError(image_filename)
317 # Leaked clusters, they are known to be harmless to data integrity
318 elif cmd_result.exit_status == 3:
319 raise error.TestWarn("Leaked clusters were noticed during "
320 "image check. No data integrity problem "
321 "was found though.")
292 322
293 else: 323 else:
294 if not os.path.exists(image_filename): 324 if not os.path.exists(image_filename):
295 logging.debug("Image file %s not found, skipping check...", 325 logging.debug("Image file %s not found, skipping check...",
296 image_filename) 326 image_filename)
297 elif not image_is_qcow2: 327 elif not image_is_qcow2:
298 logging.debug("Image file %s not qcow2, skipping check...", 328 logging.debug("Image file %s not qcow2, skipping check...",
299 image_filename) 329 image_filename)
300 330
301 331
(...skipping 26 matching lines...) Expand all
328 self.device_id = [] 358 self.device_id = []
329 self.uuid = None 359 self.uuid = None
330 360
331 # Find a unique identifier for this VM 361 # Find a unique identifier for this VM
332 while True: 362 while True:
333 self.instance = (time.strftime("%Y%m%d-%H%M%S-") + 363 self.instance = (time.strftime("%Y%m%d-%H%M%S-") +
334 kvm_utils.generate_random_string(4)) 364 kvm_utils.generate_random_string(4))
335 if not glob.glob("/tmp/*%s" % self.instance): 365 if not glob.glob("/tmp/*%s" % self.instance):
336 break 366 break
337 367
368 self.spice_port = 8000
338 self.name = name 369 self.name = name
339 self.params = params 370 self.params = params
340 self.root_dir = root_dir 371 self.root_dir = root_dir
341 self.address_cache = address_cache 372 self.address_cache = address_cache
342 373
343 374
344 def clone(self, name=None, params=None, root_dir=None, address_cache=None, 375 def clone(self, name=None, params=None, root_dir=None, address_cache=None,
345 copy_state=False): 376 copy_state=False):
346 """ 377 """
347 Return a clone of the VM object with optionally modified parameters. 378 Return a clone of the VM object with optionally modified parameters.
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 577
547 def add_nographic(help): 578 def add_nographic(help):
548 return " -nographic" 579 return " -nographic"
549 580
550 def add_uuid(help, uuid): 581 def add_uuid(help, uuid):
551 return " -uuid '%s'" % uuid 582 return " -uuid '%s'" % uuid
552 583
553 def add_pcidevice(help, host): 584 def add_pcidevice(help, host):
554 return " -pcidevice host='%s'" % host 585 return " -pcidevice host='%s'" % host
555 586
587 def add_spice(help, port, param):
588 if has_option(help,"spice"):
589 return " -spice port=%s,%s" % (port, param)
590 else:
591 return ""
592
593 def add_qxl_vga(help, qxl, vga, qxl_dev_nr=None):
594 str = ""
595 if has_option(help, "qxl"):
596 if qxl and qxl_dev_nr is not None:
597 str += " -qxl %s" % qxl_dev_nr
598 if has_option(help, "vga") and vga and vga != "qxl":
599 str += " -vga %s" % vga
600 elif has_option(help, "vga"):
601 if qxl:
602 str += " -vga qxl"
603 elif vga:
604 str += " -vga %s" % vga
605 return str
606
556 def add_kernel(help, filename): 607 def add_kernel(help, filename):
557 return " -kernel '%s'" % filename 608 return " -kernel '%s'" % filename
558 609
559 def add_initrd(help, filename): 610 def add_initrd(help, filename):
560 return " -initrd '%s'" % filename 611 return " -initrd '%s'" % filename
561 612
562 def add_kernel_cmdline(help, cmdline): 613 def add_kernel_cmdline(help, cmdline):
563 return " -append %s" % cmdline 614 return " -append %s" % cmdline
564 615
565 def add_testdev(help, filename): 616 def add_testdev(help, filename):
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 764
714 for host_port, guest_port in redirs: 765 for host_port, guest_port in redirs:
715 qemu_cmd += add_tcp_redir(help, host_port, guest_port) 766 qemu_cmd += add_tcp_redir(help, host_port, guest_port)
716 767
717 if params.get("display") == "vnc": 768 if params.get("display") == "vnc":
718 qemu_cmd += add_vnc(help, vm.vnc_port) 769 qemu_cmd += add_vnc(help, vm.vnc_port)
719 elif params.get("display") == "sdl": 770 elif params.get("display") == "sdl":
720 qemu_cmd += add_sdl(help) 771 qemu_cmd += add_sdl(help)
721 elif params.get("display") == "nographic": 772 elif params.get("display") == "nographic":
722 qemu_cmd += add_nographic(help) 773 qemu_cmd += add_nographic(help)
774 elif params.get("display") == "spice":
775 qemu_cmd += add_spice(help, self.spice_port, params.get("spice"))
776
777 qxl = ""
778 vga = ""
779 if params.get("qxl"):
780 qxl = params.get("qxl")
781 if params.get("vga"):
782 vga = params.get("vga")
783 if qxl or vga:
784 if params.get("display") == "spice":
785 qxl_dev_nr = params.get("qxl_dev_nr", None)
786 qemu_cmd += add_qxl_vga(help, qxl, vga, qxl_dev_nr)
723 787
724 if params.get("uuid") == "random": 788 if params.get("uuid") == "random":
725 qemu_cmd += add_uuid(help, vm.uuid) 789 qemu_cmd += add_uuid(help, vm.uuid)
726 elif params.get("uuid"): 790 elif params.get("uuid"):
727 qemu_cmd += add_uuid(help, params.get("uuid")) 791 qemu_cmd += add_uuid(help, params.get("uuid"))
728 792
729 if params.get("testdev") == "yes": 793 if params.get("testdev") == "yes":
730 qemu_cmd += add_testdev(help, vm.get_testlog_filename()) 794 qemu_cmd += add_testdev(help, vm.get_testlog_filename())
731 795
732 if params.get("disable_hpet") == "yes": 796 if params.get("disable_hpet") == "yes":
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 self.netdev_id = [] 902 self.netdev_id = []
839 self.device_id = [] 903 self.device_id = []
840 for nic in params.objects("nics"): 904 for nic in params.objects("nics"):
841 self.netdev_id.append(kvm_utils.generate_random_id()) 905 self.netdev_id.append(kvm_utils.generate_random_id())
842 self.device_id.append(kvm_utils.generate_random_id()) 906 self.device_id.append(kvm_utils.generate_random_id())
843 907
844 # Find available VNC port, if needed 908 # Find available VNC port, if needed
845 if params.get("display") == "vnc": 909 if params.get("display") == "vnc":
846 self.vnc_port = kvm_utils.find_free_port(5900, 6100) 910 self.vnc_port = kvm_utils.find_free_port(5900, 6100)
847 911
912 # Find available spice port
913 if params.get("spice"):
914 self.spice_port = kvm_utils.find_free_port(8000, 8100)
915
848 # Find random UUID if specified 'uuid = random' in config file 916 # Find random UUID if specified 'uuid = random' in config file
849 if params.get("uuid") == "random": 917 if params.get("uuid") == "random":
850 f = open("/proc/sys/kernel/random/uuid") 918 f = open("/proc/sys/kernel/random/uuid")
851 self.uuid = f.read().strip() 919 self.uuid = f.read().strip()
852 f.close() 920 f.close()
853 921
854 # Generate or copy MAC addresses for all NICs 922 # Generate or copy MAC addresses for all NICs
855 num_nics = len(params.objects("nics")) 923 num_nics = len(params.objects("nics"))
856 for vlan in range(num_nics): 924 for vlan in range(num_nics):
857 nic_name = params.objects("nics")[vlan] 925 nic_name = params.objects("nics")[vlan]
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1113 self.monitor.is_responsive()) 1181 self.monitor.is_responsive())
1114 1182
1115 1183
1116 def is_dead(self): 1184 def is_dead(self):
1117 """ 1185 """
1118 Return True if the qemu process is dead. 1186 Return True if the qemu process is dead.
1119 """ 1187 """
1120 return not self.process or not self.process.is_alive() 1188 return not self.process or not self.process.is_alive()
1121 1189
1122 1190
1191 def verify_kernel_crash(self):
1192 """
1193 Find kernel crash message on the VM serial console.
1194
1195 @raise: VMDeadKernelCrashError, in case a kernel crash message was
1196 found.
1197 """
1198 data = self.serial_console.get_output()
1199 match = re.search(r"BUG:.*---\[ end trace .* \]---", data,
1200 re.DOTALL|re.MULTILINE)
1201 if match is not None:
1202 raise VMDeadKernelCrashError(match.group(0))
1203
1204
1123 def get_params(self): 1205 def get_params(self):
1124 """ 1206 """
1125 Return the VM's params dict. Most modified params take effect only 1207 Return the VM's params dict. Most modified params take effect only
1126 upon VM.create(). 1208 upon VM.create().
1127 """ 1209 """
1128 return self.params 1210 return self.params
1129 1211
1130 1212
1131 def get_monitor_filename(self, monitor_name): 1213 def get_monitor_filename(self, monitor_name):
1132 """ 1214 """
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
1589 clone = temp 1671 clone = temp
1590 1672
1591 # From now on, clone is the source VM that will soon be destroyed 1673 # From now on, clone is the source VM that will soon be destroyed
1592 # and self is the destination VM that will remain alive. If this 1674 # and self is the destination VM that will remain alive. If this
1593 # is remote migration, self is a dead VM object. 1675 # is remote migration, self is a dead VM object.
1594 1676
1595 error.context("after migration") 1677 error.context("after migration")
1596 if local: 1678 if local:
1597 time.sleep(1) 1679 time.sleep(1)
1598 self.verify_alive() 1680 self.verify_alive()
1681 self.verify_kernel_crash()
1599 1682
1600 if local and stable_check: 1683 if local and stable_check:
1601 try: 1684 try:
1602 save1 = os.path.join(save_path, "src-" + clone.instance) 1685 save1 = os.path.join(save_path, "src-" + clone.instance)
1603 save2 = os.path.join(save_path, "dst-" + self.instance) 1686 save2 = os.path.join(save_path, "dst-" + self.instance)
1604 clone.save_to_file(save1) 1687 clone.save_to_file(save1)
1605 self.save_to_file(save2) 1688 self.save_to_file(save2)
1606 # Fail if we see deltas 1689 # Fail if we see deltas
1607 md5_save1 = utils.hash_file(save1) 1690 md5_save1 = utils.hash_file(save1)
1608 md5_save2 = utils.hash_file(save2) 1691 md5_save2 = utils.hash_file(save2)
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1768 Save the state of virtual machine to a file through migrate to 1851 Save the state of virtual machine to a file through migrate to
1769 exec 1852 exec
1770 """ 1853 """
1771 # Make sure we only get one iteration 1854 # Make sure we only get one iteration
1772 self.monitor.cmd("migrate_set_speed 1000g") 1855 self.monitor.cmd("migrate_set_speed 1000g")
1773 self.monitor.cmd("migrate_set_downtime 100000000") 1856 self.monitor.cmd("migrate_set_downtime 100000000")
1774 self.monitor.migrate('"exec:cat>%s"' % path) 1857 self.monitor.migrate('"exec:cat>%s"' % path)
1775 # Restore the speed and downtime of migration 1858 # Restore the speed and downtime of migration
1776 self.monitor.cmd("migrate_set_speed %d" % (32<<20)) 1859 self.monitor.cmd("migrate_set_speed %d" % (32<<20))
1777 self.monitor.cmd("migrate_set_downtime 0.03") 1860 self.monitor.cmd("migrate_set_downtime 0.03")
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698