def test_device_update_boot_order(disk_type, disk_path, error_msg): """ Wrap device update boot order steps here. Firstly,create another disk for a given path. Update previous disk with newly created disk and modified boot order. Eject disk finally. :param disk_type: the type of disk. :param disk_path: the path of disk. :param error_msg: the expected error message. """ addtional_disk = create_addtional_disk(disk_type, disk_path, device_formats[0], device_types[0], devices[0], device_targets[0], device_bus[0]) addtional_disk.boot = '2' addtional_disk.readonly = 'True' # Update disk cdrom/floppy with modified boot order,it expect fail. ret = virsh.update_device(vm_name, addtional_disk.xml, debug=True) if ret.exit_status == 0 or not ret.stderr.count("Operation not supported: " + "cannot modify field 'boot order' of the disk"): test.fail(error_msg) # Force eject cdrom or floppy, it expect succeed. eject_disk = Disk(type_name='block') eject_disk.target = {"dev": device_targets[0], "bus": device_bus[0]} eject_disk.device = devices[0] ret = virsh.update_device(vm_name, eject_disk.xml, flagstr='--force', debug=True) libvirt.check_exit_status(ret)
def update_device(vm_name, init_iso, options, start_vm): """ Update device iso file for test case :param vm_name: guest name :param init_iso: source file :param options: update-device option :param start_vm: guest start flag """ snippet = """ <disk type='file' device='%s'> <driver name='qemu' type='raw'/> <source file='%s'/> <target dev='%s'/> <readonly/> </disk> """ % (device_type, init_iso, target_device) update_iso_file = open(update_iso_xml, "w") update_iso_file.write(snippet) update_iso_file.close() cmd_options = "--force " if options == "--config" or start_vm == "no": cmd_options += " --config" # Give domain the ISO image file virsh.update_device(domainarg=vm_name, filearg=update_iso_xml, flagstr=cmd_options, debug=True)
def check_requisite_startuppolicy_cdrom(vm, params, test): """ Check iso cdrom device with startup policy in VM after iso file is renamed :param vm: one object representing VM :param params: wrapped parameters in dictionary format :param test: test assert object """ first_iso_path = params.get("virt_disk_device_source") renamed_first_iso_path = "%s.bak" % first_iso_path os.rename(first_iso_path, renamed_first_iso_path) # Save and restore the guest tmp_save_path = "/tmp/save" virsh.save(vm.name, tmp_save_path, ignore_status=False) virsh.restore(tmp_save_path, ignore_status=False) vm.wait_for_login().close() # Cdrom should be empty check_source_in_cdrom_device(vm, None, test) # Create second iso disk, and update VM with it if 'tray' in params: params.pop('tray') params.update({ "virt_disk_device_source": params.get("virt_disk_device_source_second") }) iso_cdrom_disk_second = create_iso_cdrom_disk(params, create_iso=False) virsh.update_device(vm.name, iso_cdrom_disk_second.xml, flagstr="--live", debug=True) vm.wait_for_login().close()
def check_update_device(vm, if_name, session): """ Change link state by upadte-device command, Check the results """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) # Get interface xml object iface = vmxml.get_devices(device_type="interface")[0] if iface.address: del iface.address # Change link state to up iface.link_state = "up" iface.xmltreefile.write() ret = virsh.update_device(vm.name, iface.xml, ignore_status=True, debug=True) if ret.exit_status: logging.error("Failed to update device to up state") return False if not guest_if_state(if_name, session): logging.error("Guest link should be up now") return False # Change link state to down iface.link_state = "down" iface.xmltreefile.write() ret = virsh.update_device(vm.name, iface.xml, ignore_status=True, debug=True) if ret.exit_status: logging.error("Failed to update device to down state") return False if guest_if_state(if_name, session): logging.error("Guest link should be down now") return False # Passed all test return True
def update_cdrom(vm_name, init_iso, options, start_vm): """ Update cdrom iso file for test case @param: vm_name: guest name @param: init_iso: source file @param: options: update-device option @param: start_vm: guest start flag """ snippet = """ <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <source file='%s'/> <target dev='%s' bus='ide'/> <readonly/> </disk> """ % (init_iso, disk_device) update_iso_file = open(update_iso_xml, "w") update_iso_file.write(snippet) update_iso_file.close() cmd_options = "--force " if options == "--config" or start_vm == "no": cmd_options += " --config" # Give domain the ISO image file virsh.update_device(domainarg=vm_name, filearg=update_iso_xml, flagstr=cmd_options, debug=True)
def check_twice_iso_cdrom_device_updated(vm, first_iso_disk, params, test): """ Check iso cdrom device in VM can be updated twice :param vm: one object representing VM :param first_iso_disk: disk xml with iso :param params: wrapped parameters in dictionary format :param test: test assert object """ vm.wait_for_login().close() device_target = params.get("target_dev") first_iso_path = params.get("virt_disk_device_source") another_iso_path = params.get("virt_disk_device_source_second") # Create second iso disk, and update VM with it params.update({ "virt_disk_device_source": params.get("virt_disk_device_source_second") }) iso_cdrom_disk_second = create_iso_cdrom_disk(params, create_iso=False) virsh.update_device(vm.name, iso_cdrom_disk_second.xml, ignore_status=False) # Check cdrom has been changed with new iso file check_source_in_cdrom_device(vm, another_iso_path, test) # Restore to previous iso file vm.wait_for_login().close() virsh.update_device(vm.name, first_iso_disk.xml, ignore_status=False) # Check cdrom has been restored back previous iso check_source_in_cdrom_device(vm, first_iso_path, test)
def update_cdrom(vm_name, init_iso, options, start_vm): """ Update cdrom iso file for test case """ snippet = """ <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <source file='%s'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> """ % (init_iso) update_iso_file = open(update_iso_xml, "w") update_iso_file.write(snippet) update_iso_file.close() cmd_options = "--force " if options == "--config" or start_vm == "no": cmd_options += " --config" # Give domain the ISO image file virsh.update_device(domainarg=vm_name, filearg=update_iso_xml, flagstr=cmd_options, debug=True)
def check_change_startuppolicy_cdrom_backend(vm, params, origin_device_xml, test): """ Check live update cdrom with new source type and startupPolicy BZ2003644 :param vm: one object representing VM :param params: wrapped parameters in dictionary format :param origin_device_xml: original device xml before updated :param test: test assert object """ # Create block type cdrom disk, and update VM with it if 'startupPolicy' in params: params.pop('startupPolicy') origin_first_iso_path = params.get("virt_disk_device_source") # Load module and get scsi disk name utils_misc.wait_for( lambda: linux_modules.load_module("scsi_debug lbpu=1 lbpws=1"), timeout=10, ignore_errors=True) scsi_disk = process.run("lsscsi|grep scsi_debug|" "awk '{print $6}'", shell=True).stdout_text.strip() params.update({"virt_disk_device_source": scsi_disk}) params.update({"type_name": "block"}) iso_cdrom_disk_second = create_iso_cdrom_disk(params, create_iso=False) virsh.update_device(vm.name, iso_cdrom_disk_second.xml, flagstr="--live", ignore_status=False, debug=True) vm.wait_for_login().close() # Cdrom should be updated check_source_in_cdrom_device(vm, scsi_disk, test) # Restore to original filed based one virsh.update_device(vm.name, origin_device_xml.xml, flagstr="--live", ignore_status=False, debug=True) vm.wait_for_login().close() # Cdrom should be restored check_source_in_cdrom_device(vm, origin_first_iso_path, test)
def update_device(vm_name, init_iso, options, start_vm): """ Update device iso file for test case :param vm_name: guest name :param init_iso: source file :param options: update-device option :param start_vm: guest start flag """ if 'disk_alias' not in locals() or disk_alias is None: disk_alias_update = "" else: disk_alias_update = disk_alias device_target_bus = params.get("device_target_bus", "ide") snippet = """ <disk type='file' device='%s'> <driver name='qemu' type='raw'/> <source file='%s'/> <target dev='%s' bus='%s'/> <readonly/> <alias name='%s'/> </disk> """ % (device_type, init_iso, target_device, device_target_bus, disk_alias_update) logging.info("Update xml is %s", snippet) with open(update_iso_xml, "w") as update_iso_file: update_iso_file.write(snippet) cmd_options = "--force " if options == "--config" or start_vm == "no": cmd_options += " --config" # Give domain the ISO image file return virsh.update_device(domainarg=vm_name, filearg=update_iso_xml, flagstr=cmd_options, debug=True)
def update_device(vm_name, init_iso, options, start_vm): """ Update device iso file for test case :param vm_name: guest name :param init_iso: source file :param options: update-device option :param start_vm: guest start flag """ snippet = """ <disk type='file' device='%s'> <driver name='qemu' type='raw'/> <source file='%s'/> <target dev='%s'/> <readonly/> </disk> """ % (device_type, init_iso, target_device) update_iso_file = open(update_iso_xml, "w") update_iso_file.write(snippet) update_iso_file.close() cmd_options = "--force " if options == "--config" or start_vm == "no": cmd_options += " --config" # Give domain the ISO image file return virsh.update_device(domainarg=vm_name, filearg=update_iso_xml, flagstr=cmd_options, debug=True)
def update_device(vm_name, init_iso, options, start_vm): """ Update device iso file for test case :param vm_name: guest name :param init_iso: source file :param options: update-device option :param start_vm: guest start flag """ if 'disk_alias' not in locals() or disk_alias is None: disk_alias_update = "" else: disk_alias_update = disk_alias snippet = """ <disk type='file' device='%s'> <driver name='qemu' type='raw'/> <source file='%s'/> <target dev='%s'/> <readonly/> <alias name='%s'/> </disk> """ % (device_type, init_iso, target_device, disk_alias_update) logging.info("Update xml is %s", snippet) with open(update_iso_xml, "w") as update_iso_file: update_iso_file.write(snippet) cmd_options = "--force " if options == "--config" or start_vm == "no": cmd_options += " --config" # Give domain the ISO image file return virsh.update_device(domainarg=vm_name, filearg=update_iso_xml, flagstr=cmd_options, debug=True)
def check_policy_update(origin_policy, policy_list, xml_policy_file, device_type, flag_str): """ Check updated policy after executing virsh update-device. :param origin_policy: the inherit startup policy value. :param policy_list: updated policy list. :param xml_policy_file: xml file for startupPolicy. :param device_type: device type,cdrom or disk.,etc :param flag_str: it can be --config,--live and --persistent. """ for policy in policy_list: xmltreefile = XMLTreeFile(xml_policy_file) try: policy_item = xmltreefile.find('/source') policy_item.set('startupPolicy', policy) except AttributeError as elem_attr: test.error("Fail to find startupPolicy attribute.%s", str(elem_attr)) xmltreefile.write(xml_policy_file, encoding="UTF-8") ret = virsh.update_device(vm_name, xml_policy_file, flagstr=flag_str, debug=True) if all([device_type == "disk", policy == "requisite"]): libvirt.check_exit_status(ret, True) return else: libvirt.check_exit_status(ret) def check_policy_value(active_policy, inactive_policy): """ Check policy value in dumpxml with active or inactive option :param active_policy: active policy attribute value :param inactive_policy: inactive policy attribute value """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disk_list = vmxml.devices.by_device_tag("disk") disk = disk_list[len(disk_list) - 1] if not active_policy == disk.source.attrs["startupPolicy"]: test.error( "Actual policy:%s in active state is not equal to expected:%s" % (active_policy, disk.source.attrs["startupPolicy"])) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) disk_list = vmxml.devices.by_device_tag("disk") disk = disk_list[len(disk_list) - 1] if not inactive_policy == disk.source.attrs["startupPolicy"]: test.error( "Actual policy:%s in inactive state is not equal to expected: %s" % (inactive_policy, disk.source.attrs["startupPolicy"])) if flag_str == "--live": check_policy_value(policy, origin_policy) elif flag_str == "--config": check_policy_value(origin_policy, policy) elif flag_str == "--persistent": check_policy_value(policy, policy)
def check_update_device(vm, if_name, session): """ Change link state by upadte-device command, Check the results """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) # Get interface xml object iface = vmxml.get_devices(device_type="interface")[0] if iface.address: del iface.address # Change link state to up iface.link_state = "up" iface.xmltreefile.write() ret = virsh.update_device(vm.name, iface.xml, ignore_status=True, debug=True) if ret.exit_status: logging.error("Failed to update device to up state") return False if not utils_misc.wait_for(lambda: guest_if_state(if_name, session), 5): logging.error("Guest link should be up now") return False # Change link state to down iface.link_state = "down" iface.xmltreefile.write() ret = virsh.update_device(vm.name, iface.xml, ignore_status=True, debug=True) if ret.exit_status: logging.error("Failed to update device to down state") return False if utils_misc.wait_for(lambda: guest_if_state(if_name, session), 5): logging.error("Guest link should be down now") return False # Passed all test return True
def check_policy_update(origin_policy, policy_list, xml_policy_file, device_type, flag_str): """ Check updated policy after executing virsh update-device. :param origin_policy: the inherit startup policy value. :param policy_list: updated policy list. :param xml_policy_file: xml file for startupPolicy. :param device_type: device type,cdrom or disk.,etc :param flag_str: it can be --config,--live and --persistent. """ for policy in policy_list: xmltreefile = XMLTreeFile(xml_policy_file) try: policy_item = xmltreefile.find('/source') policy_item.set('startupPolicy', policy) except AttributeError as elem_attr: test.error("Fail to find startupPolicy attribute.%s", str(elem_attr)) xmltreefile.write(xml_policy_file, encoding="UTF-8") ret = virsh.update_device(vm_name, xml_policy_file, flagstr=flag_str, debug=True) if all([device_type == "disk", policy == "requisite"]): libvirt.check_exit_status(ret, True) return else: libvirt.check_exit_status(ret) def check_policy_value(active_policy, inactive_policy): """ Check policy value in dumpxml with active or inactive option :param active_policy: active policy attribute value :param inactive_policy: inactive policy attribute value """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disk_list = vmxml.devices.by_device_tag("disk") disk = disk_list[len(disk_list)-1] if not active_policy == disk.source.attrs["startupPolicy"]: test.error("Actual policy:%s in active state is not equal to expected:%s" % (active_policy, disk.source.attrs["startupPolicy"])) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) disk_list = vmxml.devices.by_device_tag("disk") disk = disk_list[len(disk_list)-1] if not inactive_policy == disk.source.attrs["startupPolicy"]: test.error("Actual policy:%s in inactive state is not equal to expected: %s" % (inactive_policy, disk.source.attrs["startupPolicy"])) if flag_str == "--live": check_policy_value(policy, origin_policy) elif flag_str == "--config": check_policy_value(origin_policy, policy) elif flag_str == "--persistent": check_policy_value(policy, policy)
def test_batch_cdrom_operation(vm_name, disk_format, disk_device, device_target, device_bus, test): """ Test cdrom on disk with different metadata_cache size attribute :param vm_name: domain name :param disk_format: disk format :param disk_device: device name :param disk_target: the target of disk :param device_bus: device bus :param test: test case itself """ for size_type in ["100", "1000", "10"]: disk_path = "/var/lib/libvirt/images/test_image_%s" % size_type if size_type == "10": disk_path = "" if disk_path: libvirt.create_local_disk("file", disk_path, "100M", disk_format) disk_size = libvirt_disk.create_custom_metadata_disk( disk_path, disk_format, disk_device, device_target, device_bus, size_type) virsh.update_device(vm_name, disk_size.xml, flagstr='--live', ignore_status=False, debug=True) # Check max size value in cdrom part cdrom_xml = virsh.dumpxml(vm_name, debug=False).stdout_text.strip() cdrom_part_xml = re.findall( r'(<metadata_cache)(.+)((?:\n.+)+)(metadata_cache>)', cdrom_xml) cdrom_filter_str = ''.join(cdrom_part_xml[0]) cdrom_byte_match = "<max_size unit='bytes'>%s</max_size>" % size_type if cdrom_byte_match not in cdrom_filter_str: test.fail( "Failed to generate metadata_cache in cdrom operation %s" % cdrom_part_xml)
def update_iface_device(vm, params): """ Update an interface by virsh update-device :param vm: VM object :param params: Dictionary with the test parameters """ status_error = "yes" == params.get("status_error", "no") error_msg = params.get("error_msg") iface_dict = eval(params.get('iface_dict', '{}')) iface = get_vm_iface_dev(vm, iface_dict) virsh_opt = parse_virsh_opts(params) result = virsh.update_device(vm.name, iface.xml, flagstr=virsh_opt, debug=True) libvirt.check_exit_status(result, status_error) if error_msg: libvirt.check_result(result, error_msg)
def check_source_update(xml_policy_file): """ Update source and policy at the same time,then check those changes. :param xml_policy_file: VM xml policy file """ xmltreefile = XMLTreeFile(xml_policy_file) policy_item = xmltreefile.find('/source') def configure_startup_policy(update=False, policy='optional'): """ Configure startupPolicy attribute value. :param update: update value or not :param policy: policy value :return: flag_option and boolean value """ if update: del policy_item.attrib["startupPolicy"] else: policy_item.set("startupPolicy", policy) flag_option = "--live" xmltreefile.write(xml_policy_file, encoding="UTF-8") return flag_option, False # Update source and startUpPolicy attribute value. def update_source_policy(update=True, policy='optional'): """ Update startupPolicy source value. :param update: update value or not :param policy: policy value :return: flag_option and boolean value """ source_file = policy_item.get('file') if update: new_source_file = source_file+".empty" else: new_source_file = source_file+".new" shutil.copyfile(source_file, new_source_file) policy_item.set("file", new_source_file) policy_item.set("startupPolicy", policy) flag_option = "--persistent" xmltreefile.write(xml_policy_file, encoding="UTF-8") return flag_option, False function_list = [configure_startup_policy, update_source_policy, configure_startup_policy, update_source_policy] function_parameter = [False, False, True, True] # Loop all above scenarios to update device. for index in list(range(len(function_list))): try: func = function_list[index] para = function_parameter[index] flag_option, update_error = func(para) ret = virsh.update_device(vm_name, xml_policy_file, flagstr=flag_option, debug=True) libvirt.check_exit_status(ret, expect_error=update_error) except AttributeError as elem_attr: test.error("Fail to remove startupPolicy attribute:%s" % str(elem_attr)) except Exception as update_device_exception: test.error("Fail to update device:%s" % str(update_device_exception)) finally: source_file = policy_item.get('file') new_source_file = source_file+".new" if os.path.exists(new_source_file): os.remove(new_source_file)
def run(test, params, env): """ Test interface devices update """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) new_network_name = params.get("net_name") expect_error = "yes" == params.get("status_error", "no") expect_err_msg = params.get("expect_err_msg") iface_driver = params.get("iface_driver") iface_model = params.get("iface_model") iface_mtu = params.get("iface_mtu") iface_rom = params.get("iface_rom") new_iface_driver = params.get("new_iface_driver") new_iface_driver_host = params.get("new_iface_driver_host") new_iface_driver_guest = params.get("new_iface_driver_guest") new_iface_model = params.get("new_iface_model") new_iface_rom = params.get("new_iface_rom") new_iface_inbound = params.get("new_iface_inbound") new_iface_outbound = params.get("new_iface_outbound") new_iface_link = params.get("new_iface_link") new_iface_source = params.get("new_iface_source") new_iface_target = params.get("new_iface_target") new_iface_addr = params.get("new_iface_addr") new_iface_filter = params.get("new_iface_filter") new_iface_mtu = params.get("new_iface_mtu") new_iface_type = params.get("new_iface_type") create_new_net = "yes" == params.get("create_new_net") new_iface_alias = params.get("new_iface_alias") cold_update = "yes" == params.get("cold_update", "no") del_addr = "yes" == params.get("del_address") del_rom = "yes" == params.get("del_rom") # Backup the vm xml for recover at last vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: # According to the different os find different file for rom if (iface_rom and "file" in eval(iface_rom) and "%s" in eval(iface_rom)['file']): if os.path.exists(eval(iface_rom)['file'] % "pxe"): iface_rom = iface_rom % "pxe" elif os.path.exists(eval(iface_rom)['file'] % "efi"): iface_rom = iface_rom % "efi" else: logging.error("Can not find suitable rom file") iface_dict_bef = {} iface_dict_aft = {} names = locals() # Collect need update items in 2 dicts for both start vm before and after update_list_bef = [ "driver", "model", "mtu", "rom" ] for update_item_bef in update_list_bef: if names['iface_'+update_item_bef]: iface_dict_bef.update({update_item_bef: names['iface_'+update_item_bef]}) update_list_aft = [ "driver", "driver_host", "driver_guest", "model", "rom", "inbound", "outbound", "link", "source", "target", "addr", "filter", "mtu", "type", "alias"] for update_item_aft in update_list_aft: if names["new_iface_"+update_item_aft]: iface_dict_aft.update({update_item_aft: names["new_iface_"+update_item_aft]}) logging.info("iface_dict_bef is %s, iface_dict_aft is %s", iface_dict_bef, iface_dict_aft) del_list = ["del_addr", "del_rom"] for del_item in del_list: if names[del_item]: iface_dict_aft.update({del_item: "True"}) # Update vm interface with items in iface_dict_bef and start it if iface_dict_bef: libvirt.modify_vm_iface(vm_name, "update_iface", iface_dict_bef) logging.info("vm xml is %s", vm.get_xml()) if not cold_update: vm.start() if iface_mtu: # Do check for mtu size after start vm target_dev = libvirt.get_interface_details(vm_name)[0]['interface'] cmd = "ip link show %s | grep 'mtu %s'" % (target_dev, eval(iface_mtu)['size']) def check_mtu(): """ Check the mtu setting take effect for interface """ ret = process.run(cmd, ignore_status=True, shell=True) if ret.exit_status: test.fail("Can not find mtu setting in cmd result") check_mtu() utils_libvirtd.libvirtd_restart() check_mtu() # Create new network if need if create_new_net: new_net_xml = libvirt.create_net_xml(new_network_name, params) new_net_xml.sync() # Do update for iface_driver new_iface_xml = libvirt.modify_vm_iface(vm_name, "get_xml", iface_dict_aft) ret = virsh.update_device(vm_name, new_iface_xml, ignore_status=True, debug=True) libvirt.check_exit_status(ret, expect_error) if expect_error: real_err_msg = ret.stderr.strip() if not re.search(expect_err_msg, real_err_msg, re.IGNORECASE): test.fail("The real error msg:'%s' does not match expect one:" '%s' % (real_err_msg, expect_err_msg)) else: logging.info("Get expect result: %s", real_err_msg) else: if new_iface_inbound: iface_bandwidth = {} iface_bandwidth = vm_xml.VMXML.get_iftune_params(vm_name) for bound_para in ["inbound", "outbound"]: for tune_para in ["average", "peak", "burst"]: get_value = iface_bandwidth.get(bound_para).get(tune_para) expect_value = eval(names["new_iface_"+bound_para]).get(tune_para) logging.info("Get value for %s:%s is %s, expect is %s", bound_para, tune_para, get_value, expect_value) if get_value != expect_value: test.fail("Get value is not equal to expect") vmxml_aft = vm_xml.VMXML.new_from_dumpxml(vm_name) iface_aft = list(vmxml_aft.get_iface_all().values())[0] if new_iface_link: iface_link_value = iface_aft.find('link').get('state') if iface_link_value == new_iface_link: logging.info("Find link state is %s in xml", new_iface_link) # Checking the statue in guest mac_addr = iface_aft.find('mac').get('address') state_map = "%s.*\n.*%s" % (iface_link_value.upper(), mac_addr) session = vm.wait_for_serial_login() logging.info("ip link output:%s", session.cmd_output("ip link")) if_name = utils_net.get_net_if(runner=session.cmd_output, state=state_map)[0] session.close() if if_name: logging.info("Find iface state %s for %s", iface_link_value, mac_addr) else: test.fail("Can not find iface with mac %s and state %s" % (mac_addr, iface_link_value)) else: test.fail("Check fail to get link state, expect %s, but get %s" % (iface_link_value, new_iface_link)) if create_new_net and new_iface_source: iface_source_value = iface_aft.find('source').get('network') if iface_source_value == eval(new_iface_source)['network']: logging.info("Get %s in xml as set", iface_source_value) else: test.fail("Get source %s is not equal to set %s" % (iface_source_value, new_iface_source)) if new_iface_filter: iface_filter_value = iface_aft.find('filterref').get('filter') if iface_filter_value == new_iface_filter: logging.info("Get %s in xml as set", iface_filter_value) else: test.fail("Get filter %s is not equal to set %s" % (iface_filter_value, new_iface_filter)) if new_iface_alias: iface_alias_value = iface_aft.find('alias').get('name') if iface_alias_value == eval(new_iface_alias)['name']: logging.info("Get %s in xml as set", iface_alias_value) else: test.fail("Get alias %s is not equal to set %s" % (iface_alias_value, new_iface_alias)) finally: vmxml_backup.sync() if create_new_net: new_net_xml.undefine()
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 modify_iface_xml(update, status_error=False): """ Modify interface xml options """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) xml_devices = vmxml.devices iface_index = xml_devices.index( xml_devices.by_device_tag("interface")[0]) iface = xml_devices[iface_index] if iface_model: iface.model = iface_model else: del iface.model if iface_type: iface.type_name = iface_type del iface.source source = ast.literal_eval(iface_source) if source: net_ifs = utils_net.get_net_if(state="UP") # Check source device is valid or not, # if it's not in host interface list, try to set # source device to first active interface of host if (iface.type_name == "direct" and 'dev' in source and source['dev'] not in net_ifs): logging.warn( "Source device %s is not a interface" " of host, reset to %s", source['dev'], net_ifs[0]) source['dev'] = net_ifs[0] iface.source = source backend = ast.literal_eval(iface_backend) if backend: iface.backend = backend driver_dict = {} driver_host = {} driver_guest = {} if iface_driver: driver_dict = ast.literal_eval(iface_driver) if iface_driver_host: driver_host = ast.literal_eval(iface_driver_host) if iface_driver_guest: driver_guest = ast.literal_eval(iface_driver_guest) iface.driver = iface.new_driver(driver_attr=driver_dict, driver_host=driver_host, driver_guest=driver_guest) if test_target: logging.debug("iface.target is %s" % target_dev) iface.target = {"dev": target_dev} if iface.address: del iface.address if set_ip: iface.ips = [ast.literal_eval(x) for x in set_ips] logging.debug("New interface xml file: %s", iface) if unprivileged_user: # Create disk image for unprivileged user disk_index = xml_devices.index( xml_devices.by_device_tag("disk")[0]) disk_xml = xml_devices[disk_index] logging.debug("source: %s", disk_xml.source) disk_source = disk_xml.source.attrs["file"] cmd = ("cp -fZ {0} {1} && chown {2}:{2} {1}" "".format(disk_source, dst_disk, unprivileged_user)) process.run(cmd, shell=True) disk_xml.source = disk_xml.new_disk_source( attrs={"file": dst_disk}) vmxml.devices = xml_devices # Remove all channels to avoid of permission problem channels = vmxml.get_devices(device_type="channel") for channel in channels: vmxml.del_device(channel) logging.info("Unprivileged users can't use 'dac' security driver," " removing from domain xml if present...") vmxml.del_seclabel([('model', 'dac')]) # Set vm memory to 2G if it's larger than 2G if vmxml.memory > 2097152: vmxml.memory = vmxml.current_mem = 2097152 vmxml.xmltreefile.write() logging.debug("New VM xml: %s", vmxml) process.run("chmod a+rw %s" % vmxml.xml, shell=True) virsh.define(vmxml.xml, **virsh_dargs) # Try to modify interface xml by update-device or edit xml elif update: iface.xmltreefile.write() ret = virsh.update_device(vm_name, iface.xml, ignore_status=True) libvirt.check_exit_status(ret, status_error) else: vmxml.devices = xml_devices vmxml.xmltreefile.write() try: vmxml.sync() if define_error: test.fail("Define VM succeed, but it should fail") except xcepts.LibvirtXMLError as e: if not define_error: test.fail("Define VM fail: %s" % e)
def modify_iface_xml(update, status_error=False): """ Modify interface xml options """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) xml_devices = vmxml.devices iface_index = xml_devices.index( xml_devices.by_device_tag("interface")[0]) iface = xml_devices[iface_index] if iface_model: iface.model = iface_model else: del iface.model if iface_type: iface.type_name = iface_type del iface.source source = ast.literal_eval(iface_source) if source: net_ifs = utils_net.get_net_if(state="UP") # Check source device is valid or not, # if it's not in host interface list, try to set # source device to first active interface of host if (iface.type_name == "direct" and source.has_key('dev') and source['dev'] not in net_ifs): logging.warn("Source device %s is not a interface" " of host, reset to %s", source['dev'], net_ifs[0]) source['dev'] = net_ifs[0] iface.source = source backend = ast.literal_eval(iface_backend) if backend: iface.backend = backend driver_dict = {} driver_host = {} driver_guest = {} if iface_driver: driver_dict = ast.literal_eval(iface_driver) if iface_driver_host: driver_host = ast.literal_eval(iface_driver_host) if iface_driver_guest: driver_guest = ast.literal_eval(iface_driver_guest) iface.driver = iface.new_driver(driver_attr=driver_dict, driver_host=driver_host, driver_guest=driver_guest) if iface.address: del iface.address logging.debug("New interface xml file: %s", iface) if unprivileged_user: # Create disk image for unprivileged user disk_index = xml_devices.index( xml_devices.by_device_tag("disk")[0]) disk_xml = xml_devices[disk_index] logging.debug("source: %s", disk_xml.source) disk_source = disk_xml.source.attrs["file"] cmd = ("cp -fZ {0} {1} && chown {2}:{2} {1}" "".format(disk_source, dst_disk, unprivileged_user)) utils.run(cmd) disk_xml.source = disk_xml.new_disk_source( attrs={"file": dst_disk}) vmxml.devices = xml_devices # Remove all channels to avoid of permission problem channels = vmxml.get_devices(device_type="channel") for channel in channels: vmxml.del_device(channel) vmxml.xmltreefile.write() logging.debug("New VM xml: %s", vmxml) utils.run("chmod a+rw %s" % vmxml.xml) virsh.define(vmxml.xml, **virsh_dargs) # Try to modify interface xml by update-device or edit xml elif update: iface.xmltreefile.write() ret = virsh.update_device(vm_name, iface.xml, ignore_status=True) libvirt.check_exit_status(ret, status_error) else: vmxml.devices = xml_devices vmxml.xmltreefile.write() vmxml.sync()
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 run(test, params, env): """ Test network/interface function on 2 vms: - Test settings on 2 vms - Run ping check on 2 vms including pinging each other ... """ vms = params.get('vms').split() vm_list = [env.get_vm(v_name) for v_name in vms] if len(vm_list) != 2: test.cancel('More or less than 2 vms is currently unsupported') feature = params.get('feature', '') case = params.get('case', '') check_ping = 'yes' == params.get('check_ping') expect_ping_host = 'yes' == params.get('expect_ping_host', 'no') expect_ping_out = 'yes' == params.get('expect_ping_out', 'no') expect_ping_vm = 'yes' == params.get('expect_ping_vm', 'no') out_ip = params.get('out_ip', 'www.redhat.com') live_update = 'yes' == params.get('live_update', 'no') set_all = 'yes' == params.get('set_all', 'no') rand_id = '_' + utils_misc.generate_random_string(3) bridge_name = params.get('bridge_name', 'test_br0') + rand_id iface_name = utils_net.get_net_if(state="UP")[0] test_net = 'net_isolated' + rand_id bridge_created = False vmxml_backup_list = [] for vm_i in vm_list: vmxml_backup_list.append(vm_xml.VMXML.new_from_inactive_dumpxml(vm_i.name)) try: # Test feature: port isolated if feature == 'port_isolated': if not libvirt_version.version_compare(6, 2, 0): test.cancel('Libvirt version should be' ' > 6.2.0 to support port isolated') if case.startswith('set_iface'): create_bridge(bridge_name, iface_name) bridge_created = True iface_type = case.split('_')[-1] if iface_type == 'network': net_dict = {'net_forward': "{'mode': 'bridge'}", 'net_bridge': "{'name': '%s'}" % bridge_name} prepare_network(test_net, **net_dict) updated_iface_dict = { 'type': iface_type, 'source': "{'network': '%s'}" % test_net, } elif iface_type == 'bridge': updated_iface_dict = { 'type': iface_type, 'source': "{'bridge': '%s'}" % bridge_name, } else: test.error('Unsupported iface type: %s' % iface_type) # Set 2 vms to isolated=yes or set one to 'yes', the other to 'no' isolated_settings = ['yes'] * 2 if set_all else ['yes', 'no'] for i in (0, 1): vm_i = vm_list[i] new_iface_dict = dict( list(updated_iface_dict.items()) + [('port', "{'isolated': '%s'}" % isolated_settings[i])] ) libvirt.modify_vm_iface(vm_i.name, 'update_iface', new_iface_dict) logging.debug(virsh.dumpxml(vm_i.name).stdout_text) if case == 'update_iface': if params.get('iface_port'): iface_dict = {'port': params['iface_port']} for vm_i in vm_list: libvirt.modify_vm_iface(vm_i.name, 'update_iface', iface_dict) logging.debug(virsh.dumpxml(vm_i.name).stdout_text) if live_update: for vm_i in vm_list: vm_i.start() # Test Update iface with new attrs new_iface_dict = {} if params.get('new_iface_port'): new_iface_dict['port'] = params['new_iface_port'] elif params.get('del_port') == 'yes': new_iface_dict['del_port'] = True for vm_i in vm_list: updated_iface = libvirt.modify_vm_iface(vm_i.name, 'get_xml', new_iface_dict) result = virsh.update_device(vm_i.name, updated_iface, debug=True) libvirt.check_exit_status(result) if case == 'attach_iface': new_ifaces = {} for vm_i in vm_list: # Create iface xml to be attached new_iface = interface.Interface('network') new_iface.xml = libvirt.modify_vm_iface( vm_i.name, 'get_xml', {'port': params.get('new_iface_port')} ) new_ifaces[vm_i.name] = new_iface # Remove current ifaces on vm vmxml_i = vm_xml.VMXML.new_from_inactive_dumpxml(vm_i.name) vmxml_i.remove_all_device_by_type('interface') vmxml_i.sync() logging.debug(virsh.dumpxml(vm_i.name).stdout_text) # Start vm for hotplug vm_i.start() session = vm_i.wait_for_serial_login() # Hotplug iface virsh.attach_device(vm_i.name, new_iface.xml, debug=True, ignore_status=False) # Wait a few seconds for interface to be fully attached time.sleep(5) ip_l_before = session.cmd_output('ip l') logging.debug(ip_l_before) session.close() if case == 'set_network': create_bridge(bridge_name, iface_name) bridge_created = True net_dict = { 'net_forward': "{'mode': 'bridge'}", 'net_bridge': "{'name': '%s'}" % bridge_name, 'net_port': "{'isolated': '%s'}" % params.get( 'net_isolated', 'yes')} prepare_network(test_net, **net_dict) # Modify iface to connect to newly added network updated_iface_dict = {'type': 'network', 'source': "{'network': '%s'}" % test_net} for vm_i in vm_list: libvirt.modify_vm_iface(vm_i.name, 'update_iface', updated_iface_dict) logging.debug(virsh.domiflist(vm_i.name).stdout_text) # Check ping result from vm session to host, outside, the other vm if check_ping: for vm_i in vm_list: if vm_i.is_dead(): vm_i.start() host_ip = utils_net.get_host_ip_address() ping_expect = { host_ip: expect_ping_host, out_ip: expect_ping_out, } # A map of vm session and vm's ip addr session_n_ip = {} for vm_i in vm_list: mac = vm_i.get_mac_address() sess = vm_i.wait_for_serial_login() vm_ip = utils_net.get_guest_ip_addr(sess, mac) session_n_ip[sess] = vm_ip logging.debug('Vm %s ip: %s', vm_i.name, vm_ip) # Check ping result from each vm's session for i in (0, 1): sess = list(session_n_ip.keys())[i] another_sess = list(session_n_ip.keys())[1 - i] ping_expect[session_n_ip[another_sess]] = expect_ping_vm if not ping_func(sess, **ping_expect): test.fail('Ping check failed') # Remove the other session's ip from ping result, then the # next round of ping check will not do a ping check to the vm itself ping_expect.pop(session_n_ip[another_sess]) # Some test steps after ping check if feature == 'port_isolated': if case == 'attach_iface': # Test detach of iface for vm_name_i in new_ifaces: virsh.detach_device( vm_name_i, new_ifaces[vm_name_i].xml, wait_for_event=True, debug=True, ignore_status=False ) # Check whether iface successfully detached by checking 'ip l' output for vm_i in vm_list: session = vm_i.wait_for_serial_login() ip_l_after = session.cmd_output('ip l') session.close() if len(ip_l_before.splitlines()) == len(ip_l_after.splitlines()): test.fail('Output of "ip l" is not changed afte detach, ' 'interface not successfully detached')
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: # 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) 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)
def run(test, params, env): """ Test virsh nwfilter-binding-list 1)Prepare parameters 2)Run nwfilter_binding_list command 3)check result 4)Clean env """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) status_error = "yes" == params.get("status_error") new_filter_1 = params.get("newfilter_1") new_filter_2 = params.get("newfilter_2") time_wait = params.get("time_wait", 10) option = params.get("option") vmxml_backup = libvirt_xml.vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # prepare vm filterrfer parameters dict list filter_param_list_1 = [] params_key_1 = [] filter_param_list_2 = [] params_key_2 = [] for i in params.keys(): if 'parameters_name_' in i: params_key_1.append(i) params_key_1.sort() for i in range(len(params_key_1)): params_dict = {} params_dict['name'] = params[params_key_1[i]] params_dict['value'] = params['parameters_value_%s' % i] filter_param_list_1.append(params_dict) filterref_dict_1 = {} filterref_dict_1['name'] = new_filter_1 filterref_dict_1['parameters'] = filter_param_list_1 for i in params.keys(): if 'parameters_dhcp_' in i: params_key_2.append(i) params_key_2.sort() for i in range(len(params_key_2)): params_dict = {} params_dict['name'] = params[params_key_2[i]] params_dict['value'] = params['dhcp_value_%s' % i] filter_param_list_2.append(params_dict) filterref_dict_2 = {} filterref_dict_2['name'] = new_filter_2 filterref_dict_2['parameters'] = filter_param_list_2 utils_package.package_install('libvirt-daemon-config-nwfilter') def env_setting(filterref_dict_1, filterref_dict_2): ret = virsh.attach_interface(vm_name, option) utlv.check_exit_status(ret, status_error) vmxml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) devices = vmxml.get_devices('interface') iface_xml = devices[0] logging.debug("iface_xml : %s" % iface_xml) iface_xml_2 = devices[1] vmxml.del_device(iface_xml) vmxml.del_device(iface_xml_2) new_iface_1 = interface.Interface('network') logging.debug("new_iface_1 : %s" % new_iface_1) new_iface_2 = interface.Interface('network') new_iface_1.xml = iface_xml.xml new_iface_1.type_name = "network" logging.debug("new_iface_1 : %s" % new_iface_1) new_iface_2.xml = iface_xml_2.xml new_iface_1.source = {'network': "default"} new_filterref = new_iface_1.new_filterref(**filterref_dict_1) new_iface_1.filterref = new_filterref new_filterref = new_iface_2.new_filterref(**filterref_dict_2) new_iface_2.filterref = new_filterref logging.debug("new interface xml is: %s \n %s" % (new_iface_1, new_iface_2)) vmxml.add_device(new_iface_1) vmxml.add_device(new_iface_2) vmxml.sync() return new_iface_1, new_iface_2 def attach_new_device(): newnet_iface = interface.Interface('network') newnet_iface.source = {'network': "default"} newnet_iface.model = 'virtio' filterref_dict = {} filterref_list = [{'name': "CTRL_IP_LEARNING", 'value': "dhcp"}] filterref_dict['name'] = "clean-traffic" filterref_dict['parameters'] = filterref_list newnet_iface.filterref = newnet_iface.new_filterref(**filterref_dict) ret = virsh.attach_device(domainarg=vm_name, filearg=newnet_iface.xml, debug=True) utlv.check_exit_status(ret, status_error) try: # set env of start vm new_iface_1, new_iface_2 = env_setting(filterref_dict_1, filterref_dict_2) # start vm virsh.start(vm_name, debug=True) # list binding port dev logging.debug("check nwfilter binding for 2 interfaces") ret = virsh.nwfilter_binding_list(debug=True) utlv.check_result(ret, expected_match=[r"vnet\d+\s+clean-traffic"]) utlv.check_result(ret, expected_match=[r"vnet\d+\s+allow-dhcp-server"]) # detach a interface option = "--type network" + " --mac " + new_iface_1.mac_address ret = virsh.detach_interface(vm_name, option, debug=True) time.sleep(time_wait) utlv.check_exit_status(ret, status_error) logging.debug("check nwfilter binding after detach one interface:") time.sleep(3) ret = virsh.nwfilter_binding_list(debug=True) if re.search(r'vnet\d+\s+clean-traffic.*', ret.stdout): test.fail( "vnet binding clean-traffic still exists after detach the interface!" ) utlv.check_result(ret, expected_match=[r"vnet\d+\s+allow-dhcp-server"]) # update_device to delete the filter iface_dict = {'del_filter': True} new_xml = utlv.modify_vm_iface(vm_name, 'get_xml', iface_dict) virsh.update_device(domainarg=vm_name, filearg=new_xml, debug=True) logging.debug("check nwfilter-binding after delete the only interface") ret = virsh.nwfilter_binding_list(debug=True) if re.search(r'vnet\d+\s+allow-dhcp-server.*', ret.stdout): test.fail( "vnet binding allow-dhcp-server still exists after detach the interface!" ) utlv.check_exit_status(ret, status_error) # attach new interface attach_new_device() ret = virsh.nwfilter_binding_list(debug=True) logging.debug("Check nwfilter-binding exists after attach device") utlv.check_result(ret, expected_match=[r"vnet\d+\s+clean-traffic"]) finally: if vm.is_alive(): vm.destroy(gracefully=False) vmxml_backup.sync()
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: # 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) 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)
def check_source_update(xml_policy_file): """ Update source and policy at the same time,then check those changes. :param xml_policy_file: VM xml policy file """ xmltreefile = XMLTreeFile(xml_policy_file) policy_item = xmltreefile.find('/source') def configure_startup_policy(update=False, policy='optional'): """ Configure startupPolicy attribute value. :param update: update value or not :param policy: policy value :return: flag_option and boolean value """ if update: del policy_item.attrib["startupPolicy"] else: policy_item.set("startupPolicy", policy) flag_option = "--live" xmltreefile.write(xml_policy_file, encoding="UTF-8") return flag_option, False # Update source and startUpPolicy attribute value. def update_source_policy(update=True, policy='optional'): """ Update startupPolicy source value. :param update: update value or not :param policy: policy value :return: flag_option and boolean value """ source_file = policy_item.get('file') if update: new_source_file = source_file + ".empty" else: new_source_file = source_file + ".new" shutil.copyfile(source_file, new_source_file) policy_item.set("file", new_source_file) policy_item.set("startupPolicy", policy) flag_option = "--persistent" xmltreefile.write(xml_policy_file, encoding="UTF-8") return flag_option, False function_list = [ configure_startup_policy, update_source_policy, configure_startup_policy, update_source_policy ] function_parameter = [False, False, True, True] # Loop all above scenarios to update device. for index in list(range(len(function_list))): try: func = function_list[index] para = function_parameter[index] flag_option, update_error = func(para) ret = virsh.update_device(vm_name, xml_policy_file, flagstr=flag_option, debug=True) libvirt.check_exit_status(ret, expect_error=update_error) except AttributeError as elem_attr: test.error("Fail to remove startupPolicy attribute:%s" % str(elem_attr)) except Exception as update_device_exception: test.error("Fail to update device:%s" % str(update_device_exception)) finally: source_file = policy_item.get('file') new_source_file = source_file + ".new" if os.path.exists(new_source_file): os.remove(new_source_file)
def modify_iface_xml(update, status_error=False): """ Modify interface xml options """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) xml_devices = vmxml.devices iface_index = xml_devices.index( xml_devices.by_device_tag("interface")[0]) iface = xml_devices[iface_index] if iface_model: iface.model = iface_model else: del iface.model if iface_type: iface.type_name = iface_type del iface.source source = ast.literal_eval(iface_source) if source: net_ifs = utils_net.get_net_if(state="UP") # Check source device is valid or not, # if it's not in host interface list, try to set # source device to first active interface of host if (iface.type_name == "direct" and source.has_key('dev') and source['dev'] not in net_ifs): logging.warn( "Source device %s is not a interface" " of host, reset to %s", source['dev'], net_ifs[0]) source['dev'] = net_ifs[0] iface.source = source backend = ast.literal_eval(iface_backend) if backend: iface.backend = backend driver_dict = {} driver_host = {} driver_guest = {} if iface_driver: driver_dict = ast.literal_eval(iface_driver) if iface_driver_host: driver_host = ast.literal_eval(iface_driver_host) if iface_driver_guest: driver_guest = ast.literal_eval(iface_driver_guest) iface.driver = iface.new_driver(driver_attr=driver_dict, driver_host=driver_host, driver_guest=driver_guest) if iface.address: del iface.address logging.debug("New interface xml file: %s", iface) if unprivileged_user: # Create disk image for unprivileged user disk_index = xml_devices.index( xml_devices.by_device_tag("disk")[0]) disk_xml = xml_devices[disk_index] logging.debug("source: %s", disk_xml.source) disk_source = disk_xml.source.attrs["file"] cmd = ("cp -fZ {0} {1} && chown {2}:{2} {1}" "".format(disk_source, dst_disk, unprivileged_user)) utils.run(cmd) disk_xml.source = disk_xml.new_disk_source( attrs={"file": dst_disk}) vmxml.devices = xml_devices # Remove all channels to avoid of permission problem channels = vmxml.get_devices(device_type="channel") for channel in channels: vmxml.del_device(channel) vmxml.xmltreefile.write() logging.debug("New VM xml: %s", vmxml) utils.run("chmod a+rw %s" % vmxml.xml) virsh.define(vmxml.xml, **virsh_dargs) # Try to modify interface xml by update-device or edit xml elif update: iface.xmltreefile.write() ret = virsh.update_device(vm_name, iface.xml, ignore_status=True) libvirt.check_exit_status(ret, status_error) else: vmxml.devices = xml_devices vmxml.xmltreefile.write() vmxml.sync()
def run(test, params, env): """ Test interface devices update """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) network_name = params.get('network_name', 'default') new_network_name = params.get("net_name") expect_error = "yes" == params.get("status_error", "no") expect_err_msg = params.get("expect_err_msg") iface_driver = params.get("iface_driver") iface_driver_host = params.get("iface_driver_host") iface_driver_guest = params.get("iface_driver_guest") iface_model = params.get("iface_model") iface_mtu = params.get("iface_mtu") iface_rom = params.get("iface_rom") iface_filter = params.get("iface_filter") iface_boot = params.get('iface_boot') iface_coalesce = params.get('iface_coalesce') new_iface_driver = params.get("new_iface_driver") new_iface_driver_host = params.get("new_iface_driver_host") new_iface_driver_guest = params.get("new_iface_driver_guest") new_iface_model = params.get("new_iface_model") new_iface_rom = params.get("new_iface_rom") new_iface_inbound = params.get("new_iface_inbound") new_iface_outbound = params.get("new_iface_outbound") new_iface_link = params.get("new_iface_link") new_iface_source = params.get("new_iface_source") new_iface_target = params.get("new_iface_target") new_iface_addr = params.get("new_iface_addr") new_iface_filter = params.get("new_iface_filter") new_iface_mtu = params.get("new_iface_mtu") new_iface_type = params.get("new_iface_type") create_new_net = "yes" == params.get("create_new_net") new_iface_alias = params.get("new_iface_alias") new_iface_coalesce = params.get('new_iface_coalesce') cold_update = "yes" == params.get("cold_update", "no") del_addr = "yes" == params.get("del_address") del_rom = "yes" == params.get("del_rom") del_filter = "yes" == params.get("del_filter") check_libvirtd = "yes" == params.get("check_libvirtd") new_iface_filter_parameters = eval( params.get("new_iface_filter_parameters", "{}")) rules = eval(params.get("rules", "{}")) del_mac = "yes" == params.get("del_mac", "no") del_coalesce = 'yes' == params.get('del_coalesce', 'no') del_net_bandwidth = 'yes' == params.get('del_net_bandwidth', 'no') # Backup the vm xml for recover at last vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) netxml_backup = network_xml.NetworkXML.new_from_net_dumpxml(network_name) try: # Prepare network netxml = network_xml.NetworkXML.new_from_net_dumpxml(network_name) logging.debug('Network xml before update:\n%s', netxml) if del_net_bandwidth: netxml.del_element('/bandwidth') logging.debug('Network xml after update:\n%s', netxml) # According to the different os find different file for rom if (iface_rom and "file" in eval(iface_rom) and "%s" in eval(iface_rom)['file']): if rpm.RpmBackend().check_installed('ipxe-roms-qemu', '20200823'): logging.debug("Update the file path since " "ipxe-20200823-5:") iface_rom_new = iface_rom.replace('qemu-kvm', 'ipxe/qemu') iface_rom = iface_rom_new if os.path.exists(eval(iface_rom)['file'] % "pxe"): iface_rom = iface_rom % "pxe" elif os.path.exists(eval(iface_rom)['file'] % "efi"): iface_rom = iface_rom % "efi" else: logging.error("Can not find suitable rom file") iface_dict_bef = {} iface_dict_aft = {} names = locals() # Collect need update items in 2 dicts for both start vm before and after update_list_bef = [ "driver", 'driver_host', 'driver_guest', "model", "mtu", "rom", "filter", 'boot', 'coalesce' ] for update_item_bef in update_list_bef: if names['iface_' + update_item_bef]: iface_dict_bef.update( {update_item_bef: names['iface_' + update_item_bef]}) update_list_aft = [ "driver", "driver_host", "driver_guest", "model", "rom", "inbound", "outbound", "link", "source", "target", "addr", "filter", "mtu", "type", "alias", "filter_parameters", "coalesce" ] for update_item_aft in update_list_aft: if names["new_iface_" + update_item_aft]: iface_dict_aft.update( {update_item_aft: names["new_iface_" + update_item_aft]}) logging.info("iface_dict_bef is %s, iface_dict_aft is %s", iface_dict_bef, iface_dict_aft) del_list = [ "del_addr", "del_rom", "del_filter", "del_mac", "del_coalesce" ] for del_item in del_list: if names[del_item]: iface_dict_aft.update({del_item: names[del_item]}) # Operations before updating vm's iface xml if iface_boot: disk_boot = params.get('disk_book', 1) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) # Remove os boot config vm_os = vmxml.os vm_os.del_boots() vmxml.os = vm_os # Add boot config to disk disk = vmxml.get_devices('disk')[0] target_dev = disk.target.get('dev', '') logging.debug('Will set boot order %s to device %s', disk_boot, target_dev) vmxml.set_boot_order_by_target_dev(target_dev, disk_boot) vmxml.sync() # Update vm interface with items in iface_dict_bef and start it if iface_dict_bef: libvirt.modify_vm_iface(vm_name, "update_iface", iface_dict_bef) logging.info("vm xml is %s", vm.get_xml()) if not cold_update: vm.start() if iface_mtu: # Do check for mtu size after start vm target_dev = libvirt.get_interface_details(vm_name)[0]['interface'] cmd = "ip link show %s | grep 'mtu %s'" % (target_dev, eval(iface_mtu)['size']) def check_mtu(): """ Check the mtu setting take effect for interface """ ret = process.run(cmd, ignore_status=True, shell=True) if ret.exit_status: test.fail("Can not find mtu setting in cmd result") check_mtu() utils_libvirtd.libvirtd_restart() check_mtu() # Create new network if need if create_new_net: new_net_xml = libvirt.create_net_xml(new_network_name, params) new_net_xml.sync() # Do update for iface_driver logging.info('Creating new iface xml.') new_iface_xml = libvirt.modify_vm_iface(vm_name, "get_xml", iface_dict_aft) bef_pid = process.getoutput("pidof -s libvirtd") ret = virsh.update_device(vm_name, new_iface_xml, ignore_status=True, debug=True) libvirt.check_exit_status(ret, expect_error) if check_libvirtd: aft_pid = process.getoutput("pidof -s libvirtd") if aft_pid != bef_pid: test.fail("libvirtd crash after update-device!") else: logging.info("libvirtd do not crash after update-device!") if expect_error: real_err_msg = ret.stderr.strip() if not re.search(expect_err_msg, real_err_msg, re.IGNORECASE): test.fail("The real error msg:'%s' does not match expect one:" '%s' % (real_err_msg, expect_err_msg)) else: logging.info("Get expect result: %s", real_err_msg) else: if new_iface_inbound: iface_bandwidth = {} iface_bandwidth = vm_xml.VMXML.get_iftune_params(vm_name) for bound_para in ["inbound", "outbound"]: for tune_para in ["average", "peak", "burst"]: get_value = iface_bandwidth.get(bound_para).get( tune_para) expect_value = eval(names["new_iface_" + bound_para]).get(tune_para) logging.info("Get value for %s:%s is %s, expect is %s", bound_para, tune_para, get_value, expect_value) if get_value != expect_value: test.fail("Get value is not equal to expect") vmxml_aft = vm_xml.VMXML.new_from_dumpxml(vm_name) iface_aft = list(vmxml_aft.get_iface_all().values())[0] if new_iface_link: iface_link_value = iface_aft.find('link').get('state') if iface_link_value == new_iface_link: logging.info("Find link state is %s in xml", new_iface_link) # Checking the statue in guest mac_addr = iface_aft.find('mac').get('address') state_map = "%s.*\n.*%s" % (iface_link_value.upper(), mac_addr) session = vm.wait_for_serial_login() logging.info("ip link output:%s", session.cmd_output("ip link")) if_name = utils_net.get_net_if(runner=session.cmd_output, state=state_map)[0] if not check_iface_link(session, mac_addr, new_iface_link): test.fail('iface link check inside vm failed.') session.close() if if_name: logging.info("Find iface state %s for %s", iface_link_value, mac_addr) else: test.fail( "Can not find iface with mac %s and state %s" % (mac_addr, iface_link_value)) else: test.fail( "Check fail to get link state, expect %s, but get %s" % (iface_link_value, new_iface_link)) if create_new_net and new_iface_source: iface_source_value = iface_aft.find('source').get('network') if iface_source_value == eval(new_iface_source)['network']: logging.info("Get %s in xml as set", iface_source_value) else: test.fail("Get source %s is not equal to set %s" % (iface_source_value, new_iface_source)) if new_iface_filter: iface_filter_value = iface_aft.find('filterref').get('filter') if iface_filter_value == new_iface_filter: logging.info("Get %s in xml as set", iface_filter_value) else: test.fail("Get filter %s is not equal to set %s" % (iface_filter_value, new_iface_filter)) if new_iface_filter_parameters: ebtables_outputs = process.run("ebtables -t nat -L", shell=True).stdout_text for rule in rules: if rule not in ebtables_outputs: test.fail( "Can not find the corresponding rule after update filter with parameters!" ) if del_filter: # if the filter is deleted, it should not exists in the xml and the rules should be deleted as well iface_filter_value = iface_aft.find('filterref') if iface_filter_value is not None: test.fail("After delete, the filter still exists: %s" % iface_filter_value) ebtables_outputs = process.run("ebtables -t nat -L", shell=True).stdout_text logging.debug("after nwfilter deleted, ebtables rules are %s" % ebtables_outputs) time.sleep(5) entries_num = re.findall(r'entries:\s+(\d)', ebtables_outputs) for i in entries_num: if i != '0': test.fail("After delete, the rules are still exists!") if new_iface_alias: iface_alias_value = iface_aft.find('alias').get('name') if iface_alias_value == eval(new_iface_alias)['name']: logging.info("Get %s in xml as set", iface_alias_value) else: test.fail("Get alias %s is not equal to set %s" % (iface_alias_value, new_iface_alias)) if 'update_coalesce' in params['name'] or new_iface_coalesce: iface_coalesce_val = iface_aft.find('coalesce').find( 'rx').find('frames').get('max') if iface_coalesce_val == str(eval(new_iface_coalesce)['max']): logging.info('coalesce update check PASS.') else: test.fail('coalesce value not updated.') if del_coalesce: if iface_aft.find('coalesce') is None: logging.info('coalesce delete check PASS.') else: test.fail('coalesce not deleted.') finally: vmxml_backup.sync() netxml_backup.sync() if create_new_net: new_net_xml.undefine()
def run(test, params, env): """ Test virsh nwfilter-binding-list 1)Prepare parameters 2)Run nwfilter_binding_list command 3)check result 4)Clean env """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) status_error = "yes" == params.get("status_error") new_filter_1 = params.get("newfilter_1") new_filter_2 = params.get("newfilter_2") time_wait = params.get("time_wait", 10) option = params.get("option") vmxml_backup = libvirt_xml.vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # prepare vm filterrfer parameters dict list filter_param_list_1 = [] params_key_1 = [] filter_param_list_2 = [] params_key_2 = [] for i in params.keys(): if 'parameters_name_' in i: params_key_1.append(i) params_key_1.sort() for i in range(len(params_key_1)): params_dict = {} params_dict['name'] = params[params_key_1[i]] params_dict['value'] = params['parameters_value_%s' % i] filter_param_list_1.append(params_dict) filterref_dict_1 = {} filterref_dict_1['name'] = new_filter_1 filterref_dict_1['parameters'] = filter_param_list_1 for i in params.keys(): if 'parameters_dhcp_' in i: params_key_2.append(i) params_key_2.sort() for i in range(len(params_key_2)): params_dict = {} params_dict['name'] = params[params_key_2[i]] params_dict['value'] = params['dhcp_value_%s' % i] filter_param_list_2.append(params_dict) filterref_dict_2 = {} filterref_dict_2['name'] = new_filter_2 filterref_dict_2['parameters'] = filter_param_list_2 def env_setting(filterref_dict_1, filterref_dict_2): ret = virsh.attach_interface(vm_name, option) utlv.check_exit_status(ret, status_error) vmxml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) devices = vmxml.get_devices('interface') iface_xml = devices[0] logging.debug("iface_xml : %s" % iface_xml) iface_xml_2 = devices[1] vmxml.del_device(iface_xml) vmxml.del_device(iface_xml_2) new_iface_1 = interface.Interface('network') logging.debug("new_iface_1 : %s" % new_iface_1) new_iface_2 = interface.Interface('network') new_iface_1.xml = iface_xml.xml new_iface_1.type_name = "network" logging.debug("new_iface_1 : %s" % new_iface_1) new_iface_2.xml = iface_xml_2.xml new_iface_1.source = {'network': "default"} new_filterref = new_iface_1.new_filterref(**filterref_dict_1) new_iface_1.filterref = new_filterref new_filterref = new_iface_2.new_filterref(**filterref_dict_2) new_iface_2.filterref = new_filterref logging.debug("new interface xml is: %s \n %s" % (new_iface_1, new_iface_2)) vmxml.add_device(new_iface_1) vmxml.add_device(new_iface_2) vmxml.sync() return new_iface_1, new_iface_2 def attach_new_device(): newnet_iface = interface.Interface('network') newnet_iface.source = {'network': "default"} filterref_dict = {} filterref_list = [{'name': "CTRL_IP_LEARNING", 'value': "dhcp"}] filterref_dict['name'] = "clean-traffic" filterref_dict['parameters'] = filterref_list newnet_iface.filterref = newnet_iface.new_filterref(**filterref_dict) ret = virsh.attach_device(domainarg=vm_name, filearg=newnet_iface.xml, debug=True) utlv.check_exit_status(ret, status_error) try: # set env of start vm new_iface_1, new_iface_2 = env_setting(filterref_dict_1, filterref_dict_2) # start vm virsh.start(vm_name, debug=True) # list binding port dev ret = virsh.nwfilter_binding_list(debug=True) utlv.check_exit_status(ret, status_error) # detach a interface option = "--type network" + " --mac " + new_iface_1.mac_address time.sleep(time_wait) ret = virsh.detach_interface(vm_name, option, debug=True) utlv.check_exit_status(ret, status_error) ret = virsh.nwfilter_binding_list(debug=True) utlv.check_exit_status(ret, status_error) # update_device vnet1_iface = interface.Interface('network') vnet1_iface.xml = new_iface_2.xml target = {'dev': "vnet1"} vnet1_iface.target = target virsh.update_device(domainarg=vm_name, filearg=vnet1_iface.xml, debug=True) ret = virsh.nwfilter_binding_list(debug=True) utlv.check_exit_status(ret, status_error) # attach new interface attach_new_device() ret = virsh.nwfilter_binding_list(debug=True) utlv.check_exit_status(ret, status_error) finally: if vm.is_alive(): vm.destroy(gracefully=False) vmxml_backup.sync()
def run(test, params, env): """ Test bridge support from network 1) create a linux bridge and connect a physical interface to it 2) define nwfilter with "vdsm-no-mac-spoofing" 3) redefine the vm with the new create bridge and filter 4) check if guest can get public ip after vm start 5) check if guest and host can ping each other 6) check if guest and host can ping outside 7) start another vm connected to the same bridge 8) check if the 2 guests can ping each other """ def create_bridge(br_name, iface_name): """ Create a linux bridge by virsh cmd: 1. Stop NetworkManager and Start network service 2. virsh iface-bridge <iface> <name> [--no-stp] :param br_name: bridge name :param iface_name: physical interface name :return: bridge created or raise exception """ # Make sure the bridge not exist if libvirt.check_iface(br_name, "exists", "--all"): test.cancel("The bridge %s already exist" % br_name) # Create bridge utils_package.package_install('tmux') cmd = 'tmux -c "ip link add name {0} type bridge; ip link set {1} up;' \ ' ip link set {1} master {0}; ip link set {0} up;' \ ' pkill dhclient; sleep 6; dhclient {0}; ifconfig {1} 0"'.format(br_name, iface_name) process.run(cmd, shell=True, verbose=True) def create_bridge_network(br_name, net_name): """ Define and start the bridge type network """ # check if network with the same name already exists output_all = virsh.net_list("--all").stdout.strip() if re.search(net_name, output_all): test.cancel("Network with the same name already exists!") test_xml = network_xml.NetworkXML(network_name="%s" % net_name) test_xml.forward = {"mode": "bridge"} test_xml.bridge = {"name": br_name} test_xml.create() def define_nwfilter(filter_name): """ Define nwfilter vdsm-no-mac-spoofing with content like: <filter name='vdsm-no-mac-spoofing' chain='root'> <filterref filter='no-mac-spoofing'/> <filterref filter='no-arp-mac-spoofing'/> </filter> :param filter_name: the name of nwfilter :return: filter created or raise exception """ filter_uuid = params.get("filter_uuid", "11111111-b071-6127-b4ec-111111111111") filter_params = { "filter_name": "vdsm-no-mac-spoofing", "filter_chain": "root", "filter_uuid": filter_uuid, "filterref_name_1": "no-mac-spoofing", "filterref_name_2": "no-arp-mac-spoofing" } filter_xml = libvirt.create_nwfilter_xml(filter_params).xml # Run command result = virsh.nwfilter_define(filter_xml, ignore_status=True, debug=True) if result.exit_status: test.fail("Failed to define nwfilter with %s" % filter_xml) def ping(src_ip, dest_ip, ping_count, timeout, session=None): """ Wrap of ping :param src_ip: source address :param dest_ip: destination address :param ping_count: count of icmp packet :param timeout: timeout for the ping command :param session: local execution or session to execute the ping command :return: ping succeed or raise exception """ status, output = utils_net.ping(dest=dest_ip, count=ping_count, interface=src_ip, timeout=timeout, session=session, force_ipv4=True) if status: test.fail("Fail to ping %s from %s" % (dest_ip, src_ip)) def check_net_functions(guest_ip, ping_count, ping_timeout, guest_session, host_ip, remote_url, endpoint_ip): # make sure host network works well # host ping remote url ping(host_ip, remote_url, ping_count, ping_timeout) # host ping guest ping(host_ip, guest_ip, ping_count, ping_timeout) # guest ping host ping(guest_ip, host_ip, ping_count, ping_timeout, session=guest_session) # guest ping remote url ping(guest_ip, remote_url, ping_count, ping_timeout, session=guest_session) # guest ping endpoint ping(guest_ip, endpoint_ip, ping_count, ping_timeout, session=guest_session) # Get test params bridge_name = params.get("bridge_name", "test_br0") filter_name = params.get("filter_name", "vdsm-no-mac-spoofing") ping_count = params.get("ping_count", "5") ping_timeout = float(params.get("ping_timeout", "10")) iface_name = utils_net.get_net_if(state="UP")[0] bridge_script = NETWORK_SCRIPT + bridge_name iface_script = NETWORK_SCRIPT + iface_name iface_script_bk = os.path.join(data_dir.get_tmp_dir(), "iface-%s.bk" % iface_name) attach_interface = "yes" == params.get("attach_interface", "no") iface_model = params.get("iface_model", "virtio") iface_source = eval(params.get("iface_source", "{'bridge':'test_br0'}")) iface_type = params.get("iface_type", None) iface_target = params.get("iface_target", "br_target") iface_alias = params.get("iface_alias", None) hotplug = "yes" == params.get("hotplug", "no") iface_driver = params.get("iface_driver", None) start_vm2 = "yes" == params.get("start_vm2", "no") create_network = "yes" == params.get("create_network", "no") update_device = "yes" == params.get("update_with_diff_type", "no") vms = params.get("vms").split() if len(vms) <= 1: test.cancel("Need two VMs to test") else: vm1_name = vms[0] vm2_name = vms[1] vm1 = env.get_vm(vm1_name) vm2 = env.get_vm(vm2_name) # Back up the interface script process.run("cp %s %s" % (iface_script, iface_script_bk), shell=True, verbose=True) # Back up vm xml vm1_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm1_name) vm2_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm2_name) # Stop NetworkManager service NM_service = service.Factory.create_service("NetworkManager") NM_status = NM_service.status() if not NM_status: NM_service.start() mac = utils_net.generate_mac_address_simple() try: create_bridge(bridge_name, iface_name) define_nwfilter(filter_name) if hotplug: err_msgs = ("No more available PCI slots", "No more available PCI addresses") # delete the original interface on the vm before hot-plug if vm1.is_alive(): vm1.destroy() vmxml = vm_xml.VMXML.new_from_dumpxml(vm1_name) iface_xml = vmxml.get_devices('interface')[0] logging.debug("Delete the original interface") vmxml.del_device(iface_xml) vmxml.sync() vm1.start() # do hot-plug if attach_interface: logging.info("Try to hot-plug interface") options = ( "%s %s --model %s --mac %s" % (iface_type, iface_source['bridge'], iface_model, mac)) ret = virsh.attach_interface(vm1_name, options, ignore_status=True) else: logging.info("Try to hot-plug device") if create_network: create_bridge_network(bridge_name, iface_source["network"]) target = str({'dev': iface_target}) iface_alias = str({'name': iface_alias}) vm_iface_source = str(iface_source) iface_params = { "type": iface_type, "source": vm_iface_source, "filter": filter_name, "mac": mac, 'alias': iface_alias, 'target': target, 'model': iface_model, 'driver': iface_driver } attach_xml = interface.Interface(iface_params['type']) attach_xml.xml = libvirt.modify_vm_iface( vm1_name, 'get_xml', iface_params) ret = virsh.attach_device(vm1_name, attach_xml.xml, ignore_status=True, debug=True) if ret.exit_status: if any([msg in ret.stderr for msg in err_msgs]): test.error("No more pci slots, can't attach more devices") else: test.fail("Failed to attach-interface: %s" % ret.stderr.strip()) else: logging.debug("Hot-plug interface or device pass") if update_device: # As the interface type will change to actual type "bridge" in live xml, we need to ensure # the update with original "network" type will not fail. # Try to delete the nwfilter with original type in iface_params update_xml = interface.Interface(iface_type) iface_params_update = { "del_filter": "yes", "type": "network", "source": vm_iface_source } update_xml.xml = libvirt.modify_vm_iface( vm1_name, 'get_xml', iface_params_update) ret = virsh.update_device(vm1_name, update_xml.xml, ignore_status=True, debug=True) libvirt.check_exit_status(ret) else: vm_iface_source = str(iface_source) vm1_iface_params = { "type": "bridge", "source": vm_iface_source, "filter": filter_name, "mac": mac, 'driver': iface_driver, "iface_model": iface_model } libvirt.modify_vm_iface(vm1_name, "update_iface", vm1_iface_params) if vm1.is_alive(): vm1.destroy() vm1.start() # apply ip address as it may not be initialized session1 = session2 = None session1 = vm1.wait_for_serial_login() utils_net.restart_guest_network(session1) output = session1.cmd_output("ifconfig || ip a") logging.debug("guest1 ip info %s" % output) # Check guest's network function host_ip = utils_net.get_ip_address_by_interface(bridge_name) remote_url = params.get("remote_ip", "www.google.com") try: vm1_ip = utils_net.get_guest_ip_addr(session1, mac) except Exception as errs: test.fail("vm1 can't get IP with the new create bridge: %s" % errs) if hotplug: # reboot vm1 then check network function to ensure the interface still there and works fine logging.info("reboot the vm") virsh.reboot(vm1) if session1 is None: session1 = vm1.wait_for_serial_login() ping(vm1_ip, remote_url, ping_count, ping_timeout, session=session1) # restart libvirtd service then check the interface still works fine libvirtd = utils_libvirtd.Libvirtd() libvirtd.restart() vm1.cleanup_serial_console() vm1.create_serial_console() session1 = vm1.wait_for_serial_login() ping(vm1_ip, remote_url, ping_count, ping_timeout, session=session1) logging.info( "after reboot and restart libvirtd, the network works fine") if iface_driver: try: driver_dict = eval(iface_driver) if session1 is None: session1 = vm1.wait_for_serial_login() guest_iface_info = session1.cmd_output("ip l").strip() guest_iface_name = re.findall( r"^\d+: (\S+?)[@:].*state UP.*$", guest_iface_info, re.MULTILINE)[0] comb_size = driver_dict.get('queues') rx_size = driver_dict.get('rx_queue_size') session1.cmd_status("ethtool -L %s combined %s" % (guest_iface_name, comb_size)) ret, outp = session1.cmd_status_output("ethtool -l %s" % guest_iface_name) logging.debug("ethtool cmd output:%s" % outp) if not ret: pre_comb = re.search( "Pre-set maximums:[\s\S]*?Combined:.*?(\d+)", outp).group(1) cur_comb = re.search( "Current hardware settings:[\s\S]*?Combined:.*?(\d+)", outp).group(1) if int(pre_comb) != int(comb_size) or int( cur_comb) != int(comb_size): test.fail( "Fail to check the combined size: setting: %s," "Pre-set: %s, Current-set: %s" % (comb_size, pre_comb, cur_comb)) else: logging.info( "Getting correct Pre-set and Current set value" ) else: test.error("ethtool list fail: %s" % outp) # as tx_queue size is only supported for vhost-user interface, only check rx_queue size ret1, outp1 = session1.cmd_status_output("ethtool -g %s" % guest_iface_name) logging.debug("guest queue size setting is %s" % outp1) if not ret1: pre_set = re.search(r"Pre-set maximums:\s*RX:\s*(\d+)", outp1).group(1) cur_set = re.search( r"Current hardware settings:\s*RX:\s*(\d+)", outp1).group(1) if int(pre_set) != int(rx_size) or int(cur_set) != int( rx_size): test.fail("Fail to check the rx_queue_size!") except Exception as errs: test.fail("fail to get driver info") # hot-unplug interface/device if attach_interface: ret = virsh.detach_interface(vm1_name, "bridge", ignore_status=True) else: ret = virsh.detach_device(vm1_name, attach_xml.xml, ignore_status=True, debug=True) if ret.exit_status: test.fail("Hot-unplug interface/device fail") else: logging.info("hot-unplug interface/device succeed") else: if start_vm2: # Start vm2 connect to the same bridge mac2 = utils_net.generate_mac_address_simple() vm2_iface_params = { "type": "bridge", "source": vm_iface_source, "filter": filter_name, "mac": mac2 } libvirt.modify_vm_iface(vm2_name, "update_iface", vm2_iface_params) if vm2.is_alive(): vm2.destroy() vm2.start() # Check if vm1 and vm2 can ping each other try: utils_net.update_mac_ip_address(vm2, timeout=120) vm2_ip = vm2.get_address() except Exception as errs: test.fail( "vm2 can't get IP with the new create bridge: %s" % errs) session2 = vm2.wait_for_login() # make sure guest has got ip address utils_net.restart_guest_network(session2) output2 = session2.cmd_output("ifconfig || ip a") logging.debug("guest ip info %s" % output2) # check 2 guests' network functions check_net_functions(vm1_ip, ping_count, ping_timeout, session1, host_ip, remote_url, vm2_ip) check_net_functions(vm2_ip, ping_count, ping_timeout, session2, host_ip, remote_url, vm1_ip) finally: logging.debug("Start to restore") vm1_xml_bak.sync() vm2_xml_bak.sync() virsh.nwfilter_undefine(filter_name, ignore_status=True) if libvirt.check_iface(bridge_name, "exists", "--all"): virsh.iface_unbridge(bridge_name, timeout=60, debug=True) if os.path.exists(iface_script_bk): process.run("mv %s %s" % (iface_script_bk, iface_script), shell=True, verbose=True) if os.path.exists(bridge_script): process.run("rm -rf %s" % bridge_script, shell=True, verbose=True) cmd = 'tmux -c "ip link set {1} nomaster; ip link delete {0};' \ 'pkill dhclient; sleep 6; dhclient {1}"'.format(bridge_name, iface_name) process.run(cmd, shell=True, verbose=True) # reload network configuration NM_service.restart() # recover NetworkManager if NM_status is True: NM_service.start() if 'network' in iface_source and iface_source[ "network"] in virsh.net_state_dict(): virsh.net_destroy(iface_source["network"], ignore_status=False)
def run(test, params, env): """ Test interface devices update """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) new_network_name = params.get("net_name") expect_error = "yes" == params.get("status_error", "no") expect_err_msg = params.get("expect_err_msg") iface_driver = params.get("iface_driver") iface_model = params.get("iface_model") iface_mtu = params.get("iface_mtu") iface_rom = params.get("iface_rom") iface_filter = params.get("iface_filter") new_iface_driver = params.get("new_iface_driver") new_iface_driver_host = params.get("new_iface_driver_host") new_iface_driver_guest = params.get("new_iface_driver_guest") new_iface_model = params.get("new_iface_model") new_iface_rom = params.get("new_iface_rom") new_iface_inbound = params.get("new_iface_inbound") new_iface_outbound = params.get("new_iface_outbound") new_iface_link = params.get("new_iface_link") new_iface_source = params.get("new_iface_source") new_iface_target = params.get("new_iface_target") new_iface_addr = params.get("new_iface_addr") new_iface_filter = params.get("new_iface_filter") new_iface_mtu = params.get("new_iface_mtu") new_iface_type = params.get("new_iface_type") create_new_net = "yes" == params.get("create_new_net") new_iface_alias = params.get("new_iface_alias") cold_update = "yes" == params.get("cold_update", "no") del_addr = "yes" == params.get("del_address") del_rom = "yes" == params.get("del_rom") del_filter = "yes" == params.get("del_filter") # Backup the vm xml for recover at last vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: # According to the different os find different file for rom if (iface_rom and "file" in eval(iface_rom) and "%s" in eval(iface_rom)['file']): if os.path.exists(eval(iface_rom)['file'] % "pxe"): iface_rom = iface_rom % "pxe" elif os.path.exists(eval(iface_rom)['file'] % "efi"): iface_rom = iface_rom % "efi" else: logging.error("Can not find suitable rom file") iface_dict_bef = {} iface_dict_aft = {} names = locals() # Collect need update items in 2 dicts for both start vm before and after update_list_bef = ["driver", "model", "mtu", "rom", "filter"] for update_item_bef in update_list_bef: if names['iface_' + update_item_bef]: iface_dict_bef.update( {update_item_bef: names['iface_' + update_item_bef]}) update_list_aft = [ "driver", "driver_host", "driver_guest", "model", "rom", "inbound", "outbound", "link", "source", "target", "addr", "filter", "mtu", "type", "alias" ] for update_item_aft in update_list_aft: if names["new_iface_" + update_item_aft]: iface_dict_aft.update( {update_item_aft: names["new_iface_" + update_item_aft]}) logging.info("iface_dict_bef is %s, iface_dict_aft is %s", iface_dict_bef, iface_dict_aft) del_list = ["del_addr", "del_rom", "del_filter"] for del_item in del_list: if names[del_item]: iface_dict_aft.update({del_item: "True"}) # Update vm interface with items in iface_dict_bef and start it if iface_dict_bef: libvirt.modify_vm_iface(vm_name, "update_iface", iface_dict_bef) logging.info("vm xml is %s", vm.get_xml()) if not cold_update: vm.start() if iface_mtu: # Do check for mtu size after start vm target_dev = libvirt.get_interface_details(vm_name)[0]['interface'] cmd = "ip link show %s | grep 'mtu %s'" % (target_dev, eval(iface_mtu)['size']) def check_mtu(): """ Check the mtu setting take effect for interface """ ret = process.run(cmd, ignore_status=True, shell=True) if ret.exit_status: test.fail("Can not find mtu setting in cmd result") check_mtu() utils_libvirtd.libvirtd_restart() check_mtu() # Create new network if need if create_new_net: new_net_xml = libvirt.create_net_xml(new_network_name, params) new_net_xml.sync() # Do update for iface_driver new_iface_xml = libvirt.modify_vm_iface(vm_name, "get_xml", iface_dict_aft) ret = virsh.update_device(vm_name, new_iface_xml, ignore_status=True, debug=True) libvirt.check_exit_status(ret, expect_error) if expect_error: real_err_msg = ret.stderr.strip() if not re.search(expect_err_msg, real_err_msg, re.IGNORECASE): test.fail("The real error msg:'%s' does not match expect one:" '%s' % (real_err_msg, expect_err_msg)) else: logging.info("Get expect result: %s", real_err_msg) else: if new_iface_inbound: iface_bandwidth = {} iface_bandwidth = vm_xml.VMXML.get_iftune_params(vm_name) for bound_para in ["inbound", "outbound"]: for tune_para in ["average", "peak", "burst"]: get_value = iface_bandwidth.get(bound_para).get( tune_para) expect_value = eval(names["new_iface_" + bound_para]).get(tune_para) logging.info("Get value for %s:%s is %s, expect is %s", bound_para, tune_para, get_value, expect_value) if get_value != expect_value: test.fail("Get value is not equal to expect") vmxml_aft = vm_xml.VMXML.new_from_dumpxml(vm_name) iface_aft = list(vmxml_aft.get_iface_all().values())[0] if new_iface_link: iface_link_value = iface_aft.find('link').get('state') if iface_link_value == new_iface_link: logging.info("Find link state is %s in xml", new_iface_link) # Checking the statue in guest mac_addr = iface_aft.find('mac').get('address') state_map = "%s.*\n.*%s" % (iface_link_value.upper(), mac_addr) session = vm.wait_for_serial_login() logging.info("ip link output:%s", session.cmd_output("ip link")) if_name = utils_net.get_net_if(runner=session.cmd_output, state=state_map)[0] session.close() if if_name: logging.info("Find iface state %s for %s", iface_link_value, mac_addr) else: test.fail( "Can not find iface with mac %s and state %s" % (mac_addr, iface_link_value)) else: test.fail( "Check fail to get link state, expect %s, but get %s" % (iface_link_value, new_iface_link)) if create_new_net and new_iface_source: iface_source_value = iface_aft.find('source').get('network') if iface_source_value == eval(new_iface_source)['network']: logging.info("Get %s in xml as set", iface_source_value) else: test.fail("Get source %s is not equal to set %s" % (iface_source_value, new_iface_source)) if new_iface_filter: iface_filter_value = iface_aft.find('filterref').get('filter') if iface_filter_value == new_iface_filter: logging.info("Get %s in xml as set", iface_filter_value) else: test.fail("Get filter %s is not equal to set %s" % (iface_filter_value, new_iface_filter)) if del_filter: iface_filter_value = iface_aft.find('filterref') if iface_filter_value: logging.debug("After delete, the filter still exists: %s", iface_filter_value) if new_iface_alias: iface_alias_value = iface_aft.find('alias').get('name') if iface_alias_value == eval(new_iface_alias)['name']: logging.info("Get %s in xml as set", iface_alias_value) else: test.fail("Get alias %s is not equal to set %s" % (iface_alias_value, new_iface_alias)) finally: vmxml_backup.sync() if create_new_net: new_net_xml.undefine()
def run(test, params, env): """ Test interafce xml options. 1.Prepare test environment,destroy or suspend a VM. 2.Edit xml and start the domain. 3.Perform test operation. 4.Recover test environment. 5.Confirm the test result. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) host_arch = platform.machine() def prepare_pxe_boot(): """ Prepare tftp server and pxe boot files """ pkg_list = ["syslinux", "tftp-server", "tftp", "ipxe-roms-qemu", "wget"] # Try to install required packages if not utils_package.package_install(pkg_list): test.error("Failed ot install required packages") boot_initrd = params.get("boot_initrd", "EXAMPLE_INITRD") boot_vmlinuz = params.get("boot_vmlinuz", "EXAMPLE_VMLINUZ") if boot_initrd.count("EXAMPLE") or boot_vmlinuz.count("EXAMPLE"): test.cancel("Please provide initrd/vmlinuz URL") # Download pxe boot images process.system("wget %s -O %s/initrd.img" % (boot_initrd, tftp_root)) process.system("wget %s -O %s/vmlinuz" % (boot_vmlinuz, tftp_root)) process.system("cp -f /usr/share/syslinux/pxelinux.0 {0};" " mkdir -m 777 -p {0}/pxelinux.cfg".format(tftp_root), shell=True) ldlinux_file = "/usr/share/syslinux/ldlinux.c32" if os.path.exists(ldlinux_file): process.system("cp -f {0} {1}".format(ldlinux_file, tftp_root), shell=True) pxe_file = "%s/pxelinux.cfg/default" % tftp_root boot_txt = """ DISPLAY boot.txt DEFAULT rhel LABEL rhel kernel vmlinuz append initrd=initrd.img PROMPT 1 TIMEOUT 3""" with open(pxe_file, 'w') as p_file: p_file.write(boot_txt) def modify_iface_xml(sync=True): """ Modify interface xml options :param sync: whether or not sync vmxml after the iface xml modified, default to be True """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) if pxe_boot: # Config boot console for pxe boot osxml = vm_xml.VMOSXML() osxml.type = vmxml.os.type osxml.arch = vmxml.os.arch osxml.machine = vmxml.os.machine osxml.loader = "/usr/share/seabios/bios.bin" osxml.bios_useserial = "yes" if utils_misc.compare_qemu_version(4, 0, 0, False): osxml.bios_reboot_timeout = "-1" osxml.boots = ['network'] del vmxml.os vmxml.os = osxml xml_devices = vmxml.devices iface_index = xml_devices.index( xml_devices.by_device_tag("interface")[0]) iface = xml_devices[iface_index] if not sync: params.setdefault('original_iface', vmxml.devices[iface_index]) iface_bandwidth = {} iface_inbound = ast.literal_eval(iface_bandwidth_inbound) iface_outbound = ast.literal_eval(iface_bandwidth_outbound) if iface_inbound: iface_bandwidth["inbound"] = iface_inbound if iface_outbound: iface_bandwidth["outbound"] = iface_outbound if iface_bandwidth: bandwidth = iface.new_bandwidth(**iface_bandwidth) iface.bandwidth = bandwidth iface_type = params.get("iface_type", "network") iface.type_name = iface_type source = ast.literal_eval(iface_source) if not source: source = {"network": "default"} net_ifs = utils_net.get_net_if(state="UP") # Check source device is valid or not, # if it's not in host interface list, try to set # source device to first active interface of host if (iface.type_name == "direct" and 'dev' in source and source['dev'] not in net_ifs): logging.warning("Source device %s is not a interface of host, reset to %s", source['dev'], net_ifs[0]) source['dev'] = net_ifs[0] del iface.source iface.source = source if iface_model: iface.model = get_iface_model(iface_model, host_arch) if iface_rom: iface.rom = eval(iface_rom) if iface_boot: vmxml.remove_all_boots() iface.boot = iface_boot logging.debug("New interface xml file: %s", iface) if sync: vmxml.devices = xml_devices vmxml.xmltreefile.write() vmxml.sync() else: return iface def get_iface_model(iface_model, host_arch): """ Return iface_model. In case of s390x modify iface_model and log the change. :param iface_model: iface_model from params :param host_arch: host architecture, e.g. s390x :return: //interface/model@type """ if 's390x' == host_arch: logging.debug("On s390x only valid model type are the virtio(-*)." " Using virtio and ignoring config value %s" % iface_model) return "virtio" else: return iface_model def run_dnsmasq_default_test(key, value=None, exists=True, name="default"): """ Test dnsmasq configuration. :param key: key in conf file to check :param value: value in conf file to check :param exists: check the key:value exist or not :param name: The name of conf file """ conf_file = "/var/lib/libvirt/dnsmasq/%s.conf" % name if not os.path.exists(conf_file): test.cancel("Can't find %s.conf file" % name) configs = "" with open(conf_file, 'r') as f: configs = f.read() logging.debug("configs in file %s: %s", conf_file, configs) if value: config = "%s=%s" % (key, value) else: config = key if not configs.count(config): if exists: test.fail("Can't find %s=%s in configuration file" % (key, value)) else: if not exists: test.fail("Found %s=%s in configuration file" % (key, value)) def run_dnsmasq_addnhosts_test(hostip, hostnames): """ Test host ip and names configuration """ conf_file = "/var/lib/libvirt/dnsmasq/default.addnhosts" hosts_re = ".*".join(hostnames) configs = "" with open(conf_file, 'r') as f: configs = f.read() logging.debug("configs in file %s: %s", conf_file, configs) if not re.search(r"%s.*%s" % (hostip, hosts_re), configs, re.M): test.fail("Can't find '%s' in configuration file" % hostip) def run_dnsmasq_host_test(iface_mac, guest_ip, guest_name): """ Test host name and ip configuration for dnsmasq """ conf_file = "/var/lib/libvirt/dnsmasq/default.hostsfile" config = "%s,%s,%s" % (iface_mac, guest_ip, guest_name) configs = "" with open(conf_file, 'r') as f: configs = f.read() logging.debug("configs in file %s: %s", conf_file, configs) if not configs.count(config): test.fail("Can't find host configuration in file %s" % conf_file) def check_class_rules(ifname, rule_id, bandwidth): """ Check bandwidth settings via 'tc class' output """ cmd = "tc class show dev %s" % ifname class_output = process.run(cmd, shell=True).stdout_text logging.debug("Bandwidth class output: %s", class_output) class_pattern = (r"class htb %s.*rate (\d+)(K?M?)bit ceil (\d+)(K?M?)bit burst (\d+)(K?M?)b.*" % rule_id) se = re.search(class_pattern, class_output, re.M) if not se: test.fail("Can't find outbound setting for htb %s" % rule_id) logging.debug("bandwidth from tc output:%s" % str(se.groups())) rate = None if "floor" in bandwidth: rate = int(bandwidth["floor"]) * 8 elif "average" in bandwidth: rate = int(bandwidth["average"]) * 8 if rate: if se.group(2) == 'M': rate_check = int(se.group(1)) * 1000 else: rate_check = int(se.group(1)) assert rate_check == rate if "peak" in bandwidth: if se.group(4) == 'M': ceil_check = int(se.group(3)) * 1000 else: ceil_check = int(se.group(3)) assert ceil_check == int(bandwidth["peak"]) * 8 if "burst" in bandwidth: if se.group(6) == 'M': tc_burst = int(se.group(5)) * 1024 else: tc_burst = int(se.group(5)) assert tc_burst == int(bandwidth["burst"]) def check_filter_rules(ifname, bandwidth, expect_none=False): """ Check bandwidth settings via 'tc filter' output :param ifname: name of iface to be checked :param bandwidth: bandwidth to be match with :param expect_none: whether or not expect nothing in output, default to be False :return: if expect nothing from the output, return True if the output is empty, else return False """ cmd = "tc -d filter show dev %s parent ffff:" % ifname filter_output = process.run(cmd, shell=True).stdout_text logging.debug("Bandwidth filter output: %s", filter_output) if expect_none: return not filter_output.strip() if not filter_output.count("filter protocol all pref"): test.fail("Can't find 'protocol all' settings in filter rules") filter_pattern = r".*police.*rate (\d+)(K?M?)bit burst (\d+)(K?M?)b.*" se = re.search(r"%s" % filter_pattern, filter_output, re.M) if not se: test.fail("Can't find any filter policy") logging.debug("bandwidth from tc output:%s" % str(se.groups())) logging.debug("bandwidth from setting:%s" % str(bandwidth)) if "average" in bandwidth: if se.group(2) == 'M': tc_average = int(se.group(1)) * 1000 else: tc_average = int(se.group(1)) assert tc_average == int(bandwidth["average"]) * 8 if "burst" in bandwidth: if se.group(4) == 'M': tc_burst = int(se.group(3)) * 1024 else: tc_burst = int(se.group(3)) assert tc_burst == int(bandwidth["burst"]) def check_host_routes(): """ Check network routes on host """ for rt in routes: try: route = ast.literal_eval(rt) addr = "%s/%s" % (route["address"], route["prefix"]) cmd = "ip route list %s" % addr if "family" in route and route["family"] == "ipv6": cmd = "ip -6 route list %s" % addr output = process.run(cmd, shell=True).stdout_text match_obj = re.search(r"via (\S+).*metric (\d+)", output) if match_obj: via_addr = match_obj.group(1) metric = match_obj.group(2) logging.debug("via address %s for %s, matric is %s" % (via_addr, addr, metric)) assert via_addr == route["gateway"] if "metric" in route: assert metric == route["metric"] except KeyError: pass def run_bandwidth_test(check_net=False, check_iface=False): """ Test bandwidth option for network or interface by tc command. """ iface_inbound = ast.literal_eval(iface_bandwidth_inbound) iface_outbound = ast.literal_eval(iface_bandwidth_outbound) net_inbound = ast.literal_eval(net_bandwidth_inbound) net_outbound = ast.literal_eval(net_bandwidth_outbound) net_bridge_name = ast.literal_eval(net_bridge)["name"] iface_name = libvirt.get_ifname_host(vm_name, iface_mac) try: if check_net and net_inbound: # Check qdisc rules cmd = "tc -d qdisc show dev %s" % net_bridge_name qdisc_output = process.run(cmd, shell=True).stdout_text logging.debug("Bandwidth qdisc output: %s", qdisc_output) if not qdisc_output.count("qdisc ingress ffff:"): test.fail("Can't find ingress setting") check_class_rules(net_bridge_name, "1:1", {"average": net_inbound["average"], "peak": net_inbound["peak"]}) check_class_rules(net_bridge_name, "1:2", net_inbound) # Check filter rules on bridge interface if check_net and net_outbound: check_filter_rules(net_bridge_name, net_outbound) # Check class rules on interface inbound settings if check_iface and iface_inbound: check_class_rules(iface_name, "1:1", {'average': iface_inbound['average'], 'peak': iface_inbound['peak'], 'burst': iface_inbound['burst']}) if "floor" in iface_inbound: if not libvirt_version.version_compare(1, 0, 1): test.cancel("Not supported Qos options 'floor'") check_class_rules(net_bridge_name, "1:3", {'floor': iface_inbound["floor"]}) # Check filter rules on interface outbound settings if check_iface and iface_outbound: check_filter_rules(iface_name, iface_outbound) except AssertionError: stacktrace.log_exc_info(sys.exc_info()) test.fail("Failed to check network bandwidth") def check_name_ip(session): """ Check dns resolving on guest """ # Check if bind-utils is installed if "ubuntu" in vm.get_distro().lower(): pkg = "bind9" else: pkg = "bind-utils" if not utils_package.package_install(pkg, session): test.error("Failed to install bind-utils on guest") # Run host command to check if hostname can be resolved if not guest_ipv4 and not guest_ipv6: test.fail("No ip address found from parameters") guest_ip = guest_ipv4 if guest_ipv4 else guest_ipv6 cmd = "host %s | grep %s" % (guest_name, guest_ip) if session.cmd_status(cmd): test.fail("Can't resolve name %s on guest" % guest_name) def check_ipt_rules(check_ipv4=True, check_ipv6=False): """ Check iptables for network/interface """ br_name = ast.literal_eval(net_bridge)["name"] net_forward = ast.literal_eval(params.get("net_forward", "{}")) net_ipv4 = params.get("net_ipv4") net_ipv6 = params.get("net_ipv6") net_dev_in = "" net_dev_out = "" if "dev" in net_forward: net_dev_in = " -i %s" % net_forward["dev"] net_dev_out = " -o %s" % net_forward["dev"] if libvirt_version.version_compare(5, 1, 0): input_chain = "LIBVIRT_INP" output_chain = "LIBVIRT_OUT" postrouting_chain = "LIBVIRT_PRT" forward_filter = "LIBVIRT_FWX" forward_in = "LIBVIRT_FWI" forward_out = "LIBVIRT_FWO" else: input_chain = "INPUT" output_chain = "OUTPUT" postrouting_chain = "POSTROUTING" forward_filter = "FORWARD" forward_in = "FORWARD" forward_out = "FORWARD" ipt_rules = ( "%s -i %s -p udp -m udp --dport 53 -j ACCEPT" % (input_chain, br_name), "%s -i %s -p tcp -m tcp --dport 53 -j ACCEPT" % (input_chain, br_name), "{0} -i {1} -o {1} -j ACCEPT".format(forward_filter, br_name), "%s -o %s -j REJECT --reject-with icmp" % (forward_in, br_name), "%s -i %s -j REJECT --reject-with icmp" % (forward_out, br_name)) if check_ipv4: ipv4_rules = list(ipt_rules) ipv4_rules.extend( ["%s -i %s -p udp -m udp --dport 67 -j ACCEPT" % (input_chain, br_name), "%s -i %s -p tcp -m tcp --dport 67 -j ACCEPT" % (input_chain, br_name), "%s -o %s -p udp -m udp --dport 68 -j ACCEPT" % (output_chain, br_name), "%s -o %s -p udp -m udp --dport 68 " "-j CHECKSUM --checksum-fill" % (postrouting_chain, br_name)]) ctr_rule = "" nat_rules = [] if "mode" in net_forward and net_forward["mode"] == "nat": nat_port = ast.literal_eval(params.get("nat_port")) p_start = nat_port["start"] p_end = nat_port["end"] ctr_rule = " -m .* RELATED,ESTABLISHED" nat_rules = [("{0} -s {1} ! -d {1} -p tcp -j MASQUERADE" " --to-ports {2}-{3}".format(postrouting_chain, net_ipv4, p_start, p_end)), ("{0} -s {1} ! -d {1} -p udp -j MASQUERADE" " --to-ports {2}-{3}".format(postrouting_chain, net_ipv4, p_start, p_end)), ("{0} -s {1} ! -d {1}" " -j MASQUERADE".format(postrouting_chain, net_ipv4))] if nat_rules: ipv4_rules.extend(nat_rules) if (net_ipv4 and "mode" in net_forward and net_forward["mode"] in ["nat", "route"]): rules = [("%s -d %s%s -o %s%s -j ACCEPT" % (forward_in, net_ipv4, net_dev_in, br_name, ctr_rule)), ("%s -s %s -i %s%s -j ACCEPT" % (forward_out, net_ipv4, br_name, net_dev_out))] ipv4_rules.extend(rules) output = process.run('iptables-save', shell=True).stdout_text logging.debug("iptables: %s", output) if "mode" in net_forward and net_forward["mode"] == "open": if re.search(r"%s|%s" % (net_ipv4, br_name), output, re.M): test.fail("Find iptable rule for open mode") utils_libvirtd.libvirtd_restart() output_again = process.run('iptables-save', shell=True).stdout_text if re.search(r"%s|%s" % (net_ipv4, br_name), output_again, re.M): test.fail("Find iptable rule for open mode after restart " "libvirtd") else: logging.info("Can't find iptable rule for open mode as expected") else: for ipt in ipv4_rules: if not re.search(r"%s" % ipt, output, re.M): test.fail("Can't find iptable rule:\n%s" % ipt) return ipv4_rules if check_ipv6: ipv6_rules = list(ipt_rules) ipt6_rules.extend([ ("INPUT -i %s -p udp -m udp --dport 547 -j ACCEPT" % br_name)]) if (net_ipv6 and "mode" in net_forward and net_forward["mode"] in ["nat", "route"]): rules = [("%s -d %s%s -o %s -j ACCEPT" % (forward_in, net_ipv6, net_dev_in, br_name)), ("%s -s %s -i %s%s -j ACCEPT" % (forward_out, net_ipv6, br_name, net_dev_out))] ipv6_rules.extend(rules) output = process.run("ip6tables-save", shell=True).stdout_text logging.debug("ip6tables: %s", output) if "mode" in net_forward and net_forward["mode"] == "open": if re.search(r"%s|%s" % (net_ipv6, br_name), output, re.M): test.fail("Find ip6table rule for open mode") utils_libvirtd.libvirtd_restart() output_again = process.run('ip6tables-save', shell=True).stdout_text if re.search(r"%s|%s" % (net_ipv6, br_name), output_again, re.M): test.fail("Find ip6table rule for open mode after restart " "libvirtd") else: for ipt in ipv6_rules: if not re.search(r"%s" % ipt, output, re.M): test.fail("Can't find ip6table rule:\n%s" % ipt) return ipv6_rules def run_ip_test(session, ip_ver): """ Check iptables on host and ipv6 address on guest """ if ip_ver == "ipv6": # Clean up iptables rules for guest to get ipv6 address session.cmd_status("ip6tables -F") # It may take some time to get the ip address def get_ip_func(): return utils_net.get_guest_ip_addr(session, iface_mac, ip_version=ip_ver) utils_misc.wait_for(get_ip_func, 5) if not get_ip_func(): utils_net.restart_guest_network(session, iface_mac, ip_version=ip_ver) utils_misc.wait_for(get_ip_func, 5) vm_ip = get_ip_func() logging.debug("Guest has ip: %s", vm_ip) if not vm_ip: test.fail("Can't find ip address on guest") ip_gateway = net_ip_address if ip_ver == "ipv6": ip_gateway = net_ipv6_address # Cleanup ip6talbes on host for ping6 test process.system("ip6tables -F") if ip_gateway and not routes: ping_s, _ = ping(dest=ip_gateway, count=5, timeout=10, session=session) if ping_s: test.fail("Failed to ping gateway address: %s" % ip_gateway) def run_guest_libvirt(session): """ Check guest libvirt network """ # Try to install required packages if "ubuntu" in vm.get_distro().lower(): pkg = "libvirt-bin" else: pkg = "libvirt" if not utils_package.package_install(pkg, session): test.error("Failed to install libvirt package on guest") # Try to load tun module first session.cmd("lsmod | grep tun || modprobe tun") # Check network state on guest cmd = ("service libvirtd restart; virsh net-info default" " | grep 'Active:.*yes'") if session.cmd_status(cmd): test.fail("'default' network isn't in active state") # Try to destroy&start default network on guest for opt in ['net-destroy', 'net-start']: cmd = "virsh %s default" % opt status, output = session.cmd_status_output(cmd) logging.debug("Run %s on guest exit %s, output %s" % (cmd, status, output)) if status: test.fail(output) if not utils_package.package_remove("libvirt*", session): test.error("Failed to remove libvirt packages on guest") start_error = "yes" == params.get("start_error", "no") define_error = "yes" == params.get("define_error", "no") restart_error = "yes" == params.get("restart_error", "no") # network specific attributes. net_name = params.get("net_name", "default") net_bridge = params.get("net_bridge", "{'name':'virbr0'}") net_domain = params.get("net_domain") net_ip_address = params.get("net_ip_address") net_ipv6_address = params.get("net_ipv6_address") net_dns_forward = params.get("net_dns_forward") net_dns_txt = params.get("net_dns_txt") net_dns_srv = params.get("net_dns_srv") net_dns_hostip = params.get("net_dns_hostip") net_dns_hostnames = params.get("net_dns_hostnames", "").split() dhcp_start_ipv4 = params.get("dhcp_start_ipv4") dhcp_end_ipv4 = params.get("dhcp_end_ipv4") dhcp_start_ipv6 = params.get("dhcp_start_ipv6") dhcp_end_ipv6 = params.get("dhcp_end_ipv6") guest_name = params.get("guest_name") guest_ipv4 = params.get("guest_ipv4") guest_ipv6 = params.get("guest_ipv6") tftp_root = params.get("tftp_root") pxe_boot = "yes" == params.get("pxe_boot", "no") routes = params.get("routes", "").split() net_bandwidth_inbound = params.get("net_bandwidth_inbound", "{}") net_bandwidth_outbound = params.get("net_bandwidth_outbound", "{}") iface_bandwidth_inbound = params.get("iface_bandwidth_inbound", "{}") iface_bandwidth_outbound = params.get("iface_bandwidth_outbound", "{}") iface_num = params.get("iface_num", "1") iface_source = params.get("iface_source", "{}") iface_rom = params.get("iface_rom") iface_boot = params.get("iface_boot") iface_model = params.get("iface_model") multiple_guests = params.get("multiple_guests") create_network = "yes" == params.get("create_network", "no") attach_iface = "yes" == params.get("attach_iface", "no") serial_login = "******" == params.get("serial_login", "no") change_iface_option = "yes" == params.get("change_iface_option", "no") test_bridge = "yes" == params.get("test_bridge", "no") test_dnsmasq = "yes" == params.get("test_dnsmasq", "no") test_dhcp_range = "yes" == params.get("test_dhcp_range", "no") test_dns_host = "yes" == params.get("test_dns_host", "no") test_qos_bandwidth = "yes" == params.get("test_qos_bandwidth", "no") test_pg_bandwidth = "yes" == params.get("test_portgroup_bandwidth", "no") test_qos_remove = "yes" == params.get("test_qos_remove", "no") test_ipv4_address = "yes" == params.get("test_ipv4_address", "no") test_ipv6_address = "yes" == params.get("test_ipv6_address", "no") test_guest_libvirt = "yes" == params.get("test_guest_libvirt", "no") test_dns_forwarders = "yes" == params.get("test_dns_forwarders", "no") net_no_bridge = "yes" == params.get("no_bridge", "no") net_no_mac = "yes" == params.get("no_mac", "no") net_no_ip = "yes" == params.get("no_ip", "no") net_with_dev = "yes" == params.get("with_dev", "no") update_device = 'yes' == params.get('update_device', 'no') remove_bandwidth = 'yes' == params.get('remove_bandwidth', 'no') loop = int(params.get('loop', 0)) username = params.get("username") password = params.get("password") forward = ast.literal_eval(params.get("net_forward", "{}")) boot_failure = "yes" == params.get("boot_failure", "no") test_netmask = "yes" == params.get("test_netmask", "no") ipt_rules = [] ipt6_rules = [] define_macvtap = "yes" == params.get("define_macvtap", "no") net_dns_forwarders = params.get("net_dns_forwarders", "").split() # Destroy VM first if vm.is_alive() and not update_device: vm.destroy(gracefully=False) # Back up xml file. netxml_backup = NetworkXML.new_from_net_dumpxml("default") iface_mac = vm_xml.VMXML.get_first_mac_by_name(vm_name) params["guest_mac"] = iface_mac vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vms_list = [] if "floor" in ast.literal_eval(iface_bandwidth_inbound): if not libvirt_version.version_compare(1, 0, 1): test.cancel("Not supported Qos options 'floor'") # Enabling IPv6 forwarding with RA routes without accept_ra set to 2 # is likely to cause routes loss sysctl_cmd = 'sysctl net.ipv6.conf.all.accept_ra' original_accept_ra = process.run(sysctl_cmd + ' -n', shell=True).stdout_text if test_ipv6_address and original_accept_ra != '2': process.system(sysctl_cmd + '=2') # Build the xml and run test. try: if test_dnsmasq: # Check the settings before modifying network xml if net_dns_forward == "no": run_dnsmasq_default_test("domain-needed", exists=False) run_dnsmasq_default_test("local", "//", exists=False) if net_domain: run_dnsmasq_default_test("domain", net_domain, exists=False) run_dnsmasq_default_test("expand-hosts", exists=False) # Prepare pxe boot directory if pxe_boot: prepare_pxe_boot() # Edit the network xml or create a new one. if create_network: net_ifs = utils_net.get_net_if(state="UP") # Check forward device is valid or not, # if it's not in host interface list, try to set # forward device to first active interface of host if ('mode' in forward and forward['mode'] in ['passthrough', 'private', 'bridge', 'macvtap'] and 'dev' in forward and forward['dev'] not in net_ifs): logging.warning("Forward device %s is not a interface of host, reset to %s", forward['dev'], net_ifs[0]) forward['dev'] = net_ifs[0] params["net_forward"] = str(forward) if define_macvtap: for i in [0, 2, 4]: cmd = "ip l add li %s macvtap%s type macvtap" % (forward['dev'], i) process.run(cmd, shell=True, verbose=True) process.run("ip l", shell=True, verbose=True) forward_iface = params.get("forward_iface") if forward_iface: interface = [x for x in forward_iface.split()] # The guest will use first interface of the list, # check if it's valid or not, if it's not in host # interface list, try to set forward interface to # first active interface of host. if interface[0] not in net_ifs: logging.warning("Forward interface %s is not a interface of host, reset to %s", interface[0], net_ifs[0]) interface[0] = net_ifs[0] params["forward_iface"] = " ".join(interface) netxml = libvirt.create_net_xml(net_name, params) if "mode" in forward and forward["mode"] == "open": netxml.mac = utils_net.generate_mac_address_simple() try: if net_no_bridge: netxml.del_bridge() if net_no_ip: netxml.del_ip() netxml.del_ip() if net_no_mac: netxml.del_mac() except xcepts.LibvirtXMLNotFoundError: pass if net_with_dev: net_forward = netxml.forward net_forward.update({"dev": net_ifs[0]}) netxml.forward = net_forward logging.info("netxml before define is %s", netxml) try: netxml.sync() except xcepts.LibvirtXMLError as details: logging.info(str(details)) if define_error: return else: test.fail("Failed to define network") # Check open mode network xml if "mode" in forward and forward["mode"] == "open": netxml_new = NetworkXML.new_from_net_dumpxml(net_name) logging.info("netxml after define is %s", netxml_new) try: if net_no_bridge: net_bridge = str(netxml_new.bridge) if net_no_mac: netxml_new.mac except xcepts.LibvirtXMLNotFoundError as details: test.fail("Failed to check %s xml: %s" % (net_name, details)) logging.info("mac/bridge still exist even if removed before define") # Edit the interface xml. if change_iface_option: try: if update_device: updated_iface = modify_iface_xml(sync=False) virsh.update_device(vm_name, updated_iface.xml, ignore_status=False, debug=True) else: modify_iface_xml() except xcepts.LibvirtXMLError as details: logging.info(str(details)) if define_error: if not str(details).count("Failed to define"): test.fail("VM sync failed msg not expected") return else: test.fail("Failed to sync VM") # Attach interface if needed if attach_iface: iface_type = params.get("iface_type", "network") for i in range(int(iface_num)): logging.info("Try to attach interface loop %s" % i) options = ("%s %s --model %s --config" % (iface_type, net_name, iface_model)) ret = virsh.attach_interface(vm_name, options, ignore_status=True) if ret.exit_status: logging.error("Command output %s" % ret.stdout.strip()) test.fail("Failed to attach-interface") if multiple_guests: # Clone more vms for testing for i in range(int(multiple_guests)): guest_name = "%s_%s" % (vm_name, i) timeout = params.get("clone_timeout", 360) utils_libguestfs.virt_clone_cmd(vm_name, guest_name, True, timeout=timeout) vms_list.append(vm.clone(guest_name)) if test_bridge: bridge = ast.literal_eval(net_bridge) br_if = utils_net.Interface(bridge['name']) if not br_if.is_up(): test.fail("Bridge interface isn't up") if test_dnsmasq: # Check dnsmasq process dnsmasq_cmd = process.run("ps -aux|grep dnsmasq", shell=True).stdout_text logging.debug(dnsmasq_cmd) if not re.search("dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/%s.conf" % net_name, dnsmasq_cmd): test.fail("Can not find dnsmasq process or the process is not correct") # Check the settings in dnsmasq config file if net_dns_forward == "no": run_dnsmasq_default_test("domain-needed") run_dnsmasq_default_test("local", "//") if net_domain: run_dnsmasq_default_test("domain", net_domain) run_dnsmasq_default_test("expand-hosts") if net_bridge: bridge = ast.literal_eval(net_bridge) run_dnsmasq_default_test("interface", bridge['name'], name=net_name) if 'stp' in bridge and bridge['stp'] == 'on': if 'delay' in bridge and bridge['delay'] != '0': # network xml forward delay value in seconds, while on # host, check by ip command, the value is in second*100 br_delay = int(bridge['delay']) * 100 logging.debug("Expect forward_delay is %s ms" % br_delay) cmd = ("ip -d link sh %s | grep 'bridge forward_delay'" % bridge['name']) out = process.run( cmd, shell=True, ignore_status=False).stdout_text logging.debug("bridge statistics output: %s", out) pattern = (r"\s*bridge forward_delay\s+(\d+)") match_obj = re.search(pattern, out, re.M) if not match_obj: test.fail("Can't see forward delay messages from command") elif int(match_obj.group(1)) != br_delay: test.fail("Foward delay setting can't take effect") else: logging.debug("Foward delay set successfully!") if dhcp_start_ipv4 and dhcp_end_ipv4: run_dnsmasq_default_test("dhcp-range", "%s,%s" % (dhcp_start_ipv4, dhcp_end_ipv4), name=net_name) if dhcp_start_ipv6 and dhcp_end_ipv6: run_dnsmasq_default_test("dhcp-range", "%s,%s,64" % (dhcp_start_ipv6, dhcp_end_ipv6), name=net_name) if guest_name and guest_ipv4: run_dnsmasq_host_test(iface_mac, guest_ipv4, guest_name) if test_netmask and libvirt_version.version_compare(5, 1, 0): run_dnsmasq_default_test("dhcp-range", "192.168.122.2,192.168.122.254,255.255.252.0") # check the left part in dnsmasq conf run_dnsmasq_default_test("strict-order", name=net_name) if libvirt_version.version_compare(6, 0, 0): run_dnsmasq_default_test("pid-file", "/run/libvirt/network/%s.pid" % net_name, name=net_name) else: run_dnsmasq_default_test("pid-file", "/var/run/libvirt/network/%s.pid" % net_name, name=net_name) run_dnsmasq_default_test("except-interface", "lo", name=net_name) run_dnsmasq_default_test("bind-dynamic", name=net_name) run_dnsmasq_default_test("dhcp-no-override", name=net_name) if dhcp_start_ipv6 and dhcp_start_ipv4: run_dnsmasq_default_test("dhcp-lease-max", "493", name=net_name) else: range_num = int(params.get("dhcp_range", "252")) run_dnsmasq_default_test("dhcp-lease-max", str(range_num + 1), name=net_name) run_dnsmasq_default_test("dhcp-hostsfile", "/var/lib/libvirt/dnsmasq/%s.hostsfile" % net_name, name=net_name) run_dnsmasq_default_test("addn-hosts", "/var/lib/libvirt/dnsmasq/%s.addnhosts" % net_name, name=net_name) if dhcp_start_ipv6: run_dnsmasq_default_test("enable-ra", name=net_name) if test_dns_host: if net_dns_txt: dns_txt = ast.literal_eval(net_dns_txt) run_dnsmasq_default_test("txt-record", "%s,%s" % (dns_txt["name"], dns_txt["value"])) if net_dns_srv: dns_srv = ast.literal_eval(net_dns_srv) run_dnsmasq_default_test("srv-host", "_%s._%s.%s,%s,%s,%s,%s" % (dns_srv["service"], dns_srv["protocol"], dns_srv["domain"], dns_srv["target"], dns_srv["port"], dns_srv["priority"], dns_srv["weight"])) if net_dns_hostip and net_dns_hostnames: run_dnsmasq_addnhosts_test(net_dns_hostip, net_dns_hostnames) if test_dns_forwarders: if net_name == "isolatedtest": run_dnsmasq_default_test("no-resolv", name=net_name) else: net_dns_forwarder = [ast.literal_eval(x) for x in net_dns_forwarders] for forwarder in net_dns_forwarder: if ('domain' in forwarder) and ('addr' in forwarder): run_dnsmasq_default_test("server", "/%s/%s" % (forwarder['domain'], forwarder['addr'])) elif "domain" in forwarder: run_dnsmasq_default_test("server", "/%s/#" % forwarder['domain']) elif "addr" in forwarder: run_dnsmasq_default_test("server", "%s" % forwarder['addr']) run_dnsmasq_default_test("no-resolv") # Run bandwidth test for network if test_qos_bandwidth and not update_device: run_bandwidth_test(check_net=True) # If to remove bandwidth from iface, # update iface xml to the original one if remove_bandwidth: ori_iface = params['original_iface'] logging.debug(ori_iface) virsh.update_device(vm_name, ori_iface.xml, ignore_status=False, debug=True) # Check routes if needed if routes: check_host_routes() try: # Start the VM. if not update_device: vm.start() if start_error: test.fail("VM started unexpectedly") if define_macvtap: cmd = "ls /sys/devices/virtual/net" output = process.run(cmd, shell=True, verbose=True).stdout_text macvtap_list = re.findall(r'macvtap0|macvtap1|macvtap2|macvtap3' r'|macvtap4|macvtap5|macvtap6|macvtap7', output) logging.debug("The macvtap_list is %s" % macvtap_list) if set(macvtap_list) != set(['macvtap' + str(x) for x in range(8)]): test.fail("Existing macvtap device %s is not expected! should be macvtap(0-7)" % macvtap_list) if pxe_boot: # Just check network boot messages here try: vm.serial_console.read_until_output_matches( ["Loading vmlinuz", "Loading initrd.img"], utils_misc.strip_console_codes) except ExpectTimeoutError as details: if boot_failure: logging.info("Fail to boot from pxe as expected") else: test.fail("Fail to boot from pxe") else: if serial_login: session = vm.wait_for_serial_login(username=username, password=password) else: session = vm.wait_for_login() if test_dhcp_range: dhcp_range = int(params.get("dhcp_range", "252")) utils_net.restart_guest_network(session, iface_mac) vm_ip = utils_net.get_guest_ip_addr(session, iface_mac) logging.debug("Guest has ip: %s", vm_ip) if not vm_ip and dhcp_range: test.fail("Guest has invalid ip address") elif vm_ip and not dhcp_range: test.fail("Guest has ip address: %s" % vm_ip) dhcp_range = dhcp_range - 1 for vms in vms_list: # Start other VMs. vms.start() sess = vms.wait_for_serial_login() vms_mac = vms.get_virsh_mac_address() # restart guest network to get ip addr utils_net.restart_guest_network(sess, vms_mac) vms_ip = utils_net.get_guest_ip_addr(sess, vms_mac) if not vms_ip and dhcp_range: test.fail("Guest has invalid ip address") elif vms_ip and not dhcp_range: # Get IP address on guest should return Null # if it exceeds the dhcp range test.fail("Guest has ip address: %s" % vms_ip) dhcp_range = dhcp_range - 1 if vms_ip: ping_s, _ = ping(dest=vm_ip, count=5, timeout=10, session=sess) if ping_s: test.fail("Failed to ping, src: %s, " "dst: %s" % (vms_ip, vm_ip)) sess.close() # Check dnsmasq settings if take affect in guest if guest_ipv4: check_name_ip(session) # Run bandwidth test for interface if test_qos_bandwidth: run_bandwidth_test(check_iface=True) # Run bandwidth test for portgroup if test_pg_bandwidth: pg_bandwidth_inbound = params.get( "portgroup_bandwidth_inbound", "").split() pg_bandwidth_outbound = params.get( "portgroup_bandwidth_outbound", "").split() pg_name = params.get("portgroup_name", "").split() pg_default = params.get("portgroup_default", "").split() iface_inbound = ast.literal_eval(iface_bandwidth_inbound) iface_outbound = ast.literal_eval(iface_bandwidth_outbound) iface_name = libvirt.get_ifname_host(vm_name, iface_mac) if_source = ast.literal_eval(iface_source) if "portgroup" in if_source: pg = if_source["portgroup"] else: pg = "default" for (name, df, bw_ib, bw_ob) in zip(pg_name, pg_default, pg_bandwidth_inbound, pg_bandwidth_outbound): if pg == name: inbound = ast.literal_eval(bw_ib) outbound = ast.literal_eval(bw_ob) elif pg == "default" and df == "yes": inbound = ast.literal_eval(bw_ib) outbound = ast.literal_eval(bw_ob) else: continue # Interface bandwidth settings will # overwriting portgroup settings if iface_inbound: inbound = iface_inbound if iface_outbound: outbound = iface_outbound check_class_rules(iface_name, "1:1", inbound) check_filter_rules(iface_name, outbound) if test_qos_remove: # Remove the bandwidth settings in network xml logging.debug("Removing network bandwidth settings...") netxml_backup.sync() vm.destroy(gracefully=False) # Should fail to start vm vm.start() if restart_error: test.fail("VM started unexpectedly") if test_ipv6_address: ipt6_rules = check_ipt_rules(check_ipv4=False, check_ipv6=True) if not ("mode" in forward and forward["mode"] == "open"): run_ip_test(session, "ipv6") if test_ipv4_address: ipt_rules = check_ipt_rules(check_ipv4=True) if not ("mode" in forward and forward["mode"] == "open"): run_ip_test(session, "ipv4") if test_guest_libvirt: run_guest_libvirt(session) session.close() except virt_vm.VMStartError as details: logging.info(str(details)) if not (start_error or restart_error): test.fail('VM failed to start:\n%s' % details) # Destroy created network and check iptable rules if net_name != "default": virsh.net_destroy(net_name) if ipt_rules: output_des = process.run('iptables-save', shell=True).stdout_text for ipt in ipt_rules: if re.search(r"%s" % ipt, output_des, re.M): test.fail("Find iptable rule %s after net destroyed" % ipt) if ipt6_rules: output_des = process.run('ip6tables-save', shell=True).stdout_text for ipt in ipt6_rules: if re.search(r"%s" % ipt, output_des, re.M): test.fail("Find ip6table rule %s after net destroyed" % ipt) if remove_bandwidth: iface_name = libvirt.get_ifname_host(vm_name, iface_mac) cur_xml = virsh.dumpxml(vm_name).stdout_text logging.debug(cur_xml) if 'bandwidth' in cur_xml: test.fail('bandwidth still in xml') if not check_filter_rules(iface_name, 0, expect_none=True): test.fail('There should be nothing in output') if update_device and loop: loop -= 1 if loop: # Rerun this procedure again with updated params # Reset params of the corresponding loop loop_prefix = 'loop' + str(loop) + '_' for k in {k: v for k, v in params.items() if k.startswith(loop_prefix)}: params[k.lstrip(loop_prefix)] = params[k] params['loop'] = str(loop) run(test, params, env) finally: # Recover VM. if vm.is_alive(): vm.destroy(gracefully=False) for vms in vms_list: virsh.remove_domain(vms.name, "--remove-all-storage") logging.info("Restoring network...") if net_name == "default": netxml_backup.sync() else: # Destroy and undefine new created network virsh.net_destroy(net_name) virsh.net_undefine(net_name) vmxml_backup.sync() if test_ipv6_address and original_accept_ra != '2': process.system(sysctl_cmd + "=%s" % original_accept_ra) if define_macvtap: cmd = "ip l del macvtap0; ip l del macvtap2; ip l del macvtap4" process.run(cmd, shell=True, verbose=True)
def run_virsh_update_device(test, params, env): """ Test command: virsh update-device. Update device from an XML <file>. 1.Prepare test environment.Make sure a cdrom exists in VM. If not, please attach one cdrom manually. 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) if vm.is_alive() and params.get("start_vm") == "no": vm.destroy() def create_attach_xml(update_xmlfile, source_iso): """ Create a xml file to update a device. @param: update_xmlfile : Temp xml saves device infomation. @param: source_iso : disk's source file. """ try: f = open(source_iso, 'wb') f.seek((1024 * 1024) - 1) f.write(str(0)) f.close() except IOError: raise error.TestFail("Create source_iso failed!") content = """ <disk device='cdrom' type='file'> <driver name='file'/> <source file='%s'/> <target bus='ide' dev='hdc'/> <readonly/> </disk> """ % source_iso xmlfile = open(update_xmlfile, 'w') xmlfile.write(content) xmlfile.close() def check_attach(source_file, output): """ Check attached device and disk exist or not. @param: source_file : disk's source file. @param: output :VM's xml infomation . """ dom = parseString(output) source = dom.getElementsByTagName("source") output2 = "" for n in source: output2 += n.getAttribute("file") target = dom.getElementsByTagName("target") output3 = "" for n in target: output3 += n.getAttribute("dev") dom.unlink source_iso = "%s" % source_file if not re.search(source_iso, output2): raise error.TestFail("didn't see 'attached disk") if not re.search('hdc', output3): raise error.TestFail("didn't see 'attached device") domid = vm.get_id() domuuid = vm.get_uuid() # Prepare tmp directory and files. tmp_iso = os.path.join(test.virtdir, "tmp.iso") tmp2_iso = os.path.join(test.virtdir, "tmp2.iso") update_xmlfile = os.path.join(test.tmpdir, "xml_file") # Get all parameters for configuration. flag = params.get("updatedevice_flag", "") twice = "yes" == params.get("updatedevice_twice", "no") diff_iso = params.get("updatedevice_diff_iso", "no") vm_ref = params.get("updatedevice_vm_ref", "") status_error = params.get("status_error", "no") extra = params.get("updatedevice_extra", "") create_attach_xml(update_xmlfile, tmp_iso) vm_xml = os.path.join(test.tmpdir, "vm_xml") virsh.dumpxml(vm_name, extra="", to_file=vm_xml) vmxml_before = libvirt_xml.VMXML.new_from_dumpxml(vm_name) if vm_ref == "id": vm_ref = domid if twice: virsh.update_device(domainarg=domid, filearg=update_xmlfile, ignore_status=True) if diff_iso == "yes": os.remove(update_xmlfile) create_attach_xml(update_xmlfile, tmp2_iso) elif vm_ref == "uuid": vm_ref = domuuid 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) status = virsh.update_device(domainarg=vm_ref, filearg=update_xmlfile, flagstr=flag, ignore_status=True, debug=True).exit_status output = "%s" % libvirt_xml.VMXML.new_from_dumpxml(vm_name) if params.has_key("updatedevice_diff_file"): vm_xml_after = os.path.join(test.tmpdir, "vm_xml_after") virsh.dumpxml(vm_name, extra="", to_file=vm_xml_after) vm.destroy() output_shut = "%s" % libvirt_xml.VMXML.new_from_dumpxml(vm_name) # Recover environment vm.undefine() vmxml_before.define() if os.path.exists(tmp_iso): os.remove(tmp_iso) if os.path.exists(tmp2_iso): os.remove(tmp2_iso) # Check status_error flag_list = flag.split("--") for item in flag_list: option = item.strip() if option == "": continue if virsh.has_command_help_match("update-device", option) == None: status_error = "yes" break if status_error == "yes": if status == 0: raise error.TestFail("Run successfully with wrong command!") elif status_error == "no": if status != 0: raise error.TestFail("Run failed with right command") else: if flag == "--persistent" or flag == "--config": if not re.search(tmp_iso, output_shut): raise error.TestFail("virsh update-device function invalid" "didn't see 'attached device' in XML") else: if params.has_key("updatedevice_diff_file"): context_before = file(vm_xml, 'r').read().splitlines() context_after = file(vm_xml_after, 'r').read().splitlines() output_diff = difflib.Differ().compare(context_before, context_after) if not re.search(tmp_iso, "\n".join(list(output_diff))): raise error.TestFail("virsh update-device function " "invalid; can't see 'attached device'in before/after") else: if re.search(tmp_iso, output_shut): raise error.TestFail("virsh attach-device without " "--persistent/--config function invalid;can see " "'attached device'in XML") if diff_iso == "yes": check_attach(tmp2_iso, output) if vm_ref == "name": check_attach(tmp_iso, output)
def run(test, params, env): """ Test virsh nwfilter-binding-list 1)Prepare parameters 2)Run nwfilter_binding_list command 3)check result 4)Clean env """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) new_filter_1 = params.get("newfilter_1") new_filter_2 = params.get("newfilter_2") vmxml_backup = libvirt_xml.vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) new_net0_xml = os.path.join(data_dir.get_tmp_dir(), "new_net0.xml") new_net1_xml = os.path.join(data_dir.get_tmp_dir(), "new_net1.xml") option = params.get("option") status_error = "yes" == params.get("status_error") alias_name = params.get("alias_name") new_filter_name = params.get("new_filter_name") source_network = params.get("source_network") # prepare vm filterrfer parameters dict list filter_param_list_1 = [] params_key_1 = [] filter_param_list_2 = [] params_key_2 = [] for i in params.keys(): if 'parameters_name_' in i: params_key_1.append(i) params_key_1.sort() for i in range(len(params_key_1)): params_dict = {} params_dict['name'] = params[params_key_1[i]] params_dict['value'] = params['parameters_value_%s' % i] filter_param_list_1.append(params_dict) filterref_dict_1 = {} filterref_dict_1['name'] = new_filter_1 filterref_dict_1['parameters'] = filter_param_list_1 for i in params.keys(): if 'parameters_dhcp_' in i: params_key_2.append(i) params_key_2.sort() for i in range(len(params_key_2)): params_dict = {} params_dict['name'] = params[params_key_2[i]] params_dict['value'] = params['dhcp_value_%s' % i] filter_param_list_2.append(params_dict) filterref_dict_2 = {} filterref_dict_2['name'] = new_filter_2 filterref_dict_2['parameters'] = filter_param_list_2 def set_env(): """ set two interface with different network filter and change interface type """ # Add enough PCI to attach interface libvirt_pcicontr.reset_pci_num(vm_name) virsh.attach_interface(vm_name, option, debug=True) vmxml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) logging.debug("Guest xml is {}".format(vmxml)) devices = vmxml.get_devices('interface') iface_xml = devices[0] iface_xml_2 = devices[1] vmxml.del_device(iface_xml) vmxml.del_device(iface_xml_2) new_iface_1 = interface.Interface('network') new_iface_2 = interface.Interface('network') new_iface_1.xml = iface_xml.xml new_iface_2.xml = iface_xml_2.xml new_iface_1.type_name = "network" new_iface_2.type_name = "network" new_iface_1.source = {'network': source_network} new_iface_2.source = {'network': source_network} new_iface_1.target = {'dev': 'new_net0'} new_iface_2.target = {'dev': 'new_net1'} new_filterref = new_iface_1.new_filterref(**filterref_dict_1) new_iface_1.filterref = new_filterref new_filterref = new_iface_2.new_filterref(**filterref_dict_2) new_iface_2.filterref = new_filterref logging.debug("new interface xml is: %s \n %s" % (new_iface_1, new_iface_2)) vmxml.add_device(new_iface_1) vmxml.add_device(new_iface_2) vmxml.sync() return new_iface_1, new_iface_2 try: new_iface_1, new_iface_2 = set_env() # start vm virsh.start(vm_name, debug=True) # list binding port dev ret = virsh.nwfilter_binding_list(debug=True) utlv.check_exit_status(ret, status_error) virsh.nwfilter_binding_dumpxml(new_iface_1.target['dev'], to_file=new_net0_xml, debug=True) virsh.nwfilter_binding_dumpxml(new_iface_2.target['dev'], to_file=new_net1_xml, debug=True) # check dump filterbinding can pass xml validate new_net0_cmd = "virt-xml-validate %s" % new_net0_xml new_net1_cmd = "virt-xml-validate %s" % new_net1_xml valid_0 = process.run(new_net0_cmd, ignore_status=True, shell=True).exit_status valid_1 = process.run(new_net1_cmd, ignore_status=True, shell=True).exit_status if valid_0 or valid_1: test.fail("the xml can not validate successfully") # create new xml and update device newnet_iface = interface.Interface('network') newnet_iface.xml = new_iface_1.xml filterref_list = [] filterref_dict = {} filterref_dict['name'] = new_filter_name filterref_dict['parameters'] = filterref_list newnet_iface.alias = {'name': alias_name} newnet_iface.filterref = newnet_iface.new_filterref(**filterref_dict) ret = virsh.update_device(domainarg=vm_name, filearg=newnet_iface.xml, debug=True) utlv.check_exit_status(ret, status_error) ret_list = virsh.nwfilter_binding_list(debug=True) utlv.check_result(ret_list, expected_match="new_net1") ret_dump = virsh.nwfilter_binding_dumpxml('new_net0', debug=True) utlv.check_result(ret_dump, expected_match=new_filter_name) finally: if vm.is_alive(): vm.destroy(gracefully=False) vmxml_backup.sync()
def run(test, params, env): """ Test attach cdrom device with option. 1.Prepare test environment,destroy or suspend a VM. 2.Prepare test xml for cdrom devices. 3.Perform test operation. 4.Recover test environment. 5.Confirm the test result. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) virsh_dargs = {'debug': True, 'ignore_status': True} # Disk specific attributes. image_path = params.get("virt_disk_device_source", "/var/lib/libvirt/images/test.img") scenario_execution = params.get("scenario_execution") status_error = "yes" == params.get("status_error") define_error = "yes" == params.get("define_error", "no") device_obj = None # Back up xml file. if vm.is_alive(): vm.destroy(gracefully=False) vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) # Create disk xml with slice attribute device_obj = create_customized_disk(params) vmxml.add_device(device_obj) vmxml.sync() vm.start() vm.wait_for_login().close() except virt_vm.VMStartError as e: if status_error: LOG.debug("VM failed to start as expected." "Error: %s", str(e)) else: test.fail("VM failed to start." "Error: %s" % str(e)) except xcepts.LibvirtXMLError as xml_error: if not define_error: test.fail("Failed to define VM:\n%s" % xml_error) else: LOG.info("As expected, failed to define VM") except Exception as ex: test.fail("unexpected exception happen: %s" % str(ex)) else: if scenario_execution == "slice_hot_operate": # Need detach slice disk, then attach it again virsh.detach_device(vm_name, device_obj.xml, flagstr="--live", ignore_status=False, debug=True) vm.wait_for_login().close() virsh.attach_device(vm_name, device_obj.xml, flagstr="--live", ignore_status=False, debug=True) check_slice_hot_operate(vm, params, test) elif scenario_execution == "slice_cdrom_update": # Empty cdrom device empty_cdrom = create_empty_cdrom_xml(params) virsh.update_device(vm_name, empty_cdrom.xml, flagstr="--live", ignore_status=False, debug=True) vm.wait_for_login().close() virsh.update_device(vm_name, device_obj.xml, flagstr="--live", ignore_status=False, debug=True) check_slice_cdrom_update(vm, test) elif scenario_execution == "slice_disk_blockcommit": check_slice_disk_blockcommit(vm, params) elif scenario_execution == "slice_disk_blockcopy": check_slice_disk_blockcopy(vm, params) elif scenario_execution == "slice_blkdeviotune": check_slice_blkdeviotune(vm, params, test) finally: libvirt_disk.cleanup_snapshots(vm) # Recover VM. if vm.is_alive(): vm.destroy(gracefully=False) LOG.info("Restoring vm...") vmxml_backup.sync() # Clean up images for file_path in cleanup_files: if os.path.exists(file_path): os.remove(file_path)
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 modify_iface_xml(update, status_error=False): """ Modify interface xml options """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) xml_devices = vmxml.devices iface_index = xml_devices.index( xml_devices.by_device_tag("interface")[0]) iface = xml_devices[iface_index] if iface_model: iface.model = iface_model else: del iface.model if iface_type: iface.type_name = iface_type source = eval(iface_source) if iface_source: iface.source = source else: del iface.source driver_dict = {} driver_host = {} driver_guest = {} if iface_driver: driver_dict = eval(iface_driver) if iface_driver_host: driver_host = eval(iface_driver_host) if iface_driver_guest: driver_guest = eval(iface_driver_guest) iface.driver = iface.new_driver(driver_attr=driver_dict, driver_host=driver_host, driver_guest=driver_guest) if iface.address: del iface.address logging.debug("New interface xml file: %s", iface) if unprivileged_user: # Create disk image for unprivileged user disk_index = xml_devices.index( xml_devices.by_device_tag("disk")[0]) disk_xml = xml_devices[disk_index] logging.debug("source: %s", disk_xml.source) disk_source = disk_xml.source.attrs["file"] cmd = ("cp -f %s %s && chmod a+rw %s" % (disk_source, dst_disk, dst_disk)) utils.run(cmd) disk_xml.source = disk_xml.new_disk_source( attrs={"file": dst_disk}) vmxml.devices = xml_devices # Remove all channels to avoid of permission problem channels = vmxml.get_devices(device_type="channel") for channel in channels: vmxml.del_device(channel) vmxml.xmltreefile.write() logging.debug("New VM xml: %s", vmxml) utils.run("chmod a+rw %s" % vmxml.xml) virsh.define(vmxml.xml, **virsh_dargs) # Try to modify interface xml by update-device or edit xml elif update: iface.xmltreefile.write() ret = virsh.update_device(vm_name, iface.xml, ignore_status=True) libvirt.check_exit_status(ret, status_error) else: vmxml.devices = xml_devices vmxml.xmltreefile.write() vmxml.sync()
def run_virsh_update_device(test, params, env): """ Test command: virsh update-device. Update device from an XML <file>. 1.Prepare test environment.Make sure a cdrom exists in VM. If not, please attach one cdrom manually. 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) if vm.is_alive() and params.get("start_vm") == "no": vm.destroy() def create_attach_xml(update_xmlfile, source_iso): """ Create a xml file to update a device. :param update_xmlfile : Temp xml saves device information. :param source_iso : disk's source file. """ try: f = open(source_iso, 'wb') f.seek((1024 * 1024) - 1) f.write(str(0)) f.close() except IOError: raise error.TestFail("Create source_iso failed!") content = """ <disk device='cdrom' type='file'> <driver name='file'/> <source file='%s'/> <target bus='ide' dev='hdc'/> <readonly/> </disk> """ % source_iso xmlfile = open(update_xmlfile, 'w') xmlfile.write(content) xmlfile.close() def check_attach(source_file, output): """ Check attached device and disk exist or not. :param source_file : disk's source file. :param output :VM's xml information . """ dom = parseString(output) source = dom.getElementsByTagName("source") output2 = "" for n in source: output2 += n.getAttribute("file") target = dom.getElementsByTagName("target") output3 = "" for n in target: output3 += n.getAttribute("dev") dom.unlink source_iso = "%s" % source_file if not re.search(source_iso, output2): raise error.TestFail("didn't see 'attached disk") if not re.search('hdc', output3): raise error.TestFail("didn't see 'attached device") domid = vm.get_id() domuuid = vm.get_uuid() # Prepare tmp directory and files. tmp_iso = os.path.join(test.virtdir, "tmp.iso") tmp2_iso = os.path.join(test.virtdir, "tmp2.iso") update_xmlfile = os.path.join(test.tmpdir, "xml_file") # Get all parameters for configuration. flag = params.get("updatedevice_flag", "") twice = "yes" == params.get("updatedevice_twice", "no") diff_iso = params.get("updatedevice_diff_iso", "no") vm_ref = params.get("updatedevice_vm_ref", "") status_error = params.get("status_error", "no") extra = params.get("updatedevice_extra", "") create_attach_xml(update_xmlfile, tmp_iso) vm_xml = os.path.join(test.tmpdir, "vm_xml") virsh.dumpxml(vm_name, extra="", to_file=vm_xml) vmxml_before = libvirt_xml.VMXML.new_from_dumpxml(vm_name) if vm_ref == "id": vm_ref = domid if twice: virsh.update_device(domainarg=domid, filearg=update_xmlfile, ignore_status=True) if diff_iso == "yes": os.remove(update_xmlfile) create_attach_xml(update_xmlfile, tmp2_iso) elif vm_ref == "uuid": vm_ref = domuuid 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) status = virsh.update_device(domainarg=vm_ref, filearg=update_xmlfile, flagstr=flag, ignore_status=True, debug=True).exit_status output = "%s" % libvirt_xml.VMXML.new_from_dumpxml(vm_name) if params.has_key("updatedevice_diff_file"): vm_xml_after = os.path.join(test.tmpdir, "vm_xml_after") virsh.dumpxml(vm_name, extra="", to_file=vm_xml_after) vm.destroy() output_shut = "%s" % libvirt_xml.VMXML.new_from_dumpxml(vm_name) # Recover environment vm.undefine() vmxml_before.define() if os.path.exists(tmp_iso): os.remove(tmp_iso) if os.path.exists(tmp2_iso): os.remove(tmp2_iso) # Check status_error flag_list = flag.split("--") for item in flag_list: option = item.strip() if option == "": continue if virsh.has_command_help_match("update-device", option) is None: status_error = "yes" break if status_error == "yes": if status == 0: raise error.TestFail("Run successfully with wrong command!") elif status_error == "no": if status != 0: raise error.TestFail("Run failed with right command") else: if flag == "--persistent" or flag == "--config": if not re.search(tmp_iso, output_shut): raise error.TestFail("virsh update-device function invalid" "didn't see 'attached device' in XML") else: if params.has_key("updatedevice_diff_file"): context_before = file(vm_xml, 'r').read().splitlines() context_after = file(vm_xml_after, 'r').read().splitlines() output_diff = difflib.Differ().compare( context_before, context_after) if not re.search(tmp_iso, "\n".join(list(output_diff))): raise error.TestFail( "virsh update-device function " "invalid; can't see 'attached device'in before/after" ) else: if re.search(tmp_iso, output_shut): raise error.TestFail( "virsh attach-device without " "--persistent/--config function invalid;can see " "'attached device'in XML") if diff_iso == "yes": check_attach(tmp2_iso, output) if vm_ref == "name": check_attach(tmp_iso, output)
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 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 = 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 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)