def create_attach_xml(update_xmlfile, disk_type, target_bus, target_dev, source_iso="", disk_mode=""): """ Create a xml file to update a device. :param update_xmlfile : path/file to save device XML :param source_iso : disk's source backing file. :param disk_type: disk's device type: cdrom or floppy :param target_bus: disk's target bus :param target_dev: disk's target device name :param disk_mode: readonly or shareable """ if source_iso: libvirt.create_local_disk("iso", source_iso) disk_class = VMXML.get_device_class('disk') disk = disk_class(type_name='file') # Static definition for comparison in check_attach() disk.device = disk_type disk.target = dict(bus=target_bus, dev=target_dev) if source_iso: disk.driver = dict(name='qemu') disk.source = disk.new_disk_source(attrs={'file': source_iso}) if disk_mode == "readonly": disk.readonly = True if disk_mode == "shareable": disk.share = True disk.xmltreefile.write() shutil.copyfile(disk.xml, update_xmlfile)
def do_rename(vm, new_name, uuid=None, fail_info=[]): # Change name in XML logging.info("Rename %s to %s.", vm.name, new_name) try: vm = VMXML.vm_rename(vm, new_name, uuid) # give it a new uuid except LibvirtXMLError, detail: raise error.TestFail("Rename %s to %s failed:\n%s" % (vm.name, new_name, detail))
def agent_connected(): """ Callback function to check if agent channel connected. """ ga_tgt = VMXML.new_from_dumpxml(vm_name).get_section_string( '/devices/channel/target') return 'state="connected"' in ga_tgt
def create_attach_xml(update_xmlfile, source_iso, target_bus, target_dev): """ Create a xml file to update a device. :param update_xmlfile : path/file to save device XML :param source_iso : disk's source backing file. :param target_bus : disk's target bus :param target_dev : disk's target device name """ try: _file = open(source_iso, 'wb') _file.seek((1024 * 1024) - 1) _file.write(str(0)) _file.close() except IOError: raise error.TestFail("Create source_iso failed!") disk_class = VMXML.get_device_class('disk') disk = disk_class(type_name='file') # Static definition for comparison in check_attach() disk.device = 'cdrom' disk.driver = dict(name='file') disk.source = disk.new_disk_source(attrs={'file': source_iso}) disk.target = dict(bus=target_bus, dev=target_dev) disk.readonly = True disk.xmltreefile.write() shutil.copyfile(disk.xml, update_xmlfile)
def create_attach_xml(update_xmlfile, source_iso, disk_type, target_bus, target_dev, disk_mode=""): """ Create a xml file to update a device. :param update_xmlfile : path/file to save device XML :param source_iso : disk's source backing file. :param disk_type: disk's device type: cdrom or floppy :param target_bus: disk's target bus :param target_dev: disk's target device name :param disk_mode: readonly or shareable """ try: _file = open(source_iso, 'wb') _file.seek((1024 * 1024) - 1) _file.write(str(0)) _file.close() except IOError: raise error.TestFail("Create source_iso failed!") disk_class = VMXML.get_device_class('disk') disk = disk_class(type_name='file') # Static definition for comparison in check_attach() disk.device = disk_type disk.driver = dict(name='qemu') disk.source = disk.new_disk_source(attrs={'file': source_iso}) disk.target = dict(bus=target_bus, dev=target_dev) if disk_mode == "readonly": disk.readonly = True if disk_mode == "shareable": disk.share = True disk.xmltreefile.write() shutil.copyfile(disk.xml, update_xmlfile)
def create_attach_xml(params, test, update_xmlfile, source_iso, disk_type, target_bus, target_dev, disk_mode="", disk_alias=None): """ Create a xml file to update a device. :param parameters from cfg file :param update_xmlfile : path/file to save device XML :param source_iso : disk's source backing file. :param disk_type: disk's device type: cdrom or floppy :param target_bus: disk's target bus :param target_dev: disk's target device name :param disk_mode: readonly or shareable :param disk_alias: disk's alias name """ slice_test = "yes" == params.get("disk_slice", "no") try: if slice_test: libvirt.create_local_disk("file", source_iso, size="1", disk_format="qcow2", extra="-o preallocation=full") else: with open(source_iso, 'wb') as _file: _file.seek((1024 * 1024) - 1) _file.write(str(0).encode()) except IOError: test.fail("Create source_iso failed!") disk_class = VMXML.get_device_class('disk') disk = disk_class(type_name='file') # Static definition for comparison in check_attach()` disk.device = disk_type disk.driver = dict(name='qemu') disk_source = disk.new_disk_source(**{"attrs": {'file': source_iso}}) # Add slice field involved in source if slice_test: slice_size_param = process.run("du -b %s" % source_iso).stdout_text.strip() slice_size = re.findall(r'[0-9]+', slice_size_param) slice_size = ''.join(slice_size) disk_source.slices = disk.new_slices( **{"slice_type": "storage", "slice_offset": "0", "slice_size": slice_size}) disk.source = disk_source disk.target = dict(bus=target_bus, dev=target_dev) if disk_mode == "readonly": disk.readonly = True if disk_mode == "shareable": disk.share = True if disk_alias: disk.alias = dict(name=disk_alias) disk.xmltreefile.write() shutil.copyfile(disk.xml, update_xmlfile)
def do_rename(vm, new_name, uuid=None, fail_info=[]): # Change name in XML logging.info("Rename %s to %s.", vm.name, new_name) try: vm = VMXML.vm_rename(vm, new_name, uuid) # give it a new uuid except LibvirtXMLError as detail: test.fail("Rename %s to %s failed:\n%s" % (vm.name, new_name, detail)) # Exercize the defined XML try: vm.start() except virt_vm.VMStartError as detail: # Do not raise TestFail because vm should be restored fail_info.append("Start guest %s failed:%s" % (vm.name, detail)) vm.destroy() return fail_info
def create_attach_xml(test, update_xmlfile, source_iso, disk_type, target_bus, target_dev, disk_mode="", disk_alias=None): """ Create a xml file to update a device. :param update_xmlfile : path/file to save device XML :param source_iso : disk's source backing file. :param disk_type: disk's device type: cdrom or floppy :param target_bus: disk's target bus :param target_dev: disk's target device name :param disk_mode: readonly or shareable :param disk_alias: disk's alias name """ try: with open(source_iso, 'wb') as _file: _file.seek((1024 * 1024) - 1) _file.write(str(0).encode()) except IOError: test.fail("Create source_iso failed!") disk_class = VMXML.get_device_class('disk') disk = disk_class(type_name='file') # Static definition for comparison in check_attach() disk.device = disk_type disk.driver = dict(name='qemu') disk.source = disk.new_disk_source(attrs={'file': source_iso}) disk.target = dict(bus=target_bus, dev=target_dev) if disk_mode == "readonly": disk.readonly = True if disk_mode == "shareable": disk.share = True if disk_alias: disk.alias = dict(name=disk_alias) disk.xmltreefile.write() shutil.copyfile(disk.xml, update_xmlfile)
def check_result(disk_source, disk_type, disk_target, flags, attach=True): """ Check the test result of update-device command. """ vm_state = pre_vm_state active_vmxml = VMXML.new_from_dumpxml(vm_name) active_attached = is_attached(active_vmxml.devices, disk_type, disk_source, disk_target) if vm_state != "transient": inactive_vmxml = VMXML.new_from_dumpxml(vm_name, options="--inactive") inactive_attached = is_attached(inactive_vmxml.devices, disk_type, disk_source, disk_target) if flags.count("config") and not flags.count("live"): if vm_state != "transient": if attach: if not inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated" " when --config options used for" " attachment") if vm_state != "shutoff": if active_attached: raise exceptions.TestFail( "Active domain XML updated " "when --config options used" " for attachment") else: if inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated" " when --config options used for" " detachment") if vm_state != "shutoff": if not active_attached: raise exceptions.TestFail( "Active domain XML updated " "when --config options used" " for detachment") elif flags.count("live") and not flags.count("config"): if attach: if vm_state in ["paused", "running", "transient"]: if not active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --live options used for" " attachment") if vm_state in ["paused", "running"]: if inactive_attached: raise exceptions.TestFail( "Inactive domain XML updated " "when --live options used for" " attachment") else: if vm_state in ["paused", "running", "transient"]: if active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --live options used for" " detachment") if vm_state in ["paused", "running"]: if not inactive_attached: raise exceptions.TestFail( "Inactive domain XML updated " "when --live options used for" " detachment") elif flags.count("live") and flags.count("config"): if attach: if vm_state in ["paused", "running"]: if not active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --live --config options" " used for attachment") if not inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated" " when --live --config options " "used for attachment") else: if vm_state in ["paused", "running"]: if active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --live --config options" " used for detachment") if inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated" " when --live --config options " "used for detachment") elif flags.count("current") or flags == "": if attach: if vm_state in ["paused", "running", "transient"]: if not active_attached: raise exceptions.TestFail( "Active domain XML not updated " "when --current options used " "for attachment") if vm_state in ["paused", "running"]: if inactive_attached: raise exceptions.TestFail( "Inactive domain XML updated " "when --current options used " "for live attachment") if vm_state == "shutoff" and not inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated " "when --current options used for " "attachment") else: if vm_state in ["paused", "running", "transient"]: if active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --current options used " "for detachment") if vm_state in ["paused", "running"]: if not inactive_attached: raise exceptions.TestFail( "Inactive domain XML updated " "when --current options used " "for live detachment") if vm_state == "shutoff" and inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --current options used " "for detachment")
def run(test, params, env): """ Test command: virsh update-device. Update device from an XML <file>. 1.Prepare test environment, adding a cdrom/floppy to VM. 2.Perform virsh update-device operation. 3.Recover test environment. 4.Confirm the test result. """ # Before doing anything - let's be sure we can support this test # Parse flag list, skip testing early if flag is not supported # NOTE: "".split("--") returns [''] which messes up later empty test flag = params.get("updatedevice_flag", "") flag_list = [] if flag.count("--"): flag_list = flag.split("--") for item in flag_list: option = item.strip() if option == "": continue if not bool(virsh.has_command_help_match("update-device", option)): raise error.TestNAError("virsh update-device doesn't support --%s" % option) # As per RH BZ 961443 avoid testing before behavior changes if 'config' in flag_list: # SKIP tests using --config if libvirt is 0.9.10 or earlier if not libvirt_version.version_compare(0, 9, 10): raise error.TestNAError("BZ 961443: --config behavior change " "in version 0.9.10") if 'persistent' in flag_list: # SKIP tests using --persistent if libvirt 1.0.5 or earlier if not libvirt_version.version_compare(1, 0, 5): raise error.TestNAError("BZ 961443: --persistent behavior change " "in version 1.0.5") # Prepare initial vm state vm_name = params.get("main_vm") vmxml = VMXML.new_from_dumpxml(vm_name, options="--inactive") vm = env.get_vm(vm_name) start_vm = "yes" == params.get("start_vm", "no") # Get the target bus/dev disk_type = params.get("disk_type", "cdrom") target_bus = params.get("updatedevice_target_bus", "ide") target_dev = params.get("updatedevice_target_dev", "hdc") disk_mode = params.get("disk_mode", "") support_mode = ['readonly', 'shareable'] if not disk_mode and disk_mode not in support_mode: raise error.TestError("%s not in support mode %s" % (disk_mode, support_mode)) # Prepare tmp directory and files. orig_iso = os.path.join(test.virtdir, "orig.iso") test_iso = os.path.join(test.virtdir, "test.iso") test_diff_iso = os.path.join(test.virtdir, "test_diff.iso") update_xmlfile = os.path.join(test.tmpdir, "update.xml") create_attach_xml(update_xmlfile, test_iso, disk_type, target_bus, target_dev, disk_mode) # This test needs a cdrom/floppy attached first - attach a cdrom/floppy # to a shutdown vm. Then decide to restart or not if vm.is_alive(): vm.destroy(gracefully=False) # Vm should be in 'shut off' status utils_misc.wait_for(lambda: vm.state() == "shut off", 30) create_disk(vm_name, orig_iso, disk_type, target_dev, disk_mode) if start_vm: vm.start() vm.wait_for_login().close() domid = vm.get_id() else: domid = "domid invalid; domain is shut-off" # Get remaining parameters for configuration. twice = "yes" == params.get("updatedevice_twice", "no") diff_iso = "yes" == params.get("updatedevice_diff_iso", "no") vm_ref = params.get("updatedevice_vm_ref", "") status_error = "yes" == params.get("status_error", "no") extra = params.get("updatedevice_extra", "") # OK let's give this a whirl... errmsg = "" try: if vm_ref == "id": vm_ref = domid if twice: # Don't pass in any flags ret = virsh.update_device(domainarg=domid, filearg=update_xmlfile, ignore_status=True, debug=True) if not status_error: status = ret.exit_status errmsg += ret.stderr libvirt.check_exit_status(ret) if diff_iso: # Swap filename of device backing file in update.xml os.remove(update_xmlfile) create_attach_xml(update_xmlfile, test_diff_iso, disk_type, target_bus, target_dev, disk_mode) elif vm_ref == "uuid": vm_ref = vmxml.uuid elif vm_ref == "hex_id": vm_ref = hex(int(domid)) elif vm_ref.find("updatedevice_invalid") != -1: vm_ref = params.get(vm_ref) elif vm_ref == "name": vm_ref = "%s %s" % (vm_name, extra) cmdresult = virsh.update_device(domainarg=vm_ref, filearg=update_xmlfile, flagstr=flag, ignore_status=True, debug=True) status = cmdresult.exit_status if not status_error: errmsg += cmdresult.stderr active_vmxml = VMXML.new_from_dumpxml(vm_name) inactive_vmxml = VMXML.new_from_dumpxml(vm_name, options="--inactive") finally: vm.destroy(gracefully=False, free_mac_addresses=False) vmxml.undefine() vmxml.restore() vmxml.define() if os.path.exists(orig_iso): os.remove(orig_iso) if os.path.exists(test_iso): os.remove(test_iso) if os.path.exists(test_diff_iso): os.remove(test_diff_iso) # Result handling logic set errmsg only on error if status_error: if status == 0: errmsg += "\nRun successfully with wrong command!\n" else: # Normal test if status != 0: errmsg += "\nRun failed with right command\n" if diff_iso: # Expect the backing file to have updated active_attached = is_attached(active_vmxml.devices, disk_type, test_diff_iso, target_dev) inactive_attached = is_attached(inactive_vmxml.devices, disk_type, test_diff_iso, target_dev) else: # Expect backing file to remain the same active_attached = is_attached(active_vmxml.devices, disk_type, test_iso, target_dev) inactive_attached = is_attached(inactive_vmxml.devices, disk_type, test_iso, target_dev) # Check behavior of combination before individual! if "config" in flag_list and "live" in flag_list: if not active_attached: errmsg += ("Active domain XML not updated when " "--config --live options used\n") if not inactive_attached: errmsg += ("Inactive domain XML not updated when " "--config --live options used\n") elif "live" in flag_list and inactive_attached: errmsg += ("Inactive domain XML updated when " "--live option used\n") elif "config" in flag_list and active_attached: errmsg += ("Active domain XML updated when " "--config option used\n") # persistent option behavior depends on start_vm if "persistent" in flag_list: if start_vm: if not active_attached or not inactive_attached: errmsg += ("XML not updated when --persistent " "option used on active domain\n") else: if not inactive_attached: errmsg += ("XML not updated when --persistent " "option used on inactive domain\n") if len(flag_list) == 0: # Not specifying any flag is the same as specifying --current if start_vm: if not active_attached: errmsg += "Active domain XML not updated\n" elif inactive_attached: errmsg += ("Inactive domain XML updated when active " "requested\n") # Log some debugging info before destroying instances if errmsg and not status_error: logging.debug("Active XML:") logging.debug(str(active_vmxml)) logging.debug("Inactive XML:") logging.debug(str(inactive_vmxml)) logging.debug("active_attached: %s", str(active_attached)) logging.debug("inctive_attached: %s", str(inactive_attached)) logging.debug("Device XML:") logging.debug(open(update_xmlfile, "r").read()) # clean up tmp files del vmxml del active_vmxml del inactive_vmxml os.unlink(update_xmlfile) if errmsg: raise error.TestFail(errmsg)
def check_result(disk_source, disk_type, disk_target, flags, attach=True): """ Check the test result of update-device command. """ vm_state = pre_vm_state active_vmxml = VMXML.new_from_dumpxml(vm_name) active_attached = is_attached(active_vmxml.devices, disk_type, disk_source, disk_target) if vm_state != "transient": inactive_vmxml = VMXML.new_from_dumpxml(vm_name, options="--inactive") inactive_attached = is_attached(inactive_vmxml.devices, disk_type, disk_source, disk_target) if flags.count("config") and not flags.count("live"): if vm_state != "transient": if attach: if not inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --config options used for" " attachment") if vm_state != "shutoff": if active_attached: raise exceptions.TestFail("Active domain XML updated " "when --config options used" " for attachment") else: if inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --config options used for" " detachment") if vm_state != "shutoff": if not active_attached: raise exceptions.TestFail("Active domain XML updated " "when --config options used" " for detachment") elif flags.count("live") and not flags.count("config"): if attach: if vm_state in ["paused", "running", "transient"]: if not active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --live options used for" " attachment") if vm_state in ["paused", "running"]: if inactive_attached: raise exceptions.TestFail("Inactive domain XML updated " "when --live options used for" " attachment") else: if vm_state in ["paused", "running", "transient"]: if active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --live options used for" " detachment") if vm_state in ["paused", "running"]: if not inactive_attached: raise exceptions.TestFail("Inactive domain XML updated " "when --live options used for" " detachment") elif flags.count("live") and flags.count("config"): if attach: if vm_state in ["paused", "running"]: if not active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --live --config options" " used for attachment") if not inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --live --config options " "used for attachment") else: if vm_state in ["paused", "running"]: if active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --live --config options" " used for detachment") if inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --live --config options " "used for detachment") elif flags.count("current") or flags == "": if attach: if vm_state in ["paused", "running", "transient"]: if not active_attached: raise exceptions.TestFail("Active domain XML not updated " "when --current options used " "for attachment") if vm_state in ["paused", "running"]: if inactive_attached: raise exceptions.TestFail("Inactive domain XML updated " "when --current options used " "for live attachment") if vm_state == "shutoff" and not inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated " "when --current options used for " "attachment") else: if vm_state in ["paused", "running", "transient"]: if active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --current options used " "for detachment") if vm_state in ["paused", "running"]: if not inactive_attached: raise exceptions.TestFail("Inactive domain XML updated " "when --current options used " "for live detachment") if vm_state == "shutoff" and inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --current options used " "for detachment")
def run(test, params, env): """ Restart libvirtd and check the consistent of VM states. """ def agent_connected(): """ Callback function to check if agent channel connected. """ ga_tgt = VMXML.new_from_dumpxml(vm_name).get_section_string( '/devices/channel/target') return 'state="connected"' in ga_tgt vm_name = params.get('main_vm') vm = env.get_vm(vm_name) if vm.is_alive(): vm.destroy() time.sleep(2) vm.start() time.sleep(20) # Wait guest agent channel to be connected to avoid XML differ try: if not utils_misc.wait_for(agent_connected, 30): logging.warning('Agent channel not connected') except LibvirtXMLNotFoundError: pass vm_xml = VMXML.new_from_dumpxml(vm_name) logging.debug(vm_xml) # Skip the test when serial login is not available try: session = vm.wait_for_serial_login(60) except remote.LoginError: raise error.TestNAError('Serial console might needed to be ' 'configured before test.') # Send a command line without waiting result try: session.cmd('sleep 30; echo hello', timeout=0) except ShellTimeoutError: pass # Restart libvirtd utils_libvirtd.Libvirtd().restart() # Check whether guest is still working vm.cleanup_serial_console() vm.create_serial_console() try: vm.serial_console.read_until_any_line_matches(['hello'], timeout=60) except ExpectTimeoutError: raise error.TestFail('Timeout when waiting for command output. ' 'Maybe your guest is refreshed.') # Wait guest agent channel to be reconnected to avoid XML differ try: if not utils_misc.wait_for(agent_connected, 30): logging.warning('Agent channel not recovered after libvirtd ' 'restart') except LibvirtXMLNotFoundError: pass # Check whether domain XML changed vm_xml_new = VMXML.new_from_dumpxml(vm_name) if str(vm_xml) != str(vm_xml_new): diff_txt = '\n'.join( difflib.unified_diff( str(vm_xml).splitlines(), str(vm_xml_new).splitlines(), lineterm='', ) ) raise error.TestFail("XML changed after libvirtd restart:\n%s" % diff_txt)
def run(test, params, env): """ Test command: virsh update-device. Update device from an XML <file>. 1.Prepare test environment, adding a cdrom/floppy to VM. 2.Perform virsh update-device operation. 3.Recover test environment. 4.Confirm the test result. """ # Before doing anything - let's be sure we can support this test # Parse flag list, skip testing early if flag is not supported # NOTE: "".split("--") returns [''] which messes up later empty test flag = params.get("updatedevice_flag", "") flag_list = [] if flag.count("--"): flag_list = flag.split("--") for item in flag_list: option = item.strip() if option == "": continue if not bool(virsh.has_command_help_match("update-device", option)): raise error.TestNAError( "virsh update-device doesn't support --%s" % option) # As per RH BZ 961443 avoid testing before behavior changes if 'config' in flag_list: # SKIP tests using --config if libvirt is 0.9.10 or earlier if not libvirt_version.version_compare(0, 9, 10): raise error.TestNAError("BZ 961443: --config behavior change " "in version 0.9.10") if 'persistent' in flag_list: # SKIP tests using --persistent if libvirt 1.0.5 or earlier if not libvirt_version.version_compare(1, 0, 5): raise error.TestNAError("BZ 961443: --persistent behavior change " "in version 1.0.5") # Prepare initial vm state vm_name = params.get("main_vm") vmxml = VMXML.new_from_dumpxml(vm_name, options="--inactive") vm = env.get_vm(vm_name) start_vm = "yes" == params.get("start_vm", "no") # Get the target bus/dev disk_type = params.get("disk_type", "cdrom") target_bus = params.get("updatedevice_target_bus", "ide") target_dev = params.get("updatedevice_target_dev", "hdc") disk_mode = params.get("disk_mode", "") support_mode = ['readonly', 'shareable'] if not disk_mode and disk_mode not in support_mode: raise error.TestError("%s not in support mode %s" % (disk_mode, support_mode)) # Prepare tmp directory and files. orig_iso = os.path.join(test.virtdir, "orig.iso") test_iso = os.path.join(test.virtdir, "test.iso") test_diff_iso = os.path.join(test.virtdir, "test_diff.iso") update_xmlfile = os.path.join(test.tmpdir, "update.xml") create_attach_xml(update_xmlfile, test_iso, disk_type, target_bus, target_dev, disk_mode) # This test needs a cdrom/floppy attached first - attach a cdrom/floppy # to a shutdown vm. Then decide to restart or not if vm.is_alive(): vm.destroy() create_disk(vm_name, orig_iso, disk_type, target_dev, disk_mode) if start_vm: vm.start() domid = vm.get_id() else: domid = "domid invalid; domain is shut-off" # Get remaining parameters for configuration. twice = "yes" == params.get("updatedevice_twice", "no") diff_iso = "yes" == params.get("updatedevice_diff_iso", "no") vm_ref = params.get("updatedevice_vm_ref", "") status_error = "yes" == params.get("status_error", "no") extra = params.get("updatedevice_extra", "") # OK let's give this a whirl... try: if vm_ref == "id": vm_ref = domid if twice: # Don't pass in any flags virsh.update_device(domainarg=domid, filearg=update_xmlfile, ignore_status=True, debug=True) if diff_iso: # Swap filename of device backing file in update.xml os.remove(update_xmlfile) create_attach_xml(update_xmlfile, test_diff_iso, disk_type, target_bus, target_dev, disk_mode) elif vm_ref == "uuid": vm_ref = vmxml.uuid elif vm_ref == "hex_id": vm_ref = hex(int(domid)) elif vm_ref.find("updatedevice_invalid") != -1: vm_ref = params.get(vm_ref) elif vm_ref == "name": vm_ref = "%s %s" % (vm_name, extra) cmdresult = virsh.update_device(domainarg=vm_ref, filearg=update_xmlfile, flagstr=flag, ignore_status=True, debug=True) status = cmdresult.exit_status active_vmxml = VMXML.new_from_dumpxml(vm_name) inactive_vmxml = VMXML.new_from_dumpxml(vm_name, options="--inactive") finally: vm.destroy(gracefully=False, free_mac_addresses=False) vmxml.undefine() vmxml.restore() vmxml.define() if os.path.exists(orig_iso): os.remove(orig_iso) if os.path.exists(test_iso): os.remove(test_iso) if os.path.exists(test_diff_iso): os.remove(test_diff_iso) # Result handling logic set errmsg only on error errmsg = None if status_error: if status == 0: errmsg = "Run successfully with wrong command!" else: # Normal test if status != 0: errmsg = "Run failed with right command" if diff_iso: # Expect the backing file to have updated active_attached = is_attached(active_vmxml.devices, disk_type, test_diff_iso, target_dev) inactive_attached = is_attached(inactive_vmxml.devices, disk_type, test_diff_iso, target_dev) else: # Expect backing file to remain the same active_attached = is_attached(active_vmxml.devices, disk_type, test_iso, target_dev) inactive_attached = is_attached(inactive_vmxml.devices, disk_type, test_iso, target_dev) # Check behavior of combination before individual! if "config" in flag_list and "live" in flag_list: if not active_attached: errmsg = ("Active domain XML not updated when " "--config --live options used") if not inactive_attached: errmsg = ("Inactive domain XML not updated when " "--config --live options used") elif "live" in flag_list and inactive_attached: errmsg = ("Inactive domain XML updated when " "--live option used") elif "config" in flag_list and active_attached: errmsg = ("Active domain XML updated when " "--config option used") # persistent option behavior depends on start_vm if "persistent" in flag_list: if start_vm: if not active_attached or not inactive_attached: errmsg = ("XML not updated when --persistent " "option used on active domain") else: if not inactive_attached: errmsg = ("XML not updated when --persistent " "option used on inactive domain") if len(flag_list) == 0: # Not specifying any flag is the same as specifying --current if start_vm: if not active_attached: errmsg = "Active domain XML not updated" elif inactive_attached: errmsg = ("Inactive domain XML updated when active " "requested") # Log some debugging info before destroying instances if errmsg is not None: logging.debug("Active XML:") logging.debug(str(active_vmxml)) logging.debug("Inactive XML:") logging.debug(str(inactive_vmxml)) logging.debug("active_attached: %s", str(active_attached)) logging.debug("inctive_attached: %s", str(inactive_attached)) logging.debug("Device XML:") logging.debug(open(update_xmlfile, "r").read()) # clean up tmp files del vmxml del active_vmxml del inactive_vmxml os.unlink(update_xmlfile) if errmsg is not None: raise error.TestFail(errmsg)
def run(test, params, env): """ Test command: virsh update-device. Update device from an XML <file>. 1.Prepare test environment, adding a cdrom/floppy to VM. 2.Perform virsh update-device operation. 3.Recover test environment. 4.Confirm the test result. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) pre_vm_state = params.get("at_dt_device_pre_vm_state") virsh_dargs = {"debug": True, "ignore_status": True} def is_attached(vmxml_devices, disk_type, source_file, target_dev): """ Check attached device and disk exist or not. :param vmxml_devices: VMXMLDevices instance :param disk_type: disk's device type: cdrom or floppy :param source_file : disk's source file to check :param target_dev : target device name :return: True/False if backing file and device found """ disks = vmxml_devices.by_device_tag('disk') for disk in disks: logging.debug("Check disk XML:\n%s", open(disk['xml']).read()) if disk.device != disk_type: continue if disk.target['dev'] != target_dev: continue if disk.xmltreefile.find('source') is not None: if disk.source.attrs['file'] != source_file: continue else: continue # All three conditions met logging.debug("Find %s in given disk XML", source_file) return True logging.debug("Not find %s in gievn disk XML", source_file) return False def check_result(disk_source, disk_type, disk_target, flags, attach=True): """ Check the test result of update-device command. """ vm_state = pre_vm_state active_vmxml = VMXML.new_from_dumpxml(vm_name) active_attached = is_attached(active_vmxml.devices, disk_type, disk_source, disk_target) if vm_state != "transient": inactive_vmxml = VMXML.new_from_dumpxml(vm_name, options="--inactive") inactive_attached = is_attached(inactive_vmxml.devices, disk_type, disk_source, disk_target) if flags.count("config") and not flags.count("live"): if vm_state != "transient": if attach: if not inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --config options used for" " attachment") if vm_state != "shutoff": if active_attached: raise exceptions.TestFail("Active domain XML updated " "when --config options used" " for attachment") else: if inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --config options used for" " detachment") if vm_state != "shutoff": if not active_attached: raise exceptions.TestFail("Active domain XML updated " "when --config options used" " for detachment") elif flags.count("live") and not flags.count("config"): if attach: if vm_state in ["paused", "running", "transient"]: if not active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --live options used for" " attachment") if vm_state in ["paused", "running"]: if inactive_attached: raise exceptions.TestFail("Inactive domain XML updated " "when --live options used for" " attachment") else: if vm_state in ["paused", "running", "transient"]: if active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --live options used for" " detachment") if vm_state in ["paused", "running"]: if not inactive_attached: raise exceptions.TestFail("Inactive domain XML updated " "when --live options used for" " detachment") elif flags.count("live") and flags.count("config"): if attach: if vm_state in ["paused", "running"]: if not active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --live --config options" " used for attachment") if not inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --live --config options " "used for attachment") else: if vm_state in ["paused", "running"]: if active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --live --config options" " used for detachment") if inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --live --config options " "used for detachment") elif flags.count("current") or flags == "": if attach: if vm_state in ["paused", "running", "transient"]: if not active_attached: raise exceptions.TestFail("Active domain XML not updated " "when --current options used " "for attachment") if vm_state in ["paused", "running"]: if inactive_attached: raise exceptions.TestFail("Inactive domain XML updated " "when --current options used " "for live attachment") if vm_state == "shutoff" and not inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated " "when --current options used for " "attachment") else: if vm_state in ["paused", "running", "transient"]: if active_attached: raise exceptions.TestFail("Active domain XML not updated" " when --current options used " "for detachment") if vm_state in ["paused", "running"]: if not inactive_attached: raise exceptions.TestFail("Inactive domain XML updated " "when --current options used " "for live detachment") if vm_state == "shutoff" and inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --current options used " "for detachment") def check_rhel_version(release_ver, session=None): """ Login to guest and check its release version """ rhel_release = {"rhel6": "Red Hat Enterprise Linux Server release 6", "rhel7": "Red Hat Enterprise Linux Server release 7", "fedora": "Fedora release"} version_file = "/etc/redhat-release" if not rhel_release.has_key(release_ver): logging.error("Can't support this version of guest: %s", release_ver) return False cmd = "grep '%s' %s" % (rhel_release[release_ver], version_file) if session: s = session.cmd_status(cmd) else: s = process.run(cmd, ignore_status=True, shell=True).exit_status logging.debug("Check version cmd return:%s", s) if s == 0: return True else: return False vmxml_backup = VMXML.new_from_dumpxml(vm_name, options="--inactive") # Before doing anything - let's be sure we can support this test # Parse flag list, skip testing early if flag is not supported # NOTE: "".split("--") returns [''] which messes up later empty test at_flag = params.get("at_dt_device_at_options", "") dt_flag = params.get("at_dt_device_dt_options", "") flag_list = [] if at_flag.count("--"): flag_list.extend(at_flag.split("--")) if dt_flag.count("--"): flag_list.extend(dt_flag.split("--")) for item in flag_list: option = item.strip() if option == "": continue if not bool(virsh.has_command_help_match("update-device", option)): raise exceptions.TestSkipError("virsh update-device doesn't support " "--%s" % option) # As per RH BZ 961443 avoid testing before behavior changes if 'config' in flag_list: # SKIP tests using --config if libvirt is 0.9.10 or earlier if not libvirt_version.version_compare(0, 9, 10): raise exceptions.TestSkipError("BZ 961443: --config behavior change " "in version 0.9.10") if 'persistent' in flag_list or 'live' in flag_list: # SKIP tests using --persistent if libvirt 1.0.5 or earlier if not libvirt_version.version_compare(1, 0, 5): raise exceptions.TestSkipError("BZ 961443: --persistent behavior " "change in version 1.0.5") # Get the target bus/dev disk_type = params.get("disk_type", "cdrom") target_bus = params.get("updatedevice_target_bus", "ide") target_dev = params.get("updatedevice_target_dev", "hdc") disk_mode = params.get("disk_mode", "") support_mode = ['readonly', 'shareable'] if not disk_mode and disk_mode not in support_mode: raise exceptions.TestError("%s not in support mode %s" % (disk_mode, support_mode)) # Prepare tmp directory and files. orig_iso = os.path.join(data_dir.get_tmp_dir(), "orig.iso") test_iso = os.path.join(data_dir.get_tmp_dir(), "test.iso") # Check the version first. host_rhel6 = check_rhel_version('rhel6') guest_rhel6 = False if not vm.is_alive(): vm.start() session = vm.wait_for_login() if check_rhel_version('rhel6', session): guest_rhel6 = True session.close() vm.destroy(gracefully=False) try: # Prepare the disk first. create_disk(vm_name, orig_iso, disk_type, target_dev, disk_mode) vmxml_for_test = VMXML.new_from_dumpxml(vm_name, options="--inactive") # Turn VM into certain state. if pre_vm_state == "running": if at_flag == "--config" or dt_flag == "--config": if host_rhel6: raise exceptions.TestSkipError("Config option not supported" " on this host") logging.info("Starting %s..." % vm_name) if vm.is_dead(): vm.start() vm.wait_for_login().close() elif pre_vm_state == "shutoff": if not at_flag or not dt_flag: if host_rhel6: raise exceptions.TestSkipError("Default option not supported" " on this host") logging.info("Shuting down %s..." % vm_name) if vm.is_alive(): vm.destroy(gracefully=False) elif pre_vm_state == "paused": if at_flag == "--config" or dt_flag == "--config": if host_rhel6: raise exceptions.TestSkipError("Config option not supported" " on this host") logging.info("Pausing %s..." % vm_name) if vm.is_dead(): vm.start() vm.wait_for_login().close() if not vm.pause(): raise exceptions.TestSkipError("Cann't pause the domain") elif pre_vm_state == "transient": logging.info("Creating %s..." % vm_name) vm.undefine() if virsh.create(vmxml_for_test.xml, **virsh_dargs).exit_status: vmxml_backup.define() raise exceptions.TestSkipError("Cann't create the domain") vm.wait_for_login().close() except Exception, e: logging.error(str(e)) if os.path.exists(orig_iso): os.remove(orig_iso) vmxml_backup.sync() raise exceptions.TestSkipError(str(e))
def run(test, params, env): """ Restart libvirtd and check the consistent of VM states. """ def agent_connected(): """ Callback function to check if agent channel connected. """ ga_tgt = VMXML.new_from_dumpxml(vm_name).get_section_string( '/devices/channel/target') return 'state="connected"' in ga_tgt vm_name = params.get('main_vm') vm = env.get_vm(vm_name) username = params.get("username") password = params.get("password") # Wait guest agent channel to be connected to avoid XML differ try: if not utils_misc.wait_for(agent_connected, 30): logging.warning('Agent channel not connected') except LibvirtXMLNotFoundError: pass vm_xml = VMXML.new_from_dumpxml(vm_name) logging.debug(vm_xml) # Skip the test when serial login is not available try: session = vm.wait_for_serial_login(60, username=username, password=password) except remote.LoginError: test.cancel('Serial console might needed to be ' 'configured before test.') # Send a command line without waiting result try: session.cmd('sleep 30; echo hello', timeout=0) except ShellTimeoutError: pass # Restart libvirtd utils_libvirtd.Libvirtd().restart() # Check whether guest is still working vm.cleanup_serial_console() vm.create_serial_console() try: vm.serial_console.read_until_any_line_matches(['hello'], timeout=60) except ExpectTimeoutError: test.fail('Timeout when waiting for command output. ' 'Maybe your guest is refreshed.') # Wait guest agent channel to be reconnected to avoid XML differ try: if not utils_misc.wait_for(agent_connected, 30): logging.warning('Agent channel not recovered after libvirtd ' 'restart') except LibvirtXMLNotFoundError: pass # Check whether domain XML changed vm_xml_new = VMXML.new_from_dumpxml(vm_name) if str(vm_xml) != str(vm_xml_new): diff_txt = '\n'.join( difflib.unified_diff( str(vm_xml).splitlines(), str(vm_xml_new).splitlines(), lineterm='', )) test.fail("XML changed after libvirtd restart:\n%s" % diff_txt)
def run(test, params, env): """ Test command: virsh update-device. Update device from an XML <file>. 1.Prepare test environment, adding a cdrom/floppy to VM. 2.Perform virsh update-device operation. 3.Recover test environment. 4.Confirm the test result. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) pre_vm_state = params.get("at_dt_device_pre_vm_state") virsh_dargs = {"debug": True, "ignore_status": True} def is_attached(vmxml_devices, disk_type, source_file, target_dev): """ Check attached device and disk exist or not. :param vmxml_devices: VMXMLDevices instance :param disk_type: disk's device type: cdrom or floppy :param source_file : disk's source file to check :param target_dev : target device name :return: True/False if backing file and device found """ disks = vmxml_devices.by_device_tag('disk') for disk in disks: logging.debug("Check disk XML:\n%s", open(disk['xml']).read()) if disk.device != disk_type: continue if disk.target['dev'] != target_dev: continue if disk.xmltreefile.find('source') is not None and \ 'file' in disk.source.attrs: if disk.source.attrs['file'] != source_file: continue else: continue # All three conditions met logging.debug("Find %s in given disk XML", source_file) return True logging.debug("Not find %s in gievn disk XML", source_file) return False def check_result(disk_source, disk_type, disk_target, flags, attach=True): """ Check the test result of update-device command. """ vm_state = pre_vm_state active_vmxml = VMXML.new_from_dumpxml(vm_name) active_attached = is_attached(active_vmxml.devices, disk_type, disk_source, disk_target) if vm_state != "transient": inactive_vmxml = VMXML.new_from_dumpxml(vm_name, options="--inactive") inactive_attached = is_attached(inactive_vmxml.devices, disk_type, disk_source, disk_target) if flags.count("config") and not flags.count("live"): if vm_state != "transient": if attach: if not inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated" " when --config options used for" " attachment") if vm_state != "shutoff": if active_attached: raise exceptions.TestFail( "Active domain XML updated " "when --config options used" " for attachment") else: if inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated" " when --config options used for" " detachment") if vm_state != "shutoff": if not active_attached: raise exceptions.TestFail( "Active domain XML updated " "when --config options used" " for detachment") elif flags.count("live") and not flags.count("config"): if attach: if vm_state in ["paused", "running", "transient"]: if not active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --live options used for" " attachment") if vm_state in ["paused", "running"]: if inactive_attached: raise exceptions.TestFail( "Inactive domain XML updated " "when --live options used for" " attachment") else: if vm_state in ["paused", "running", "transient"]: if active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --live options used for" " detachment") if vm_state in ["paused", "running"]: if not inactive_attached: raise exceptions.TestFail( "Inactive domain XML updated " "when --live options used for" " detachment") elif flags.count("live") and flags.count("config"): if attach: if vm_state in ["paused", "running"]: if not active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --live --config options" " used for attachment") if not inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated" " when --live --config options " "used for attachment") else: if vm_state in ["paused", "running"]: if active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --live --config options" " used for detachment") if inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated" " when --live --config options " "used for detachment") elif flags.count("current") or flags == "": if attach: if vm_state in ["paused", "running", "transient"]: if not active_attached: raise exceptions.TestFail( "Active domain XML not updated " "when --current options used " "for attachment") if vm_state in ["paused", "running"]: if inactive_attached: raise exceptions.TestFail( "Inactive domain XML updated " "when --current options used " "for live attachment") if vm_state == "shutoff" and not inactive_attached: raise exceptions.TestFail( "Inactive domain XML not updated " "when --current options used for " "attachment") else: if vm_state in ["paused", "running", "transient"]: if active_attached: raise exceptions.TestFail( "Active domain XML not updated" " when --current options used " "for detachment") if vm_state in ["paused", "running"]: if not inactive_attached: raise exceptions.TestFail( "Inactive domain XML updated " "when --current options used " "for live detachment") if vm_state == "shutoff" and inactive_attached: raise exceptions.TestFail("Inactive domain XML not updated" " when --current options used " "for detachment") def check_rhel_version(release_ver, session=None): """ Login to guest and check its release version """ rhel_release = { "rhel6": "Red Hat Enterprise Linux Server release 6", "rhel7": "Red Hat Enterprise Linux Server release 7", "fedora": "Fedora release" } version_file = "/etc/redhat-release" if release_ver not in rhel_release: logging.error("Can't support this version of guest: %s", release_ver) return False cmd = "grep '%s' %s" % (rhel_release[release_ver], version_file) if session: s = session.cmd_status(cmd) else: s = process.run(cmd, ignore_status=True, shell=True).exit_status logging.debug("Check version cmd return:%s", s) if s == 0: return True else: return False vmxml_backup = VMXML.new_from_dumpxml(vm_name, options="--inactive") # Before doing anything - let's be sure we can support this test # Parse flag list, skip testing early if flag is not supported # NOTE: "".split("--") returns [''] which messes up later empty test at_flag = params.get("at_dt_device_at_options", "") dt_flag = params.get("at_dt_device_dt_options", "") flag_list = [] if at_flag.count("--"): flag_list.extend(at_flag.split("--")) if dt_flag.count("--"): flag_list.extend(dt_flag.split("--")) for item in flag_list: option = item.strip() if option == "": continue if not bool(virsh.has_command_help_match("update-device", option)): raise exceptions.TestSkipError( "virsh update-device doesn't support " "--%s" % option) # As per RH BZ 961443 avoid testing before behavior changes if 'config' in flag_list: # SKIP tests using --config if libvirt is 0.9.10 or earlier if not libvirt_version.version_compare(0, 9, 10): raise exceptions.TestSkipError( "BZ 961443: --config behavior change " "in version 0.9.10") if 'persistent' in flag_list or 'live' in flag_list: # SKIP tests using --persistent if libvirt 1.0.5 or earlier if not libvirt_version.version_compare(1, 0, 5): raise exceptions.TestSkipError("BZ 961443: --persistent behavior " "change in version 1.0.5") # Get the target bus/dev disk_type = params.get("disk_type", "cdrom") target_bus = params.get("updatedevice_target_bus", "ide") target_dev = params.get("updatedevice_target_dev", "hdc") disk_mode = params.get("disk_mode", "") support_mode = ['readonly', 'shareable'] if not disk_mode and disk_mode not in support_mode: raise exceptions.TestError("%s not in support mode %s" % (disk_mode, support_mode)) # Prepare tmp directory and files. orig_iso = os.path.join(data_dir.get_tmp_dir(), "orig.iso") test_iso = os.path.join(data_dir.get_tmp_dir(), "test.iso") # Check the version first. host_rhel6 = False guest_rhel6 = False if not params.get("skip_release_check", "no") == "yes": host_rhel6 = check_rhel_version('rhel6') if not vm.is_alive(): vm.start() session = vm.wait_for_login() if check_rhel_version('rhel6', session): guest_rhel6 = True session.close() vm.destroy(gracefully=False) try: # Prepare the disk first. create_disk(vm_name, orig_iso, disk_type, target_dev, disk_mode) vmxml_for_test = VMXML.new_from_dumpxml(vm_name, options="--inactive") # Turn VM into certain state. if pre_vm_state == "running": if at_flag == "--config" or dt_flag == "--config": if host_rhel6: raise exceptions.TestSkipError( "Config option not supported" " on this host") logging.info("Starting %s..." % vm_name) if vm.is_dead(): vm.start() vm.wait_for_login().close() elif pre_vm_state == "shutoff": if not at_flag or not dt_flag: if host_rhel6: raise exceptions.TestSkipError( "Default option not supported" " on this host") logging.info("Shuting down %s..." % vm_name) if vm.is_alive(): vm.destroy(gracefully=False) elif pre_vm_state == "paused": if at_flag == "--config" or dt_flag == "--config": if host_rhel6: raise exceptions.TestSkipError( "Config option not supported" " on this host") logging.info("Pausing %s..." % vm_name) if vm.is_dead(): vm.start() vm.wait_for_login().close() if not vm.pause(): raise exceptions.TestSkipError("Cann't pause the domain") elif pre_vm_state == "transient": logging.info("Creating %s..." % vm_name) vm.undefine() if virsh.create(vmxml_for_test.xml, **virsh_dargs).exit_status: vmxml_backup.define() raise exceptions.TestSkipError("Cann't create the domain") vm.wait_for_login().close() except Exception as e: logging.error(str(e)) if os.path.exists(orig_iso): os.remove(orig_iso) vmxml_backup.sync() raise exceptions.TestSkipError(str(e)) # Get remaining parameters for configuration. vm_ref = params.get("updatedevice_vm_ref", "domname") at_status_error = "yes" == params.get("at_status_error", "no") dt_status_error = "yes" == params.get("dt_status_error", "no") dom_uuid = vm.get_uuid() dom_id = vm.get_id() # Set domain reference. if vm_ref == "domname": vm_ref = vm_name elif vm_ref == "domid": vm_ref = dom_id elif vm_ref == "domuuid": vm_ref = dom_uuid elif vm_ref == "hexdomid" and dom_id is not None: vm_ref = hex(int(dom_id)) try: # Get disk alias disk_alias = libvirt.get_disk_alias(vm, orig_iso) # Firstly detach the disk. update_xmlfile = os.path.join(data_dir.get_tmp_dir(), "update.xml") create_attach_xml(update_xmlfile, disk_type, target_bus, target_dev, "", disk_mode, disk_alias) ret = virsh.update_device(vm_ref, filearg=update_xmlfile, flagstr=dt_flag, ignore_status=True, debug=True) if vm.is_paused(): vm.resume() vm.wait_for_login().close() if vm.is_alive() and not guest_rhel6: time.sleep(5) # For rhel7 guest, need to update twice for it to take effect. ret = virsh.update_device(vm_ref, filearg=update_xmlfile, flagstr=dt_flag, ignore_status=True, debug=True) os.remove(update_xmlfile) libvirt.check_exit_status(ret, dt_status_error) if not ret.exit_status: check_result(orig_iso, disk_type, target_dev, dt_flag, False) # Then attach the disk. if pre_vm_state == "paused": if not vm.pause(): raise exceptions.TestFail("Cann't pause the domain") create_attach_xml(update_xmlfile, disk_type, target_bus, target_dev, test_iso, disk_mode, disk_alias) ret = virsh.update_device(vm_ref, filearg=update_xmlfile, flagstr=at_flag, ignore_status=True, debug=True) if vm.is_paused(): vm.resume() vm.wait_for_login().close() update_twice = False if vm.is_alive() and not guest_rhel6: # For rhel7 guest, need to update twice for it to take effect. if (pre_vm_state in ["running", "paused"] and dt_flag == "--config" and at_flag != "--config"): update_twice = True elif (pre_vm_state == "transient" and dt_flag.count("config") and not at_flag.count("config")): update_twice = True if update_twice: time.sleep(5) ret = virsh.update_device(vm_ref, filearg=update_xmlfile, flagstr=at_flag, ignore_status=True, debug=True) libvirt.check_exit_status(ret, at_status_error) os.remove(update_xmlfile) if not ret.exit_status: check_result(test_iso, disk_type, target_dev, at_flag) # Try to start vm at last. if vm.is_dead(): vm.start() vm.wait_for_login().close() finally: vm.destroy(gracefully=False, free_mac_addresses=False) vmxml_backup.sync() if os.path.exists(orig_iso): os.remove(orig_iso) if os.path.exists(test_iso): os.remove(test_iso)