def edit_iface(vm_name): """ Modify vm's interface information by virsh edit command. """ iface_type = params.get("iface_type") iface_model = params.get("iface_model") edit_error = "yes" == params.get("edit_error", "no") if iface_type: edit_cmd = (r":%s /<interface type=.*>/<interface type='{0}'>/" "".format(iface_type)) status = libvirt.exec_virsh_edit(vm_name, [edit_cmd]) elif iface_model: edit_cmd = (r":/<interface/,/<\/interface>/s/<model type=.*\/>/" "<model type='%s'\/>/" % iface_model) status = libvirt.exec_virsh_edit(vm_name, [edit_cmd]) if not status and not edit_error: logging.error("Expect success, but failure") return False if edit_error and status: logging.error("Expect error, but success") return False # Destroy domain and start it to check if vm can be started start_error = "yes" == params.get("start_error", "no") vm.destroy() ret = virsh.start(vm_name, ignore_status=True) if start_error and not ret.exit_status: logging.error("Vm started unexpectedly") return False if not start_error and ret.exit_status: logging.error("Vm failed to start") return False return True
def edit_vcpu(source): """ Modify vm's cpu information by virsh edit command. :param source : virsh edit's option. :return: True if edit successed,False if edit failed. """ vcpucount_result = virsh.vcpucount(vm_name, options="--config --maximum") if vcpucount_result.exit_status: # Fail back to libvirt_xml way to test vcpucount. original_vcpu = str(vmxml.vcpu) else: original_vcpu = vcpucount_result.stdout.strip() expected_vcpu = str(int(original_vcpu) + 1) if not status_error == "yes": # check if topology is defined and change vcpu accordingly try: vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(source) topology = vmxml_backup.get_cpu_topology() sockets = str(int(topology['sockets']) + 1) cores = topology['cores'] threads = topology['threads'] vmcpu_xml = vm_xml.VMCPUXML() vmcpu_xml['topology'] = { 'sockets': sockets, 'cores': cores, 'threads': threads } vmxml_backup['cpu'] = vmcpu_xml vmxml_backup.sync() expected_vcpu = str(int(sockets) * int(cores) * int(threads)) except: expected_vcpu = str(int(original_vcpu) + 1) dic_mode = { "edit": r":%s /[0-9]*<\/vcpu>/" + expected_vcpu + r"<\/vcpu>", "recover": r":%s /[0-9]*<\/vcpu>/" + original_vcpu + r"<\/vcpu>" } status = libvirt.exec_virsh_edit(source, [dic_mode["edit"]]) logging.info(status) if not status: vmxml.sync() return status if libvirtd_stat == "off": return False if params.get("paused_after_start_vm") == "yes": virsh.resume(vm_name, ignore_status=True) virsh.destroy(vm_name) elif params.get("start_vm") == "yes": virsh.destroy(vm_name) new_vcpus = str(vm_xml.VMXML.new_from_inactive_dumpxml(vm_name).vcpu) # Recover cpuinfo # Use name rather than source, since source could be domid status = libvirt.exec_virsh_edit(vm_name, [dic_mode["recover"]]) vmxml.sync() if status and new_vcpus != expected_vcpu: return False return status
def edit_vcpu(source): """ Modify vm's cpu information by virsh edit command. :param source : virsh edit's option. :return: True if edit successed,False if edit failed. """ vcpucount_result = virsh.vcpucount(vm_name, options="--config --maximum") if vcpucount_result.exit_status: # Fail back to libvirt_xml way to test vcpucount. original_vcpu = str(vmxml.vcpu) else: original_vcpu = vcpucount_result.stdout.strip() expected_vcpu = str(int(original_vcpu) + 1) if not status_error == "yes": # check if topology is defined and change vcpu accordingly try: vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(source) topology = vmxml_backup.get_cpu_topology() sockets = str(int(topology['sockets']) + 1) cores = topology['cores'] threads = topology['threads'] vmcpu_xml = vm_xml.VMCPUXML() vmcpu_xml['topology'] = {'sockets': sockets, 'cores': cores, 'threads': threads} vmxml_backup['cpu'] = vmcpu_xml vmxml_backup.sync() expected_vcpu = str(int(sockets) * int(cores) * int(threads)) except: expected_vcpu = str(int(original_vcpu) + 1) dic_mode = { "edit": r":%s /[0-9]*<\/vcpu>/" + expected_vcpu + r"<\/vcpu>", "recover": r":%s /[0-9]*<\/vcpu>/" + original_vcpu + r"<\/vcpu>"} status = libvirt.exec_virsh_edit(source, [dic_mode["edit"]]) logging.info(status) if not status: vmxml.sync() return status if libvirtd_stat == "off": return False if params.get("paused_after_start_vm") == "yes": virsh.resume(vm_name, ignore_status=True) virsh.destroy(vm_name) elif params.get("start_vm") == "yes": virsh.destroy(vm_name) new_vcpus = str(vm_xml.VMXML.new_from_inactive_dumpxml(vm_name).vcpu) # Recover cpuinfo # Use name rather than source, since source could be domid status = libvirt.exec_virsh_edit(vm_name, [dic_mode["recover"]]) vmxml.sync() if status and new_vcpus != expected_vcpu: return False return status
def add_video_device(video_model, domain_xml, is_primary=None, status_error=False, **kwargs): """ add the video device xml snippet, then sync the guest xml """ video_dev = Video() video_dev.model_type = video_model if is_primary: video_dev.primary = "yes" for key, value in list(iteritems(kwargs)): setattr(video_dev, key, value) domain_xml.add_device(video_dev) try: # Take relevant line only from the XML (without header) video_xml_string = str(video_dev).split('\n')[-1] # Prepare a string for VI to replace with it using virsh edit utility replace_string = r":%s:<video>\_.\{-}</video>:"+video_xml_string+":" status = libvirt.exec_virsh_edit(vm_name, [replace_string]) if status: domain_xml.sync() else: # Raise exception which is handled right after in except block. raise Exception('Virsh edit has failed, but that is ' 'intentional in negative cases.') except Exception as error: logging.debug(error) if not status_error: test.fail("Failed to define the guest after adding the %s video " "device xml. Details: %s " % (video_model, error)) logging.debug("This is the expected failing in negative cases.") else: if status_error: test.fail("xml sync should failed as it is a negative case.") logging.debug("Add devices succeed in positive case.")
def run(test, params, env): """ Test numa node memory binding with automatic numa placement """ logging.debug("The test has been started.") vm_name = params.get("main_vm") backup_xml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) replace_string = params.get("replace_string", '') host_numa_node = utils_misc.NumaInfo() node_list = host_numa_node.online_nodes_withmem if len(node_list) < 2: test.cancel("The host only has {} numa node, but 2 is " "required at least".format(len(node_list))) try: prepare_vm(vm_name, node_list) status = libvirt.exec_virsh_edit(vm_name, [replace_string]) if status: test.fail( 'Failure expected during virsh edit, but no failure occurs.') else: logging.info( 'Virsh edit has failed, but that is intentional in ' 'negative cases.') except Exception as e: test.error("Unexpected error happened during the test execution: {}" .format(e)) finally: backup_xml.sync()
def modify_rng_xml(dparams, sync=True, get_xml=False): """ Modify interface xml options :params dparams: parameters for organize xml :params sync: whether sync to domain xml, if get_xml is True, then sync will not take effect :params get_xml: whether get device xml :return: if get_xml=True, return xml file """ rng_model = dparams.get("rng_model", "virtio") rng_rate = dparams.get("rng_rate") backend_model = dparams.get("backend_model", "random") backend_type = dparams.get("backend_type") backend_dev = dparams.get("backend_dev", "") backend_source_list = dparams.get("backend_source", "").split() backend_protocol = dparams.get("backend_protocol") rng_alias = dparams.get("rng_alias") vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) rng_xml = rng.Rng() rng_xml.rng_model = rng_model if rng_rate: rng_xml.rate = ast.literal_eval(rng_rate) backend = rng.Rng.Backend() backend.backend_model = backend_model if backend_type: backend.backend_type = backend_type if backend_dev: backend.backend_dev = backend_dev if backend_source_list: source_list = [ast.literal_eval(source) for source in backend_source_list] backend.source = source_list if backend_protocol: backend.backend_protocol = backend_protocol rng_xml.backend = backend if detach_alias: rng_xml.alias = dict(name=rng_alias) if with_packed: rng_xml.driver = dict(packed=driver_packed) logging.debug("Rng xml: %s", rng_xml) if get_xml: return rng_xml if sync: vmxml.add_device(rng_xml) vmxml.xmltreefile.write() vmxml.sync() else: status = libvirt.exec_virsh_edit( vm_name, [(r":/<devices>/s/$/%s" % re.findall(r"<rng.*<\/rng>", str(rng_xml), re.M )[0].replace("/", "\/"))]) if not status: test.fail("Failed to edit vm xml")
def enable_secure_boot(vm, vmxml, test, **kwargs): """ Enroll Uefi secure key and set to boot from hd :param vm: The instance of VM Guest :param vmxml: The instance of VMXML class :param test: Avocado test object :param kwargs: Key words to setup boot from Uefi.iso """ uefi_iso = kwargs.get("uefi_iso", "") uefi_target_dev = kwargs.get("uefi_target_dev", "") uefi_device_bus = kwargs.get("uefi_device_bus", "") custom_codes = kwargs.get("uefi_custom_codes", "") dict_os_attrs = {} # Enable smm=on for secure boot logging.debug("Set smm=on in VMFeaturesXML") features_xml = vmxml.features features_xml.smm = "on" vmxml.features = features_xml # Add cdrom device with Uefi.iso add_cdrom_device(vmxml, uefi_iso, uefi_target_dev, uefi_device_bus) vmxml.remove_all_boots() dict_os_attrs.update({"boots": ["cdrom"]}) dict_os_attrs.update({"secure": "yes"}) vmxml.set_os_attrs(**dict_os_attrs) logging.debug("Enable secure boot mode:\n%s", open(vmxml.xml).read()) # Enroll key in Uefi shell vmxml.undefine() if vmxml.define(): if vm.is_dead(): vm.start() console_session = vm.wait_for_serial_login(timeout=240) set_secure_key(console_session, custom_codes, test) console_session.close() else: test.fail("Failed to define %s from %s" % (vm.name, vmxml.xml)) # Change OS boot to hd device edit_cmd = [] edit_cmd.append(":%s/boot dev=\'cdrom/boot dev=\'hd") utlv.exec_virsh_edit(vm.name, edit_cmd)
def edit_vcpu(source): """ Modify vm's cpu information by virsh edit command. :param source : virsh edit's option. :return: True if edit successed,False if edit failed. """ vcpucount_result = virsh.vcpucount(vm_name, options="--config --maximum") if vcpucount_result.exit_status: # Fail back to libvirt_xml way to test vcpucount. original_vcpu = str(vmxml.vcpu) else: original_vcpu = vcpucount_result.stdout.strip() expected_vcpu = str(int(original_vcpu) + 1) dic_mode = { "edit": r":%s /[0-9]*<\/vcpu>/" + expected_vcpu + r"<\/vcpu>", "recover": r":%s /[0-9]*<\/vcpu>/" + original_vcpu + r"<\/vcpu>" } status = libvirt.exec_virsh_edit(source, [dic_mode["edit"]]) logging.info(status) if not status: return status if libvirtd_stat == "off": return False if params.get("paused_after_start_vm") == "yes": virsh.resume(vm_name, ignore_status=True) virsh.destroy(vm_name) elif params.get("start_vm") == "yes": virsh.destroy(vm_name) new_vcpus = str(vm_xml.VMXML.new_from_inactive_dumpxml(vm_name).vcpu) # Recover cpuinfo # Use name rather than source, since source could be domid status = libvirt.exec_virsh_edit(vm_name, [dic_mode["recover"]]) if status and new_vcpus != expected_vcpu: return False return status
def edit_vcpu(source): """ Modify vm's cpu information by virsh edit command. :param source : virsh edit's option. :return: True if edit successed,False if edit failed. """ vcpucount_result = virsh.vcpucount(vm_name, options="--config --maximum") if vcpucount_result.exit_status: # Fail back to libvirt_xml way to test vcpucount. original_vcpu = str(vmxml.vcpu) else: original_vcpu = vcpucount_result.stdout.strip() expected_vcpu = str(int(original_vcpu) + 1) dic_mode = { "edit": r":%s /[0-9]*<\/vcpu>/" + expected_vcpu + r"<\/vcpu>", "recover": r":%s /[0-9]*<\/vcpu>/" + original_vcpu + r"<\/vcpu>"} status = libvirt.exec_virsh_edit(source, [dic_mode["edit"]]) logging.info(status) if not status: return status if libvirtd_stat == "off": return False if params.get("paused_after_start_vm") == "yes": virsh.resume(vm_name, ignore_status=True) virsh.destroy(vm_name) elif params.get("start_vm") == "yes": virsh.destroy(vm_name) new_vcpus = str(vm_xml.VMXML.new_from_inactive_dumpxml(vm_name).vcpu) # Recover cpuinfo # Use name rather than source, since source could be domid status = libvirt.exec_virsh_edit(vm_name, [dic_mode["recover"]]) if status and new_vcpus != expected_vcpu: return False return status
def edit_vm(vm_name, test): """ Edit the running VM using the virsh edit feature and the VI editor and verify the status. Command failure is expected behavior. :param vm_name: The name of the VM to edit :param test: Avocado test object """ replace_string = r":%s:memAccess='shared':memAccess='invalid':" status = libvirt.exec_virsh_edit(vm_name, [replace_string]) if status: test.fail('Failure expected during virsh edit, but no failure occurs.') else: logging.info('Virsh edit has failed, but that is intentional in ' 'negative cases.')
def modify_rng_xml(dparams, sync=True): """ Modify interface xml options """ rng_model = dparams.get("rng_model", "virtio") rng_rate = dparams.get("rng_rate") backend_model = dparams.get("backend_model", "random") backend_type = dparams.get("backend_type") backend_dev = dparams.get("backend_dev", "") backend_source_list = dparams.get("backend_source", "").split() backend_protocol = dparams.get("backend_protocol") vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) rng_xml = rng.Rng() rng_xml.rng_model = rng_model if rng_rate: rng_xml.rate = ast.literal_eval(rng_rate) backend = rng.Rng.Backend() backend.backend_model = backend_model if backend_type: backend.backend_type = backend_type if backend_dev: backend.backend_dev = backend_dev if backend_source_list: source_list = [ast.literal_eval(source) for source in backend_source_list] backend.source = source_list if backend_protocol: backend.backend_protocol = backend_protocol rng_xml.backend = backend logging.debug("Rng xml: %s", rng_xml) if sync: vmxml.add_device(rng_xml) vmxml.xmltreefile.write() vmxml.sync() else: status = libvirt.exec_virsh_edit( vm_name, [(r":/<devices>/s/$/%s" % re.findall(r"<rng.*<\/rng>", str(rng_xml), re.M )[0].replace("/", "\/"))]) if not status: test.fail("Failed to edit vm xml")
def edit_rng(vm_name): """ Modify rng device in xml. """ rng_model = params.get("rng_model") rng_backend = params.get("rng_backend") backend_model = params.get("backend_model") backend_type = params.get("backend_type") edit_error = "yes" == params.get("edit_error", "no") edit_cmd = [] del_cmd = r":g/<rng.*<\/rng>/d" edit_cmd.append(del_cmd) if backend_type: bc_type = "type='%s'" % backend_type else: bc_type = "" update_cmd = (r":/<devices>/s/$/<rng model='%s'>" "<backend model='%s' %s>%s<\/backend><\/rng>" % (rng_model, backend_model, bc_type, rng_backend)) edit_cmd.append(update_cmd) status = libvirt.exec_virsh_edit(vm_name, edit_cmd) vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) if not libvirtd.is_running(): logging.error("libvirtd isn't running") return False if not status and not edit_error: logging.error("Expect success, but failure") return False if edit_error and status: logging.error("Expect error, but success") return False # Destroy domain and start it to check if vm can be started start_error = "yes" == params.get("start_error", "no") vm.destroy() ret = virsh.start(vm_name, ignore_status=True) if start_error and not ret.exit_status: logging.error("Vm started unexpectedly") return False if not start_error and ret.exit_status: logging.error("Vm failed to start") return False return True
def edit_memory(source): """ Modify vm's maximum and current memory(unit and value). :param source: virsh edit's option. :return: True if edit succeeded,False if edit failed. """ mem_unit = params.get("mem_unit", "K") mem_value = params.get("mem_value", "1048576") mem_delta = params.get("mem_delta", 1000) edit_cmd = [] del_cmd = r":g/currentMemory/d" edit_cmd.append(del_cmd) update_cmd = r":%s/<memory unit='KiB'>[0-9]*<\/memory>/<memory unit='" update_cmd += mem_unit + "'>" + mem_value + r"<\/memory>" edit_cmd.append(update_cmd) try: expected_mem = int( utils_misc.normalize_data_size(mem_value + mem_unit, 'K').split('.')[0]) except ValueError: logging.error("Fail to translate %s to KiB", mem_value + mem_unit) return False logging.debug("Expected max memory is %s", expected_mem) status = libvirt.exec_virsh_edit(source, edit_cmd) try: if status: # Restart vm to check memory value virsh.destroy(vm_name) virsh.start(vm_name) new_mem = vm.get_max_mem() if new_mem - expected_mem > int(mem_delta): logging.error("New max memory %s is not excepted", new_mem) return False except Exception as e: logging.error("Error occurred when check domain memory: %s", e) return False return status
def edit_memory(source): """ Modify vm's maximum and current memory(unit and value). :param source: virsh edit's option. :return: True if edit successed,False if edit failed. """ mem_unit = params.get("mem_unit", "K") mem_value = params.get("mem_value", "1048576") mem_delta = params.get("mem_delta", 1000) edit_cmd = [] del_cmd = r":g/currentMemory/d" edit_cmd.append(del_cmd) update_cmd = r":%s/<memory unit='KiB'>[0-9]*<\/memory>/<memory unit='" update_cmd += mem_unit + "'>" + mem_value + r"<\/memory>" edit_cmd.append(update_cmd) try: expected_mem = int(utils_misc.normalize_data_size( mem_value + mem_unit, 'K').split('.')[0]) except ValueError: logging.error("Fail to translate %s to KiB", mem_value + mem_unit) return False logging.debug("Expected max memory is %s", expected_mem) status = libvirt.exec_virsh_edit(source, edit_cmd) try: if status: # Restart vm to check memory value virsh.destroy(vm_name) virsh.start(vm_name) new_mem = vm.get_max_mem() if new_mem - expected_mem > int(mem_delta): logging.error("New max memory %s is not excepted", new_mem) return False except Exception as e: logging.error("Error occured when check domain memory: %s", e) return False return status
def run(test, params, env): """ Test numa node memory binding with automatic numa placement """ logging.debug("The test has been started.") vm_name = params.get("main_vm") backup_xml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) replace_string = params.get("replace_string", '') try: prepare_vm(vm_name, test) status = libvirt.exec_virsh_edit(vm_name, [replace_string]) if status: test.fail( 'Failure expected during virsh edit, but no failure occurs.') else: logging.info('Virsh edit has failed, but that is intentional in ' 'negative cases.') except Exception as e: test.error( "Unexpected error happened during the test execution: {}".format( e)) finally: backup_xml.sync()
def run(test, params, env): """ Test misc tests of virtual cpu features 1) check dumpxml after snapshot-create/revert 2) check vendor_id 3) check maximum vcpus with topology settings :param test: test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def update_cpu_xml(): """ Update cpu xml for test """ vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Create cpu xml for test if vmxml.xmltreefile.find('cpu'): cpu_xml = vmxml.cpu else: cpu_xml = vm_xml.VMCPUXML() if cpu_mode: cpu_xml.mode = cpu_mode if cpu_vendor_id: cpu_xml.vendor_id = cpu_vendor_id # Update vm's cpu vmxml.cpu = cpu_xml vmxml.sync() if vcpu_max: if with_topology: vm_xml.VMXML.set_vm_vcpus(vm_name, int(vcpu_max), cores=int(vcpu_max), sockets=1, threads=1, add_topology=with_topology, topology_correction=with_topology) else: vm_xml.VMXML.set_vm_vcpus(vm_name, int(vcpu_max)) def do_snapshot(vm_name, expected_str): """ Run snapshot related commands: snapshot-create-as, snapshot-list snapshot-dumpxml, snapshot-revert :param vm_name: vm name :param expected_str: expected string in snapshot-dumpxml :raise: test.fail if virsh command failed """ snapshot_name = vm_name + "-snap" virsh_dargs = {'debug': True} cmd_result = virsh.snapshot_create_as(vm_name, snapshot_name, **virsh_dargs) libvirt.check_exit_status(cmd_result) try: snapshots = virsh.snapshot_list(vm_name, **virsh_dargs) except process.CmdError: test.fail("Failed to get snapshots list for %s" % vm_name) if snapshot_name not in snapshots: test.fail("The snapshot '%s' was not in snapshot-list." % snapshot_name) cmd_result = virsh.snapshot_dumpxml(vm_name, snapshot_name, **virsh_dargs) libvirt.check_result(cmd_result, expected_match=expected_str) cmd_result = virsh.snapshot_revert(vm_name, "", "--current", **virsh_dargs) libvirt.check_exit_status(cmd_result) libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get('main_vm') vm = env.get_vm(vm_name) cpu_mode = params.get('cpu_mode') vcpu_max = params.get('vcpu_max') expected_str_before_startup = params.get("expected_str_before_startup") expected_str_after_startup = params.get("expected_str_after_startup") test_operations = params.get("test_operations") check_vendor_id = "yes" == params.get("check_vendor_id", "no") virsh_edit_cmd = params.get("virsh_edit_cmd") with_topology = "yes" == params.get("with_topology", "no") status_error = "yes" == params.get("status_error", "no") err_msg = params.get("err_msg") cpu_vendor_id = None expected_qemuline = None cmd_in_guest = params.get("cmd_in_guest") bkxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: if check_vendor_id: output = virsh.capabilities(debug=True) host_vendor = re.findall(r'<vendor>(\w+)<', output)[0] cpu_vendor_id = 'GenuineIntel' if host_vendor != "Intel": cpu_vendor_id = 'AuthenticAMD' logging.debug("Set cpu vendor_id to %s on this host.", cpu_vendor_id) expected_qemuline = "vendor=" + cpu_vendor_id cmd_in_guest = ("cat /proc/cpuinfo | grep vendor_id | grep {}". format(cpu_vendor_id)) # Update xml for test update_cpu_xml() vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) logging.debug("Pre-test xml is %s", vmxml.xmltreefile) if expected_str_before_startup: libvirt.check_dumpxml(vm, expected_str_before_startup) if test_operations: for action in test_operations.split(","): if action == "do_snapshot": do_snapshot(vm_name, expected_str_before_startup) if virsh_edit_cmd: status = libvirt.exec_virsh_edit(vm_name, virsh_edit_cmd.split(",")) if status == status_error: test.fail("Virsh edit got unexpected result.") # Check if vm could start successfully if not status_error: result = virsh.start(vm_name, debug=True) libvirt.check_exit_status(result) if expected_str_after_startup: libvirt.check_dumpxml(vm, expected_str_after_startup) if expected_qemuline: libvirt.check_qemu_cmd_line(expected_qemuline) if cmd_in_guest: vm_session = vm.wait_for_login() status, output = vm_session.cmd_status_output(cmd_in_guest) if status: vm_session.close() test.fail("Failed to run '{}' in vm with " "messages:\n{}".format(cmd_in_guest, output)) vm_session.close() if cpu_mode == 'maximum': check_vm_cpu_model(output.strip(), cmd_in_guest, test) finally: logging.debug("Recover test environment") if vm.is_alive(): vm.destroy() libvirt.clean_up_snapshots(vm_name, domxml=bkxml) bkxml.sync()
def run(test, params, env): """ Test vsock device: 1.Edit/start guest with vsock device. 2.Hotplug/hotunplug vsock device. 3.Coldplug/Coldunplug vsock device 4.Check if hotplugged vsock communicates. """ def remove_all_vsocks(vm, vmxml): """ Removes all vsock devices from current domain to avoid failures due to original domain definition which must have been backed up earlier for correct restore. :param vm: the current test domain :param vmxml: VMXML of the current test domain :return: None """ vmxml.remove_all_device_by_type('vsock') was_alive = vm.is_alive() vmxml.sync() if was_alive: vm.start() def env_setup(): """ 1. Install build dependency for nc-vsock both on guest and host. 2. Get nc-vsock code 3. Build nc-vsock on both guest and host. :return: None """ session = vm.wait_for_login() cmds = [ 'rpm -q lsof || yum -y install lsof', 'rpm -q git || yum -y install git', 'rpm -q make || yum -y install make', 'rpm -q gcc && yum -y reinstall gcc || yum -y install gcc', 'rm -rf %s' % NC_VSOCK_DIR, 'git clone %s %s' % (git_repo, NC_VSOCK_DIR), 'cd %s && make' % NC_VSOCK_DIR, ] for cmd in cmds: for where in ["guest", "host"]: session_arg = session if where == "guest" else None status, output = utils_misc.cmd_status_output( cmd, shell=True, timeout=CMD_TIMEOUT, session=session_arg) cancel_if_failed(cmd, status, output, where) session.close() def cancel_if_failed(cmd, status, output, where): """ Cancel test execution as soon as command failed reporting output :param cmd: Command that was executed :param status: Exit status of command :param output: Output of command :param where: "guest" or "host" :return: """ if status: test.cancel("Failed to run %s on %s output: %s" % (cmd, where, output)) def write_from_host_to_guest(): """ 1. Create file for stdin to nc-vsock 2. Invoke nc-vsock as client writing to guest cid :return msg: The message sent to the server """ msg = "message from client" process.run('echo %s > %s' % (msg, NC_VSOCK_CLI_TXT), shell=True) output = process.run( "%s %d %s < %s" % (NC_VSOCK_CMD, int(cid), VSOCK_PORT, NC_VSOCK_CLI_TXT), shell=True).stdout_text logging.debug(output) process.system_output('cat %s' % NC_VSOCK_CLI_TXT) return msg def wait_for_guest_to_receive(server): """ nc-vsock server finishes as soon as it received data. We report if it's still running. :param server: The started server instance accepting requests :return: Nothing """ server.join(5) if server.is_alive(): logging.debug("The server thread is still running in the guest.") def validate_data_transfer_by_vsock(): """ 1. Setup nc-vsock on host and guest 2. Start vsock server on guest (wait a bit) 3. Send message from host to guest using correct cid 4. Get received message from vsock server 5. Verify message was sent """ env_setup() session = vm.wait_for_login() def _start_vsock_server_in_guest(): """ Starts the nc-vsock server to listen on VSOCK_PORT in the guest. The server will stop as soon as it received message from host. :return: """ session.cmd("%s -l %s > %s" % (NC_VSOCK_CMD, VSOCK_PORT, NC_VSOCK_SRV_OUT)) server = Thread(target=_start_vsock_server_in_guest) server.start() time.sleep(5) sent_data = write_from_host_to_guest() wait_for_guest_to_receive(server) received_data = session.cmd_output('cat %s' % NC_VSOCK_SRV_OUT).strip() if not sent_data == received_data: test.fail("Data transfer error with vsock device\n" "Sent: '%s'\n" "Received:'%s'" % (sent_data, received_data)) session.close() def managedsave_restore(): """ Check that vm can be saved and restarted with current configuration """ result = virsh.managedsave(vm_name, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) result = virsh.start(vm_name) utils_test.libvirt.check_exit_status(result, expect_error=False) start_vm = params.get("start_vm", "no") vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(params["main_vm"]) auto_cid = params.get("auto_cid", "no") status_error = params.get("status_error", "no") == "yes" edit_xml = params.get("edit_xml", "no") == "yes" option = params.get("option", "") git_repo = params.get("git_repo", "") invalid_cid = params.get("invalid_cid", "no") == "yes" managedsave = params.get("managedsave", "no") == "yes" no_vsock = params.get("no_vsock", "no") == "yes" vsock_num = params.get("num") communication = params.get("communication", "no") == "yes" detach_device_alias = params.get("detach_device_alias", "no") == "yes" # Backup xml file vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() remove_all_vsocks(vm, vmxml) # Define vsock device xml vsock_dev = Vsock() vsock_dev.model_type = "virtio" if process.run("modprobe vhost_vsock").exit_status != 0: test.fail("Failed to load vhost_vsock module") if invalid_cid: cid = "-1" else: cid = random.randint(3, 10) vsock_dev.cid = {'auto': auto_cid, 'address': cid} vsock_dev.alias = {'name': 'ua-' + str(uuid.uuid1())} logging.debug(vsock_dev) if start_vm == "no" and vm.is_alive(): virsh.destroy() try: if edit_xml: edit_status1 = libvirt.exec_virsh_edit( vm_name, [(r":/<devices>/s/$/%s" % re.findall(r"<vsock.*<\/vsock>", str(vsock_dev), re.M)[0].replace("/", "\/"))]) edit_status2 = True if vsock_num == 2: edit_status2 = libvirt.exec_virsh_edit( vm_name, [(r":/<devices>/s/$/%s" % re.findall(r"<vsock.*<\/vsock>", str(vsock_dev), re.M)[0].replace("/", "\/"))]) logging.debug(vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)) if status_error: if edit_status1 or edit_status2: test.fail("virsh edit should fail\n") else: if not edit_status1: test.fail("Failed to edit vm xml with vsock device\n") else: result = virsh.start(vm_name, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) else: session = vm.wait_for_login() session.close() result = virsh.attach_device(vm_name, vsock_dev.xml, flagstr=option, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) if option == "--config": result = virsh.start(vm_name, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) logging.debug(vmxml) vsock_list = vmxml.devices.by_device_tag("vsock") cid = vsock_list[0].cid['address'] if 0 == len(vsock_list): test.fail("No vsock device found in live xml\n") if communication: validate_data_transfer_by_vsock() if managedsave and not no_vsock: managedsave_restore() def _detach_completed(): status = process.run("lsof /dev/vhost-vsock", ignore_status=True, shell=True).exit_status return status == 1 if detach_device_alias: result = virsh.detach_device_alias(vm.name, vsock_dev.alias['name'], ignore_status=False, debug=True, wait_for_event=True, event_timeout=20) else: result = virsh.detach_device(vm_name, vsock_dev.xml, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) utils_misc.wait_for(_detach_completed, timeout=20) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) vsock_list = vmxml.get_devices("vsock") if vsock_list: test.fail( "Still find vsock device in live xml after hotunplug\n") if managedsave and no_vsock: managedsave_restore() finally: if vm.is_alive(): vm.destroy(gracefully=False) backup_xml.sync()
def run(test, params, env): """ LXC container life cycle testing by virsh command """ uri = params.get("connect_uri", "lxc:///") vm_name = params.get("main_vm") dom_type = params.get("lxc_domtype", "lxc") vcpu = int(params.get("lxc_vcpu", 1)) max_mem = int(params.get("lxc_max_mem", 500000)) current_mem = int(params.get("lxc_current_mem", 500000)) os_type = params.get("lxc_ostype", "exe") os_arch = params.get("lxc_osarch", "x86_64") os_init = params.get("lxc_osinit", "/bin/sh") emulator_path = params.get("lxc_emulator", "/usr/libexec/libvirt_lxc") interface_type = params.get("lxc_interface_type", "network") net_name = params.get("lxc_net_name", "default") full_os = ("yes" == params.get("lxc_full_os", "no")) install_root = params.get("lxc_install_root", "/") fs_target = params.get("lxc_fs_target", "/") fs_accessmode = params.get("lxc_fs_accessmode", "passthrough") passwd = params.get("lxc_fs_passwd", "redhat") def generate_container_xml(): """ Generate container xml """ vmxml = vm_xml.VMXML(dom_type) vmxml.vm_name = vm_name vmxml.max_mem = max_mem vmxml.current_mem = current_mem vmxml.vcpu = vcpu # Generate os vm_os = vm_xml.VMOSXML() vm_os.type = os_type vm_os.arch = os_arch vm_os.init = os_init vmxml.os = vm_os # Generate emulator emulator = Emulator() emulator.path = emulator_path # Generate console console = Console() filesystem = Filesystem() filesystem.accessmode = fs_accessmode filesystem.source = {'dir': install_root} filesystem.target = {'dir': fs_target} # Add emulator and console in devices devices = vm_xml.VMXMLDevices() devices.append(emulator) devices.append(console) devices.append(filesystem) # Add network device network = Interface(type_name=interface_type) network.mac_address = utils_net.generate_mac_address_simple() network.source = {interface_type: net_name} devices.append(network) vmxml.set_devices(devices) return vmxml def check_state(expected_state): result = virsh.domstate(vm_name, uri=uri) utlv.check_exit_status(result) vm_state = result.stdout.strip() if vm_state == expected_state: logging.info("Get expected state: %s", vm_state) else: raise TestFail("Get unexpected state: %s", vm_state) virsh_args = {'uri': uri, 'debug': True} try: vmxml = generate_container_xml() with open(vmxml.xml, 'r') as f: logging.info("Container XML:\n%s", f.read()) if full_os: if not os.path.exists(install_root): os.mkdir(install_root) # Install core os under installroot cmd = "yum --releasever=/ --installroot=%s" % install_root cmd += " --nogpgcheck -y groupinstall core" process.run(cmd, shell=True) # Fix root login on console process.run("echo 'pts/0' >> %s/etc/securetty" % install_root, shell=True) for i in [ "session required pam_selinux.so close", "session required pam_selinux.so open", "session required pam_loginuid.so" ]: process.run('sed -i s/"%s\"/"#%s"/g %s/etc/pam.d/login' % (i, i, install_root), shell=True) # Fix root login for sshd process.run('sed -i s/"%s\"/"#%s"/g %s/etc/pam.d/sshd' % (i, i, install_root), shell=True) # Config basic network net_file = install_root + '/etc/sysconfig/network' with open(net_file, 'w') as f: f.write('NETWORKING=yes\nHOSTNAME=%s\n' % vm_name) net_script = install_root + '/etc/sysconfig/network-scripts/ifcfg-eth0' with open(net_script, 'w') as f: f.write('DEVICE=eth0\nBOOTPROTO=dhcp\nONBOOT=yes\n') # Set root password and enable sshd session = aexpect.ShellSession("chroot %s" % install_root) session.sendline('echo %s|passwd root --stdin' % passwd) session.sendline('chkconfig sshd on') session.close() # Create result = virsh.create(vmxml.xml, **virsh_args) utlv.check_exit_status(result) check_state('running') # Destroy result = virsh.destroy(vm_name, **virsh_args) utlv.check_exit_status(result) if not virsh.domain_exists(vm_name, **virsh_args): logging.info("Destroy transient LXC domain successfully") else: raise TestFail("Transient LXC domain still exist after destroy") # Define result = virsh.define(vmxml.xml, **virsh_args) utlv.check_exit_status(result) check_state('shut off') # List result = virsh.dom_list('--inactive', **virsh_args) utlv.check_exit_status(result) if re.findall("(%s)\s+shut off" % vm_name, result.stdout): logging.info("Find %s in virsh list output", vm_name) else: raise TestFail("Not find %s in virsh list output") # Dumpxml result = virsh.dumpxml(vm_name, uri=uri, debug=False) utlv.check_exit_status(result) # Edit edit_vcpu = '2' logging.info("Change vcpu of LXC container to %s", edit_vcpu) edit_cmd = [r":%s /[0-9]*<\/vcpu>/" + edit_vcpu + r"<\/vcpu>"] if not utlv.exec_virsh_edit(vm_name, edit_cmd, connect_uri=uri): raise TestFail("Run edit command fail") else: result = virsh.dumpxml(vm_name, **virsh_args) new_vcpu = re.search(r'(\d*)</vcpu>', result.stdout).group(1) if new_vcpu == edit_vcpu: logging.info("vcpu number is expected after do edit") else: raise TestFail("vcpu number is unexpected after do edit") # Start result = virsh.start(vm_name, **virsh_args) utlv.check_exit_status(result) check_state('running') # Suspend result = virsh.suspend(vm_name, **virsh_args) utlv.check_exit_status(result) check_state('paused') # Resume result = virsh.resume(vm_name, **virsh_args) utlv.check_exit_status(result) check_state('running') # Reboot(not supported on RHEL6) result = virsh.reboot(vm_name, **virsh_args) supported_err = 'not supported by the connection driver: virDomainReboot' if supported_err in result.stderr.strip(): logging.info("Reboot is not supported") else: utlv.check_exit_status(result) # Destroy result = virsh.destroy(vm_name, **virsh_args) utlv.check_exit_status(result) check_state('shut off') # Undefine result = virsh.undefine(vm_name, **virsh_args) utlv.check_exit_status(result) if not virsh.domain_exists(vm_name, **virsh_args): logging.info("Undefine LXC domain successfully") else: raise TestFail("LXC domain still exist after undefine") finally: virsh.remove_domain(vm_name, **virsh_args) if full_os and os.path.exists(install_root): shutil.rmtree(install_root)
def trigger_events(dom, events_list=[]): """ Trigger various events in events_list :param dom: the vm objects corresponding to the domain :return: the expected output that virsh event command prints out """ expected_events_list = [] save_path = os.path.join(tmpdir, "%s_event.save" % dom.name) print(dom.name) xmlfile = dom.backup_xml() new_disk = os.path.join(tmpdir, "%s_new_disk.img" % dom.name) dest_path = os.path.join(data_dir.get_data_dir(), "copy") try: for event in events_list: logging.debug("Current event is: %s", event) if event in ['start', 'restore', 'create', 'edit', 'define', 'undefine', 'crash', 'device-removal-failed', 'watchdog', 'io-error']: if dom.is_alive(): dom.destroy() if event in ['create', 'define']: dom.undefine() else: if not dom.is_alive(): dom.start() dom.wait_for_login().close() if event == "resume": dom.pause() if event == "undefine": virsh.undefine(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Undefined Removed") elif event == "create": virsh.create(xmlfile, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") expected_events_list.append("'lifecycle' for %s:" " Started Booted") elif event == "destroy": virsh.destroy(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Stopped Destroyed") elif event == "define": virsh.define(xmlfile, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Defined Added") elif event == "start": virsh.start(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") expected_events_list.append("'lifecycle' for %s:" " Started Booted") dom.wait_for_login().close() elif event == "suspend": virsh.suspend(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") if not libvirt_version.version_compare(5, 3, 0): expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") elif event == "resume": virsh.resume(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") elif event == "save": virsh.save(dom.name, save_path, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") expected_events_list.append("'lifecycle' for %s:" " Stopped Saved") elif event == "restore": if not os.path.exists(save_path): logging.error("%s not exist", save_path) else: virsh.restore(save_path, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Started Restored") expected_events_list.append("'lifecycle' for %s:" " Resumed Snapshot") elif event == "edit": #Check whether 'description' element exists. domxml = virsh.dumpxml(dom.name).stdout.strip() find_desc = parseString(domxml).getElementsByTagName("description") if find_desc == []: #If not exists, add one for it. logging.info("Adding <description> to guest") virsh.desc(dom.name, "--config", "Added desc for testvm", **virsh_dargs) #The edit operation is to delete 'description' element. edit_cmd = [r":g/<description.*<\/description>/d"] utlv.exec_virsh_edit(dom.name, edit_cmd) expected_events_list.append("'lifecycle' for %s:" " Defined Updated") elif event == "shutdown": if signal_name is None: virsh.shutdown(dom.name, **virsh_dargs) # Wait a few seconds for shutdown finish time.sleep(3) if utils_misc.compare_qemu_version(2, 9, 0): #Shutdown reason distinguished from qemu_2.9.0-9 expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished after guest request") else: os.kill(dom.get_pid(), getattr(signal, signal_name)) if utils_misc.compare_qemu_version(2, 9, 0): expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished after host request") if not utils_misc.compare_qemu_version(2, 9, 0): expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished") wait_for_shutoff(dom) expected_events_list.append("'lifecycle' for %s:" " Stopped Shutdown") elif event == "crash": if not vmxml.xmltreefile.find('devices').findall('panic'): # Set panic device panic_dev = Panic() panic_dev.model = panic_model panic_dev.addr_type = addr_type panic_dev.addr_iobase = addr_iobase vmxml.add_device(panic_dev) vmxml.on_crash = "coredump-restart" vmxml.sync() logging.info("Guest xml now is: %s", vmxml) dom.start() session = dom.wait_for_login() # Stop kdump in the guest session.cmd("systemctl stop kdump", ignore_all_errors=True) # Enable sysRq session.cmd("echo 1 > /proc/sys/kernel/sysrq") try: # Crash the guest session.cmd("echo c > /proc/sysrq-trigger", timeout=90) except (ShellTimeoutError, ShellProcessTerminatedError) as details: logging.info(details) session.close() expected_events_list.append("'lifecycle' for %s:" " Crashed Panicked") expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") elif event == "reset": virsh.reset(dom.name, **virsh_dargs) expected_events_list.append("'reboot' for %s") elif event == "vcpupin": virsh.vcpupin(dom.name, '0', '0', **virsh_dargs) expected_events_list.append("'tunable' for %s:" "\n\tcputune.vcpupin0: 0") elif event == "emulatorpin": virsh.emulatorpin(dom.name, '0', **virsh_dargs) expected_events_list.append("'tunable' for %s:" "\n\tcputune.emulatorpin: 0") elif event == "setmem": mem_size = int(params.get("mem_size", 512000)) virsh.setmem(dom.name, mem_size, **virsh_dargs) expected_events_list.append("'balloon-change' for %s:") elif event == "device-added-removed": add_disk(dom.name, new_disk, 'vdb', '') expected_events_list.append("'device-added' for %s:" " virtio-disk1") virsh.detach_disk(dom.name, 'vdb', **virsh_dargs) expected_events_list.append("'device-removed' for %s:" " virtio-disk1") iface_xml_obj = create_iface_xml() iface_xml_obj.xmltreefile.write() virsh.detach_device(dom.name, iface_xml_obj.xml, **virsh_dargs) expected_events_list.append("'device-removed' for %s:" " net0") time.sleep(2) virsh.attach_device(dom.name, iface_xml_obj.xml, **virsh_dargs) expected_events_list.append("'device-added' for %s:" " net0") elif event == "block-threshold": add_disk(dom.name, new_disk, 'vdb', '', format=disk_format) logging.debug(process.run('qemu-img info %s -U' % new_disk)) virsh.domblkthreshold(vm_name, 'vdb', '100M') session = dom.wait_for_login() session.cmd("mkfs.ext4 /dev/vdb && mount /dev/vdb /mnt && ls /mnt && " "dd if=/dev/urandom of=/mnt/bigfile bs=1M count=300 && sync") time.sleep(5) session.close() expected_events_list.append("'block-threshold' for %s:" " dev: vdb(%s) 104857600 29368320") virsh.detach_disk(dom.name, 'vdb', **virsh_dargs) elif event == "change-media": target_device = "hdc" device_target_bus = params.get("device_target_bus", "ide") disk_blk = vm_xml.VMXML.get_disk_blk(dom.name) logging.info("disk_blk %s", disk_blk) if target_device not in disk_blk: logging.info("Adding cdrom to guest") if dom.is_alive(): dom.destroy() add_disk(dom.name, new_disk, target_device, ("--type cdrom --sourcetype file --driver qemu " + "--config --targetbus %s" % device_target_bus)) dom.start() all_options = new_disk + " --insert" virsh.change_media(dom.name, target_device, all_options, **virsh_dargs) expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " opened") expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " closed") all_options = new_disk + " --eject" virsh.change_media(dom.name, target_device, all_options, **virsh_dargs) expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " opened") elif event == "hwclock": session = dom.wait_for_login() try: session.cmd("hwclock --systohc", timeout=60) except (ShellTimeoutError, ShellProcessTerminatedError) as details: logging.info(details) session.close() expected_events_list.append("'rtc-change' for %s:") elif event == "metadata_set": metadata_uri = params.get("metadata_uri") metadata_key = params.get("metadata_key") metadata_value = params.get("metadata_value") virsh.metadata(dom.name, metadata_uri, options="", key=metadata_key, new_metadata=metadata_value, **virsh_dargs) expected_events_list.append("'metadata-change' for %s: " "element http://app.org/") elif event == "metadata_edit": metadata_uri = "http://herp.derp/" metadata_key = "herp" metadata_value = "<derp xmlns:foobar='http://foo.bar/'>foo<bar></bar></derp>" virsh_cmd = r"virsh metadata %s --uri %s --key %s %s" virsh_cmd = virsh_cmd % (dom.name, metadata_uri, metadata_key, "--edit") session = aexpect.ShellSession("sudo -s") logging.info("Running command: %s", virsh_cmd) try: session.sendline(virsh_cmd) session.sendline(r":insert") session.sendline(metadata_value) session.sendline(".") session.send('ZZ') remote.handle_prompts(session, None, None, r"[\#\$]\s*$", debug=True, timeout=60) except Exception as e: test.error("Error occured: %s" % e) session.close() # Check metadata after edit virsh.metadata(dom.name, metadata_uri, options="", key=metadata_key, **virsh_dargs) expected_events_list.append("'metadata-change' for %s: " "element http://app.org/") elif event == "metadata_remove": virsh.metadata(dom.name, metadata_uri, options="--remove", key=metadata_key, **virsh_dargs) expected_events_list.append("'metadata-change' for %s: " "element http://app.org/") elif event == "blockcommit": disk_path = dom.get_blk_devices()['vda']['source'] virsh.snapshot_create_as(dom.name, "s1 --disk-only --no-metadata", **virsh_dargs) snapshot_path = dom.get_blk_devices()['vda']['source'] virsh.blockcommit(dom.name, "vda", "--active --pivot", **virsh_dargs) expected_events_list.append("'block-job' for %s: " "Active Block Commit for " + "%s" % snapshot_path + " ready") expected_events_list.append("'block-job-2' for %s: " "Active Block Commit for vda ready") expected_events_list.append("'block-job' for %s: " "Active Block Commit for " + "%s" % disk_path + " completed") expected_events_list.append("'block-job-2' for %s: " "Active Block Commit for vda completed") os.unlink(snapshot_path) elif event == "blockcopy": disk_path = dom.get_blk_devices()['vda']['source'] dom.undefine() virsh.blockcopy(dom.name, "vda", dest_path, "--pivot", **virsh_dargs) expected_events_list.append("'block-job' for %s: " "Block Copy for " + "%s" % disk_path + " ready") expected_events_list.append("'block-job-2' for %s: " "Block Copy for vda ready") expected_events_list.append("'block-job' for %s: " "Block Copy for " + "%s" % dest_path + " completed") expected_events_list.append("'block-job-2' for %s: " "Block Copy for vda completed") elif event == "detach-dimm": prepare_vmxml_mem(vmxml) tg_size = params.get("dimm_size") tg_sizeunit = params.get("dimm_unit") dimm_xml = utils_hotplug.create_mem_xml(tg_size, None, None, tg_sizeunit) virsh.attach_device(dom.name, dimm_xml.xml, flagstr="--config", **virsh_dargs) vmxml_dimm = vm_xml.VMXML.new_from_dumpxml(dom.name) logging.debug("Current vmxml with plugged dimm dev is %s\n" % vmxml_dimm) virsh.start(dom.name, **virsh_dargs) dom.wait_for_login().close() result = virsh.detach_device(dom.name, dimm_xml.xml, debug=True, ignore_status=True) expected_fails = params.get("expected_fails") utlv.check_result(result, expected_fails) vmxml_live = vm_xml.VMXML.new_from_dumpxml(dom.name) logging.debug("Current vmxml after hot-unplug dimm is %s\n" % vmxml_live) expected_events_list.append("'device-removal-failed' for %s: dimm0") elif event == "watchdog": vmxml.remove_all_device_by_type('watchdog') watchdog_dev = Watchdog() watchdog_dev.model_type = params.get("watchdog_model") action = params.get("action") watchdog_dev.action = action vmxml.add_device(watchdog_dev) vmxml.sync() logging.debug("Current vmxml with watchdog dev is %s\n" % vmxml) virsh.start(dom.name, **virsh_dargs) session = dom.wait_for_login() try: session.cmd("echo 0 > /dev/watchdog") except (ShellTimeoutError, ShellProcessTerminatedError) as details: test.fail("Failed to trigger watchdog: %s" % details) session.close() # watchdog acts slowly, waiting for it. time.sleep(30) expected_events_list.append("'watchdog' for %s: " + "%s" % action) if action == 'pause': expected_events_list.append("'lifecycle' for %s: Suspended Watchdog") virsh.resume(dom.name, **virsh_dargs) else: # action == 'reset' expected_events_list.append("'reboot' for %s") elif event == "io-error": part_size = params.get("part_size") resume_event = params.get("resume_event") suspend_event = params.get("suspend_event") process.run("truncate -s %s %s" % (part_size, small_part), shell=True) utlv.mkfs(small_part, part_format) utils_misc.mount(small_part, mount_point, None) add_disk(dom.name, new_disk, 'vdb', '--subdriver qcow2 --config', 'qcow2') dom.start() session = dom.wait_for_login() session.cmd("mkfs.ext4 /dev/vdb && mount /dev/vdb /mnt && ls /mnt && " "dd if=/dev/zero of=/mnt/test.img bs=1M count=50", ignore_all_errors=True) time.sleep(5) session.close() expected_events_list.append("'io-error' for %s: " + "%s" % new_disk + r" \(virtio-disk1\) pause") expected_events_list.append("'io-error-reason' for %s: " + "%s" % new_disk + r" \(virtio-disk1\) pause due to enospc") expected_events_list.append(suspend_event) process.run("df -hT") virsh.resume(dom.name, **virsh_dargs) time.sleep(5) expected_events_list.append(resume_event) expected_events_list.append("'io-error' for %s: " + "%s" % new_disk + r" \(virtio-disk1\) pause") expected_events_list.append("'io-error-reason' for %s: " + "%s" % new_disk + r" \(virtio-disk1\) pause due to enospc") expected_events_list.append(suspend_event) ret = virsh.domstate(dom.name, "--reason", **virsh_dargs) if ret.stdout.strip() != "paused (I/O error)": test.fail("Domain state should still be paused due to I/O error!") else: test.error("Unsupported event: %s" % event) # Event may not received immediately time.sleep(3) finally: if os.path.exists(save_path): os.unlink(save_path) if os.path.exists(new_disk): os.unlink(new_disk) if os.path.exists(dest_path): os.unlink(dest_path) return [(dom.name, event) for event in expected_events_list]
def trigger_events(dom, events_list=[]): """ Trigger various events in events_list :param dom: the vm objects corresponding to the domain :return: the expected output that virsh event command prints out """ expected_events_list = [] save_path = os.path.join(tmpdir, "%s_event.save" % dom.name) print(dom.name) xmlfile = dom.backup_xml() try: for event in events_list: logging.debug("Current event is: %s", event) if event in ['start', 'restore', 'create', 'edit', 'define', 'undefine', 'crash']: if dom.is_alive(): dom.destroy() if event in ['create', 'define']: dom.undefine() else: if not dom.is_alive(): dom.start() dom.wait_for_login().close() if event == "resume": dom.pause() if event == "undefine": virsh.undefine(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Undefined Removed") elif event == "create": virsh.create(xmlfile, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") expected_events_list.append("'lifecycle' for %s:" " Started Booted") elif event == "destroy": virsh.destroy(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Stopped Destroyed") elif event == "define": virsh.define(xmlfile, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Defined Added") elif event == "start": virsh.start(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") expected_events_list.append("'lifecycle' for %s:" " Started Booted") dom.wait_for_login().close() elif event == "suspend": virsh.suspend(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") if not libvirt_version.version_compare(5, 3, 0): expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") elif event == "resume": virsh.resume(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") elif event == "save": virsh.save(dom.name, save_path, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") expected_events_list.append("'lifecycle' for %s:" " Stopped Saved") elif event == "restore": if not os.path.exists(save_path): logging.error("%s not exist", save_path) else: virsh.restore(save_path, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Started Restored") expected_events_list.append("'lifecycle' for %s:" " Resumed Snapshot") elif event == "edit": #Check whether 'description' element exists. domxml = virsh.dumpxml(dom.name).stdout.strip() find_desc = parseString(domxml).getElementsByTagName("description") if find_desc == []: #If not exists, add one for it. logging.info("Adding <description> to guest") virsh.desc(dom.name, "--config", "Added desc for testvm", **virsh_dargs) #The edit operation is to delete 'description' element. edit_cmd = [r":g/<description.*<\/description>/d"] utlv.exec_virsh_edit(dom.name, edit_cmd) expected_events_list.append("'lifecycle' for %s:" " Defined Updated") elif event == "shutdown": if signal_name is None: virsh.shutdown(dom.name, **virsh_dargs) # Wait a few seconds for shutdown finish time.sleep(3) if utils_misc.compare_qemu_version(2, 9, 0): #Shutdown reason distinguished from qemu_2.9.0-9 expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished after guest request") else: os.kill(dom.get_pid(), getattr(signal, signal_name)) if utils_misc.compare_qemu_version(2, 9, 0): expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished after host request") if not utils_misc.compare_qemu_version(2, 9, 0): expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished") wait_for_shutoff(dom) expected_events_list.append("'lifecycle' for %s:" " Stopped Shutdown") elif event == "crash": if not vmxml.xmltreefile.find('devices').findall('panic'): # Set panic device panic_dev = Panic() panic_dev.model = panic_model panic_dev.addr_type = addr_type panic_dev.addr_iobase = addr_iobase vmxml.add_device(panic_dev) vmxml.on_crash = "coredump-restart" vmxml.sync() logging.info("Guest xml now is: %s", vmxml) dom.start() session = dom.wait_for_login() # Stop kdump in the guest session.cmd("systemctl stop kdump", ignore_all_errors=True) # Enable sysRq session.cmd("echo 1 > /proc/sys/kernel/sysrq") try: # Crash the guest session.cmd("echo c > /proc/sysrq-trigger", timeout=60) except (ShellTimeoutError, ShellProcessTerminatedError) as details: logging.info(details) session.close() expected_events_list.append("'lifecycle' for %s:" " Crashed Panicked") expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") elif event == "reset": virsh.reset(dom.name, **virsh_dargs) expected_events_list.append("'reboot' for %s") elif event == "vcpupin": virsh.vcpupin(dom.name, '0', '0', **virsh_dargs) expected_events_list.append("'tunable' for %s:" "\n\tcputune.vcpupin0: 0") elif event == "emulatorpin": virsh.emulatorpin(dom.name, '0', **virsh_dargs) expected_events_list.append("'tunable' for %s:" "\n\tcputune.emulatorpin: 0") elif event == "setmem": mem_size = int(params.get("mem_size", 512000)) virsh.setmem(dom.name, mem_size, **virsh_dargs) expected_events_list.append("'balloon-change' for %s:") elif event == "device-added-removed": add_disk(dom.name, new_disk, 'vdb', '') expected_events_list.append("'device-added' for %s:" " virtio-disk1") virsh.detach_disk(dom.name, 'vdb', **virsh_dargs) expected_events_list.append("'device-removed' for %s:" " virtio-disk1") iface_xml_obj = create_iface_xml() iface_xml_obj.xmltreefile.write() virsh.detach_device(dom.name, iface_xml_obj.xml, **virsh_dargs) expected_events_list.append("'device-removed' for %s:" " net0") time.sleep(2) virsh.attach_device(dom.name, iface_xml_obj.xml, **virsh_dargs) expected_events_list.append("'device-added' for %s:" " net0") elif event == "block-threshold": add_disk(dom.name, new_disk, 'vdb', '', format=disk_format) logging.debug(process.run('qemu-img info %s -U' % new_disk)) virsh.domblkthreshold(vm_name, 'vdb', '100M') session = dom.wait_for_login() session.cmd("mkfs.ext4 /dev/vdb && mount /dev/vdb /mnt && ls /mnt && " "dd if=/dev/urandom of=/mnt/bigfile bs=1M count=300 && sync") time.sleep(5) session.close() expected_events_list.append("'block-threshold' for %s:" " dev: vdb(%s) 104857600 29368320") virsh.detach_disk(dom.name, 'vdb', **virsh_dargs) elif event == "change-media": target_device = "hdc" device_target_bus = params.get("device_target_bus", "ide") disk_blk = vm_xml.VMXML.get_disk_blk(dom.name) logging.info("disk_blk %s", disk_blk) if target_device not in disk_blk: logging.info("Adding cdrom to guest") if dom.is_alive(): dom.destroy() add_disk(dom.name, "''", target_device, ("--type cdrom --sourcetype file --driver qemu " + "--config --targetbus %s" % device_target_bus)) dom.start() all_options = new_disk + " --insert" virsh.change_media(dom.name, target_device, all_options, **virsh_dargs) expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " opened") expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " closed") all_options = new_disk + " --eject" virsh.change_media(dom.name, target_device, all_options, **virsh_dargs) expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " opened") elif event == "hwclock": session = dom.wait_for_login() try: session.cmd("hwclock --systohc", timeout=60) except (ShellTimeoutError, ShellProcessTerminatedError) as details: logging.info(details) session.close() expected_events_list.append("'rtc-change' for %s:") elif event == "metadata_set": metadata_uri = params.get("metadata_uri") metadata_key = params.get("metadata_key") metadata_value = params.get("metadata_value") virsh.metadata(dom.name, metadata_uri, options="", key=metadata_key, new_metadata=metadata_value, **virsh_dargs) expected_events_list.append("'metadata-change' for %s: " "element http://app.org/") elif event == "metadata_edit": metadata_uri = "http://herp.derp/" metadata_key = "herp" metadata_value = "<derp xmlns:foobar='http://foo.bar/'>foo<bar></bar></derp>" virsh_cmd = r"virsh metadata %s --uri %s --key %s %s" virsh_cmd = virsh_cmd % (dom.name, metadata_uri, metadata_key, "--edit") session = aexpect.ShellSession("sudo -s") logging.info("Running command: %s", virsh_cmd) try: session.sendline(virsh_cmd) session.sendline(r":insert") session.sendline(metadata_value) session.sendline(".") session.send('ZZ') remote.handle_prompts(session, None, None, r"[\#\$]\s*$", debug=True, timeout=60) except Exception as e: test.error("Error occured: %s" % e) session.close() # Check metadata after edit virsh.metadata(dom.name, metadata_uri, options="", key=metadata_key, **virsh_dargs) expected_events_list.append("'metadata-change' for %s: " "element http://app.org/") elif event == "metadata_remove": virsh.metadata(dom.name, metadata_uri, options="--remove", key=metadata_key, **virsh_dargs) expected_events_list.append("'metadata-change' for %s: " "element http://app.org/") else: test.error("Unsupported event: %s" % event) # Event may not received immediately time.sleep(3) finally: if os.path.exists(save_path): os.unlink(save_path) if os.path.exists(new_disk): os.unlink(new_disk) return [(dom.name, event) for event in expected_events_list]
def trigger_events(dom, events_list=[]): """ Trigger various events in events_list :param dom: the vm objects corresponding to the domain :return: the expected output that virsh event command prints out """ expected_events_list = [] save_path = os.path.join(tmpdir, "%s_event.save" % dom.name) print(dom.name) xmlfile = dom.backup_xml() try: for event in events_list: if event in ['start', 'restore', 'create', 'define', 'undefine']: if dom.is_alive(): dom.destroy() if event in ['create', 'define']: dom.undefine() else: if not dom.is_alive(): dom.start() dom.wait_for_login().close() if event == "resume": dom.pause() if event == "undefine": virsh.undefine(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Undefined Removed") elif event == "create": virsh.create(xmlfile, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") expected_events_list.append("'lifecycle' for %s:" " Started Booted") elif event == "destroy": virsh.destroy(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Stopped Destroyed") elif event == "define": virsh.define(xmlfile, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Defined Added") elif event == "start": virsh.start(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") expected_events_list.append("'lifecycle' for %s:" " Started Booted") dom.wait_for_login().close() elif event == "suspend": virsh.suspend(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") elif event == "resume": virsh.resume(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") elif event == "save": virsh.save(dom.name, save_path, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") expected_events_list.append("'lifecycle' for %s:" " Stopped Saved") elif event == "restore": if not os.path.exists(save_path): logging.error("%s not exist", save_path) else: virsh.restore(save_path, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Started Restored") expected_events_list.append("'lifecycle' for %s:" " Resumed Snapshot") elif event == "edit": #Check whether 'description' element exists. domxml = virsh.dumpxml(dom.name).stdout.strip() find_desc = parseString(domxml).getElementsByTagName("description") if find_desc == []: #If not exists, add one for it. logging.info("Adding <description> to guest") virsh.desc(dom.name, "--config", "Added desc for testvm", **virsh_dargs) #The edit operation is to delete 'description' element. edit_cmd = [r":g/<description.*<\/description>/d"] utlv.exec_virsh_edit(dom.name, edit_cmd) expected_events_list.append("'lifecycle' for %s:" " Defined Updated") elif event == "shutdown": if signal_name is None: virsh.shutdown(dom.name, **virsh_dargs) # Wait a few seconds for shutdown finish time.sleep(3) expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished after guest request") expected_events_list.append("'lifecycle' for %s:" " Stopped Shutdown") else: os.kill(dom.get_pid(), getattr(signal, signal_name)) expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished after host request") expected_events_list.append("'lifecycle' for %s:" " Stopped Shutdown") elif event == "reset": virsh.reset(dom.name, **virsh_dargs) expected_events_list.append("'reboot' for %s") elif event == "vcpupin": virsh.vcpupin(dom.name, '0', '0', **virsh_dargs) expected_events_list.append("'tunable' for %s:" "\n\tcputune.vcpupin0: 0") elif event == "emulatorpin": virsh.emulatorpin(dom.name, '0', **virsh_dargs) expected_events_list.append("'tunable' for %s:" "\n\tcputune.emulatorpin: 0") elif event == "setmem": mem_size = int(params.get("mem_size", 512000)) virsh.setmem(dom.name, mem_size, **virsh_dargs) expected_events_list.append("'balloon-change' for %s:") elif event == "device-added-removed": add_disk(dom.name, new_disk, 'vdb', '') expected_events_list.append("'device-added' for %s:" " virtio-disk1") virsh.detach_disk(dom.name, 'vdb', **virsh_dargs) expected_events_list.append("'device-removed' for %s:" " virtio-disk1") iface_xml_obj = create_iface_xml() iface_xml_obj.xmltreefile.write() virsh.detach_device(dom.name, iface_xml_obj.xml, **virsh_dargs) expected_events_list.append("'device-removed' for %s:" " net0") time.sleep(2) virsh.attach_device(dom.name, iface_xml_obj.xml, **virsh_dargs) expected_events_list.append("'device-added' for %s:" " net0") elif event == "change-media": target_device = "hdc" disk_blk = vm_xml.VMXML.get_disk_blk(dom.name) logging.info("disk_blk %s", disk_blk) if target_device not in disk_blk: logging.info("Adding cdrom to guest") if dom.is_alive(): dom.destroy() add_disk(dom.name, "''", target_device, "--type cdrom --sourcetype file --config") dom.start() all_options = new_disk + " --insert" virsh.change_media(dom.name, target_device, all_options, ignore_status=True, debug=True) expected_events_list.append("'tray-change' for %s disk ide0-1-0:" " opened") expected_events_list.append("'tray-change' for %s disk ide0-1-0:" " closed") all_options = new_disk + " --eject" virsh.change_media(dom.name, target_device, all_options, ignore_status=True, debug=True) expected_events_list.append("'tray-change' for %s disk ide0-1-0:" " opened") else: test.error("Unsupported event: %s" % event) # Event may not received immediately time.sleep(3) finally: if os.path.exists(save_path): os.unlink(save_path) if os.path.exists(new_disk): os.unlink(new_disk) return [(dom.name, event) for event in expected_events_list]
def run(test, params, env): """ Test misc tests of virtual cpu features 1) check dumpxml after snapshot-create/revert 2) check vendor_id 3) check maximum vcpus with topology settings :param test: test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def update_cpu_xml(): """ Update cpu xml for test """ vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Create cpu xml for test if vmxml.xmltreefile.find('cpu'): cpu_xml = vmxml.cpu else: cpu_xml = vm_xml.VMCPUXML() if customize_cpu_features: for idx in range(len(cpu_xml.get_feature_list()) - 1, -1, -1): cpu_xml.remove_feature(idx) domcapa_xml = domcapability_xml.DomCapabilityXML() features = domcapa_xml.get_additional_feature_list( 'host-model', ignore_features=None) for feature in features: for feature_name, feature_policy in feature.items(): # For host-passthrough mode, adding "invtsc" requires # more settings, so it will be ignored. if feature_name != "invtsc": cpu_xml.add_feature(feature_name, feature_policy) if cpu_mode: cpu_xml.mode = cpu_mode if cpu_vendor_id: cpu_xml.vendor_id = cpu_vendor_id # Update vm's cpu vmxml.cpu = cpu_xml vmxml.sync() if vcpu_max: if with_topology: vm_xml.VMXML.set_vm_vcpus(vm_name, int(vcpu_max), cores=int(vcpu_max), sockets=1, threads=1, add_topology=with_topology, topology_correction=with_topology) else: vm_xml.VMXML.set_vm_vcpus(vm_name, int(vcpu_max)) def do_snapshot(vm_name, expected_str): """ Run snapshot related commands: snapshot-create-as, snapshot-list snapshot-dumpxml, snapshot-revert :param vm_name: vm name :param expected_str: expected string in snapshot-dumpxml :raise: test.fail if virsh command failed """ snapshot_name = vm_name + "-snap" virsh_dargs = {'debug': True} cmd_result = virsh.snapshot_create_as(vm_name, snapshot_name, **virsh_dargs) libvirt.check_exit_status(cmd_result) try: snapshots = virsh.snapshot_list(vm_name, **virsh_dargs) except process.CmdError: test.fail("Failed to get snapshots list for %s" % vm_name) if snapshot_name not in snapshots: test.fail("The snapshot '%s' was not in snapshot-list." % snapshot_name) cmd_result = virsh.snapshot_dumpxml(vm_name, snapshot_name, **virsh_dargs) libvirt.check_result(cmd_result, expected_match=expected_str) cmd_result = virsh.snapshot_revert(vm_name, "", "--current", **virsh_dargs) libvirt.check_exit_status(cmd_result) def check_feature_list(vm, original_dict): """ Compare new cpu feature list and original cpu :param vm: VM object :original_dict: Cpu feature dict , {"name1":"policy1","name2":"policy2"} """ new_cpu_xml = vm_xml.VMXML.new_from_dumpxml(vm.name).cpu new_feature_dict = new_cpu_xml.get_dict_type_feature() if new_feature_dict != original_dict: test.fail('CPU feature lists are different, original is :%s,' ' new is %s:' % (original_dict, new_feature_dict)) libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get('main_vm') vm = env.get_vm(vm_name) cpu_mode = params.get('cpu_mode') vcpu_max = params.get('vcpu_max') expected_str_before_startup = params.get("expected_str_before_startup") expected_str_after_startup = params.get("expected_str_after_startup") test_operations = params.get("test_operations") check_vendor_id = "yes" == params.get("check_vendor_id", "no") virsh_edit_cmd = params.get("virsh_edit_cmd") with_topology = "yes" == params.get("with_topology", "no") status_error = "yes" == params.get("status_error", "no") err_msg = params.get("err_msg") cpu_vendor_id = None expected_qemuline = None cmd_in_guest = params.get("cmd_in_guest") customize_cpu_features = "yes" == params.get("customize_cpu_features", "no") bkxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) managed_save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name try: if check_vendor_id: output = virsh.capabilities(debug=True) host_vendor = re.findall(r'<vendor>(\w+)<', output)[0] cpu_vendor_id = 'GenuineIntel' if host_vendor != "Intel": cpu_vendor_id = 'AuthenticAMD' logging.debug("Set cpu vendor_id to %s on this host.", cpu_vendor_id) expected_qemuline = "vendor=" + cpu_vendor_id cmd_in_guest = ("cat /proc/cpuinfo | grep vendor_id | grep {}". format(cpu_vendor_id)) # Update xml for test update_cpu_xml() vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) logging.debug("Pre-test xml is %s", vmxml.xmltreefile) cpu_xml = vmxml.cpu feature_dict = cpu_xml.get_dict_type_feature() if expected_str_before_startup: libvirt.check_dumpxml(vm, expected_str_before_startup) if test_operations: for action in test_operations.split(","): if action == "do_snapshot": do_snapshot(vm_name, expected_str_before_startup) if virsh_edit_cmd: status = libvirt.exec_virsh_edit(vm_name, virsh_edit_cmd.split(",")) if status == status_error: test.fail("Virsh edit got unexpected result.") # Check if vm could start successfully if not status_error: result = virsh.start(vm_name, debug=True) libvirt.check_exit_status(result) if expected_str_after_startup: libvirt.check_dumpxml(vm, expected_str_after_startup) if expected_qemuline: libvirt.check_qemu_cmd_line(expected_qemuline) if cmd_in_guest: vm_session = vm.wait_for_login() status, output = vm_session.cmd_status_output(cmd_in_guest) if status: vm_session.close() test.fail("Failed to run '{}' in vm with " "messages:\n{}".format(cmd_in_guest, output)) vm_session.close() if cpu_mode == 'maximum': check_vm_cpu_model(output.strip(), cmd_in_guest, test) # Add case: Check cpu xml after domain Managedsaved and restored if test_operations: for item in test_operations.split(','): if item == "managedsave_restore": # (1)Domain Manage saved virsh.managedsave(vm_name, ignore_status=False, debug=True) check_feature_list(vm, feature_dict) # (2)Domain Restore virsh.restore(managed_save_file, ignore_status=False, debug=True) # (5)Check mode and feature list here libvirt.check_dumpxml(vm, cpu_mode) check_feature_list(vm, feature_dict) finally: logging.debug("Recover test environment") if os.path.exists(managed_save_file): virsh.managedsave_remove(vm_name, debug=True) if vm.is_alive(): vm.destroy() libvirt.clean_up_snapshots(vm_name, domxml=bkxml) bkxml.sync()
def run(test, params, env): """ Test vsock device: 1.Edit/start guest with vsock device. 2.Hotplug/hotunplug vsock device. 3.Coldplug/Coldunplug vsock device """ def env_setup(): session = vm.wait_for_login() cmd = [ 'rpm -q lsof || yum -y install lsof', 'rpm -q git || yum -y install git', 'rpm -q make || yum -y install make', 'rpm -q gcc && yum -y reinstall gcc || yum -y install gcc', 'rm -rf /tmp/nc-vsock', 'git clone %s /tmp/nc-vsock' % git_repo, 'cd /tmp/nc-vsock/ && make', ] for i in range(len(cmd)): status1 = session.cmd_status(cmd[i]) logging.debug(status1) status2 = process.run(cmd[i], shell=True).exit_status logging.debug(status2) if (status1 + status2) != 0: test.cancel("Failed to install pkg %s" % cmd[i]) session.close() def validate_data_transfer_by_vsock(): env_setup() def _vsock_server(): session.cmd("/tmp/nc-vsock/nc-vsock -l 1234 > /tmp/testfile") server = threading.Thread(target=_vsock_server) session = vm.wait_for_login() server.start() process.run('echo "test file" > /tmp/testfile', shell=True) output = process.run("/tmp/nc-vsock/nc-vsock %d 1234 < /tmp/testfile" % int(cid), shell=True).stdout_text logging.debug(output) server.join(5) data_host = process.run("sha256sum /tmp/testfile", shell=True).stdout_text logging.debug(session.cmd_status_output("cat /tmp/testfile")[1]) data_guest = session.cmd_status_output("sha256sum /tmp/testfile")[1] logging.debug(data_guest[1]) if data_guest != data_host: test.fail("Data transfer error with vsock device\n") session.close() def managedsave_restore(): result = virsh.managedsave(vm_name, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) result = virsh.start(vm_name) utils_test.libvirt.check_exit_status(result, expect_error=False) start_vm = params.get("start_vm", "no") vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(params["main_vm"]) auto_cid = params.get("auto_cid", "no") status_error = params.get("status_error", "no") == "yes" edit_xml = params.get("edit_xml", "no") == "yes" option = params.get("option", "") git_repo = params.get("git_repo", "") invalid_cid = params.get("invalid_cid", "no") == "yes" managedsave = params.get("managedsave", "no") == "yes" no_vsock = params.get("no_vsock", "no") == "yes" vsock_num = params.get("num") commuication = params.get("communication", "no") == "yes" # Backup xml file vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Add vsock device to domain vmxml.remove_all_device_by_type('vsock') vsock_dev = Vsock() vsock_dev.model_type = "virtio" if process.run("modprobe vhost_vsock").exit_status != 0: test.fail("Failed to load vhost_vsock module") if invalid_cid: cid = "-1" else: cid = random.randint(3, 10) vsock_dev.cid = {'auto': auto_cid, 'address': cid} chars = string.ascii_letters + string.digits + '-_' alias_name = 'ua-' + ''.join( random.choice(chars) for _ in list(range(64))) vsock_dev.alias = {'name': alias_name} logging.debug(vsock_dev) if start_vm == "no" and vm.is_alive(): virsh.destroy() try: if edit_xml: edit_status1 = libvirt.exec_virsh_edit( vm_name, [(r":/<devices>/s/$/%s" % re.findall(r"<vsock.*<\/vsock>", str(vsock_dev), re.M)[0].replace("/", "\/"))]) edit_status2 = True if vsock_num == 2: edit_status2 = libvirt.exec_virsh_edit( vm_name, [(r":/<devices>/s/$/%s" % re.findall(r"<vsock.*<\/vsock>", str(vsock_dev), re.M)[0].replace("/", "\/"))]) logging.debug(vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)) if status_error: if edit_status1 or edit_status2: test.fail("virsh edit should fail\n") else: if not edit_status1: test.fail("Failed to edit vm xml with vsock device\n") else: result = virsh.start(vm_name, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) else: session = vm.wait_for_login() session.close() result = virsh.attach_device(vm_name, file_opt=vsock_dev.xml, flagstr=option, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) if option == "--config": result = virsh.start(vm_name, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) logging.debug(vmxml) vsock_list = vmxml.devices.by_device_tag("vsock") cid = vsock_list[0].cid['address'] if 0 == len(vsock_list): test.fail("No vsock device found in live xml\n") if commuication: validate_data_transfer_by_vsock() if managedsave and not no_vsock: managedsave_restore() def _detach_completed(): status = process.run("lsof /dev/vhost-vsock", ignore_status=True, shell=True).exit_status return status == 1 result = virsh.detach_device(vm_name, file_opt=vsock_dev.xml, debug=True) utils_test.libvirt.check_exit_status(result, expect_error=False) utils_misc.wait_for(_detach_completed, timeout=20) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) vsock_list = vmxml.get_devices("vsock") if vsock_list: test.fail( "Still find vsock device in live xml after hotunplug\n") if managedsave and no_vsock: managedsave_restore() finally: if vm.is_alive(): vm.destroy(gracefully=False) backup_xml.sync()
def trigger_events(dom, events_list=[]): """ Trigger various events in events_list :param dom: the vm objects corresponding to the domain :return: the expected output that virsh event command prints out """ expected_events_list = [] save_path = os.path.join(tmpdir, "%s_event.save" % dom.name) print(dom.name) xmlfile = dom.backup_xml() try: for event in events_list: if event in [ 'start', 'restore', 'create', 'define', 'undefine', 'crash' ]: if dom.is_alive(): dom.destroy() if event in ['create', 'define']: dom.undefine() else: if not dom.is_alive(): dom.start() dom.wait_for_login().close() if event == "resume": dom.pause() if event == "undefine": virsh.undefine(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Undefined Removed") elif event == "create": virsh.create(xmlfile, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") expected_events_list.append("'lifecycle' for %s:" " Started Booted") elif event == "destroy": virsh.destroy(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Stopped Destroyed") elif event == "define": virsh.define(xmlfile, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Defined Added") elif event == "start": virsh.start(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") expected_events_list.append("'lifecycle' for %s:" " Started Booted") dom.wait_for_login().close() elif event == "suspend": virsh.suspend(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") if not libvirt_version.version_compare(5, 3, 0): expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") elif event == "resume": virsh.resume(dom.name, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") elif event == "save": virsh.save(dom.name, save_path, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Suspended Paused") expected_events_list.append("'lifecycle' for %s:" " Stopped Saved") elif event == "restore": if not os.path.exists(save_path): logging.error("%s not exist", save_path) else: virsh.restore(save_path, **virsh_dargs) expected_events_list.append("'lifecycle' for %s:" " Started Restored") expected_events_list.append("'lifecycle' for %s:" " Resumed Snapshot") elif event == "edit": #Check whether 'description' element exists. domxml = virsh.dumpxml(dom.name).stdout.strip() find_desc = parseString(domxml).getElementsByTagName( "description") if find_desc == []: #If not exists, add one for it. logging.info("Adding <description> to guest") virsh.desc(dom.name, "--config", "Added desc for testvm", **virsh_dargs) #The edit operation is to delete 'description' element. edit_cmd = [r":g/<description.*<\/description>/d"] utlv.exec_virsh_edit(dom.name, edit_cmd) expected_events_list.append("'lifecycle' for %s:" " Defined Updated") elif event == "shutdown": if signal_name is None: virsh.shutdown(dom.name, **virsh_dargs) # Wait a few seconds for shutdown finish time.sleep(3) if utils_misc.compare_qemu_version(2, 9, 0): #Shutdown reason distinguished from qemu_2.9.0-9 expected_events_list.append( "'lifecycle' for %s:" " Shutdown Finished after guest request") else: os.kill(dom.get_pid(), getattr(signal, signal_name)) if utils_misc.compare_qemu_version(2, 9, 0): expected_events_list.append( "'lifecycle' for %s:" " Shutdown Finished after host request") if not utils_misc.compare_qemu_version(2, 9, 0): expected_events_list.append("'lifecycle' for %s:" " Shutdown Finished") expected_events_list.append("'lifecycle' for %s:" " Stopped Shutdown") elif event == "crash": if not vmxml.xmltreefile.find('devices').findall('panic'): # Set panic device panic_dev = Panic() panic_dev.model = panic_model panic_dev.addr_type = addr_type panic_dev.addr_iobase = addr_iobase vmxml.add_device(panic_dev) vmxml.on_crash = "coredump-restart" vmxml.sync() logging.info("Guest xml now is: %s", vmxml) dom.start() session = dom.wait_for_login() # Stop kdump in the guest session.cmd("systemctl stop kdump", ignore_all_errors=True) # Enable sysRq session.cmd("echo 1 > /proc/sys/kernel/sysrq") try: # Crash the guest session.cmd("echo c > /proc/sysrq-trigger", timeout=60) except (ShellTimeoutError, ShellProcessTerminatedError) as details: logging.info(details) session.close() expected_events_list.append("'lifecycle' for %s:" " Crashed Panicked") expected_events_list.append("'lifecycle' for %s:" " Resumed Unpaused") elif event == "reset": virsh.reset(dom.name, **virsh_dargs) expected_events_list.append("'reboot' for %s") elif event == "vcpupin": virsh.vcpupin(dom.name, '0', '0', **virsh_dargs) expected_events_list.append("'tunable' for %s:" "\n\tcputune.vcpupin0: 0") elif event == "emulatorpin": virsh.emulatorpin(dom.name, '0', **virsh_dargs) expected_events_list.append("'tunable' for %s:" "\n\tcputune.emulatorpin: 0") elif event == "setmem": mem_size = int(params.get("mem_size", 512000)) virsh.setmem(dom.name, mem_size, **virsh_dargs) expected_events_list.append("'balloon-change' for %s:") elif event == "device-added-removed": add_disk(dom.name, new_disk, 'vdb', '') expected_events_list.append("'device-added' for %s:" " virtio-disk1") virsh.detach_disk(dom.name, 'vdb', **virsh_dargs) expected_events_list.append("'device-removed' for %s:" " virtio-disk1") iface_xml_obj = create_iface_xml() iface_xml_obj.xmltreefile.write() virsh.detach_device(dom.name, iface_xml_obj.xml, **virsh_dargs) expected_events_list.append("'device-removed' for %s:" " net0") time.sleep(2) virsh.attach_device(dom.name, iface_xml_obj.xml, **virsh_dargs) expected_events_list.append("'device-added' for %s:" " net0") elif event == "change-media": target_device = "hdc" device_target_bus = params.get("device_target_bus", "ide") disk_blk = vm_xml.VMXML.get_disk_blk(dom.name) logging.info("disk_blk %s", disk_blk) if target_device not in disk_blk: logging.info("Adding cdrom to guest") if dom.is_alive(): dom.destroy() add_disk( dom.name, "''", target_device, ("--type cdrom --sourcetype file --driver qemu " + "--config --targetbus %s" % device_target_bus)) dom.start() all_options = new_disk + " --insert" virsh.change_media(dom.name, target_device, all_options, **virsh_dargs) expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " opened") expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " closed") all_options = new_disk + " --eject" virsh.change_media(dom.name, target_device, all_options, **virsh_dargs) expected_events_list.append("'tray-change' for %s disk" + " .*%s.*:" % device_target_bus + " opened") else: test.error("Unsupported event: %s" % event) # Event may not received immediately time.sleep(3) finally: if os.path.exists(save_path): os.unlink(save_path) if os.path.exists(new_disk): os.unlink(new_disk) return [(dom.name, event) for event in expected_events_list]
def run(test, params, env): """ LXC container life cycle testing by virsh command """ uri = params.get("connect_uri", "lxc:///") vm_name = params.get("main_vm") dom_type = params.get("lxc_domtype", "lxc") vcpu = int(params.get("lxc_vcpu", 1)) max_mem = int(params.get("lxc_max_mem", 500000)) current_mem = int(params.get("lxc_current_mem", 500000)) os_type = params.get("lxc_ostype", "exe") os_arch = params.get("lxc_osarch", "x86_64") os_init = params.get("lxc_osinit", "/bin/sh") emulator_path = params.get("lxc_emulator", "/usr/libexec/libvirt_lxc") interface_type = params.get("lxc_interface_type", "network") net_name = params.get("lxc_net_name", "default") full_os = ("yes" == params.get("lxc_full_os", "no")) install_root = params.get("lxc_install_root", "/") fs_target = params.get("lxc_fs_target", "/") fs_accessmode = params.get("lxc_fs_accessmode", "passthrough") passwd = params.get("lxc_fs_passwd", "redhat") def generate_container_xml(): """ Generate container xml """ vmxml = vm_xml.VMXML(dom_type) vmxml.vm_name = vm_name vmxml.max_mem = max_mem vmxml.current_mem = current_mem vmxml.vcpu = vcpu # Generate os vm_os = vm_xml.VMOSXML() vm_os.type = os_type vm_os.arch = os_arch vm_os.init = os_init vmxml.os = vm_os # Generate emulator emulator = Emulator() emulator.path = emulator_path # Generate console console = Console() filesystem = Filesystem() filesystem.accessmode = fs_accessmode filesystem.source = {'dir': install_root} filesystem.target = {'dir': fs_target} # Add emulator and console in devices devices = vm_xml.VMXMLDevices() devices.append(emulator) devices.append(console) devices.append(filesystem) # Add network device network = Interface(type_name=interface_type) network.mac_address = utils_net.generate_mac_address_simple() network.source = {interface_type: net_name} devices.append(network) vmxml.set_devices(devices) return vmxml def check_state(expected_state): result = virsh.domstate(vm_name, uri=uri) utlv.check_exit_status(result) vm_state = result.stdout.strip() if vm_state == expected_state: logging.info("Get expected state: %s", vm_state) else: raise TestFail("Get unexpected state: %s", vm_state) virsh_args = {'uri': uri, 'debug': True} try: vmxml = generate_container_xml() with open(vmxml.xml, 'r') as f: logging.info("Container XML:\n%s", f.read()) if full_os: if not os.path.exists(install_root): os.mkdir(install_root) # Install core os under installroot cmd = "yum --releasever=/ --installroot=%s" % install_root cmd += " --nogpgcheck -y groupinstall core" process.run(cmd, shell=True) # Fix root login on console process.run("echo 'pts/0' >> %s/etc/securetty" % install_root, shell=True) for i in ["session required pam_selinux.so close", "session required pam_selinux.so open", "session required pam_loginuid.so"]: process.run('sed -i s/"%s\"/"#%s"/g %s/etc/pam.d/login' % (i, i, install_root), shell=True) # Fix root login for sshd process.run('sed -i s/"%s\"/"#%s"/g %s/etc/pam.d/sshd' % (i, i, install_root), shell=True) # Config basic network net_file = install_root + '/etc/sysconfig/network' with open(net_file, 'w') as f: f.write('NETWORKING=yes\nHOSTNAME=%s\n' % vm_name) net_script = install_root + '/etc/sysconfig/network-scripts/ifcfg-eth0' with open(net_script, 'w') as f: f.write('DEVICE=eth0\nBOOTPROTO=dhcp\nONBOOT=yes\n') # Set root password and enable sshd session = aexpect.ShellSession("chroot %s" % install_root) session.sendline('echo %s|passwd root --stdin' % passwd) session.sendline('chkconfig sshd on') session.close() # Create result = virsh.create(vmxml.xml, **virsh_args) utlv.check_exit_status(result) check_state('running') # Destroy result = virsh.destroy(vm_name, **virsh_args) utlv.check_exit_status(result) if not virsh.domain_exists(vm_name, **virsh_args): logging.info("Destroy transient LXC domain successfully") else: raise TestFail("Transient LXC domain still exist after destroy") # Define result = virsh.define(vmxml.xml, **virsh_args) utlv.check_exit_status(result) check_state('shut off') # List result = virsh.dom_list('--inactive', **virsh_args) utlv.check_exit_status(result) if re.findall("(%s)\s+shut off" % vm_name, result.stdout): logging.info("Find %s in virsh list output", vm_name) else: raise TestFail("Not find %s in virsh list output") # Dumpxml result = virsh.dumpxml(vm_name, uri=uri, debug=False) utlv.check_exit_status(result) # Edit edit_vcpu = '2' logging.info("Change vcpu of LXC container to %s", edit_vcpu) edit_cmd = [r":%s /[0-9]*<\/vcpu>/" + edit_vcpu + r"<\/vcpu>"] if not utlv.exec_virsh_edit(vm_name, edit_cmd, connect_uri=uri): raise TestFail("Run edit command fail") else: result = virsh.dumpxml(vm_name, **virsh_args) new_vcpu = re.search(r'(\d*)</vcpu>', result.stdout).group(1) if new_vcpu == edit_vcpu: logging.info("vcpu number is expected after do edit") else: raise TestFail("vcpu number is unexpected after do edit") # Start result = virsh.start(vm_name, **virsh_args) utlv.check_exit_status(result) check_state('running') # Suspend result = virsh.suspend(vm_name, **virsh_args) utlv.check_exit_status(result) check_state('paused') # Resume result = virsh.resume(vm_name, **virsh_args) utlv.check_exit_status(result) check_state('running') # Reboot(not supported on RHEL6) result = virsh.reboot(vm_name, **virsh_args) supported_err = 'not supported by the connection driver: virDomainReboot' if supported_err in result.stderr.strip(): logging.info("Reboot is not supported") else: utlv.check_exit_status(result) # Destroy result = virsh.destroy(vm_name, **virsh_args) utlv.check_exit_status(result) check_state('shut off') # Undefine result = virsh.undefine(vm_name, **virsh_args) utlv.check_exit_status(result) if not virsh.domain_exists(vm_name, **virsh_args): logging.info("Undefine LXC domain successfully") else: raise TestFail("LXC domain still exist after undefine") finally: virsh.remove_domain(vm_name, **virsh_args) if full_os and os.path.exists(install_root): shutil.rmtree(install_root)