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 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 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 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): """ 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)
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. """ 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 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")