def result_confirm(self, params): """ Confirm if VM installation is succeed """ if self.twice_execute and self.kill_first: get_pid_cmd = "ps -ef | grep '%s' | grep qemu-kvm | grep -v grep"\ % self.vm_name result = utils.run(get_pid_cmd, ignore_status=True) if result.exit_status: raise error.TestFail("First install failed!") install_pid = result.stdout.strip().split()[1] utils_misc.safe_kill(int(install_pid), signal.SIGKILL) self.td.join() if self.read_only: if virsh.domain_exists(self.vm_name): raise error.TestFail("Domain '%s' should not exist" % self.vm_name) os.chmod(self.image_path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) else: if not virsh.domain_exists(self.vm_name): raise error.TestFail("Domain '%s' should exists, no matter its" " installation is succeed or failed!" % self.vm_name) else: if not self.kill_first: if self.vm.is_dead(): self.vm.start() try: self.vm.wait_for_login() except remote.LoginTimeoutError, detail: raise error.TestFail(str(detail)) else: virsh.remove_domain(self.vm_name)
def check_vm_state_after_abort(vm_name, vm_state_after_abort, src_uri, dest_uri, test): """ Check the VM state after domjobabort the migration :param vm_name: str, vm name :param vm_state_after_abort: str, like "{'source': 'running', 'target': 'nonexist'}" source: local host, target: remote host :param src_uri: uri for source host :param dest_uri: uri for target host :param test: test object """ state_dict = eval(vm_state_after_abort) logging.debug("Check guest state should be {} on source host".format( state_dict['source'])) libvirt.check_vm_state(vm_name, state=state_dict['source'], uri=src_uri) logging.debug("Check guest persistent on source host") cmd_res = virsh.domstats(vm_name, '--list-persistent', debug=True, ignore_status=False) if not cmd_res.stdout_text.count(vm_name): test.fail( "The guest is expected to be persistent on source host, but it isn't" ) logging.debug("Check guest state should be {} on target host".format( state_dict['target'])) if state_dict['target'] == 'nonexist': if virsh.domain_exists(vm_name, uri=dest_uri): test.fail("The domain on target host is found, but expected not") else: libvirt.check_vm_state(vm_name, state=state_dict['target'], uri=dest_uri)
def recover(self, params): """ Recover test environment """ abnormal_type = params.get("abnormal_type") cpu_enable = True if self.cpu_status else False utils_misc.set_cpu_status(self.cpu_num, cpu_enable) if virsh.domain_exists(self.vm_new_name): virsh.remove_domain(self.vm_new_name) if os.path.exists(self.new_image_file): os.remove(self.new_image_file) if self.twice_execute: if virsh.domain_exists(self.vm_new_name1): virsh.remove_domain(self.vm_new_name1) if os.path.exists(self.new_image_file1): os.remove(self.new_image_file1) if abnormal_type == "memory_lack": if params.has_key('memory_pid'): pid = params.get('memory_pid') if isinstance(pid,str): pid = int(pid) utils_misc.safe_kill(pid, signal.SIGKILL) utils.run("swapon -a") tmp_c_file = params.get("tmp_c_file", "/tmp/test.c") tmp_exe_file = params.get("tmp_exe_file", "/tmp/test") if os.path.exists(tmp_c_file): os.remove(tmp_c_file) if os.path.exists(tmp_exe_file): os.remove(tmp_exe_file) elif abnormal_type in ["disk_lack", ""]: if self.selinux_enforcing: utils_selinux.set_status("enforcing") tmp_file = os.path.join(self.mount_dir, "tmp") if os.path.exists(tmp_file): os.remove(tmp_file) # Sometimes one umount action is not enough utils_misc.wait_for(lambda: utils_misc.umount(self.partition, self.mount_dir, self.fs_type), 120) if self.iscsi_dev: self.iscsi_dev.cleanup() os.rmdir(self.mount_dir) elif abnormal_type == "cpu_lack": os.system("cat /sys/fs/cgroup/cpuset/cpuset.cpus > /sys/fs/cgroup/cpuset/machine.slice/cpuset.cpus") remove_machine_cgroup()
def recover(self, params): """ Recover test environment """ abnormal_type = params.get("abnormal_type") if self.cpu_status: cpu.offline(self.cpu_num) else: cpu.online(self.cpu_num) if virsh.domain_exists(self.vm_new_name): virsh.remove_domain(self.vm_new_name) if os.path.exists(self.new_image_file): os.remove(self.new_image_file) if self.twice_execute: if virsh.domain_exists(self.vm_new_name1): virsh.remove_domain(self.vm_new_name1) if os.path.exists(self.new_image_file1): os.remove(self.new_image_file1) if abnormal_type == "memory_lack": if 'memory_pid' in params: pid = params.get('memory_pid') utils_misc.safe_kill(pid, signal.SIGKILL) process.run("swapon -a", shell=True) tmp_c_file = params.get("tmp_c_file", "/tmp/test.c") tmp_exe_file = params.get("tmp_exe_file", "/tmp/test") if os.path.exists(tmp_c_file): os.remove(tmp_c_file) if os.path.exists(tmp_exe_file): os.remove(tmp_exe_file) elif abnormal_type in ["disk_lack", ""]: if self.selinux_enforcing: utils_selinux.set_status("enforcing") tmp_file = os.path.join(self.mount_dir, "tmp") if os.path.exists(tmp_file): os.remove(tmp_file) # Sometimes one umount action is not enough utils_misc.wait_for( lambda: utils_misc.umount(self.partition, self.mount_dir, self. fs_type), 120) if self.iscsi_dev: self.iscsi_dev.cleanup() os.rmdir(self.mount_dir) remove_machine_cgroup()
def recover(self, params): """ Recover test environment """ abnormal_type = params.get("abnormal_type") cpu_enable = True if self.cpu_status else False utils_misc.set_cpu_status(self.cpu_num, cpu_enable) if virsh.domain_exists(self.vm_new_name): virsh.remove_domain(self.vm_new_name) if os.path.exists(self.new_image_file): os.remove(self.new_image_file) if self.twice_execute: if virsh.domain_exists(self.vm_new_name1): virsh.remove_domain(self.vm_new_name1) if os.path.exists(self.new_image_file1): os.remove(self.new_image_file1) if abnormal_type == "memory_lack": if 'memory_pid' in params: pid = params.get('memory_pid') utils_misc.safe_kill(pid, signal.SIGKILL) process.run("swapon -a", shell=True) tmp_c_file = params.get("tmp_c_file", "/tmp/test.c") tmp_exe_file = params.get("tmp_exe_file", "/tmp/test") if os.path.exists(tmp_c_file): os.remove(tmp_c_file) if os.path.exists(tmp_exe_file): os.remove(tmp_exe_file) elif abnormal_type in ["disk_lack", ""]: if self.selinux_enforcing: utils_selinux.set_status("enforcing") tmp_file = os.path.join(self.mount_dir, "tmp") if os.path.exists(tmp_file): os.remove(tmp_file) # Sometimes one umount action is not enough utils_misc.wait_for(lambda: utils_misc.umount(self.partition, self.mount_dir, self.fs_type), 120) if self.iscsi_dev: self.iscsi_dev.cleanup() os.rmdir(self.mount_dir) remove_machine_cgroup()
def clean_clone_vm(): """ Clean up cloned domain. """ try: if virsh.domain_exists(vm_clone_name): if virsh.is_alive(vm_clone_name): virsh.destroy(vm_clone_name, ignore_status=False) virsh.undefine(vm_clone_name, ignore_status=False) if os.path.exists(clone_image): os.remove(clone_image) except error.CmdError, detail: raise error.TestFail("Clean clone guest failed!:%s" % detail)
def __init__(self, test, params): self.vm_name = params.get("vm_name", "test-vm1") while virsh.domain_exists(self.vm_name): self.vm_name += ".test" params["main_vm"] = self.vm_name ios_file = os.path.join(data_dir.get_data_dir(), params.get('cdrom_cd1')) if not os.path.exists(ios_file): raise error.TestNAError("Please prepare ios file:%s" % ios_file) self.env = params.get('env') self.vm = self.env.create_vm("libvirt", None, self.vm_name, params, test.bindir) self.env.register_vm(self.vm_name, self.vm) self.twice_execute = "yes" == params.get("twice_execute", "no") self.kill_first = "yes" == params.get("kill_first", "no") self.read_only = "yes" == params.get("read_only", "no") self.selinux_enforcing = utils_selinux.is_enforcing() if self.selinux_enforcing: utils_selinux.set_status("permissive") self.image_path = os.path.join(test.virtdir, "test_image") if not os.path.exists(self.image_path): os.mkdir(self.image_path) if self.read_only: os.chmod(self.image_path, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) params["image_name"] = os.path.join(self.image_path, self.vm_name) params["image_format"] = "raw" params['force_create_image'] = "yes" params['remove_image'] = "yes" params['shutdown_cleanly'] = "yes" params['shutdown_cleanly_timeout'] = 120 params['guest_port_unattended_install'] = 12323 params['inactivity_watcher'] = "error" params['inactivity_treshold'] = 1800 params['image_verify_bootable'] = "no" params['unattended_delivery_method'] = "cdrom" params['drive_index_unattended'] = 1 params['drive_index_cd1'] = 2 params['boot_once'] = "d" params['medium'] = "cdrom" params['wait_no_ack'] = "yes" params['image_raw_device'] = "yes" params['backup_image_before_testing'] = "no" params['kernel_params'] = ("ks=cdrom nicdelay=60 " "console=ttyS0,115200 console=tty0") params['cdroms'] += " unattended" params['redirs'] += " unattended_install" self.params = params self.test = test
def recover(self, params=None): """ Recover test environment """ if self.selinux_enforcing: utils_selinux.set_status("enforcing") if virsh.domain_exists(self.vm_name): virsh.remove_domain(self.vm_name) image_file = params.get("image_name") if os.path.exists(image_file): os.remove(image_file) if os.path.isdir(self.image_path): os.rmdir(self.image_path) self.env.unregister_vm(self.vm_name)
def __init__(self, test, params): self.vm_name = params.get("vm_name", "test-vm1") self.test = test while virsh.domain_exists(self.vm_name): self.vm_name += ".test" params["main_vm"] = self.vm_name ios_file = os.path.join(data_dir.get_data_dir(), params.get('cdrom_cd1')) if not os.path.exists(ios_file): self.test.cancel("Please prepare ios file:%s" % ios_file) self.env = params.get('env') self.vm = self.env.create_vm("libvirt", None, self.vm_name, params, test.bindir) self.env.register_vm(self.vm_name, self.vm) self.twice_execute = "yes" == params.get("twice_execute", "no") self.kill_first = "yes" == params.get("kill_first", "no") self.read_only = "yes" == params.get("read_only", "no") self.selinux_enforcing = utils_selinux.is_enforcing() if self.selinux_enforcing: utils_selinux.set_status("permissive") self.image_path = os.path.join(test.virtdir, "test_image") if not os.path.exists(self.image_path): os.mkdir(self.image_path) if self.read_only: os.chmod(self.image_path, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) params["image_name"] = os.path.join(self.image_path, self.vm_name) params["image_format"] = "raw" params['force_create_image'] = "yes" params['remove_image'] = "yes" params['shutdown_cleanly'] = "yes" params['shutdown_cleanly_timeout'] = 120 params['guest_port_unattended_install'] = 12323 params['inactivity_watcher'] = "error" params['inactivity_treshold'] = 1800 params['image_verify_bootable'] = "no" params['unattended_delivery_method'] = "cdrom" params['drive_index_unattended'] = 1 params['drive_index_cd1'] = 2 params['boot_once'] = "d" params['medium'] = "cdrom" params['wait_no_ack'] = "yes" params['image_raw_device'] = "yes" params['backup_image_before_testing'] = "no" params['kernel_params'] = ("ks=cdrom nicdelay=60 " "console=ttyS0,115200 console=tty0") params['cdroms'] += " unattended" params['redirs'] += " unattended_install" self.params = params
def result_confirm(self, params): """ Confirm if virt-clone executed succeed """ if self.kill_first: # Stop this threading first_pid = self.cgroup.get_pids(self.cgroup_index)[-1] utils_misc.safe_kill(int(first_pid), signal.SIGKILL) else: self.td0.join(self.time_out) if self.td1: self.td1.join(self.time_out) abnormal_type = params.get("abnormal_type") if abnormal_type == "cpu_lack": if not virsh.domain_exists(self.vm_new_name): raise error.TestFail("Clone '%s' failed" % self.vm_new_name) else: result = virsh.start(self.vm_new_name, ignore_status=True) if result.exit_status: raise error.TestFail("Cloned domain cannot be started!") elif abnormal_type == "disk_lack": if virsh.domain_exists(self.vm_new_name): raise error.TestFail("Clone '%s' succeed but expect failed!" % self.vm_new_name) else: if self.twice_execute and not self.kill_first: if virsh.domain_exists(self.vm_new_name): raise error.TestFail("Clone '%s' succeed but expect" " failed!" % self.vm_new_name) if virsh.domain_exists(self.vm_new_name1): raise error.TestFail("Clone '%s' succeed but expect" " failed!" % self.vm_new_name1) elif self.twice_execute and self.kill_first: if not virsh.domain_exists(self.vm_new_name): raise error.TestFail("Clone '%s' failed!" % self.vm_new_name)
def result_confirm(self, params): """ Confirm if virt-clone executed succeed """ if self.kill_first: # Stop this threading first_pid = self.cgroup.get_pids(self.cgroup_index)[-1] utils_misc.safe_kill(int(first_pid), signal.SIGKILL) else: self.td0.join(self.time_out) if self.td1: self.td1.join(self.time_out) abnormal_type = params.get("abnormal_type") if abnormal_type == "cpu_lack": if not virsh.domain_exists(self.vm_new_name): self.test.fail("Clone '%s' failed" % self.vm_new_name) else: result = virsh.start(self.vm_new_name, ignore_status=True) if result.exit_status: self.test.fail("Cloned domain cannot be started!") elif abnormal_type == "disk_lack": if virsh.domain_exists(self.vm_new_name): self.test.fail("Clone '%s' succeed but expect failed!" % self.vm_new_name) else: if self.twice_execute and not self.kill_first: if virsh.domain_exists(self.vm_new_name): self.test.fail("Clone '%s' succeed but expect" " failed!" % self.vm_new_name) if virsh.domain_exists(self.vm_new_name1): self.test.fail("Clone '%s' succeed but expect" " failed!" % self.vm_new_name1) elif self.twice_execute and self.kill_first: if not virsh.domain_exists(self.vm_new_name): self.test.fail("Clone '%s' failed!" % self.vm_new_name)
def run_test(self): """ Start test, clone a guest in a cgroup """ if virsh.domain_exists(self.vm_new_name): raise error.TestNAError("'%s' already exists! Please" " select another domain name!" % self.vm_new_name) if os.path.exists(self.new_image_file): os.remove(self.new_image_file) modules = utils_cgroup.CgroupModules(self.cgroup_dir) modules.init(['cpuset']) self.cgroup = utils_cgroup.Cgroup('cpuset', None) self.cgroup.initialize(modules) self.cgroup_index = self.cgroup.mk_cgroup(cgroup=self.cgroup_name) # Before use the cpu, set it to be enable if self.cpu_status < 1: utils_misc.set_cpu_status(self.cpu_num, True) self.cgroup.set_property("cpuset.cpus", self.cpu_num, self.cgroup_index, check=False) self.cgroup.set_property("cpuset.mems", 0, self.cgroup_index, check=False) self.td0 = threading.Thread( target=self.cgroup.cgexec, args=(self.cgroup_name, "virt-clone", "-o %s -n %s --force --file %s" % (self.vm_name, self.vm_new_name, self.new_image_file))) self.td1 = None if self.twice_execute: self.vm_new_name1 = self.vm_new_name + "1" self.new_image_file1 = self.new_image_file + "1" self.td1 = threading.Thread( target=self.cgroup.cgexec, args=(self.cgroup_name, "virt-clone", "-o %s -n %s --force --file %s" % (self.vm_name, self.vm_new_name1, self.new_image_file1))) self.td1.start() self.td0.start() # Wait for virt-clone has been started time.sleep(30)
def check_new_name(output, expected_name): """ Verify guest name changed to the new name. """ found = False if output_mode == "libvirt": found = virsh.domain_exists(expected_name) if output_mode == "local": found = os.path.isfile( os.path.join(output_storage, expected_name + "-sda")) if output_mode in ["rhev", "vdsm"]: ovf = get_ovf_content(output) found = "<Name>%s</Name>" % expected_name in ovf else: return if found: logging.info("Guest name renamed when converting it") else: test.fail("Rename guest failed")
def check_new_name(output, expected_name): """ Verify guest name changed to the new name. """ found = False if output_mode == "libvirt": found = virsh.domain_exists(expected_name) if output_mode == "local": found = os.path.isfile(os.path.join(output_storage, expected_name + "-sda")) if output_mode in ["rhev", "vdsm"]: ovf = get_ovf_content(output) found = "<Name>%s</Name>" % expected_name in ovf else: return if found: logging.info("Guest name renamed when converting it") else: raise exceptions.TestFail("Rename guest failed")
def run(test, params, env): """ Test svirt in virt-install. (1). Init variables. (2). Set selinux on host. (3). Set label of image. (4). run unattended install. (5). clean up. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("host_selinux", "enforcing") # Set selinux status on host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the image label. disk_label = params.get("disk_label", None) vm_name = params.get("main_vm", None) vm_params = params.object_params(vm_name) base_dir = params.get("images_base_dir", data_dir.get_data_dir()) image_filename = storage.get_image_filename(vm_params, base_dir) utils_selinux.set_context_of_file(image_filename, disk_label) try: try: unattended_install.run(test, params, env) # Install completed. if status_error: raise error.TestFail('Test successed in negative case.') except error.CmdError, e: # Install failed. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # cleanup utils_selinux.set_status(backup_sestatus) if virsh.domain_exists(vm_name): virsh.remove_domain(vm_name)
def cleanup_dest(vm, src_uri=""): """ Clean up the destination host environment when doing the uni-direction migration. """ logging.info("Cleaning up VMs on %s" % vm.connect_uri) try: if virsh.domain_exists(vm.name, uri=vm.connect_uri): vm_state = vm.state() if vm_state == "paused": vm.resume() elif vm_state == "shut off": vm.start() vm.destroy(gracefully=False) if vm.is_persistent(): vm.undefine() except Exception, detail: logging.error("Cleaning up destination failed.\n%s" % detail)
def cleanup_dest(vm, src_uri=""): """ Clean up the destination host environment when doing the uni-direction migration. """ logging.info("Cleaning up VMs on %s" % vm.connect_uri) try: if virsh.domain_exists(vm.name, uri=vm.connect_uri): vm_state = vm.state() if vm_state == "paused": vm.resume() elif vm_state == "shut off": vm.start() vm.destroy() if vm.is_persistent(): vm.undefine() except Exception, detail: logging.error("Cleaning up destination failed.\n%s" % detail)
def run_test(self): """ Start test, clone a guest in a cgroup """ if virsh.domain_exists(self.vm_new_name): self.test.cancel("'%s' already exists! Please" " select another domain name!" % self.vm_new_name) if os.path.exists(self.new_image_file): os.remove(self.new_image_file) modules = utils_cgroup.CgroupModules(self.cgroup_dir) modules.init(['cpuset']) self.cgroup = utils_cgroup.Cgroup('cpuset', None) self.cgroup.initialize(modules) self.cgroup_index = self.cgroup.mk_cgroup(cgroup=self.cgroup_name) # Before use the cpu, set it to be enable if self.cpu_status < 1: utils_misc.set_cpu_status(self.cpu_num, True) self.cgroup.set_property("cpuset.cpus", self.cpu_num, self.cgroup_index, check=False) self.cgroup.set_property("cpuset.mems", 0, self.cgroup_index, check=False) self.td0 = threading.Thread(target=self.cgroup.cgexec, args=(self.cgroup_name, "virt-clone", "-o %s -n %s --force --file %s" % (self.vm_name, self.vm_new_name, self.new_image_file))) self.td1 = None if self.twice_execute: self.vm_new_name1 = self.vm_new_name + "1" self.new_image_file1 = self.new_image_file + "1" self.td1 = threading.Thread(target=self.cgroup.cgexec, args=(self.cgroup_name, "virt-clone", "-o %s -n %s --force --file %s" % (self.vm_name, self.vm_new_name1, self.new_image_file1))) self.td1.start() self.td0.start() # Wait for virt-clone has been started time.sleep(30)
def cleanup_dest(vm): """ Clean up the destination host environment when doing the uni-direction migration. :param vm: the guest to be cleaned up """ logging.info("Cleaning up VMs on %s", vm.connect_uri) try: if virsh.domain_exists(vm.name, uri=vm.connect_uri): vm_state = vm.state() if vm_state == "paused": vm.resume() elif vm_state == "shut off": vm.start() vm.destroy(gracefully=False) if vm.is_persistent(): vm.undefine() except Exception as detail: logging.error("Cleaning up destination failed.\n%s", detail)
def run_virsh_undefine(test, params, env): """ Test virsh undefine command. Undefine an inactive domain, or convert persistent to transient. 1.Prepare test environment. 2.Backup the VM's information to a xml file. 3.When the libvirtd == "off", stop the libvirtd service. 4.Perform virsh undefine operation. 5.Recover test environment.(libvirts service,VM) 6.Confirm the test result. """ vm_ref = params.get("undefine_vm_ref", "vm_name") extra = params.get("undefine_extra", "") libvirtd_state = params.get("libvirtd", "on") status_error = params.get("status_error") undefine_twice = params.get("undefine_twice", 'no') local_ip = params.get("local_ip", "LOCAL.EXAMPLE.COM") remote_ip = params.get("remote_ip", "REMOTE.EXAMPLE.COM") xml_file = os.path.join(test.tmpdir, 'tmp.xml') remote_user = params.get("remote_user", "user") remote_password = params.get("remote_password", "password") remote_prompt = params.get("remote_prompt", "#") vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vm_id = vm.get_id() vm_uuid = vm.get_uuid() # Back up xml file.Xen host has no guest xml file to define a guset. virsh.dumpxml(vm_name, extra="", to_file=xml_file) # Confirm how to reference a VM. if vm_ref == "vm_name": vm_ref = vm_name elif vm_ref == "id": vm_ref = vm_id elif vm_ref == "hex_vm_id": vm_ref = hex(int(vm_id)) elif vm_ref == "uuid": vm_ref = vm_uuid elif vm_ref.find("invalid") != -1: vm_ref = params.get(vm_ref) # Turn libvirtd into certain state. if libvirtd_state == "off": utils_libvirtd.libvirtd_stop() # Test virsh undefine command. status = 0 try: uri = libvirt_vm.complete_uri(local_ip) except error.CmdError: status = 1 uri = None if vm_ref != "remote": vm_ref = "%s %s" % (vm_ref, extra) cmdresult = virsh.undefine(vm_ref, uri=uri, ignore_status=True, debug=True) status = cmdresult.exit_status if status: logging.debug("Error status, command output: %s", cmdresult.stdout) if undefine_twice == "yes": status2 = virsh.undefine(vm_ref, uri=uri, ignore_status=True).exit_status else: if remote_ip.count("EXAMPLE.COM") or local_ip.count("EXAMPLE.COM"): raise error.TestNAError("remote_ip and/or local_ip parameters not" " changed from default values") session = remote.remote_login("ssh", remote_ip, "22", remote_user, remote_password, remote_prompt) cmd_undefine = "virsh -c %s undefine %s" % (uri, vm_name) status, output = session.cmd_status_output(cmd_undefine) logging.info("Undefine output: %s", output) # Recover libvirtd state. if libvirtd_state == "off": utils_libvirtd.libvirtd_start() # Shutdown VM. if virsh.domain_exists(vm.name, uri=uri): try: if vm.is_alive(): vm.destroy() except error.CmdError, detail: logging.error("Detail: %s", detail)
user_pwd = "[['%s', '%s']]" % (params.get("sasl_user"), params.get("sasl_pwd")) v2v_sasl = utils_sasl.SASL(sasl_user_pwd=user_pwd) v2v_sasl.server_ip = params.get("remote_ip") v2v_sasl.server_user = params.get('remote_user') v2v_sasl.server_pwd = params.get('remote_pwd') v2v_sasl.setup(remote=True) # Create libvirt dir pool if output_mode == 'libvirt': pvt.pre_pool(pool_name, pool_type, pool_target, '') uri = utils_v2v.Uri('xen').get_uri(xen_host) # Check if xen guest exists if not virsh.domain_exists(vm_name, uri=uri): logging.error('VM %s not exists', vm_name) if checkpoint in bk_list: virsh_instance = virsh.VirshPersistent() virsh_instance.set_uri(uri) bk_xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) if checkpoint == 'guest_uuid': uuid = virsh.domuuid(vm_name, uri=uri).stdout.strip() v2v_params['main_vm'] = uuid elif checkpoint == 'xvda_disk': v2v_params['input_mode'] = 'disk' # Get remote disk image path blklist = virsh.domblklist(vm_name, uri=uri).stdout.split('\n') logging.debug('domblklist %s:\n%s', vm_name, blklist)
status = 1 # Recover libvirtd state. if libvirtd_state == "off": utils_libvirtd.libvirtd_start() # Shutdown VM. if virsh.domain_exists(vm.name): try: if vm.is_alive(): vm.destroy(gracefully=False) except error.CmdError, detail: logging.error("Detail: %s", detail) # Check if VM exists. vm_exist = virsh.domain_exists(vm_name) # Check if xml file exists. xml_exist = False if vm.is_qemu() and os.path.exists("/etc/libvirt/qemu/%s.xml" % vm_name): xml_exist = True if vm.is_lxc() and os.path.exists("/etc/libvirt/lxc/%s.xml" % vm_name): xml_exist = True if vm.is_xen() and os.path.exists("/etc/xen/%s" % vm_name): xml_exist = True # Check if save file exists if use --managed-save save_exist = False if os.path.exists(save_file): save_exist = True
def run(test, params, env): """ Test virsh domblkthreshold option. 1.Prepare backend storage (file/luks/iscsi/gluster/ceph/nbd) 2.Start VM 3.Set domblkthreshold on target device in VM 4.Trigger one threshold event 5.Check threshold event is received as expected 6.Clean up test environment """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) virsh_dargs = {'debug': True, 'ignore_status': True} block_threshold_timeout = params.get("block_threshold_timeout", "120") event_type = params.get("event_type", "block-threshold") block_threshold_option = params.get("block_threshold_option", "--loop") def set_vm_block_domblkthreshold(vm_name, target_device, threshold, **dargs): """ Set VM block threshold on specific target device. :param vm_name: VM name. :param target_device: target device in VM :param threshold: threshold value with specific unit such as 100M :param dargs: mutable parameter dict """ ret = virsh.domblkthreshold(vm_name, target_device, threshold, **dargs) libvirt.check_exit_status(ret) def trigger_block_threshold_event(vm_domain, target): """ Trigger block threshold event. :param vm_domain: VM name :param target: Disk dev in VM. """ try: session = vm_domain.wait_for_login() time.sleep(10) cmd = ("fdisk -l /dev/{0} && mkfs.ext4 -F /dev/{0} && " " mount /dev/{0} /mnt && " " dd if=/dev/urandom of=/mnt/bigfile bs=1M count=101" .format(target)) status, output = session.cmd_status_output(cmd) if status: test.error("Failed to mount and fill data in VM: %s" % output) except (remote.LoginError, virt_vm.VMError, aexpect.ShellError) as e: logging.error(str(e)) raise def check_threshold_event(vm_name, event_type, event_timeout, options, **dargs): """ Check threshold event. :param vm_name: VM name :param event_type: event type. :param event_timeout: event timeout value :param options: event option :dargs: dynamic parameters. """ ret = virsh.event(vm_name, event_type, event_timeout, options, **dargs) logging.debug(ret.stdout_text) libvirt.check_exit_status(ret) def create_vol(p_name, vol_params): """ Create volume. :param p_name: Pool name. :param vol_params: Volume parameters dict. """ # Clean up dirty volumes if pool has. pv = libvirt_storage.PoolVolume(p_name) vol_name_list = pv.list_volumes() for vol_name in vol_name_list: pv.delete_volume(vol_name) volxml = vol_xml.VolXML() v_xml = volxml.new_vol(**vol_params) v_xml.xmltreefile.write() ret = virsh.vol_create(p_name, v_xml.xml, **virsh_dargs) libvirt.check_exit_status(ret) def trigger_block_commit(vm_name, target, blockcommit_options, **virsh_dargs): """ Trigger blockcommit. :param vm_name: VM name :param target: Disk dev in VM. :param blockcommit_options: blockcommit option :param virsh_dargs: additional parameters """ result = virsh.blockcommit(vm_name, target, blockcommit_options, ignore_status=False, **virsh_dargs) def trigger_block_copy(vm_name, target, dest_path, blockcopy_options, **virsh_dargs): """ Trigger blockcopy :param vm_name: string, VM name :param target: string, target disk :param dest_path: string, the path of copied disk :param blockcopy_options: string, some options applied :param virsh_dargs: additional options """ result = virsh.blockcopy(vm_name, target, dest_path, blockcopy_options, **virsh_dargs) libvirt.check_exit_status(result) def trigger_mirror_threshold_event(vm_domain, target): """ Trigger mirror mode block threshold event. :param vm_domain: VM name :param target: Disk target in VM. """ try: session = vm_domain.wait_for_login() # Sleep 10 seconds to let wait for events thread start first in main thread time.sleep(10) cmd = ("dd if=/dev/urandom of=file bs=1G count=3") status, output = session.cmd_status_output(cmd) if status: test.error("Failed to fill data in VM target: %s with %s" % (target, output)) except (remote.LoginError, virt_vm.VMError, aexpect.ShellError) as e: logging.error(str(e)) raise except Exception as ex: raise def get_mirror_source_index(vm_name, dev_index=0): """ Get mirror source index :param vm_name: VM name :param dev_index: Disk device index. :return mirror source index in integer """ disk_list = vm_xml.VMXML.get_disk_source(vm_name) disk_mirror = disk_list[dev_index].find('mirror') if disk_mirror is None: test.fail("Failed to get disk mirror") disk_mirror_source = disk_mirror.find('source') return int(disk_mirror_source.get('index')) # Disk specific attributes. device = params.get("virt_disk_device", "disk") device_target = params.get("virt_disk_device_target", "vdd") device_format = params.get("virt_disk_device_format", "raw") device_type = params.get("virt_disk_device_type", "file") device_bus = params.get("virt_disk_device_bus", "virtio") backend_storage_type = params.get("backend_storage_type", "iscsi") # Backend storage auth info storage_size = params.get("storage_size", "1G") enable_auth = "yes" == params.get("enable_auth") use_auth_usage = "yes" == params.get("use_auth_usage") auth_sec_usage_type = params.get("auth_sec_usage_type", "iscsi") auth_sec_usage_target = params.get("auth_sec_usage_target", "libvirtiscsi") auth_sec_uuid = "" luks_sec_uuid = "" disk_auth_dict = {} disk_encryption_dict = {} status_error = "yes" == params.get("status_error") define_error = "yes" == params.get("define_error") mirror_mode_blockcommit = "yes" == params.get("mirror_mode_blockcommit", "no") mirror_mode_blockcopy = "yes" == params.get("mirror_mode_blockcopy", "no") default_snapshot_test = "yes" == params.get("default_snapshot_test", "no") block_threshold_value = params.get("block_threshold_value", "100M") snapshot_external_disks = [] tmp_dir = data_dir.get_tmp_dir() dest_path = params.get("dest_path", "/var/lib/libvirt/images/newclone") pvt = None # Initialize one NbdExport object nbd = None img_file = os.path.join(data_dir.get_tmp_dir(), "%s_test.img" % vm_name) if ((backend_storage_type == "luks") and not libvirt_version.version_compare(3, 9, 0)): test.cancel("Cannot support <encryption> inside disk in this libvirt version.") # Start VM and get all partitions in VM. if vm.is_dead(): vm.start() session = vm.wait_for_login() old_parts = utils_disk.get_parts_list(session) session.close() vm.destroy(gracefully=False) # Back up xml file. vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Additional disk images. disks_img = [] try: # Clean up dirty secrets in test environments if there are. utils_secret.clean_up_secrets() # Setup backend storage if backend_storage_type == "file": image_filename = params.get("image_filename", "raw.img") disk_path = os.path.join(data_dir.get_tmp_dir(), image_filename) device_source = libvirt.create_local_disk(backend_storage_type, disk_path, storage_size, device_format) disks_img.append({"format": device_format, "source": disk_path, "path": disk_path}) disk_src_dict = {'attrs': {'file': device_source, 'type_name': 'file'}} # Setup backend storage elif backend_storage_type == "luks": luks_encrypt_passwd = params.get("luks_encrypt_passwd", "password") luks_secret_passwd = params.get("luks_secret_passwd", "password") # Create secret luks_sec_uuid = libvirt.create_secret(params) logging.debug("A secret created with uuid = '%s'", luks_sec_uuid) virsh.secret_set_value(luks_sec_uuid, luks_secret_passwd, encode=True, ignore_status=False, debug=True) image_filename = params.get("image_filename", "raw.img") device_source = os.path.join(data_dir.get_tmp_dir(), image_filename) disks_img.append({"format": device_format, "source": device_source, "path": device_source}) disk_src_dict = {'attrs': {'file': device_source, 'type_name': 'file'}} disk_encryption_dict = {"encryption": "luks", "secret": {"type": "passphrase", "uuid": luks_sec_uuid}} cmd = ("qemu-img create -f luks " "--object secret,id=sec0,data=`printf '%s' | base64`,format=base64 " "-o key-secret=sec0 %s %s" % (luks_encrypt_passwd, device_source, storage_size)) if process.system(cmd, shell=True): test.error("Can't create a luks encrypted img by qemu-img") elif backend_storage_type == "iscsi": iscsi_host = params.get("iscsi_host") iscsi_port = params.get("iscsi_port") if device_type == "block": device_source = libvirt.setup_or_cleanup_iscsi(is_setup=True) disk_src_dict = {'attrs': {'dev': device_source}} elif device_type == "network": chap_user = params.get("chap_user", "redhat") chap_passwd = params.get("chap_passwd", "password") auth_sec_usage = params.get("auth_sec_usage", "libvirtiscsi") auth_sec_dict = {"sec_usage": "iscsi", "sec_target": auth_sec_usage} auth_sec_uuid = libvirt.create_secret(auth_sec_dict) # Set password of auth secret (not luks encryption secret) virsh.secret_set_value(auth_sec_uuid, chap_passwd, encode=True, ignore_status=False, debug=True) iscsi_target, lun_num = libvirt.setup_or_cleanup_iscsi( is_setup=True, is_login=False, image_size=storage_size, chap_user=chap_user, chap_passwd=chap_passwd, portal_ip=iscsi_host) # ISCSI auth attributes for disk xml disk_auth_dict = {"auth_user": chap_user, "secret_type": auth_sec_usage_type, "secret_usage": auth_sec_usage_target} device_source = "iscsi://%s:%s/%s/%s" % (iscsi_host, iscsi_port, iscsi_target, lun_num) disk_src_dict = {"attrs": {"protocol": "iscsi", "name": "%s/%s" % (iscsi_target, lun_num)}, "hosts": [{"name": iscsi_host, "port": iscsi_port}]} elif backend_storage_type == "gluster": gluster_vol_name = params.get("gluster_vol_name", "gluster_vol1") gluster_pool_name = params.get("gluster_pool_name", "gluster_pool1") gluster_img_name = params.get("gluster_img_name", "gluster1.img") gluster_host_ip = gluster.setup_or_cleanup_gluster( is_setup=True, vol_name=gluster_vol_name, pool_name=gluster_pool_name, **params) device_source = "gluster://%s/%s/%s" % (gluster_host_ip, gluster_vol_name, gluster_img_name) cmd = ("qemu-img create -f %s " "%s %s" % (device_format, device_source, storage_size)) if process.system(cmd, shell=True): test.error("Can't create a gluster type img by qemu-img") disk_src_dict = {"attrs": {"protocol": "gluster", "name": "%s/%s" % (gluster_vol_name, gluster_img_name)}, "hosts": [{"name": gluster_host_ip, "port": "24007"}]} elif backend_storage_type == "ceph": ceph_host_ip = params.get("ceph_host_ip", "EXAMPLE_HOSTS") ceph_mon_ip = params.get("ceph_mon_ip", "EXAMPLE_MON_HOST") ceph_host_port = params.get("ceph_host_port", "EXAMPLE_PORTS") ceph_disk_name = params.get("ceph_disk_name", "EXAMPLE_SOURCE_NAME") ceph_client_name = params.get("ceph_client_name") ceph_client_key = params.get("ceph_client_key") ceph_auth_user = params.get("ceph_auth_user") ceph_auth_key = params.get("ceph_auth_key") enable_auth = "yes" == params.get("enable_auth") key_file = os.path.join(data_dir.get_tmp_dir(), "ceph.key") key_opt = "" # Prepare a blank params to confirm if delete the configure at the end of the test ceph_cfg = "" if not utils_package.package_install(["ceph-common"]): test.error("Failed to install ceph-common") # Create config file if it doesn't exist ceph_cfg = ceph.create_config_file(ceph_mon_ip) # If enable auth, prepare a local file to save key if ceph_client_name and ceph_client_key: with open(key_file, 'w') as f: f.write("[%s]\n\tkey = %s\n" % (ceph_client_name, ceph_client_key)) key_opt = "--keyring %s" % key_file auth_sec_dict = {"sec_usage": auth_sec_usage_type, "sec_name": "ceph_auth_secret"} auth_sec_uuid = libvirt.create_secret(auth_sec_dict) virsh.secret_set_value(auth_sec_uuid, ceph_auth_key, debug=True) disk_auth_dict = {"auth_user": ceph_auth_user, "secret_type": auth_sec_usage_type, "secret_uuid": auth_sec_uuid} else: test.error("No ceph client name/key provided.") device_source = "rbd:%s:mon_host=%s:keyring=%s" % (ceph_disk_name, ceph_mon_ip, key_file) cmd = ("rbd -m {0} {1} info {2} && rbd -m {0} {1} rm " "{2}".format(ceph_mon_ip, key_opt, ceph_disk_name)) cmd_result = process.run(cmd, ignore_status=True, shell=True) logging.debug("pre clean up rbd disk if exists: %s", cmd_result) # Create an local image and make FS on it. disk_cmd = ("qemu-img create -f %s %s %s" % (device_format, img_file, storage_size)) process.run(disk_cmd, ignore_status=False, shell=True) # Convert the image to remote storage disk_path = ("rbd:%s:mon_host=%s" % (ceph_disk_name, ceph_mon_ip)) if ceph_client_name and ceph_client_key: disk_path += (":id=%s:key=%s" % (ceph_auth_user, ceph_auth_key)) rbd_cmd = ("rbd -m %s %s info %s 2> /dev/null|| qemu-img convert -O" " %s %s %s" % (ceph_mon_ip, key_opt, ceph_disk_name, device_format, img_file, disk_path)) process.run(rbd_cmd, ignore_status=False, shell=True) disk_src_dict = {"attrs": {"protocol": "rbd", "name": ceph_disk_name}, "hosts": [{"name": ceph_host_ip, "port": ceph_host_port}]} elif backend_storage_type == "nfs": pool_name = params.get("pool_name", "nfs_pool") pool_target = params.get("pool_target", "nfs_mount") pool_type = params.get("pool_type", "netfs") nfs_server_dir = params.get("nfs_server_dir", "nfs_server") emulated_image = params.get("emulated_image") image_name = params.get("nfs_image_name", "nfs.img") tmp_dir = data_dir.get_tmp_dir() pvt = libvirt.PoolVolumeTest(test, params) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image) # Set virt_use_nfs virt_use_nfs = params.get("virt_use_nfs", "off") result = process.run("setsebool virt_use_nfs %s" % virt_use_nfs, shell=True) if result.exit_status: test.error("Failed to set virt_use_nfs value") nfs_mount_dir = os.path.join(tmp_dir, pool_target) device_source = nfs_mount_dir + image_name # Create one image on nfs server libvirt.create_local_disk("file", device_source, '1', "raw") disks_img.append({"format": device_format, "source": device_source, "path": device_source}) disk_src_dict = {'attrs': {'file': device_source, 'type_name': 'file'}} # Create dir based pool,and then create one volume on it. elif backend_storage_type == "dir": pool_name = params.get("pool_name", "dir_pool") pool_target = params.get("pool_target") pool_type = params.get("pool_type") emulated_image = params.get("emulated_image") image_name = params.get("dir_image_name", "luks_1.img") # Create and start dir_based pool. pvt = libvirt.PoolVolumeTest(test, params) if not os.path.exists(pool_target): os.mkdir(pool_target) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image) sp = libvirt_storage.StoragePool() if not sp.is_pool_active(pool_name): sp.set_pool_autostart(pool_name) sp.start_pool(pool_name) # Create one volume on the pool. volume_name = params.get("vol_name") volume_alloc = params.get("vol_alloc") volume_cap_unit = params.get("vol_cap_unit") volume_cap = params.get("vol_cap") volume_target_path = params.get("sec_volume") volume_target_format = params.get("target_format") volume_target_encypt = params.get("target_encypt", "") volume_target_label = params.get("target_label") vol_params = {"name": volume_name, "capacity": int(volume_cap), "allocation": int(volume_alloc), "format": volume_target_format, "path": volume_target_path, "label": volume_target_label, "capacity_unit": volume_cap_unit} try: # If Libvirt version is lower than 2.5.0 # Creating luks encryption volume is not supported,so skip it. create_vol(pool_name, vol_params) except AssertionError as info: err_msgs = ("create: invalid option") if str(info).count(err_msgs): test.cancel("Creating luks encryption volume " "is not supported on this libvirt version") else: test.error("Failed to create volume." "Error: %s" % str(info)) disk_src_dict = {'attrs': {'file': volume_target_path}} device_source = volume_target_path elif backend_storage_type == "nbd": # Get server hostname. hostname = process.run('hostname', ignore_status=False, shell=True, verbose=True).stdout_text.strip() # Setup backend storage nbd_server_host = hostname nbd_server_port = params.get("nbd_server_port") image_path = params.get("emulated_image", "/var/lib/libvirt/images/nbdtest.img") # Create NbdExport object nbd = NbdExport(image_path, image_format=device_format, port=nbd_server_port) nbd.start_nbd_server() # Prepare disk source xml source_attrs_dict = {"protocol": "nbd"} disk_src_dict = {} disk_src_dict.update({"attrs": source_attrs_dict}) disk_src_dict.update({"hosts": [{"name": nbd_server_host, "port": nbd_server_port}]}) device_source = "nbd://%s:%s/%s" % (nbd_server_host, nbd_server_port, image_path) logging.debug("device source is: %s", device_source) # Add disk xml. vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disk_xml = Disk(type_name=device_type) disk_xml.device = device disk_xml.target = {"dev": device_target, "bus": device_bus} driver_dict = {"name": "qemu", "type": device_format} disk_xml.driver = driver_dict disk_source = disk_xml.new_disk_source(**disk_src_dict) if disk_auth_dict: logging.debug("disk auth dict is: %s" % disk_auth_dict) disk_xml.auth = disk_xml.new_auth(**disk_auth_dict) if disk_encryption_dict: disk_encryption_dict = {"encryption": "luks", "secret": {"type": "passphrase", "uuid": luks_sec_uuid}} disk_encryption = disk_xml.new_encryption(**disk_encryption_dict) disk_xml.encryption = disk_encryption disk_xml.source = disk_source logging.debug("new disk xml is: %s", disk_xml) # Sync VM xml except mirror_mode_blockcommit or mirror_mode_blockcopy if (not mirror_mode_blockcommit and not mirror_mode_blockcopy): vmxml.add_device(disk_xml) try: vmxml.sync() vm.start() vm.wait_for_login().close() except xcepts.LibvirtXMLError as xml_error: if not define_error: test.fail("Failed to define VM:\n%s", str(xml_error)) except virt_vm.VMStartError as details: # When use wrong password in disk xml for cold plug cases, # VM cannot be started if status_error: logging.info("VM failed to start as expected: %s", str(details)) else: test.fail("VM should start but failed: %s" % str(details)) func_name = trigger_block_threshold_event # Additional operations before set block threshold if backend_storage_type == "file": logging.info("Create snapshot...") snap_opt = " %s --disk-only " snap_opt += "%s,snapshot=external,file=%s" if default_snapshot_test: for index in range(1, 5): snapshot_name = "snapshot_%s" % index snap_path = "%s/%s_%s.snap" % (tmp_dir, vm_name, index) snapshot_external_disks.append(snap_path) snap_option = snap_opt % (snapshot_name, device_target, snap_path) virsh.snapshot_create_as(vm_name, snap_option, ignore_status=False, debug=True) if mirror_mode_blockcommit: if not libvirt_version.version_compare(6, 6, 0): test.cancel("Set threshold for disk mirroring feature is not supported on current version") vmxml.del_device(disk_xml) virsh.snapshot_create_as(vm_name, "--disk-only --no-metadata", ignore_status=False, debug=True) # Do active blockcommit in background. blockcommit_options = "--active" mirror_blockcommit_thread = threading.Thread(target=trigger_block_commit, args=(vm_name, 'vda', blockcommit_options,), kwargs={'debug': True}) mirror_blockcommit_thread.start() device_target = "vda[1]" func_name = trigger_mirror_threshold_event if mirror_mode_blockcopy: if not libvirt_version.version_compare(6, 6, 0): test.cancel("Set threshold for disk mirroring feature is not supported on current version") # Do transient blockcopy in backgroud. blockcopy_options = "--transient-job " # Do cleanup if os.path.exists(dest_path): libvirt.delete_local_disk("file", dest_path) mirror_blockcopy_thread = threading.Thread(target=trigger_block_copy, args=(vm_name, 'vda', dest_path, blockcopy_options,), kwargs={'debug': True}) mirror_blockcopy_thread.start() mirror_blockcopy_thread.join(10) device_target = "vda[%d]" % get_mirror_source_index(vm_name) func_name = trigger_mirror_threshold_event set_vm_block_domblkthreshold(vm_name, device_target, block_threshold_value, **{"debug": True}) cli_thread = threading.Thread(target=func_name, args=(vm, device_target)) cli_thread.start() check_threshold_event(vm_name, event_type, block_threshold_timeout, block_threshold_option, **{"debug": True}) finally: # Delete snapshots. if virsh.domain_exists(vm_name): #To delete snapshot, destroy VM first. if vm.is_alive(): vm.destroy() libvirt.clean_up_snapshots(vm_name, domxml=vmxml_backup) vmxml_backup.sync("--snapshots-metadata") if os.path.exists(img_file): libvirt.delete_local_disk("file", img_file) for img in disks_img: if os.path.exists(img["path"]): libvirt.delete_local_disk("file", img["path"]) for disk in snapshot_external_disks: libvirt.delete_local_disk('file', disk) if os.path.exists(dest_path): libvirt.delete_local_disk("file", dest_path) # Clean up backend storage if backend_storage_type == "iscsi": libvirt.setup_or_cleanup_iscsi(is_setup=False) elif backend_storage_type == "gluster": gluster.setup_or_cleanup_gluster(is_setup=False, vol_name=gluster_vol_name, pool_name=gluster_pool_name, **params) elif backend_storage_type == "ceph": # Remove ceph configure file if created. if ceph_cfg: os.remove(ceph_cfg) cmd = ("rbd -m {0} {1} info {2} && rbd -m {0} {1} rm " "{2}".format(ceph_mon_ip, key_opt, ceph_disk_name)) cmd_result = process.run(cmd, ignore_status=True, shell=True) logging.debug("result of rbd removal: %s", cmd_result) if os.path.exists(key_file): os.remove(key_file) elif backend_storage_type == "nfs": result = process.run("setsebool virt_use_nfs off", shell=True) if result.exit_status: logging.info("Failed to restore virt_use_nfs value") elif backend_storage_type == "nbd": if nbd: try: nbd.cleanup() except Exception as ndbEx: logging.info("Clean Up nbd failed: %s" % str(ndbEx)) # Clean up secrets if auth_sec_uuid: virsh.secret_undefine(auth_sec_uuid) if luks_sec_uuid: virsh.secret_undefine(luks_sec_uuid) # Clean up pools if pvt: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_image)
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 run(test, params, env): """ Convert specific xen guest """ for v in list(params.values()): if "V2V_EXAMPLE" in v: test.cancel("Please set real value for %s" % v) if utils_v2v.V2V_EXEC is None: test.cancel('Missing command: virt-v2v') vm_name = params.get('main_vm') new_vm_name = params.get('new_vm_name') xen_host = params.get('xen_hostname') xen_host_user = params.get('xen_host_user', 'root') xen_host_passwd = params.get('xen_host_passwd', 'redhat') output_mode = params.get('output_mode') v2v_timeout = int(params.get('v2v_timeout', 1200)) status_error = 'yes' == params.get('status_error', 'no') pool_name = params.get('pool_name', 'v2v_test') pool_type = params.get('pool_type', 'dir') pool_target = params.get('pool_target_path', 'v2v_pool') pvt = libvirt.PoolVolumeTest(test, params) address_cache = env.get('address_cache') checkpoint = params.get('checkpoint', '') bk_list = ['vnc_autoport', 'vnc_encrypt', 'vnc_encrypt_warning'] error_list = [] def log_fail(msg): """ Log error and update error list """ logging.error(msg) error_list.append(msg) def set_graphics(virsh_instance, param): """ Set graphics attributes of vm xml """ vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name, virsh_instance=virsh_instance) graphic = vmxml.xmltreefile.find('devices').find('graphics') for key in param: logging.debug('Set %s=\'%s\'' % (key, param[key])) graphic.set(key, param[key]) vmxml.sync(virsh_instance=virsh_instance) def check_rhev_file_exist(vmcheck): """ Check if rhev files exist """ file_path = { 'rhev-apt.exe': r'C:\rhev-apt.exe', 'rhsrvany.exe': r'"C:\program files\redhat\rhev\apt\rhsrvany.exe"' } fail = False for key in file_path: status = vmcheck.session.cmd_status('dir %s' % file_path[key]) if not status: logging.error('%s exists' % key) fail = True if fail: log_fail('RHEV file exists after convert to kvm') def check_grub_file(vmcheck, check): """ Check grub file content """ logging.info('Checking grub file') grub_file = utils_misc.get_bootloader_cfg(session=vmcheck.session) if not grub_file: test.error('Not found grub file') content = vmcheck.session.cmd('cat %s' % grub_file) if check == 'console_xvc0': if 'console=xvc0' in content: log_fail('"console=xvc0" still exists') def check_kernel(vmcheck): """ Check content of /etc/sysconfig/kernel """ logging.info('Checking /etc/sysconfig/kernel file') content = vmcheck.session.cmd('cat /etc/sysconfig/kernel') logging.debug(content) if 'DEFAULTKERNEL=kernel' not in content: log_fail('Not find "DEFAULTKERNEL=kernel"') elif 'DEFAULTKERNEL=kernel-xen' in content: log_fail('DEFAULTKERNEL is "kernel-xen"') def check_sound_card(vmcheck, check): """ Check sound status of vm from xml """ xml = virsh.dumpxml(vm_name, session_id=vmcheck.virsh_session_id).stdout logging.debug(xml) if check == 'sound' and '<sound model' in xml: log_fail('Sound card should be removed') if check == 'pcspk' and "<sound model='pcspk'" not in xml: log_fail('Sound card should be "pcspk"') def check_rhsrvany_md5(vmcheck): """ Check if MD5 and SHA1 of rhsrvany.exe are correct """ logging.info('Check md5 and sha1 of rhsrvany.exe') val_md5, val_sha1 = params.get('val_md5'), params.get('val_sha1') logging.info('Expect MD5=%s, SHA1=%s', val_md5, val_sha1) if not val_md5 or not val_sha1: test.error('No MD5 or SHA1 value provided') cmd_sha1 = params.get('cmd_sha1') cmd_md5 = cmd_sha1 + ' MD5' sha1 = vmcheck.session.cmd_output(cmd_sha1, safe=True).strip().split('\n')[1].replace(' ', '') md5 = vmcheck.session.cmd_output(cmd_md5, safe=True).strip().split('\n')[1].replace(' ', '') logging.info('Actual MD5=%s, SHA1=%s', md5, sha1) if sha1 == val_sha1 and md5 == val_md5: logging.info('MD5 and SHA1 are correct') else: log_fail('MD5 or SHA1 of rhsrvany.exe not correct') def check_disk(vmcheck, count): """ Check if number of disks meets expectation """ logging.info('Expect number of disks: %d', count) actual = vmcheck.session.cmd('lsblk |grep disk |wc -l').strip() logging.info('Actual number of disks: %s', actual) if int(actual) != count: log_fail('Number of disks is wrong') def check_result(result, status_error): """ Check virt-v2v command result """ libvirt.check_exit_status(result, status_error) output = result.stdout + result.stderr if not status_error and checkpoint != 'vdsm': if output_mode == 'rhev': if not utils_v2v.import_vm_to_ovirt(params, address_cache, timeout=v2v_timeout): test.fail('Import VM failed') elif output_mode == 'libvirt': try: virsh.start(vm_name, debug=True, ignore_status=False) except Exception as e: test.fail('Start vm failed: %s', str(e)) # Check guest following the checkpoint document after convertion logging.info('Checking common checkpoints for v2v') vmchecker = VMChecker(test, params, env) params['vmchecker'] = vmchecker ret = vmchecker.run() if len(ret) == 0: logging.info("All common checkpoints passed") # Check specific checkpoints if checkpoint == 'rhev_file': check_rhev_file_exist(vmchecker.checker) if checkpoint == 'console_xvc0': check_grub_file(vmchecker.checker, 'console_xvc0') if checkpoint in ('vnc_autoport', 'vnc_encrypt'): vmchecker.check_graphics(params[checkpoint]) if checkpoint == 'sdl': if output_mode == 'libvirt': vmchecker.check_graphics({'type': 'vnc'}) elif output_mode == 'rhev': vmchecker.check_graphics({'type': 'spice'}) if checkpoint == 'pv_with_regular_kernel': check_kernel(vmchecker.checker) if checkpoint in ['sound', 'pcspk']: check_sound_card(vmchecker.checker, checkpoint) if checkpoint == 'rhsrvany_md5': check_rhsrvany_md5(vmchecker.checker) if checkpoint == 'multidisk': check_disk(vmchecker.checker, params['disk_count']) log_check = utils_v2v.check_log(params, output) if log_check: log_fail(log_check) # Merge 2 error lists if params.get('vmchecker'): error_list.extend(params['vmchecker'].errors) # Virtio drivers will not be installed without virtio-win setup if checkpoint == 'virtio_win_unset': missing_list = params.get('missing').split(',') expect_errors = ['Not find driver: ' + x for x in missing_list] logging.debug('Expect errors: %s' % expect_errors) logging.debug('Actual errors: %s' % error_list) if set(error_list) == set(expect_errors): error_list[:] = [] else: logging.error('Virtio drivers not meet expectation') if len(error_list): test.fail('%d checkpoints failed: %s' % (len(error_list), error_list)) try: v2v_params = { 'hostname': xen_host, 'hypervisor': 'xen', 'main_vm': vm_name, 'v2v_opts': '-v -x', 'input_mode': 'libvirt', 'new_name': new_vm_name, 'storage': params.get('output_storage', 'default'), 'network': params.get('network'), 'bridge': params.get('bridge'), 'target': params.get('target') } bk_xml = None os.environ['LIBGUESTFS_BACKEND'] = 'direct' # Setup ssh-agent access to xen hypervisor logging.info('set up ssh-agent access ') ssh_key.setup_ssh_key(xen_host, user=xen_host_user, port=22, password=xen_host_passwd) utils_misc.add_identities_into_ssh_agent() if params.get('output_format'): v2v_params.update({'output_format': params.get('output_format')}) # Build rhev related options if output_mode == 'rhev': # Create SASL user on the ovirt host user_pwd = "[['%s', '%s']]" % (params.get("sasl_user"), params.get("sasl_pwd")) v2v_sasl = utils_sasl.SASL(sasl_user_pwd=user_pwd) v2v_sasl.server_ip = params.get("remote_ip") v2v_sasl.server_user = params.get('remote_user') v2v_sasl.server_pwd = params.get('remote_pwd') v2v_sasl.setup(remote=True) # Create libvirt dir pool if output_mode == 'libvirt': pvt.pre_pool(pool_name, pool_type, pool_target, '') uri = utils_v2v.Uri('xen').get_uri(xen_host) # Check if xen guest exists if not virsh.domain_exists(vm_name, uri=uri): logging.error('VM %s not exists', vm_name) virsh_instance = virsh.VirshPersistent() virsh_instance.set_uri(uri) if checkpoint in bk_list: bk_xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) if checkpoint == 'guest_uuid': uuid = virsh.domuuid(vm_name, uri=uri).stdout.strip() v2v_params['main_vm'] = uuid if checkpoint in ['format_convert', 'xvda_disk']: # Get remote disk image path blklist = virsh.domblklist(vm_name, uri=uri).stdout.split('\n') logging.debug('domblklist %s:\n%s', vm_name, blklist) for line in blklist: if line.startswith(('hda', 'vda', 'sda')): params['remote_disk_image'] = line.split()[-1] break # Local path of disk image params['img_path'] = data_dir.get_tmp_dir() + '/%s.img' % vm_name if checkpoint == 'xvda_disk': v2v_params['input_mode'] = 'disk' v2v_params.update({'input_file': params['img_path']}) # Copy remote image to local with scp remote.scp_from_remote(xen_host, 22, xen_host_user, xen_host_passwd, params['remote_disk_image'], params['img_path']) if checkpoint == 'pool_uuid': virsh.pool_start(pool_name) pooluuid = virsh.pool_uuid(pool_name).stdout.strip() v2v_params['storage'] = pooluuid if checkpoint.startswith('vnc'): vm_xml.VMXML.set_graphics_attr(vm_name, {'type': 'vnc'}, virsh_instance=virsh_instance) if checkpoint == 'vnc_autoport': params[checkpoint] = {'autoport': 'yes'} vm_xml.VMXML.set_graphics_attr(vm_name, params[checkpoint], virsh_instance=virsh_instance) elif checkpoint in ['vnc_encrypt', 'vnc_encrypt_warning']: params[checkpoint] = {'passwd': params.get('vnc_passwd', 'redhat')} vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) vm_xml.VMXML.add_security_info( vmxml, params[checkpoint]['passwd'], virsh_instance=virsh_instance) logging.debug(virsh_instance.dumpxml(vm_name, extra='--security-info')) if checkpoint.startswith('libguestfs_backend'): value = checkpoint[19:] if value == 'empty': value = '' logging.info('Set LIBGUESTFS_BACKEND to "%s"', value) os.environ['LIBGUESTFS_BACKEND'] = value if checkpoint == 'same_name': logging.info('Convert guest and rename to %s', new_vm_name) v2v_params.update({'new_name': new_vm_name}) if checkpoint == 'no_passwordless_SSH': logging.info('Unset $SSH_AUTH_SOCK') os.unsetenv('SSH_AUTH_SOCK') if checkpoint in ['xml_without_image', 'format_convert']: xml_file = os.path.join(data_dir.get_tmp_dir(), '%s.xml' % vm_name) virsh.dumpxml(vm_name, to_file=xml_file, uri=uri) v2v_params['hypervisor'] = 'kvm' v2v_params['input_mode'] = 'libvirtxml' v2v_params.update({'input_file': xml_file}) if params.get('img_path'): cmd = "sed -i 's|%s|%s|' %s" % (params['remote_disk_image'], params['img_path'], xml_file) process.run(cmd) logging.debug(process.run('cat %s' % xml_file).stdout_text) if checkpoint == 'format_convert': v2v_params['output_format'] = 'qcow2' if checkpoint == 'ssh_banner': session = remote.remote_login("ssh", xen_host, "22", "root", xen_host_passwd, "#") ssh_banner_content = r'"# no default banner path\n' \ r'#Banner /path/banner file\n' \ r'Banner /etc/ssh/ssh_banner"' logging.info('Create ssh_banner file') session.cmd('echo -e %s > /etc/ssh/ssh_banner' % ssh_banner_content) logging.info('Content of ssh_banner file:') logging.info(session.cmd_output('cat /etc/ssh/ssh_banner')) logging.info('Restart sshd service on xen host') session.cmd('service sshd restart') if checkpoint.startswith('virtio_win'): src_dir = params.get('virtio_win_dir') dest_dir = os.path.join(data_dir.get_tmp_dir(), 'virtio-win') iso_path = os.path.join(dest_dir, 'virtio-win.iso') if not os.path.exists(dest_dir): shutil.copytree(src_dir, dest_dir) virtio_win_env = params.get('virtio_win_env', 'VIRTIO_WIN') process.run('rpm -e virtio-win') if process.run('rpm -q virtio-win', ignore_status=True).exit_status == 0: test.error('not removed') if checkpoint.endswith('unset'): logging.info('Unset env %s' % virtio_win_env) os.unsetenv(virtio_win_env) if checkpoint.endswith('custom'): logging.info('Set env %s=%s' % (virtio_win_env, dest_dir)) os.environ[virtio_win_env] = dest_dir if checkpoint.endswith('iso_mount'): logging.info('Mount iso to /opt') process.run('mount %s /opt' % iso_path) os.environ[virtio_win_env] = '/opt' if checkpoint.endswith('iso_file'): logging.info('Set env %s=%s' % (virtio_win_env, iso_path)) os.environ[virtio_win_env] = iso_path if checkpoint == 'cdrom': xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) logging.debug(xml.xmltreefile) disks = xml.get_disk_all() logging.debug('Disks: %r', disks) for disk in list(disks.values()): # Check if vm has cdrom attached if disk.get('device') == 'cdrom' and disk.find('source') is None: test.error('No CDROM image attached') if checkpoint == 'vdsm': extra_pkg = params.get('extra_pkg') logging.info('Install %s', extra_pkg) utils_package.package_install(extra_pkg.split(',')) # Backup conf file for recovery for conf in params['bk_conf'].strip().split(','): logging.debug('Back up %s', conf) shutil.copyfile(conf, conf + '.bk') logging.info('Configure libvirt for vdsm') process.run('vdsm-tool configure --force') logging.info('Start vdsm service') service_manager = service.Factory.create_generic_service() service_manager.start('vdsmd') # Setup user and password user_pwd = "[['%s', '%s']]" % (params.get("sasl_user"), params.get("sasl_pwd")) v2v_sasl = utils_sasl.SASL(sasl_user_pwd=user_pwd) v2v_sasl.server_ip = 'localhost' v2v_sasl.server_user = params.get('sasl_server_user', 'root') v2v_sasl.server_pwd = params.get('sasl_server_passwd') v2v_sasl.setup() v2v_params['sasl_user'] = params.get("sasl_user") v2v_params['sasl_pwd'] = params.get("sasl_pwd") if checkpoint == 'multidisk': params['disk_count'] = 0 blklist = virsh.domblklist(vm_name, uri=uri).stdout.split('\n') logging.info(blklist) for line in blklist: if '/' in line: params['disk_count'] += 1 logging.info('Total disks: %d', params['disk_count']) # Check if xen guest exists again if not virsh.domain_exists(vm_name, uri=uri): logging.error('VM %s not exists', vm_name) # Execute virt-v2v v2v_result = utils_v2v.v2v_cmd(v2v_params) if new_vm_name: vm_name = new_vm_name params['main_vm'] = new_vm_name check_result(v2v_result, status_error) finally: process.run('ssh-agent -k') if checkpoint == 'vdsm': logging.info('Stop vdsmd') service_manager = service.Factory.create_generic_service() service_manager.stop('vdsmd') if params.get('extra_pkg'): utils_package.package_remove(params['extra_pkg'].split(',')) for conf in params['bk_conf'].strip().split(','): if os.path.exists(conf + '.bk'): logging.debug('Recover %s', conf) os.remove(conf) shutil.move(conf + '.bk', conf) logging.info('Restart libvirtd') libvirtd = utils_libvirtd.Libvirtd() libvirtd.restart() logging.info('Start network "default"') virsh.net_start('default') virsh.undefine(vm_name) if params.get('vmchecker'): params['vmchecker'].cleanup() if output_mode == 'libvirt': pvt.cleanup_pool(pool_name, pool_type, pool_target, '') if bk_xml: bk_xml.sync(virsh_instance=virsh_instance) virsh_instance.close_session() if checkpoint == 'ssh_banner': logging.info('Remove ssh_banner file') session = remote.remote_login("ssh", xen_host, "22", "root", xen_host_passwd, "#") session.cmd('rm -f /etc/ssh/ssh_banner') session.cmd('service sshd restart') if checkpoint.startswith('virtio_win'): utils_package.package_install(['virtio-win'])
def run(test, params, env): """ Convert specific xen guest """ for v in list(params.values()): if "V2V_EXAMPLE" in v: test.cancel("Please set real value for %s" % v) if utils_v2v.V2V_EXEC is None: test.cancel('Missing command: virt-v2v') vm_name = params.get('main_vm') new_vm_name = params.get('new_vm_name') xen_host = params.get('xen_hostname') xen_host_user = params.get('xen_host_user', 'root') xen_host_passwd = params.get('xen_host_passwd', 'redhat') output_mode = params.get('output_mode') v2v_timeout = int(params.get('v2v_timeout', 1200)) status_error = 'yes' == params.get('status_error', 'no') skip_vm_check = params.get('skip_vm_check', 'no') skip_reason = params.get('skip_reason') pool_name = params.get('pool_name', 'v2v_test') pool_type = params.get('pool_type', 'dir') pool_target = params.get('pool_target_path', 'v2v_pool') pvt = libvirt.PoolVolumeTest(test, params) address_cache = env.get('address_cache') checkpoint = params.get('checkpoint', '') bk_list = ['vnc_autoport', 'vnc_encrypt', 'vnc_encrypt_warning'] error_list = [] # For construct rhv-upload option in v2v cmd output_method = params.get("output_method") rhv_upload_opts = params.get("rhv_upload_opts") storage_name = params.get('storage_name') # for get ca.crt file from ovirt engine rhv_passwd = params.get("rhv_upload_passwd") rhv_passwd_file = params.get("rhv_upload_passwd_file") ovirt_engine_passwd = params.get("ovirt_engine_password") ovirt_hostname = params.get("ovirt_engine_url").split( '/')[2] if params.get("ovirt_engine_url") else None ovirt_ca_file_path = params.get("ovirt_ca_file_path") local_ca_file_path = params.get("local_ca_file_path") def log_fail(msg): """ Log error and update error list """ logging.error(msg) error_list.append(msg) def set_graphics(virsh_instance, param): """ Set graphics attributes of vm xml """ vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) graphic = vmxml.xmltreefile.find('devices').find('graphics') for key in param: logging.debug('Set %s=\'%s\'' % (key, param[key])) graphic.set(key, param[key]) vmxml.sync(virsh_instance=virsh_instance) def check_grub_file(vmcheck, check): """ Check grub file content """ logging.info('Checking grub file') grub_file = utils_misc.get_bootloader_cfg(session=vmcheck.session) if not grub_file: test.error('Not found grub file') content = vmcheck.session.cmd('cat %s' % grub_file) if check == 'console_xvc0': if 'console=xvc0' in content: log_fail('"console=xvc0" still exists') def check_kernel(vmcheck): """ Check content of /etc/sysconfig/kernel """ logging.info('Checking /etc/sysconfig/kernel file') content = vmcheck.session.cmd('cat /etc/sysconfig/kernel') logging.debug(content) if 'DEFAULTKERNEL=kernel' not in content: log_fail('Not find "DEFAULTKERNEL=kernel"') elif 'DEFAULTKERNEL=kernel-xen' in content: log_fail('DEFAULTKERNEL is "kernel-xen"') def check_sound_card(vmcheck, check): """ Check sound status of vm from xml """ xml = virsh.dumpxml(vm_name, session_id=vmcheck.virsh_session_id).stdout logging.debug(xml) if check == 'sound' and '<sound model' in xml: log_fail('Sound card should be removed') if check == 'pcspk' and output_mode == 'libvirt' and "<sound model='pcspk'" not in xml: log_fail('Sound card should be "pcspk"') def check_rhsrvany_md5(vmcheck): """ Check if MD5 and SHA1 of rhsrvany.exe are correct """ logging.info('Check md5 and sha1 of rhsrvany.exe') val_md5, val_sha1 = params.get('val_md5'), params.get('val_sha1') logging.info('Expect MD5=%s, SHA1=%s', val_md5, val_sha1) if not val_md5 or not val_sha1: test.error('No MD5 or SHA1 value provided') cmd_sha1 = params.get('cmd_sha1') cmd_md5 = cmd_sha1 + ' MD5' sha1 = vmcheck.session.cmd_output( cmd_sha1, safe=True).strip().split('\n')[1].replace(' ', '') md5 = vmcheck.session.cmd_output( cmd_md5, safe=True).strip().split('\n')[1].replace(' ', '') logging.info('Actual MD5=%s, SHA1=%s', md5, sha1) if sha1 == val_sha1 and md5 == val_md5: logging.info('MD5 and SHA1 are correct') else: log_fail('MD5 or SHA1 of rhsrvany.exe not correct') def check_disk(vmcheck, count): """ Check if number of disks meets expectation """ logging.info('Expect number of disks: %d', count) actual = vmcheck.session.cmd('lsblk |grep disk |wc -l').strip() logging.info('Actual number of disks: %s', actual) if int(actual) != count: log_fail('Number of disks is wrong') def check_result(result, status_error): """ Check virt-v2v command result """ libvirt.check_exit_status(result, status_error) output = result.stdout + result.stderr if not status_error and checkpoint != 'vdsm': if output_mode == 'rhev': if not utils_v2v.import_vm_to_ovirt( params, address_cache, timeout=v2v_timeout): test.fail('Import VM failed') elif output_mode == 'libvirt': try: virsh.start(vm_name, debug=True, ignore_status=False) except Exception as e: test.fail('Start vm failed: %s', str(e)) # Check guest following the checkpoint document after convertion logging.info('Checking common checkpoints for v2v') vmchecker = VMChecker(test, params, env) params['vmchecker'] = vmchecker if params.get('skip_vm_check') != 'yes': ret = vmchecker.run() if len(ret) == 0: logging.info("All common checkpoints passed") else: logging.info('Skip checking vm after conversion: %s' % skip_reason) # Check specific checkpoints if checkpoint == 'console_xvc0': check_grub_file(vmchecker.checker, 'console_xvc0') if checkpoint in ('vnc_autoport', 'vnc_encrypt'): vmchecker.check_graphics(params[checkpoint]) if checkpoint == 'sdl': if output_mode == 'libvirt': vmchecker.check_graphics({'type': 'vnc'}) elif output_mode == 'rhev': vmchecker.check_graphics({'type': 'spice'}) if checkpoint == 'pv_with_regular_kernel': check_kernel(vmchecker.checker) if checkpoint in ['sound', 'pcspk']: check_sound_card(vmchecker.checker, checkpoint) if checkpoint == 'rhsrvany_md5': check_rhsrvany_md5(vmchecker.checker) if checkpoint == 'multidisk': check_disk(vmchecker.checker, params['disk_count']) log_check = utils_v2v.check_log(params, output) if log_check: log_fail(log_check) # Merge 2 error lists if params.get('vmchecker'): error_list.extend(params['vmchecker'].errors) # Virtio drivers will not be installed without virtio-win setup if checkpoint == 'virtio_win_unset': missing_list = params.get('missing').split(',') expect_errors = ['Not find driver: ' + x for x in missing_list] logging.debug('Expect errors: %s' % expect_errors) logging.debug('Actual errors: %s' % error_list) if set(error_list) == set(expect_errors): error_list[:] = [] else: logging.error('Virtio drivers not meet expectation') if len(error_list): test.fail('%d checkpoints failed: %s' % (len(error_list), error_list)) try: v2v_params = { 'hostname': xen_host, 'hypervisor': 'xen', 'main_vm': vm_name, 'v2v_opts': '-v -x', 'input_mode': 'libvirt', 'new_name': new_vm_name, 'password': xen_host_passwd, 'storage': params.get('output_storage', 'default'), 'network': params.get('network'), 'bridge': params.get('bridge'), 'target': params.get('target'), 'output_method': output_method, 'storage_name': storage_name, 'rhv_upload_opts': rhv_upload_opts } bk_xml = None os.environ['LIBGUESTFS_BACKEND'] = 'direct' # Setup ssh-agent access to xen hypervisor logging.info('set up ssh-agent access ') ssh_key.setup_ssh_key(xen_host, user=xen_host_user, port=22, password=xen_host_passwd) utils_misc.add_identities_into_ssh_agent() if params.get('output_format'): v2v_params.update({'output_format': params.get('output_format')}) # Build rhev related options if output_mode == 'rhev': # To RHV doesn't support 'qcow2' right now v2v_params['output_format'] = 'raw' # create different sasl_user name for different job params.update({ 'sasl_user': params.get("sasl_user") + utils_misc.generate_random_string(3) }) logging.info('sals user name is %s' % params.get("sasl_user")) # Create SASL user on the ovirt host user_pwd = "[['%s', '%s']]" % (params.get("sasl_user"), params.get("sasl_pwd")) v2v_sasl = utils_sasl.SASL(sasl_user_pwd=user_pwd) v2v_sasl.server_ip = params.get("remote_ip") v2v_sasl.server_user = params.get('remote_user') v2v_sasl.server_pwd = params.get('remote_pwd') v2v_sasl.setup(remote=True) if output_method == 'rhv_upload': # Create password file for '-o rhv_upload' to connect to ovirt with open(rhv_passwd_file, 'w') as f: f.write(rhv_passwd) # Copy ca file from ovirt to local remote.scp_from_remote(ovirt_hostname, 22, 'root', ovirt_engine_passwd, ovirt_ca_file_path, local_ca_file_path) # Create libvirt dir pool if output_mode == 'libvirt': pvt.pre_pool(pool_name, pool_type, pool_target, '') uri = utils_v2v.Uri('xen').get_uri(xen_host) # Check if xen guest exists if not virsh.domain_exists(vm_name, uri=uri): logging.error('VM %s not exists', vm_name) virsh_instance = virsh.VirshPersistent() virsh_instance.set_uri(uri) if checkpoint in bk_list: bk_xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) if checkpoint == 'guest_uuid': uuid = virsh.domuuid(vm_name, uri=uri).stdout.strip() v2v_params['main_vm'] = uuid if checkpoint in ['format_convert', 'xvda_disk']: # Get remote disk image path blklist = virsh.domblklist(vm_name, uri=uri).stdout.split('\n') logging.debug('domblklist %s:\n%s', vm_name, blklist) for line in blklist: if line.strip().startswith(('hda', 'vda', 'sda', 'xvda')): params['remote_disk_image'] = line.split()[-1] break # Local path of disk image params['img_path'] = data_dir.get_tmp_dir() + '/%s.img' % vm_name if checkpoint == 'xvda_disk': v2v_params['input_mode'] = 'disk' v2v_params['hypervisor'] = 'kvm' v2v_params.update({'input_file': params['img_path']}) # Copy remote image to local with scp remote.scp_from_remote(xen_host, 22, xen_host_user, xen_host_passwd, params['remote_disk_image'], params['img_path']) if checkpoint == 'pool_uuid': virsh.pool_start(pool_name) pooluuid = virsh.pool_uuid(pool_name).stdout.strip() v2v_params['storage'] = pooluuid if checkpoint.startswith('vnc'): vm_xml.VMXML.set_graphics_attr(vm_name, {'type': 'vnc'}, virsh_instance=virsh_instance) if checkpoint == 'vnc_autoport': params[checkpoint] = {'autoport': 'yes'} vm_xml.VMXML.set_graphics_attr(vm_name, params[checkpoint], virsh_instance=virsh_instance) elif checkpoint in ['vnc_encrypt', 'vnc_encrypt_warning']: params[checkpoint] = { 'passwd': params.get('vnc_passwd', 'redhat') } vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) vm_xml.VMXML.add_security_info(vmxml, params[checkpoint]['passwd'], virsh_instance=virsh_instance) logging.debug( virsh_instance.dumpxml(vm_name, extra='--security-info')) if checkpoint.startswith('libguestfs_backend'): value = checkpoint[19:] if value == 'empty': value = '' logging.info('Set LIBGUESTFS_BACKEND to "%s"', value) os.environ['LIBGUESTFS_BACKEND'] = value if checkpoint == 'same_name': logging.info('Convert guest and rename to %s', new_vm_name) v2v_params.update({'new_name': new_vm_name}) if checkpoint == 'no_passwordless_SSH': logging.info('Unset $SSH_AUTH_SOCK') os.unsetenv('SSH_AUTH_SOCK') if checkpoint in ['xml_without_image', 'format_convert']: xml_file = os.path.join(data_dir.get_tmp_dir(), '%s.xml' % vm_name) virsh.dumpxml(vm_name, to_file=xml_file, uri=uri) v2v_params['hypervisor'] = 'kvm' v2v_params['input_mode'] = 'libvirtxml' v2v_params.update({'input_file': xml_file}) if params.get('img_path'): cmd = "sed -i 's|%s|%s|' %s" % (params['remote_disk_image'], params['img_path'], xml_file) process.run(cmd) logging.debug(process.run('cat %s' % xml_file).stdout_text) if checkpoint == 'ssh_banner': session = remote.remote_login("ssh", xen_host, "22", "root", xen_host_passwd, "#") ssh_banner_content = r'"# no default banner path\n' \ r'#Banner /path/banner file\n' \ r'Banner /etc/ssh/ssh_banner"' logging.info('Create ssh_banner file') session.cmd('echo -e %s > /etc/ssh/ssh_banner' % ssh_banner_content) logging.info('Content of ssh_banner file:') logging.info(session.cmd_output('cat /etc/ssh/ssh_banner')) logging.info('Restart sshd service on xen host') session.cmd('service sshd restart') if checkpoint.startswith('virtio_win'): src_dir = params.get('virtio_win_dir') dest_dir = os.path.join(data_dir.get_tmp_dir(), 'virtio-win') iso_path = os.path.join(dest_dir, 'virtio-win.iso') if not os.path.exists(dest_dir): shutil.copytree(src_dir, dest_dir) virtio_win_env = params.get('virtio_win_env', 'VIRTIO_WIN') process.run('rpm -e virtio-win') if process.run('rpm -q virtio-win', ignore_status=True).exit_status == 0: test.error('not removed') if checkpoint.endswith('unset'): logging.info('Unset env %s' % virtio_win_env) os.unsetenv(virtio_win_env) if checkpoint.endswith('custom'): logging.info('Set env %s=%s' % (virtio_win_env, dest_dir)) os.environ[virtio_win_env] = dest_dir if checkpoint.endswith('iso_mount'): logging.info('Mount iso to /opt') process.run('mount %s /opt' % iso_path) os.environ[virtio_win_env] = '/opt' if checkpoint.endswith('iso_file'): logging.info('Set env %s=%s' % (virtio_win_env, iso_path)) os.environ[virtio_win_env] = iso_path if checkpoint == 'cdrom': xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) logging.debug(xml.xmltreefile) disks = xml.get_disk_all() logging.debug('Disks: %r', disks) for disk in list(disks.values()): # Check if vm has cdrom attached if disk.get( 'device') == 'cdrom' and disk.find('source') is None: test.error('No CDROM image attached') if checkpoint == 'vdsm': extra_pkg = params.get('extra_pkg') logging.info('Install %s', extra_pkg) utils_package.package_install(extra_pkg.split(',')) # Backup conf file for recovery for conf in params['bk_conf'].strip().split(','): logging.debug('Back up %s', conf) shutil.copyfile(conf, conf + '.bk') logging.info('Configure libvirt for vdsm') process.run('vdsm-tool configure --force') logging.info('Start vdsm service') service_manager = service.Factory.create_generic_service() service_manager.start('vdsmd') # Setup user and password user_pwd = "[['%s', '%s']]" % (params.get("sasl_user"), params.get("sasl_pwd")) v2v_sasl = utils_sasl.SASL(sasl_user_pwd=user_pwd) v2v_sasl.server_ip = 'localhost' v2v_sasl.server_user = params.get('sasl_server_user', 'root') v2v_sasl.server_pwd = params.get('sasl_server_passwd') v2v_sasl.setup() v2v_params['sasl_user'] = params.get("sasl_user") v2v_params['sasl_pwd'] = params.get("sasl_pwd") if checkpoint == 'multidisk': params['disk_count'] = 0 blklist = virsh.domblklist(vm_name, uri=uri).stdout.split('\n') logging.info(blklist) for line in blklist: if '/' in line: params['disk_count'] += 1 logging.info('Total disks: %d', params['disk_count']) # Check if xen guest exists again if not virsh.domain_exists(vm_name, uri=uri): logging.error('VM %s not exists', vm_name) # Execute virt-v2v v2v_result = utils_v2v.v2v_cmd(v2v_params) if new_vm_name: vm_name = new_vm_name params['main_vm'] = new_vm_name check_result(v2v_result, status_error) finally: # Cleanup constant files utils_v2v.cleanup_constant_files(params) process.run('ssh-agent -k') if checkpoint == 'vdsm': logging.info('Stop vdsmd') service_manager = service.Factory.create_generic_service() service_manager.stop('vdsmd') if params.get('extra_pkg'): utils_package.package_remove(params['extra_pkg'].split(',')) for conf in params['bk_conf'].strip().split(','): if os.path.exists(conf + '.bk'): logging.debug('Recover %s', conf) os.remove(conf) shutil.move(conf + '.bk', conf) logging.info('Restart libvirtd') libvirtd = utils_libvirtd.Libvirtd() libvirtd.restart() logging.info('Start network "default"') virsh.net_start('default') virsh.undefine(vm_name) if params.get('vmchecker'): params['vmchecker'].cleanup() if output_mode == 'libvirt': pvt.cleanup_pool(pool_name, pool_type, pool_target, '') if bk_xml: bk_xml.sync(virsh_instance=virsh_instance) virsh_instance.close_session() if checkpoint == 'ssh_banner': logging.info('Remove ssh_banner file') session = remote.remote_login("ssh", xen_host, "22", "root", xen_host_passwd, "#") session.cmd('rm -f /etc/ssh/ssh_banner') session.cmd('service sshd restart') if checkpoint.startswith('virtio_win'): utils_package.package_install(['virtio-win'])
user_pwd = "[['%s', '%s']]" % (params.get("sasl_user"), params.get("sasl_pwd")) v2v_sasl = utils_sasl.SASL(sasl_user_pwd=user_pwd) v2v_sasl.server_ip = params.get("remote_ip") v2v_sasl.server_user = params.get('remote_user') v2v_sasl.server_pwd = params.get('remote_pwd') v2v_sasl.setup(remote=True) # Create libvirt dir pool if output_mode == 'libvirt': pvt.pre_pool(pool_name, pool_type, pool_target, '') uri = utils_v2v.Uri('xen').get_uri(xen_host) # Check if xen guest exists if not virsh.domain_exists(vm_name, uri=uri): logging.error('VM %s not exists', vm_name) virsh_instance = virsh.VirshPersistent() virsh_instance.set_uri(uri) if checkpoint in bk_list: bk_xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) if checkpoint == 'guest_uuid': uuid = virsh.domuuid(vm_name, uri=uri).stdout.strip() v2v_params['main_vm'] = uuid if checkpoint in ['format_convert', 'xvda_disk']: # Get remote disk image path blklist = virsh.domblklist(vm_name, uri=uri).stdout.split('\n') logging.debug('domblklist %s:\n%s', vm_name, blklist)
def run(test, params, env): """ Test virsh undefine command. Undefine an inactive domain, or convert persistent to transient. 1.Prepare test environment. 2.Backup the VM's information to a xml file. 3.When the libvirtd == "off", stop the libvirtd service. 4.Perform virsh undefine operation. 5.Recover test environment.(libvirts service,VM) 6.Confirm the test result. """ vm_ref = params.get("undefine_vm_ref", "vm_name") extra = params.get("undefine_extra", "") option = params.get("undefine_option", "") libvirtd_state = params.get("libvirtd", "on") status_error = ("yes" == params.get("status_error", "no")) undefine_twice = ("yes" == params.get("undefine_twice", 'no')) local_ip = params.get("local_ip", "LOCAL.EXAMPLE.COM") local_pwd = params.get("local_pwd", "password") remote_ip = params.get("remote_ip", "REMOTE.EXAMPLE.COM") remote_user = params.get("remote_user", "user") remote_pwd = params.get("remote_pwd", "password") remote_prompt = params.get("remote_prompt", "#") pool_type = params.get("pool_type") pool_name = params.get("pool_name", "test") pool_target = params.get("pool_target") volume_size = params.get("volume_size", "1G") vol_name = params.get("vol_name", "test_vol") emulated_img = params.get("emulated_img", "emulated_img") emulated_size = "%sG" % (int(volume_size[:-1]) + 1) disk_target = params.get("disk_target", "vdb") wipe_data = "yes" == params.get("wipe_data", "no") if wipe_data: option += " --wipe-storage" nvram_o = None if platform.machine() == 'aarch64': nvram_o = " --nvram" option += nvram_o vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) vm_id = vm.get_id() vm_uuid = vm.get_uuid() # polkit acl related params uri = params.get("virsh_uri") unprivileged_user = params.get('unprivileged_user') if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = '******' if not libvirt_version.version_compare(1, 1, 1): if params.get('setup_libvirt_polkit') == 'yes': test.cancel("API acl test not supported in current" " libvirt version.") # Back up xml file.Xen host has no guest xml file to define a guset. backup_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Confirm how to reference a VM. if vm_ref == "vm_name": vm_ref = vm_name elif vm_ref == "id": vm_ref = vm_id elif vm_ref == "hex_vm_id": vm_ref = hex(int(vm_id)) elif vm_ref == "uuid": vm_ref = vm_uuid elif vm_ref.find("invalid") != -1: vm_ref = params.get(vm_ref) volume = None pvtest = None status3 = None elems = backup_xml.xmltreefile.findall('/devices/disk/source') existing_images = [elem.get('file') for elem in elems] # Backup images since remove-all-storage could remove existing libvirt # managed guest images if existing_images and option.count("remove-all-storage"): for img in existing_images: backup_img = img + '.bak' logging.info('Backup %s to %s', img, backup_img) shutil.copyfile(img, backup_img) try: save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name if option.count("managedsave") and vm.is_alive(): virsh.managedsave(vm_name) if not vm.is_lxc(): snp_list = virsh.snapshot_list(vm_name) if option.count("snapshot"): snp_file_list = [] if not len(snp_list): virsh.snapshot_create(vm_name) logging.debug("Create a snapshot for test!") else: # Backup snapshots for domain for snp_item in snp_list: tmp_file = os.path.join(data_dir.get_tmp_dir(), snp_item + ".xml") virsh.snapshot_dumpxml(vm_name, snp_item, to_file=tmp_file) snp_file_list.append(tmp_file) else: if len(snp_list): test.cancel("This domain has snapshot(s), " "cannot be undefined!") if option.count("remove-all-storage"): pvtest = utlv.PoolVolumeTest(test, params) pvtest.pre_pool(pool_name, pool_type, pool_target, emulated_img, emulated_size=emulated_size) new_pool = libvirt_storage.PoolVolume(pool_name) if not new_pool.create_volume(vol_name, volume_size): test.fail("Creation of volume %s failed." % vol_name) volumes = new_pool.list_volumes() volume = volumes[vol_name] virsh.attach_disk(vm_name, volume, disk_target, "--config") # Turn libvirtd into certain state. if libvirtd_state == "off": utils_libvirtd.libvirtd_stop() # Test virsh undefine command. output = "" if vm_ref != "remote": vm_ref = "%s %s" % (vm_ref, extra) cmdresult = virsh.undefine(vm_ref, option, unprivileged_user=unprivileged_user, uri=uri, ignore_status=True, debug=True) status = cmdresult.exit_status output = cmdresult.stdout.strip() if status: logging.debug("Error status, command output: %s", cmdresult.stderr.strip()) if undefine_twice: status2 = virsh.undefine(vm_ref, nvram_o, ignore_status=True).exit_status else: if remote_ip.count("EXAMPLE.COM") or local_ip.count("EXAMPLE.COM"): test.cancel("remote_ip and/or local_ip parameters" " not changed from default values") try: local_user = params.get("username", "root") uri = libvirt_vm.complete_uri(local_ip) # setup ssh auto login from remote machine to test machine # for the command to execute remotely ssh_key.setup_remote_ssh_key(remote_ip, remote_user, remote_pwd, hostname2=local_ip, user2=local_user, password2=local_pwd) session = remote.remote_login("ssh", remote_ip, "22", remote_user, remote_pwd, remote_prompt) cmd_undefine = "virsh -c %s undefine %s" % (uri, vm_name) status, output = session.cmd_status_output(cmd_undefine) logging.info("Undefine output: %s", output) except (process.CmdError, remote.LoginError, aexpect.ShellError) as de: logging.error("Detail: %s", de) status = 1 # Recover libvirtd state. if libvirtd_state == "off": utils_libvirtd.libvirtd_start() # Shutdown VM. if virsh.domain_exists(vm.name): try: if vm.is_alive(): vm.destroy(gracefully=False) except process.CmdError as detail: logging.error("Detail: %s", detail) # After vm.destroy, virsh.domain_exists returns True due to # timing issue and tests fails. time.sleep(2) # Check if VM exists. vm_exist = virsh.domain_exists(vm_name) # Check if xml file exists. xml_exist = False if vm.is_qemu() and os.path.exists("/etc/libvirt/qemu/%s.xml" % vm_name): xml_exist = True if vm.is_lxc() and os.path.exists("/etc/libvirt/lxc/%s.xml" % vm_name): xml_exist = True if vm.is_xen() and os.path.exists("/etc/xen/%s" % vm_name): xml_exist = True # Check if save file exists if use --managed-save save_exist = os.path.exists(save_file) # Check if save file exists if use --managed-save volume_exist = volume and os.path.exists(volume) # Test define with acl control and recover domain. if params.get('setup_libvirt_polkit') == 'yes': if virsh.domain_exists(vm.name): virsh.undefine(vm_ref, nvram_o, ignore_status=True) cmd = "chmod 666 %s" % backup_xml.xml process.run(cmd, ignore_status=False, shell=True) s_define = virsh.define(backup_xml.xml, unprivileged_user=unprivileged_user, uri=uri, ignore_status=True, debug=True) status3 = s_define.exit_status finally: # Recover main VM. try: backup_xml.sync() except LibvirtXMLError: # sync() tries to undefines and define the xml to sync # but virsh_undefine test would have undefined already # may lead to error out backup_xml.define() # Recover existing guest images if existing_images and option.count("remove-all-storage"): for img in existing_images: backup_img = img + '.bak' logging.info('Recover image %s to %s', backup_img, img) shutil.move(backup_img, img) # Clean up pool if pvtest: pvtest.cleanup_pool(pool_name, pool_type, pool_target, emulated_img) # Recover VM snapshots. if option.count("snapshot") and (not vm.is_lxc()): logging.debug("Recover snapshots for domain!") for file_item in snp_file_list: virsh.snapshot_create(vm_name, file_item) # Check results. if status_error: if not status: test.fail("virsh undefine return unexpected result.") if params.get('setup_libvirt_polkit') == 'yes': if status3 == 0: test.fail("virsh define with false acl permission" + " should failed.") else: if status: test.fail("virsh undefine failed.") if undefine_twice: if not status2: test.fail("Undefine the same VM twice succeeded.") if vm_exist: test.fail("VM still exists after undefine.") if xml_exist: test.fail("Xml file still exists after undefine.") if option.count("managedsave") and save_exist: test.fail("Save file still exists after undefine.") if option.count("remove-all-storage") and volume_exist: test.fail("Volume file '%s' still exists after" " undefine." % volume) if wipe_data and option.count("remove-all-storage"): if not output.count("Wiping volume '%s'" % disk_target): test.fail("Command didn't wipe volume storage!") if params.get('setup_libvirt_polkit') == 'yes': if status3: test.fail("virsh define with right acl permission" + " should succeeded")
else: raise exceptions.TestFail("Expect fail, but run " "successfully: %s" % bug_url) finally: # Recover VM may fail unexpectedly, we need using try/except to # proceed the following cleanup steps try: # Abort exist blockjob to avoid any possible lock error virsh.blockjob(vm_name, target, '--abort', ignore_status=True) vm.destroy(gracefully=False) # It may take a long time to shutdown the VM which has # blockjob running utils_misc.wait_for( lambda: virsh.domstate(vm_name, ignore_status=True). exit_status, 180) if virsh.domain_exists(vm_name): if active_snap or with_shallow: option = "--snapshots-metadata" else: option = None original_xml.sync(option) else: original_xml.define() except Exception, e: logging.error(e) for disk in snapshot_external_disks: if os.path.exists(disk): os.remove(disk) # Clean up libvirt pool, which may be created by 'set_vm_disk' if disk_type == 'volume': virsh.pool_destroy(pool_name, ignore_status=True, debug=True)
def run(test, params, env): """ Test svirt in virt-install. (1). Init variables. (2). Set selinux on host. (3). Set label of image. (4). run a virt-install command. (5). clean up. As this test only care whether the qemu-kvm process can access the image. It is not necessary to install a full os in a vm. Just verify the vm is alive after virt-install command is enough. Then we can save a lot of time and make this test independent from unattended_install. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_install_vm_sec_type", "dynamic") sec_model = params.get("svirt_install_vm_sec_model", "selinux") sec_label = params.get("svirt_install_vm_sec_label", None) sec_relabel = params.get("svirt_install_vm_sec_relabel", "yes") # Set selinux status on host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the image label. disk_label = params.get("svirt_install_disk_label", None) vm_name = params.get("main_vm", None) # svirt will prevent accessing via a symble link. data_path = data_dir.get_data_dir() real_data_path = os.path.realpath(data_path) image_path = os.path.join(real_data_path, "svirt_image") if virsh.domain_exists(vm_name): virsh.remove_domain(vm_name) if not os.path.exists(image_path): utils_test.libvirt.create_local_disk("file", path=image_path) try: utils_selinux.set_context_of_file(image_path, disk_label) cmd = "virt-install --name %s --import --disk" % vm_name cmd += " path=%s --ram '1024' " % image_path cmd += " --security" if sec_type == 'static': if sec_label is None: raise ValueError("Seclabel is not setted for static.") cmd += " type=static,label=%s" % (sec_label) elif sec_type == 'dynamic': cmd += " type=dynamic" else: raise ValueError("Security type %s is not supported." % sec_type) if sec_relabel is not None: cmd += ",relabel=%s" % sec_relabel cmd += " --noautoconsole --graphics vnc --video vga &" utils.run(cmd, ignore_status=True) def _vm_alive(): return virsh.is_alive(vm_name) if (utils_misc.wait_for(_vm_alive, timeout=5)): if status_error: raise error.TestFail('Test succeeded in negative case.') else: if not status_error: raise error.TestFail("Test failed in positive case.") finally: # cleanup utils_selinux.set_status(backup_sestatus) if virsh.domain_exists(vm_name): virsh.remove_domain(vm_name) if not os.path.exists(image_path): utils_test.libvirt.delete_local_disk("file", path=image_path)
vm.start() # Checking for --persistent. logging.debug("Checking for --persistent option.") check_dest_persistent = True if options.count("persistent") or extra.count("persistent"): if not vm.is_persistent(): check_dest_persistent = False # Checking for --undefinesource. logging.debug("Checking for --undefinesource option.") check_src_undefine = True if options.count("undefinesource") or extra.count("undefinesource"): logging.info("Verifying <virsh domstate> DOES return an error." "%s should not exist on %s." % (vm_name, src_uri)) if virsh.domain_exists(vm_name, uri=src_uri): check_src_undefine = False # Checking for --dname. logging.debug("Checking for --dname option.") check_dest_dname = True if options.count("dname") or extra.count("dname"): dname = extra.split()[1].strip() if not virsh.domain_exists(dname, uri=dest_uri): check_dest_dname = False # Checking for --xml. logging.debug("Checking for --xml option.") check_dest_xml = True if options.count("xml") or extra.count("xml"): if dest_xmlfile:
def run(test, params, env): """ Test various options of virt-v2v. """ if utils_v2v.V2V_EXEC is None: raise ValueError('Missing command: virt-v2v') for v in list(params.values()): if "V2V_EXAMPLE" in v: test.cancel("Please set real value for %s" % v) vm_name = params.get("main_vm", "EXAMPLE") new_vm_name = params.get("new_vm_name") input_mode = params.get("input_mode") v2v_options = params.get("v2v_options", "") hypervisor = params.get("hypervisor", "kvm") remote_host = params.get("remote_host", "EXAMPLE") vpx_dc = params.get("vpx_dc", "EXAMPLE") esx_ip = params.get("esx_ip", "EXAMPLE") source_user = params.get("username", "root") output_mode = params.get("output_mode") output_storage = params.get("output_storage", "default") disk_img = params.get("input_disk_image", "") nfs_storage = params.get("storage") no_root = 'yes' == params.get('no_root', 'no') mnt_point = params.get("mnt_point") export_domain_uuid = params.get("export_domain_uuid", "") fake_domain_uuid = params.get("fake_domain_uuid") vdsm_image_uuid = params.get("vdsm_image_uuid") vdsm_vol_uuid = params.get("vdsm_vol_uuid") vdsm_vm_uuid = params.get("vdsm_vm_uuid") vdsm_ovf_output = params.get("vdsm_ovf_output") v2v_user = params.get("unprivileged_user", "") v2v_timeout = int(params.get("v2v_timeout", 1200)) status_error = "yes" == params.get("status_error", "no") su_cmd = "su - %s -c " % v2v_user output_uri = params.get("oc_uri", "") pool_name = params.get("pool_name", "v2v_test") pool_type = params.get("pool_type", "dir") pool_target = params.get("pool_target", "v2v_pool") emulated_img = params.get("emulated_image_path", "v2v-emulated-img") pvt = utlv.PoolVolumeTest(test, params) new_v2v_user = False address_cache = env.get('address_cache') params['vmcheck_flag'] = False checkpoint = params.get('checkpoint', '') error_flag = 'strict' def create_pool(user_pool=False, pool_name=pool_name, pool_target=pool_target): """ Create libvirt pool as the output storage """ if output_uri == "qemu:///session" or user_pool: target_path = os.path.join("/home", v2v_user, pool_target) cmd = su_cmd + "'mkdir %s'" % target_path process.system(cmd, verbose=True) cmd = su_cmd + "'virsh pool-create-as %s dir" % pool_name cmd += " --target %s'" % target_path process.system(cmd, verbose=True) else: pvt.pre_pool(pool_name, pool_type, pool_target, emulated_img) def cleanup_pool(user_pool=False, pool_name=pool_name, pool_target=pool_target): """ Clean up libvirt pool """ if output_uri == "qemu:///session" or user_pool: cmd = su_cmd + "'virsh pool-destroy %s'" % pool_name process.system(cmd, verbose=True) target_path = os.path.join("/home", v2v_user, pool_target) cmd = su_cmd + "'rm -rf %s'" % target_path process.system(cmd, verbose=True) else: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_img) def get_all_uuids(output): """ Get export domain uuid, image uuid and vol uuid from command output. """ tmp_target = re.findall(r"qemu-img\s'convert'\s.+\s'(\S+)'\n", output) if len(tmp_target) < 1: test.error("Fail to find tmp target file name when converting vm" " disk image") targets = tmp_target[0].split('/') return (targets[3], targets[5], targets[6]) def get_ovf_content(output): """ Find and read ovf file. """ export_domain_uuid, _, vol_uuid = get_all_uuids(output) export_vm_dir = os.path.join(mnt_point, export_domain_uuid, 'master/vms') ovf_content = "" if os.path.isdir(export_vm_dir): ovf_id = "ovf:id='%s'" % vol_uuid ret = to_text( process.system_output("grep -R \"%s\" %s" % (ovf_id, export_vm_dir))) ovf_file = ret.split(":")[0] if os.path.isfile(ovf_file): ovf_f = open(ovf_file, "r") ovf_content = ovf_f.read() ovf_f.close() else: logging.error("Can't find ovf file to read") return ovf_content def get_img_path(output): """ Get the full path of the converted image. """ img_name = vm_name + "-sda" if output_mode == "libvirt": img_path = virsh.vol_path(img_name, output_storage).stdout.strip() elif output_mode == "local": img_path = os.path.join(output_storage, img_name) elif output_mode in ["rhev", "vdsm"]: export_domain_uuid, image_uuid, vol_uuid = get_all_uuids(output) img_path = os.path.join(mnt_point, export_domain_uuid, 'images', image_uuid, vol_uuid) return img_path def check_vmtype(ovf, expected_vmtype): """ Verify vmtype in ovf file. """ if output_mode != "rhev": return if expected_vmtype == "server": vmtype_int = 1 elif expected_vmtype == "desktop": vmtype_int = 0 else: return if "<VmType>%s</VmType>" % vmtype_int in ovf: logging.info("Find VmType=%s in ovf file", expected_vmtype) else: test.fail("VmType check failed") def check_image(img_path, check_point, expected_value): """ Verify image file allocation mode and format """ if not img_path or not os.path.isfile(img_path): test.error("Image path: '%s' is invalid" % img_path) img_info = utils_misc.get_image_info(img_path) logging.debug("Image info: %s", img_info) if check_point == "allocation": if expected_value == "sparse": if img_info['vsize'] > img_info['dsize']: logging.info("%s is a sparse image", img_path) else: test.fail("%s is not a sparse image" % img_path) elif expected_value == "preallocated": if img_info['vsize'] <= img_info['dsize']: logging.info("%s is a preallocated image", img_path) else: test.fail("%s is not a preallocated image" % img_path) if check_point == "format": if expected_value == img_info['format']: logging.info("%s format is %s", img_path, expected_value) else: test.fail("%s format is not %s" % (img_path, expected_value)) def check_new_name(output, expected_name): """ Verify guest name changed to the new name. """ found = False if output_mode == "libvirt": found = virsh.domain_exists(expected_name) if output_mode == "local": found = os.path.isfile( os.path.join(output_storage, expected_name + "-sda")) if output_mode in ["rhev", "vdsm"]: ovf = get_ovf_content(output) found = "<Name>%s</Name>" % expected_name in ovf else: return if found: logging.info("Guest name renamed when converting it") else: test.fail("Rename guest failed") def check_nocopy(output): """ Verify no image created if convert command use --no-copy option """ img_path = get_img_path(output) if not os.path.isfile(img_path): logging.info("No image created with --no-copy option") else: test.fail("Find %s" % img_path) def check_connection(output, expected_uri): """ Check output connection uri used when converting guest """ init_msg = "Initializing the target -o libvirt -oc %s" % expected_uri if init_msg in output: logging.info("Find message: %s", init_msg) else: test.fail("Not find message: %s" % init_msg) def check_ovf_snapshot_id(ovf_content): """ Check if snapshot id in ovf file consists of '0's """ search = re.search("ovf:vm_snapshot_id='(.*?)'", ovf_content) if search: snapshot_id = search.group(1) logging.debug('vm_snapshot_id = %s', snapshot_id) if snapshot_id.count('0') >= 32: test.fail('vm_snapshot_id consists with "0"') else: test.fail('Fail to find snapshot_id') def setup_esx_ssh_key(hostname, user, password, port=22): """ Setup up remote login in esx server by using public key """ logging.debug('Performing SSH key setup on %s:%d as %s.' % (hostname, port, user)) try: session = remote.remote_login(client='ssh', host=hostname, username=user, port=port, password=password, prompt=r'[ $#%]') public_key = ssh_key.get_public_key() session.cmd("echo '%s' >> /etc/ssh/keys-root/authorized_keys; " % public_key) logging.debug('SSH key setup complete.') session.close() except Exception as err: logging.debug('SSH key setup has failed. %s', err) def check_source(output): """ Check if --print-source option print the correct info """ # Parse source info source = output.split('\n')[2:] for i in range(len(source)): if source[i].startswith('\t'): source[i - 1] += source[i] source[i] = '' source_strip = [x.strip() for x in source if x.strip()] source_info = {} for line in source_strip: source_info[line.split(':')[0]] = line.split(':', 1)[1].strip() logging.debug('Source info to check: %s', source_info) checklist = [ 'nr vCPUs', 'hypervisor type', 'source name', 'memory', 'disks', 'NICs' ] if hypervisor in ['kvm', 'xen']: checklist.extend(['display', 'CPU features']) for key in checklist: if key not in source_info: test.fail('%s info missing' % key) v2v_virsh = None close_virsh = False if hypervisor == 'kvm': v2v_virsh = virsh else: virsh_dargs = { 'uri': ic_uri, 'remote_ip': remote_host, 'remote_user': source_user, 'remote_pwd': source_pwd, 'debug': True } v2v_virsh = virsh.VirshPersistent(**virsh_dargs) close_virsh = True # Check single values fail = [] try: xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=v2v_virsh) finally: if close_virsh: v2v_virsh.close_session() check_map = {} check_map['nr vCPUs'] = xml.vcpu check_map['hypervisor type'] = xml.hypervisor_type check_map['source name'] = xml.vm_name check_map['memory'] = str(int(xml.max_mem) * 1024) + ' (bytes)' if hypervisor in ['kvm', 'xen']: check_map['display'] = xml.get_graphics_devices()[0].type_name logging.info('KEY:\tSOURCE<-> XML') for key in check_map: logging.info('%-15s:%18s <-> %s', key, source_info[key], check_map[key]) if str(check_map[key]) not in source_info[key]: fail.append(key) # Check disk info disk = list(xml.get_disk_all().values())[0] def _get_disk_subelement_attr_value(obj, attr, subattr): if obj.find(attr) is not None: return obj.find(attr).get(subattr) bus = _get_disk_subelement_attr_value(disk, 'target', 'bus') driver_type = _get_disk_subelement_attr_value(disk, 'driver', 'type') path = _get_disk_subelement_attr_value(disk, 'source', 'file') # For esx, disk output is like "disks: json: { ... } (raw) [scsi]" # For xen, disk output is like "disks: json: { ... } [ide]" # For kvm, disk output is like "/rhel8.0-2.qcow2 (qcow2) [virtio-blk]" if hypervisor == 'kvm': disks_info_pattern = "%s \(%s\) \[%s" % (path, driver_type, bus) elif hypervisor == 'esx': # replace '.vmdk' with '-flat.vmdk', this is done in v2v path_pattern1 = path.split()[1].replace('.vmdk', '-flat.vmdk') # In newer qemu version, '_' is replaced with '%5f'. path_pattern2 = path_pattern1.replace('_', '%5f') # For esx, '(raw)' is fixed? Let's see if others will be met. disks_info_pattern = '|'.join([ "https://%s/folder/%s\?dcPath=data&dsName=esx.*} \(raw\) \[%s" % (remote_host, i, bus) for i in [path_pattern1, path_pattern2] ]) elif hypervisor == 'xen': disks_info_pattern = "file\.path.*%s.*file\.host.*%s.* \[%s" % ( path, remote_host, bus) source_disks = source_info['disks'].split() logging.info('disks:%s<->%s', source_info['disks'], disks_info_pattern) if not re.search(disks_info_pattern, source_info['disks']): fail.append('disks') # Check nic info nic = list(xml.get_iface_all().values())[0] type = nic.get('type') mac = nic.find('mac').get('address') nic_source = nic.find('source') name = nic_source.get(type) nic_info = '%s "%s" mac: %s' % (type, name, mac) logging.info('NICs:%s<->%s', source_info['NICs'], nic_info) if nic_info.lower() not in source_info['NICs'].lower(): fail.append('NICs') # Check cpu features if hypervisor in ['kvm', 'xen']: feature_list = xml.features.get_feature_list() logging.info('CPU features:%s<->%s', source_info['CPU features'], feature_list) if sorted(source_info['CPU features'].split(',')) != sorted( feature_list): fail.append('CPU features') if fail: test.fail('Source info not correct for: %s' % fail) def check_man_page(in_man, not_in_man): """ Check if content of man page or help info meets expectation """ man_page = process.run('man virt-v2v', verbose=False).stdout_text.strip() if in_man: logging.info('Checking man page of virt-v2v for "%s"', in_man) if in_man not in man_page: test.fail('"%s" not in man page' % in_man) if not_in_man: logging.info('Checking man page of virt-v2v for "%s"', not_in_man) if not_in_man in man_page: test.fail('"%s" not removed from man page' % not_in_man) def check_result(cmd, result, status_error): """ Check virt-v2v command result """ utils_v2v.check_exit_status(result, status_error, error_flag) output = to_text(result.stdout + result.stderr, errors=error_flag) output_stdout = to_text(result.stdout, errors=error_flag) if status_error: if checkpoint == 'length_of_error': log_lines = output.split('\n') v2v_start = False for line in log_lines: if line.startswith('virt-v2v:'): v2v_start = True if line.startswith('libvirt:'): v2v_start = False if v2v_start and len(line) > 72: test.fail('Error log longer than 72 charactors: %s' % line) if checkpoint == 'disk_not_exist': vol_list = virsh.vol_list(pool_name) logging.info(vol_list) if vm_name in vol_list.stdout: test.fail('Disk exists for vm %s' % vm_name) else: if output_mode == "rhev" and checkpoint != 'quiet': ovf = get_ovf_content(output) logging.debug("ovf content: %s", ovf) check_ovf_snapshot_id(ovf) if '--vmtype' in cmd: expected_vmtype = re.findall(r"--vmtype\s(\w+)", cmd)[0] check_vmtype(ovf, expected_vmtype) if '-oa' in cmd and '--no-copy' not in cmd: expected_mode = re.findall(r"-oa\s(\w+)", cmd)[0] img_path = get_img_path(output) def check_alloc(): try: check_image(img_path, "allocation", expected_mode) return True except exceptions.TestFail: pass if not utils_misc.wait_for(check_alloc, timeout=600, step=10.0): test.fail('Allocation check failed.') if '-of' in cmd and '--no-copy' not in cmd and '--print-source' not in cmd and checkpoint != 'quiet': expected_format = re.findall(r"-of\s(\w+)", cmd)[0] img_path = get_img_path(output) check_image(img_path, "format", expected_format) if '-on' in cmd: expected_name = re.findall(r"-on\s(\w+)", cmd)[0] check_new_name(output, expected_name) if '--no-copy' in cmd: check_nocopy(output) if '-oc' in cmd: expected_uri = re.findall(r"-oc\s(\S+)", cmd)[0] check_connection(output, expected_uri) if output_mode == "rhev": if not utils_v2v.import_vm_to_ovirt(params, address_cache): test.fail("Import VM failed") else: params['vmcheck_flag'] = True if output_mode == "libvirt": if "qemu:///session" not in v2v_options and not no_root: virsh.start(vm_name, debug=True, ignore_status=False) if checkpoint == ['vmx', 'vmx_ssh']: vmchecker = VMChecker(test, params, env) params['vmchecker'] = vmchecker params['vmcheck_flag'] = True ret = vmchecker.run() if len(ret) == 0: logging.info("All common checkpoints passed") if checkpoint == 'quiet': if len(output.strip().splitlines()) > 10: test.fail('Output is not empty in quiet mode') if checkpoint == 'dependency': if 'libguestfs-winsupport' not in output: test.fail('libguestfs-winsupport not in dependency') if all(pkg_pattern not in output for pkg_pattern in ['VMF', 'edk2-ovmf']): test.fail('OVMF/AAVMF not in dependency') if 'qemu-kvm-rhev' in output: test.fail('qemu-kvm-rhev is in dependency') if 'libX11' in output: test.fail('libX11 is in dependency') if 'kernel-rt' in output: test.fail('kernel-rt is in dependency') win_img = params.get('win_image') command = 'guestfish -a %s -i' if process.run(command % win_img, ignore_status=True).exit_status == 0: test.fail('Command "%s" success' % command % win_img) if checkpoint == 'no_dcpath': if '--dcpath' in output: test.fail('"--dcpath" is not removed') if checkpoint == 'debug_overlays': search = re.search('Overlay saved as(.*)', output) if not search: test.fail('Not find log of saving overlays') overlay_path = search.group(1).strip() logging.debug('Overlay file location: %s' % overlay_path) if os.path.isfile(overlay_path): logging.info('Found overlay file: %s' % overlay_path) else: test.fail('Overlay file not saved') if checkpoint.startswith('empty_nic_source'): target_str = '%s "eth0" mac: %s' % (params[checkpoint][0], params[checkpoint][1]) logging.info('Expect log: %s', target_str) if target_str not in output_stdout.lower(): test.fail('Expect log not found: %s' % target_str) if checkpoint == 'print_source': check_source(output_stdout) if checkpoint == 'machine_readable': if os.path.exists(params.get('example_file', '')): # Checking items in example_file exist in latest # output regardless of the orders and new items. with open(params['example_file']) as f: for line in f: if line.strip() not in output_stdout.strip(): test.fail( '%s not in --machine-readable output' % line.strip()) else: test.error('No content to compare with') if checkpoint == 'compress': img_path = get_img_path(output) logging.info('Image path: %s', img_path) qemu_img_cmd = 'qemu-img check %s' % img_path qemu_img_locking_feature_support = libvirt_storage.check_qemu_image_lock_support( ) if qemu_img_locking_feature_support: qemu_img_cmd = 'qemu-img check %s -U' % img_path disk_check = process.run(qemu_img_cmd).stdout_text logging.info(disk_check) compress_info = disk_check.split(',')[-1].split('%')[0].strip() compress_rate = float(compress_info) logging.info('%s%% compressed', compress_rate) if compress_rate < 0.1: test.fail('Disk image NOT compressed') if checkpoint == 'tail_log': messages = params['tail'].get_output() logging.info('Content of /var/log/messages during conversion:') logging.info(messages) msg_content = params['msg_content'] if msg_content in messages: test.fail('Found "%s" in /var/log/messages' % msg_content) log_check = utils_v2v.check_log(params, output) if log_check: test.fail(log_check) check_man_page(params.get('in_man'), params.get('not_in_man')) backup_xml = None vdsm_domain_dir, vdsm_image_dir, vdsm_vm_dir = ("", "", "") try: if checkpoint.startswith('empty_nic_source'): xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) iface = xml.get_devices('interface')[0] disks = xml.get_devices('disk') del iface.source iface.type_name = checkpoint.split('_')[-1] iface.source = {iface.type_name: ''} params[checkpoint] = [iface.type_name, iface.mac_address] logging.debug(iface.source) devices = vm_xml.VMXMLDevices() devices.extend(disks) devices.append(iface) xml.set_devices(devices) logging.info(xml.xmltreefile) params['input_xml'] = xml.xmltreefile.name # Build input options input_option = "" if input_mode is None: pass elif input_mode == "libvirt": uri_obj = utils_v2v.Uri(hypervisor) ic_uri = uri_obj.get_uri(remote_host, vpx_dc, esx_ip) if checkpoint == 'with_ic': ic_uri = 'qemu:///session' input_option = "-i %s -ic %s %s" % (input_mode, ic_uri, vm_name) if checkpoint == 'without_ic': input_option = '-i %s %s' % (input_mode, vm_name) # Build network&bridge option to avoid network error v2v_options += " -b %s -n %s" % (params.get("output_bridge"), params.get("output_network")) elif input_mode == "disk": input_option += "-i %s %s" % (input_mode, disk_img) elif input_mode == 'libvirtxml': input_xml = params.get('input_xml') input_option += '-i %s %s' % (input_mode, input_xml) elif input_mode in ['ova']: test.cancel("Unsupported input mode: %s" % input_mode) else: test.error("Unknown input mode %s" % input_mode) input_format = params.get("input_format", "") input_allo_mode = params.get("input_allo_mode") if input_format: input_option += " -if %s" % input_format if not status_error: logging.info("Check image before convert") check_image(disk_img, "format", input_format) if input_allo_mode: check_image(disk_img, "allocation", input_allo_mode) # Build output options output_option = "" if output_mode: output_option = "-o %s -os %s" % (output_mode, output_storage) if checkpoint == 'rhv': output_option = output_option.replace('rhev', 'rhv') output_format = params.get("output_format") if output_format and output_format != input_format: output_option += " -of %s" % output_format output_allo_mode = params.get("output_allo_mode") if output_allo_mode: output_option += " -oa %s" % output_allo_mode # Build vdsm related options if output_mode in ['vdsm', 'rhev']: if not os.path.isdir(mnt_point): os.mkdir(mnt_point) if not utils_misc.mount(nfs_storage, mnt_point, "nfs"): test.error("Mount NFS Failed") if output_mode == 'vdsm': v2v_options += " --vdsm-image-uuid %s" % vdsm_image_uuid v2v_options += " --vdsm-vol-uuid %s" % vdsm_vol_uuid v2v_options += " --vdsm-vm-uuid %s" % vdsm_vm_uuid v2v_options += " --vdsm-ovf-output %s" % vdsm_ovf_output vdsm_domain_dir = os.path.join(mnt_point, fake_domain_uuid) vdsm_image_dir = os.path.join(mnt_point, export_domain_uuid, "images", vdsm_image_uuid) vdsm_vm_dir = os.path.join(mnt_point, export_domain_uuid, "master/vms", vdsm_vm_uuid) # For vdsm_domain_dir, just create a dir to test BZ#1176591 os.makedirs(vdsm_domain_dir) os.makedirs(vdsm_image_dir) os.makedirs(vdsm_vm_dir) # Output more messages except quiet mode if checkpoint == 'quiet': v2v_options += ' -q' elif checkpoint not in [ 'length_of_error', 'empty_nic_source_network', 'empty_nic_source_bridge', 'machine_readable' ]: v2v_options += " -v -x" # Prepare for libvirt unprivileged user session connection if "qemu:///session" in v2v_options or no_root: try: pwd.getpwnam(v2v_user) except KeyError: # create new user process.system("useradd %s" % v2v_user, ignore_status=True) new_v2v_user = True user_info = pwd.getpwnam(v2v_user) logging.info("Convert to qemu:///session by user '%s'", v2v_user) if input_mode == "disk": # Copy image from souce and change the image owner and group disk_path = os.path.join(data_dir.get_tmp_dir(), os.path.basename(disk_img)) logging.info('Copy image file %s to %s', disk_img, disk_path) shutil.copyfile(disk_img, disk_path) input_option = input_option.replace(disk_img, disk_path) os.chown(disk_path, user_info.pw_uid, user_info.pw_gid) elif not no_root: test.cancel("Only support convert local disk") # Setup ssh-agent access to xen hypervisor if hypervisor == 'xen': user = params.get("xen_host_user", "root") source_pwd = passwd = params.get("xen_host_passwd", "redhat") logging.info("set up ssh-agent access ") ssh_key.setup_ssh_key(remote_host, user=user, port=22, password=passwd) utils_misc.add_identities_into_ssh_agent() # Check if xen guest exists uri = utils_v2v.Uri(hypervisor).get_uri(remote_host) if not virsh.domain_exists(vm_name, uri=uri): logging.error('VM %s not exists', vm_name) # If the input format is not define, we need to either define # the original format in the source metadata(xml) or use '-of' # to force the output format, see BZ#1141723 for detail. if '-of' not in v2v_options and checkpoint != 'xen_no_output_format': v2v_options += ' -of %s' % params.get("default_output_format", "qcow2") # Create password file for access to ESX hypervisor if hypervisor == 'esx': source_pwd = vpx_passwd = params.get("vpx_password") vpx_passwd_file = os.path.join(data_dir.get_tmp_dir(), "vpx_passwd") logging.info("Building ESX no password interactive verification.") pwd_f = open(vpx_passwd_file, 'w') pwd_f.write(vpx_passwd) pwd_f.close() output_option += " --password-file %s" % vpx_passwd_file # if don't specify any output option for virt-v2v, 'default' pool # will be used. if output_mode is None: # Cleanup first to avoid failure if 'default' pool exists. pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_img) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_img) # Create libvirt dir pool if output_mode == "libvirt": create_pool() # Work around till bug fixed os.environ['LIBGUESTFS_BACKEND'] = 'direct' if checkpoint in ['with_ic', 'without_ic']: new_v2v_user = True v2v_options += ' -on %s' % new_vm_name create_pool(user_pool=True, pool_name='src_pool', pool_target='v2v_src_pool') create_pool(user_pool=True) logging.debug(virsh.pool_list(uri='qemu:///session')) sh_install_vm = params.get('sh_install_vm') if not sh_install_vm: test.error('Source vm installing script missing') with open(sh_install_vm) as fh: cmd_install_vm = fh.read().strip() process.run('su - %s -c "%s"' % (v2v_user, cmd_install_vm), timeout=10, shell=True) params['cmd_clean_vm'] = "%s 'virsh undefine %s'" % (su_cmd, vm_name) if checkpoint == 'vmx': mount_point = params.get('mount_point') if not os.path.isdir(mount_point): os.mkdir(mount_point) nfs_vmx = params.get('nfs_vmx') if not utils_misc.mount(nfs_vmx, mount_point, 'nfs', verbose=True): test.error('Mount nfs for vmx failed') vmx = params.get('vmx') input_option = '-i vmx %s' % vmx v2v_options += " -b %s -n %s" % (params.get("output_bridge"), params.get("output_network")) if checkpoint == 'vmx_ssh': esx_user = params.get("esx_host_user", "root") esx_pwd = params.get("esx_host_passwd", "123qweP") vmx = params.get('vmx') setup_esx_ssh_key(esx_ip, esx_user, esx_pwd) try: utils_misc.add_identities_into_ssh_agent() except Exception: process.run("ssh-agent -k") raise exceptions.TestError("Fail to setup ssh-agent") input_option = '-i vmx -it ssh %s' % vmx v2v_options += " -b %s -n %s" % (params.get("output_bridge"), params.get("output_network")) if checkpoint == 'simulate_nfs': simulate_images = params.get("simu_images_path") simulate_vms = params.get("simu_vms_path") simulate_dom_md = params.get("simu_dom_md_path") os.makedirs(simulate_images) os.makedirs(simulate_vms) process.run('touch %s' % simulate_dom_md) process.run('chmod -R 777 /tmp/rhv/') # Running virt-v2v command cmd = "%s %s %s %s" % (utils_v2v.V2V_EXEC, input_option, output_option, v2v_options) if v2v_user: cmd_export_env = 'export LIBGUESTFS_BACKEND=direct' cmd = "%s '%s;%s'" % (su_cmd, cmd_export_env, cmd) if params.get('cmd_free') == 'yes': cmd = params.get('check_command') # only set error to 'ignore' to avoid exception for RHEL7-84978 if "guestfish" in cmd: error_flag = "replace" # Set timeout to kill v2v process before conversion succeed if checkpoint == 'disk_not_exist': v2v_timeout = 30 # Get tail content of /var/log/messages if checkpoint == 'tail_log': params['tail_log'] = os.path.join(data_dir.get_tmp_dir(), 'tail_log') params['tail'] = aexpect.Tail(command='tail -f /var/log/messages', output_func=utils_misc.log_line, output_params=(params['tail_log'], )) cmd_result = process.run(cmd, timeout=v2v_timeout, verbose=True, ignore_status=True) if new_vm_name: vm_name = new_vm_name params['main_vm'] = new_vm_name check_result(cmd, cmd_result, status_error) finally: if hypervisor == "xen": process.run("ssh-agent -k") if hypervisor == "esx": process.run("rm -rf %s" % vpx_passwd_file) for vdsm_dir in [vdsm_domain_dir, vdsm_image_dir, vdsm_vm_dir]: if os.path.exists(vdsm_dir): shutil.rmtree(vdsm_dir) if os.path.exists(mnt_point): utils_misc.umount(nfs_storage, mnt_point, "nfs") os.rmdir(mnt_point) if output_mode == "local": image_name = vm_name + "-sda" img_file = os.path.join(output_storage, image_name) xml_file = img_file + ".xml" for local_file in [img_file, xml_file]: if os.path.exists(local_file): os.remove(local_file) if output_mode == "libvirt": if "qemu:///session" in v2v_options or no_root: cmd = su_cmd + "'virsh undefine %s'" % vm_name try: process.system(cmd) except Exception: logging.error('Undefine "%s" failed', vm_name) if no_root: cleanup_pool(user_pool=True, pool_name='src_pool', pool_target='v2v_src_pool') cleanup_pool(user_pool=True) else: virsh.remove_domain(vm_name) cleanup_pool() if output_mode is None: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_img) vmcheck_flag = params.get("vmcheck_flag") if vmcheck_flag: vmcheck = utils_v2v.VMCheck(test, params, env) vmcheck.cleanup() if checkpoint in ['with_ic', 'without_ic']: process.run(params['cmd_clean_vm']) if new_v2v_user: process.system("userdel -f %s" % v2v_user) if backup_xml: backup_xml.sync() if checkpoint == 'vmx': utils_misc.umount(params['nfs_vmx'], params['mount_point'], 'nfs') os.rmdir(params['mount_point']) if checkpoint == 'simulate_nfs': process.run('rm -rf /tmp/rhv/')
else: if not self.kill_first: if self.vm.is_dead(): self.vm.start() try: self.vm.wait_for_login() except remote.LoginTimeoutError, detail: raise error.TestFail(str(detail)) else: virsh.remove_domain(self.vm_name) if self.twice_execute or self.read_only: self.td1 = threading.Thread(target=unattended_install.run, args=(self.test, params, self.env)) self.td1.start() self.td1.join() if not virsh.domain_exists(self.vm_name): raise error.TestFail("Domain '%s' installation failed!" % self.vm_name) def recover(self, params=None): """ Recover test environment """ if self.selinux_enforcing: utils_selinux.set_status("enforcing") if virsh.domain_exists(self.vm_name): virsh.remove_domain(self.vm_name) image_file = params.get("image_name") if os.path.exists(image_file): os.remove(image_file) if os.path.isdir(self.image_path):
def run(test, params, env): """ Test virsh blockcopy with various option based on transient_guest. 1.Prepare backend storage (iscsi) 2.Start VM 3.Execute virsh blockcopy target command 4.Check status after operation accomplished 5.Clean up test environment """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) def setup_file_backend_env(params): """ Setup iscsi test environment :param params: one dict to wrap up parameters """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) type_name = params.get("virt_disk_device_type") disk_device = params.get("virt_disk_device") device_target = params.get("virt_disk_device_target") device_bus = params.get("virt_disk_device_bus") device_format = params.get("virt_disk_device_format") blockcopy_image_name = params.get("blockcopy_image_name") emulated_size = int(params.get("emulated_size", "2")) libvirt.create_local_disk("file", blockcopy_image_name, emulated_size, "qcow2") disk_src_dict = {"attrs": {"file": blockcopy_image_name}} file_disk = libvirt_disk.create_primitive_disk_xml( type_name, disk_device, device_target, device_bus, device_format, disk_src_dict, None) logging.debug("guest xml after undefined and recreated:\n%s", file_disk) return file_disk def start_pivot_blkcpy_on_transient_vm(): """ Start blockcopy with pivot option """ external_snapshot_disks = libvirt_disk.make_external_disk_snapshots( vm, device_target, "trans_snapshot", snapshot_take) logging.debug("external snapshots:%s\n", external_snapshot_disks) external_snapshot_disks.pop() for sub_option in ["--shallow --pivot", "--pivot"]: tmp_copy_path = os.path.join( data_dir.get_data_dir(), "%s_%s.img" % (vm_name, sub_option[2:5])) tmp_blkcopy_path.append(tmp_copy_path) if os.path.exists(tmp_copy_path): libvirt.delete_local_disk('file', tmp_copy_path) virsh.blockcopy(vm_name, device_target, tmp_copy_path, options=sub_option, ignore_status=False, debug=True) back_chain_files = libvirt_disk.get_chain_backing_files( tmp_copy_path) back_chain_files = back_chain_files[1:len(back_chain_files)] logging.debug("debug blockcopy xml restore:%s and %s\n", external_snapshot_disks, back_chain_files) if back_chain_files != external_snapshot_disks: test.fail("can not get identical backing chain") utils_misc.wait_for( lambda: libvirt.check_blockjob(vm_name, device_target), 5) #After pivot, no backing chain exists external_snapshot_disks = [] def check_info_in_libvird_log_file(matchedMsg=None): """ Check if information can be found in libvirtd log. :params matchedMsg: expected matched messages """ # Check libvirtd log file. libvirtd_log_file = log_config_path if not os.path.exists(libvirtd_log_file): test.fail("Expected VM log file: %s not exists" % libvirtd_log_file) cmd = ("grep -nr '%s' %s" % (matchedMsg, libvirtd_log_file)) return process.run(cmd, ignore_status=True, shell=True).exit_status == 0 def check_bandwidth_progress(bandwidth_value): """ Check bandwidth :param bandwidth_value: expected bandwidth value """ ret = utils_misc.wait_for( lambda: libvirt.check_blockjob(vm_name, device_target, "bandwidth", bandwidth_value), 30) if not ret: test.fail("Failed to get bandwidth limit output") def _extend_blkcpy_execution(sub_option, sub_status_error, pre_created=False): """ Wrap up blockcopy execution combining with various options :params sub_option: option :params sub_status_error: expected error or not :params pre_created: whether pre-created """ tmp_copy_path = os.path.join(data_dir.get_data_dir(), "%s_%s.img" % (vm_name, sub_option)) if os.path.exists(tmp_copy_path): libvirt.delete_local_disk('file', tmp_copy_path) if pre_created: libvirt.create_local_disk('file', tmp_copy_path, '10M', 'qcow2') tmp_option = params.get("options") % sub_option if "default" in tmp_option: tmp_option = " --wait --verbose" result = virsh.blockcopy(vm_name, device_target, tmp_copy_path, options=tmp_option, ignore_status=True, debug=True) logging.debug(sub_status_error) libvirt.check_exit_status(result, expect_error=sub_status_error) def start_granularity_blkcpy_on_transient_vm(): """Start blockcopy with granularity operations """ granularity_value = params.get('granularity_value').split() option_status_error = [ value == 'yes' for value in params.get('option_status_error').split() ] for sub_option, sub_status_error in zip(granularity_value, option_status_error): _extend_blkcpy_execution(sub_option, sub_status_error) if not option_status_error: #Check log whether granularity keyword is there result = utils_misc.wait_for( lambda: check_info_in_libvird_log_file('"granularity":%s' % sub_option), timeout=20) if not result: test.fail( "Failed to get expected messages from log file: %s." % log_config_path) virsh.blockjob(vm_name, device_target, '--abort', ignore_status=True) def start_bandwidth_blkcpy_on_transient_vm(): """Start blockcopy with bandwidth operations """ bandwidth_value = params.get('bandwidth_value').split() option_status_error = [ value == 'yes' for value in params.get('option_status_error').split() ] for sub_option, sub_status_error in zip(bandwidth_value, option_status_error): _extend_blkcpy_execution(sub_option, sub_status_error) if not sub_status_error and 'default' not in sub_option: check_bandwidth_progress(sub_option) virsh.blockjob(vm_name, device_target, '--abort', ignore_status=True) def start_timeout_blkcpy_on_transient_vm(): """Start blockcopy with timeout operations """ timeout_value = params.get('timeout_value').split() option_status_error = [ value == 'yes' for value in params.get('option_status_error').split() ] for sub_option, sub_status_error in zip(timeout_value, option_status_error): _extend_blkcpy_execution(sub_option, sub_status_error) virsh.blockjob(vm_name, device_target, '--abort', ignore_status=True) def start_bufsize_blkcpy_on_transient_vm(): """Start blockcopy with buffer size operations """ bufsize_value = params.get('bufsize_value').split() option_status_error = [ value == 'yes' for value in params.get('option_status_error').split() ] for sub_option, sub_status_error in zip(bufsize_value, option_status_error): _extend_blkcpy_execution(sub_option, sub_status_error) if not option_status_error: #Check log whether buf-size keyword is there result = utils_misc.wait_for( lambda: check_info_in_libvird_log_file('buf-size'), timeout=20) if not result: test.fail( "Failed to get expected messages from log file: %s." % log_config_path) virsh.blockjob(vm_name, device_target, '--abort', ignore_status=True) def start_reuse_external_blkcpy_on_transient_vm(): """Start reuse external blockcopy operations """ reuse_external_value = params.get('reuse-external_value').split() option_status_error = [ value == 'yes' for value in params.get('option_status_error').split() ] for sub_option, sub_status_error in zip(reuse_external_value, option_status_error): _extend_blkcpy_execution(sub_option, sub_status_error, pre_created=True) if option_status_error: #Check blockcommit job information job_result = virsh.blockjob( vm_name, device_target, '--info', ignore_status=True).stdout_text.strip() if 'No current block job for' not in job_result: test.fail( "Failed to get unexpected active blockcommit job") virsh.blockjob(vm_name, device_target, '--abort', ignore_status=True) # Disk specific attributes. device_target = params.get("virt_disk_device_target", "vdd") blockcopy_option = params.get("blockcopy_option") backend_storage_type = params.get("backend_storage_type") device_type = params.get("virt_disk_device_type") status_error = "yes" == params.get("status_error") define_error = "yes" == params.get("define_error") snapshot_take = int(params.get("snapshot_take", "4")) # Configure libvirtd log path log_config_path = params.get("libvirtd_debug_file", "/var/log/libvirt/libvird.log") # Additional disk images. tmp_blkcopy_path = [] external_snapshot_disks = [] attach_disk_xml = None # Start VM and get all partitions in VM. if vm.is_dead(): vm.start() session = vm.wait_for_login() old_parts = utils_disk.get_parts_list(session) session.close() vm.destroy(gracefully=False) # Back up xml file. vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: # Setup backend storage if backend_storage_type == "file": attach_disk_xml = setup_file_backend_env(params) # Add disk xml. vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) logging.debug("disk xml is:\n%s" % attach_disk_xml) # Sync VM xml. if attach_disk_xml is None: test.fail("Fail to create attached disk xml") else: vmxml.add_device(attach_disk_xml) vmxml.sync() try: # Create a transient VM transient_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) virsh.undefine(vm_name, debug=True, ignore_status=False) virsh.create(transient_vmxml.xml, ignore_status=False, debug=True) vm.wait_for_login().close() debug_xml = vm_xml.VMXML.new_from_dumpxml(vm_name) logging.debug("guest xml after undefined and recreated:%s\n", debug_xml) except xcepts.LibvirtXMLError as xml_error: if not define_error: test.fail("Failed to define VM:\n%s" % str(xml_error)) except virt_vm.VMStartError as details: # VM cannot be started if status_error: logging.info("VM failed to start as expected: %s", str(details)) else: test.fail("VM should start but failed: %s" % str(details)) if blockcopy_option in ['pivot_shadow']: start_pivot_blkcpy_on_transient_vm() if blockcopy_option in ['granularity']: start_granularity_blkcpy_on_transient_vm() if blockcopy_option in ['bandwidth']: start_bandwidth_blkcpy_on_transient_vm() if blockcopy_option in ['timeout']: start_timeout_blkcpy_on_transient_vm() if blockcopy_option in ['buf_size']: start_bufsize_blkcpy_on_transient_vm() if blockcopy_option in ['reuse_external']: start_reuse_external_blkcpy_on_transient_vm() finally: if virsh.domain_exists(vm_name): #To clean up snapshots and restore VM try: libvirt.clean_up_snapshots(vm_name, domxml=vmxml_backup) finally: if vm.is_alive(): vm.destroy(gracefully=False) virsh.define(vmxml_backup.xml, debug=True) vmxml_backup.sync() # Clean up backend storage for tmp_path in tmp_blkcopy_path: if os.path.exists(tmp_path): libvirt.delete_local_disk('file', tmp_path) if backend_storage_type == "iscsi": libvirt.setup_or_cleanup_iscsi(is_setup=False)
uri = libvirt_vm.complete_uri(local_ip) session = remote.remote_login("ssh", remote_ip, "22", remote_user, remote_password, remote_prompt) cmd_undefine = "virsh -c %s undefine %s" % (uri, vm_name) status, output = session.cmd_status_output(cmd_undefine) logging.info("Undefine output: %s", output) except (error.CmdError, remote.LoginError, aexpect.ShellError), detail: logging.error("Detail: %s", detail) status = 1 # Recover libvirtd state. if libvirtd_state == "off": utils_libvirtd.libvirtd_start() # Shutdown VM. if virsh.domain_exists(vm.name): try: if vm.is_alive(): vm.destroy() except error.CmdError, detail: logging.error("Detail: %s", detail) # Check if VM exists. vm_exist = virsh.domain_exists(vm.name) # Check if xml file exists. xml_exist = False if (os.path.exists("/etc/libvirt/qemu/%s.xml" % vm_name) or os.path.exists("/etc/xen/%s" % vm_name)): xml_exist = True
def run(test, params, env): """ Test command: virsh blockcopy. This command can copy a disk backing image chain to dest. 1. Positive testing 1.1 Copy a disk to a new image file. 1.2 Reuse existing destination copy. 1.3 Valid blockcopy timeout and bandwidth test. 2. Negative testing 2.1 Copy a disk to a non-exist directory. 2.2 Copy a disk with invalid options. 2.3 Do block copy for a persistent domain. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) target = params.get("target_disk", "") replace_vm_disk = "yes" == params.get("replace_vm_disk", "no") disk_source_protocol = params.get("disk_source_protocol") disk_type = params.get("disk_type") pool_name = params.get("pool_name") image_size = params.get("image_size") emu_image = params.get("emulated_image") copy_to_nfs = "yes" == params.get("copy_to_nfs", "no") mnt_path_name = params.get("mnt_path_name") options = params.get("blockcopy_options", "") bandwidth = params.get("blockcopy_bandwidth", "") bandwidth_byte = "yes" == params.get("bandwidth_byte", "no") reuse_external = "yes" == params.get("reuse_external", "no") persistent_vm = params.get("persistent_vm", "no") status_error = "yes" == params.get("status_error", "no") active_error = "yes" == params.get("active_error", "no") active_snap = "yes" == params.get("active_snap", "no") active_save = "yes" == params.get("active_save", "no") check_state_lock = "yes" == params.get("check_state_lock", "no") check_finish_job = "yes" == params.get("check_finish_job", "yes") with_shallow = "yes" == params.get("with_shallow", "no") with_blockdev = "yes" == params.get("with_blockdev", "no") setup_libvirt_polkit = "yes" == params.get('setup_libvirt_polkit') bug_url = params.get("bug_url", "") timeout = int(params.get("timeout", 1200)) relative_path = params.get("relative_path") rerun_flag = 0 blkdev_n = None back_n = 'blockdev-backing-iscsi' snapshot_external_disks = [] snapshots_take = int(params.get("snapshots_take", '0')) external_disk_only_snapshot = "yes" == params.get( "external_disk_only_snapshot", "no") enable_iscsi_auth = "yes" == params.get("enable_iscsi_auth", "no") # Skip/Fail early if with_blockdev and not libvirt_version.version_compare(1, 2, 13): raise exceptions.TestSkipError("--blockdev option not supported in " "current version") if not target: raise exceptions.TestSkipError("Require target disk to copy") if setup_libvirt_polkit and not libvirt_version.version_compare(1, 1, 1): raise exceptions.TestSkipError("API acl test not supported in current" " libvirt version") if copy_to_nfs and not libvirt_version.version_compare(1, 1, 1): raise exceptions.TestSkipError("Bug will not fix: %s" % bug_url) if bandwidth_byte and not libvirt_version.version_compare(1, 3, 3): raise exceptions.TestSkipError("--bytes option not supported in " "current version") if relative_path == "yes" and not libvirt_version.version_compare(3, 0, 0): test.cancel( "Forbid using relative path or file name only is added since libvirt-3.0.0" ) if "--transient-job" in options and not libvirt_version.version_compare( 4, 5, 0): test.cancel( "--transient-job option is supported until libvirt 4.5.0 version") # Check the source disk if vm_xml.VMXML.check_disk_exist(vm_name, target): logging.debug("Find %s in domain %s", target, vm_name) else: raise exceptions.TestFail("Can't find %s in domain %s" % (target, vm_name)) original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) tmp_dir = data_dir.get_tmp_dir() # Prepare dest path params dest_path = params.get("dest_path", "") dest_format = params.get("dest_format", "") # Ugh... this piece of chicanery brought to you by the QemuImg which # will "add" the 'dest_format' extension during the check_format code. # So if we create the file with the extension and then remove it when # doing the check_format later, then we avoid erroneous failures. dest_extension = "" if dest_format != "": dest_extension = ".%s" % dest_format # Prepare for --reuse-external option if reuse_external: options += "--reuse-external --wait" # Set rerun_flag=1 to do blockcopy twice, and the first time created # file can be reused in the second time if no dest_path given # This will make sure the image size equal to original disk size if dest_path == "/path/non-exist": if os.path.exists(dest_path) and not os.path.isdir(dest_path): os.remove(dest_path) else: rerun_flag = 1 # Prepare other options if dest_format == "raw": options += " --raw" if with_blockdev: options += " --blockdev" if len(bandwidth): options += " --bandwidth %s" % bandwidth if bandwidth_byte: options += " --bytes" if with_shallow: options += " --shallow" # Prepare acl options uri = params.get("virsh_uri") unprivileged_user = params.get('unprivileged_user') if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = '******' extra_dict = { 'uri': uri, 'unprivileged_user': unprivileged_user, 'debug': True, 'ignore_status': True, 'timeout': timeout } libvirtd_utl = utils_libvirtd.Libvirtd() libvirtd_log_path = os.path.join(data_dir.get_tmp_dir(), "libvirt_daemons.log") libvirtd_conf_dict = { "log_filter": '"3:json 1:libvirt 1:qemu"', "log_outputs": '"1:file:%s"' % libvirtd_log_path } logging.debug("the libvirtd conf file content is :\n %s" % libvirtd_conf_dict) libvirtd_conf = utl.customize_libvirt_config(libvirtd_conf_dict) def check_format(dest_path, dest_extension, expect): """ Check the image format :param dest_path: Path of the copy to create :param expect: Expect image format """ # And now because the QemuImg will add the extension for us # we have to remove it here. path_noext = dest_path.strip(dest_extension) params['image_name'] = path_noext params['image_format'] = expect image = qemu_storage.QemuImg(params, "/", path_noext) if image.get_format() == expect: logging.debug("%s format is %s", dest_path, expect) else: raise exceptions.TestFail("%s format is not %s" % (dest_path, expect)) def _blockjob_and_libvirtd_chk(cmd_result): """ Raise TestFail when blockcopy fail with block-job-complete error or blockcopy hang with state change lock. This is a specific bug verify, so ignore status_error here. """ failure_msg = "" err_msg = "internal error: unable to execute QEMU command" err_msg += " 'block-job-complete'" if err_msg in cmd_result.stderr: failure_msg += "Virsh cmd error happened: %s\n" % err_msg err_pattern = "Timed out during operation: cannot acquire" err_pattern += " state change lock" ret = chk_libvirtd_log(libvirtd_log_path, err_pattern, "error") if ret: failure_msg += "Libvirtd log error happened: %s\n" % err_pattern if failure_msg: if not libvirt_version.version_compare(1, 3, 2): bug_url_ = "https://bugzilla.redhat.com/show_bug.cgi?id=1197592" failure_msg += "Hit on bug: %s " % bug_url_ test.fail(failure_msg) def _make_snapshot(snapshot_numbers_take): """ Make external disk snapshot :param snapshot_numbers_take: snapshot numbers. """ for count in range(0, snapshot_numbers_take): snap_xml = snapshot_xml.SnapshotXML() snapshot_name = "blockcopy_snap" snap_xml.snap_name = snapshot_name + "_%s" % count snap_xml.description = "blockcopy snapshot" # Add all disks into xml file. vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) disks = vmxml.devices.by_device_tag('disk') # Remove non-storage disk such as 'cdrom' for disk in disks: if disk.device != 'disk': disks.remove(disk) new_disks = [] src_disk_xml = disks[0] disk_xml = snap_xml.SnapDiskXML() disk_xml.xmltreefile = src_disk_xml.xmltreefile del disk_xml.device del disk_xml.address disk_xml.snapshot = "external" disk_xml.disk_name = disk_xml.target['dev'] # Only qcow2 works as external snapshot file format, update it # here driver_attr = disk_xml.driver driver_attr.update({'type': 'qcow2'}) disk_xml.driver = driver_attr new_attrs = disk_xml.source.attrs if 'file' in disk_xml.source.attrs: new_file = os.path.join(tmp_dir, "blockcopy_shallow_%s.snap" % count) snapshot_external_disks.append(new_file) new_attrs.update({'file': new_file}) hosts = None elif ('dev' in disk_xml.source.attrs or 'name' in disk_xml.source.attrs or 'pool' in disk_xml.source.attrs): if (disk_xml.type_name == 'block' or disk_source_protocol == 'iscsi'): disk_xml.type_name = 'block' if 'name' in new_attrs: del new_attrs['name'] del new_attrs['protocol'] elif 'pool' in new_attrs: del new_attrs['pool'] del new_attrs['volume'] del new_attrs['mode'] back_path = utl.setup_or_cleanup_iscsi( is_setup=True, is_login=True, image_size="1G", emulated_image=back_n) emulated_iscsi.append(back_n) cmd = "qemu-img create -f qcow2 %s 1G" % back_path process.run(cmd, shell=True) new_attrs.update({'dev': back_path}) hosts = None new_src_dict = {"attrs": new_attrs} if hosts: new_src_dict.update({"hosts": hosts}) disk_xml.source = disk_xml.new_disk_source(**new_src_dict) new_disks.append(disk_xml) snap_xml.set_disks(new_disks) snapshot_xml_path = snap_xml.xml logging.debug("The snapshot xml is: %s" % snap_xml.xmltreefile) options = "--disk-only --xmlfile %s " % snapshot_xml_path snapshot_result = virsh.snapshot_create(vm_name, options, debug=True) if snapshot_result.exit_status != 0: raise exceptions.TestFail(snapshot_result.stderr) snap_path = '' save_path = '' emulated_iscsi = [] nfs_cleanup = False try: # Prepare dest_path tmp_file = time.strftime("%Y-%m-%d-%H.%M.%S.img") tmp_file += dest_extension if not dest_path: if enable_iscsi_auth: utils_secret.clean_up_secrets() setup_auth_enabled_iscsi_disk(vm, params) dest_path = os.path.join(tmp_dir, tmp_file) elif with_blockdev: blkdev_n = 'blockdev-iscsi' dest_path = utl.setup_or_cleanup_iscsi(is_setup=True, is_login=True, image_size=image_size, emulated_image=blkdev_n) emulated_iscsi.append(blkdev_n) # Make sure the new disk show up utils_misc.wait_for(lambda: os.path.exists(dest_path), 5) else: if copy_to_nfs: tmp_dir = "%s/%s" % (tmp_dir, mnt_path_name) dest_path = os.path.join(tmp_dir, tmp_file) # Domain disk replacement with desire type if replace_vm_disk: # Calling 'set_vm_disk' is bad idea as it left lots of cleanup jobs # after test, such as pool, volume, nfs, iscsi and so on # TODO: remove this function in the future if disk_source_protocol == 'iscsi': emulated_iscsi.append(emu_image) if disk_source_protocol == 'netfs': nfs_cleanup = True utl.set_vm_disk(vm, params, tmp_dir, test) new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) if with_shallow or external_disk_only_snapshot or enable_iscsi_auth: _make_snapshot(snapshots_take) # Prepare transient/persistent vm if persistent_vm == "no" and vm.is_persistent(): vm.undefine() elif persistent_vm == "yes" and not vm.is_persistent(): new_xml.define() # Run blockcopy command to create destination file if rerun_flag == 1: options1 = "--wait %s --finish --verbose" % dest_format if with_blockdev: options1 += " --blockdev" if with_shallow: options1 += " --shallow" cmd_result = virsh.blockcopy(vm_name, target, dest_path, options1, **extra_dict) status = cmd_result.exit_status if status != 0: raise exceptions.TestFail("Run blockcopy command fail: %s" % cmd_result.stdout.strip() + cmd_result.stderr) elif not os.path.exists(dest_path): raise exceptions.TestFail("Cannot find the created copy") if "--transient-job" in options: pool = ThreadPool(processes=1) async_result = pool.apply_async( blockcopy_thread, (vm_name, target, dest_path, options)) kill_blockcopy_process() utl.check_blockjob(vm_name, target) return # Run the real testing command cmd_result = virsh.blockcopy(vm_name, target, dest_path, options, **extra_dict) # check BZ#1197592 _blockjob_and_libvirtd_chk(cmd_result) status = cmd_result.exit_status if not libvirtd_utl.is_running(): raise exceptions.TestFail("Libvirtd service is dead") if not status_error: if status == 0: ret = utils_misc.wait_for( lambda: check_xml(vm_name, target, dest_path, options), 5) if not ret: raise exceptions.TestFail("Domain xml not expected after" " blockcopy") if options.count("--bandwidth"): if options.count('--bytes'): bandwidth += 'B' else: bandwidth += 'M' if not (bandwidth in ['0B', '0M']) and not utl.check_blockjob( vm_name, target, "bandwidth", bandwidth): raise exceptions.TestFail("Check bandwidth failed") val = options.count("--pivot") + options.count("--finish") # Don't wait for job finish when using --byte option val += options.count('--bytes') if val == 0 and check_finish_job: try: finish_job(vm_name, target, timeout) except JobTimeout as excpt: raise exceptions.TestFail("Run command failed: %s" % excpt) if options.count("--raw") and not with_blockdev: check_format(dest_path, dest_extension, dest_format) if active_snap: snap_path = "%s/%s.snap" % (tmp_dir, vm_name) snap_opt = "--disk-only --atomic --no-metadata " snap_opt += "vda,snapshot=external,file=%s" % snap_path ret = virsh.snapshot_create_as(vm_name, snap_opt, ignore_status=True, debug=True) utl.check_exit_status(ret, active_error) if active_save: save_path = "%s/%s.save" % (tmp_dir, vm_name) ret = virsh.save(vm_name, save_path, ignore_status=True, debug=True) utl.check_exit_status(ret, active_error) if check_state_lock: # Run blockjob pivot in subprocess as it will hang # for a while, run blockjob info again to check # job state command = "virsh blockjob %s %s --pivot" % (vm_name, target) session = aexpect.ShellSession(command) ret = virsh.blockjob(vm_name, target, "--info") err_info = "cannot acquire state change lock" if err_info in ret.stderr: raise exceptions.TestFail("Hit on bug: %s" % bug_url) utl.check_exit_status(ret, status_error) session.close() else: raise exceptions.TestFail(cmd_result.stdout.strip() + cmd_result.stderr) else: if status: logging.debug("Expect error: %s", cmd_result.stderr) else: # Commit id '4c297728' changed how virsh exits when # unexpectedly failing due to timeout from a fail (1) # to a success(0), so we need to look for a different # marker to indicate the copy aborted. As "stdout: Now # in mirroring phase" could be in stdout which fail the # check, so also do check in libvirtd log to confirm. if options.count("--timeout") and options.count("--wait"): log_pattern = "Copy aborted" if (re.search(log_pattern, cmd_result.stdout.strip()) or chk_libvirtd_log(libvirtd_log_path, log_pattern, "debug")): logging.debug("Found success a timed out block copy") else: raise exceptions.TestFail("Expect fail, but run " "successfully: %s" % bug_url) finally: # Recover VM may fail unexpectedly, we need using try/except to # proceed the following cleanup steps try: # Abort exist blockjob to avoid any possible lock error virsh.blockjob(vm_name, target, '--abort', ignore_status=True) vm.destroy(gracefully=False) # It may take a long time to shutdown the VM which has # blockjob running utils_misc.wait_for( lambda: virsh.domstate(vm_name, ignore_status=True). exit_status, 180) if virsh.domain_exists(vm_name): if active_snap or with_shallow: option = "--snapshots-metadata" else: option = None original_xml.sync(option) else: original_xml.define() except Exception as e: logging.error(e) for disk in snapshot_external_disks: if os.path.exists(disk): os.remove(disk) # Clean up libvirt pool, which may be created by 'set_vm_disk' if disk_type == 'volume': virsh.pool_destroy(pool_name, ignore_status=True, debug=True) # Restore libvirtd conf and restart libvirtd libvirtd_conf.restore() libvirtd_utl.restart() if libvirtd_log_path and os.path.exists(libvirtd_log_path): os.unlink(libvirtd_log_path) # Clean up NFS try: if nfs_cleanup: utl.setup_or_cleanup_nfs(is_setup=False) except Exception as e: logging.error(e) # Clean up iSCSI try: for iscsi_n in list(set(emulated_iscsi)): utl.setup_or_cleanup_iscsi(is_setup=False, emulated_image=iscsi_n) # iscsid will be restarted, so give it a break before next loop time.sleep(5) except Exception as e: logging.error(e) if os.path.exists(dest_path): os.remove(dest_path) if os.path.exists(snap_path): os.remove(snap_path) if os.path.exists(save_path): os.remove(save_path) # Restart virtlogd service to release VM log file lock try: path.find_command('virtlogd') process.run('systemctl reset-failed virtlogd') process.run('systemctl restart virtlogd ') except path.CmdNotFoundError: pass
def run(test, params, env): """ Test storage pool and volumes with applications such as: install vms, attached to vms... """ pool_type = params.get("pool_type") pool_name = "test_%s_app" % pool_type pool_target = params.get("pool_target") emulated_img = params.get("emulated_img", "emulated_img") volume_count = int(params.get("volume_count", 1)) volume_size = params.get("volume_size", "1G") emulated_size = "%sG" % (volume_count * int(volume_size[:-1]) + 1) application = params.get("application", "install") disk_target = params.get("disk_target", "vdb") test_message = params.get("test_message", "") vm_name = params.get("main_vm", "virt-tests-vm1") if application == "install": vm_name = params.get("vm_name", "vm1") try: pvtest = utlv.PoolVolumeTest(test, params) pvtest.pre_pool(pool_name, pool_type, pool_target, emulated_img, emulated_size) logging.debug("Current pools:\n%s", libvirt_storage.StoragePool().list_pools()) new_pool = libvirt_storage.PoolVolume(pool_name) volumes = create_volumes(new_pool, volume_count, volume_size) if application == "attach": vm = env.get_vm(vm_name) session = vm.wait_for_login() # The attach-disk action based on running guest, # so no need to recover the guest, it will be # recovered automatically after shutdown/reboot virsh.attach_disk(vm_name, volumes.values()[volume_count-1], disk_target) vm_attach_device = "/dev/%s" % disk_target # Test if attached disk can be used normally utlv.mk_part(vm_attach_device, session=session) session.cmd("mkfs.ext4 %s1" % vm_attach_device) session.cmd("mount %s1 /mnt" % vm_attach_device) session.cmd("echo %s > /mnt/test" % test_message) output = session.cmd_output("cat /mnt/test").strip() if output != test_message: raise error.TestFail("%s cannot be used normally!" % vm_attach_device) elif application == "install": # Get a nonexist domain name while virsh.domain_exists(vm_name): vm_name += "_test" params["image_name"] = volumes.values()[volume_count-1] params["image_format"] = "raw" try: unattended_install.run(test, params, env) except error.CmdError, detail: raise error.TestFail("Guest install failed:%s" % detail) finally: try: if application == "install": if virsh.domain_exists(vm_name): virsh.remove_domain(vm_name) finally: pvtest.cleanup_pool(pool_name, pool_type, pool_target, emulated_img)
status = 1 # Recover libvirtd state. if libvirtd_state == "off": utils_libvirtd.libvirtd_start() # Shutdown VM. if virsh.domain_exists(vm.name): try: if vm.is_alive(): vm.destroy(gracefully=False) except error.CmdError, detail: logging.error("Detail: %s", detail) # Check if VM exists. vm_exist = virsh.domain_exists(vm_name) # Check if xml file exists. xml_exist = False if os.path.exists("/etc/libvirt/qemu/%s.xml" % vm_name) or\ os.path.exists("/etc/xen/%s" % vm_name): xml_exist = True # Check if save file exists if use --managed-save save_exist = False if os.path.exists(save_file): save_exist = True # Check if save file exists if use --managed-save volume_exist = False if volume and os.path.exists(volume):
def run(test, params, env): """ Test virsh undefine command. Undefine an inactive domain, or convert persistent to transient. 1.Prepare test environment. 2.Backup the VM's information to a xml file. 3.When the libvirtd == "off", stop the libvirtd service. 4.Perform virsh undefine operation. 5.Recover test environment.(libvirts service,VM) 6.Confirm the test result. """ vm_ref = params.get("undefine_vm_ref", "vm_name") extra = params.get("undefine_extra", "") option = params.get("undefine_option", "") libvirtd_state = params.get("libvirtd", "on") status_error = ("yes" == params.get("status_error", "no")) undefine_twice = ("yes" == params.get("undefine_twice", 'no')) local_ip = params.get("local_ip", "LOCAL.EXAMPLE.COM") remote_ip = params.get("remote_ip", "REMOTE.EXAMPLE.COM") remote_user = params.get("remote_user", "user") remote_pwd = params.get("remote_pwd", "password") remote_prompt = params.get("remote_prompt", "#") pool_type = params.get("pool_type") pool_name = params.get("pool_name", "test") pool_target = params.get("pool_target") volume_size = params.get("volume_size", "1G") vol_name = params.get("vol_name", "test_vol") emulated_img = params.get("emulated_img", "emulated_img") emulated_size = "%sG" % (int(volume_size[:-1]) + 1) disk_target = params.get("disk_target", "vdb") wipe_data = "yes" == params.get("wipe_data", "no") if wipe_data: option += " --wipe-storage" vm_name = params.get("main_vm", "virt-tests-vm1") vm = env.get_vm(vm_name) vm_id = vm.get_id() vm_uuid = vm.get_uuid() # polkit acl related params uri = params.get("virsh_uri") unprivileged_user = params.get('unprivileged_user') if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = '******' if not libvirt_version.version_compare(1, 1, 1): if params.get('setup_libvirt_polkit') == 'yes': raise error.TestNAError("API acl test not supported in current" " libvirt version.") # Back up xml file.Xen host has no guest xml file to define a guset. backup_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Confirm how to reference a VM. if vm_ref == "vm_name": vm_ref = vm_name elif vm_ref == "id": vm_ref = vm_id elif vm_ref == "hex_vm_id": vm_ref = hex(int(vm_id)) elif vm_ref == "uuid": vm_ref = vm_uuid elif vm_ref.find("invalid") != -1: vm_ref = params.get(vm_ref) volume = None pvtest = None status3 = None try: save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name if option.count("managedsave") and vm.is_alive(): virsh.managedsave(vm_name) if not vm.is_lxc(): snp_list = virsh.snapshot_list(vm_name) if option.count("snapshot"): snp_file_list = [] if not len(snp_list): virsh.snapshot_create(vm_name) logging.debug("Create a snapshot for test!") else: # Backup snapshots for domain for snp_item in snp_list: tmp_file = os.path.join(test.tmpdir, snp_item + ".xml") virsh.snapshot_dumpxml(vm_name, snp_item, to_file=tmp_file) snp_file_list.append(tmp_file) else: if len(snp_list): raise error.TestNAError("This domain has snapshot(s), " "cannot be undefined!") if option.count("remove-all-storage"): pvtest = utlv.PoolVolumeTest(test, params) pvtest.pre_pool(pool_name, pool_type, pool_target, emulated_img, emulated_size=emulated_size) new_pool = libvirt_storage.PoolVolume(pool_name) if not new_pool.create_volume(vol_name, volume_size): raise error.TestFail("Creation of volume %s failed." % vol_name) volumes = new_pool.list_volumes() volume = volumes[vol_name] virsh.attach_disk(vm_name, volume, disk_target, "--config") # Turn libvirtd into certain state. if libvirtd_state == "off": utils_libvirtd.libvirtd_stop() # Test virsh undefine command. output = "" if vm_ref != "remote": vm_ref = "%s %s" % (vm_ref, extra) cmdresult = virsh.undefine(vm_ref, option, unprivileged_user=unprivileged_user, uri=uri, ignore_status=True, debug=True) status = cmdresult.exit_status output = cmdresult.stdout.strip() if status: logging.debug("Error status, command output: %s", cmdresult.stderr.strip()) if undefine_twice: status2 = virsh.undefine(vm_ref, ignore_status=True).exit_status else: if remote_ip.count("EXAMPLE.COM") or local_ip.count("EXAMPLE.COM"): raise error.TestNAError("remote_ip and/or local_ip parameters" " not changed from default values") try: uri = libvirt_vm.complete_uri(local_ip) session = remote.remote_login("ssh", remote_ip, "22", remote_user, remote_pwd, remote_prompt) cmd_undefine = "virsh -c %s undefine %s" % (uri, vm_name) status, output = session.cmd_status_output(cmd_undefine) logging.info("Undefine output: %s", output) except (error.CmdError, remote.LoginError, aexpect.ShellError), de: logging.error("Detail: %s", de) status = 1 # Recover libvirtd state. if libvirtd_state == "off": utils_libvirtd.libvirtd_start() # Shutdown VM. if virsh.domain_exists(vm.name): try: if vm.is_alive(): vm.destroy(gracefully=False) except error.CmdError, detail: logging.error("Detail: %s", detail)
def run(test, params, env): """ Test virsh blockcopy --xml option. 1.Prepare backend storage (file/block/iscsi/ceph/nbd) 2.Start VM 3.Prepare target xml 4.Execute virsh blockcopy --xml command 5.Check VM xml after operation accomplished 6.Clean up test environment """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) virsh_dargs = {'debug': True, 'ignore_status': True} ignore_check = False def check_blockcopy_xml(vm_name, source_image, ignore_check=False): """ Check blockcopy xml in VM. :param vm_name: VM name :param source_image: source image name. :param ignore_check: default is False. """ if ignore_check: return source_imge_list = [] blklist = virsh.domblklist(vm_name).stdout_text.splitlines() for line in blklist: if line.strip().startswith(('hd', 'vd', 'sd', 'xvd')): source_imge_list.append(line.split()[-1]) logging.debug('domblklist %s:\n%s', vm_name, source_imge_list) if not any(source_image in s for s in source_imge_list): test.fail("Cannot find expected source image: %s" % source_image) # Disk specific attributes. device = params.get("virt_disk_device", "disk") device_target = params.get("virt_disk_device_target", "vdd") device_format = params.get("virt_disk_device_format", "raw") device_type = params.get("virt_disk_device_type", "file") device_bus = params.get("virt_disk_device_bus", "virtio") backend_storage_type = params.get("backend_storage_type", "iscsi") blockcopy_option = params.get("blockcopy_option") # Backend storage auth info storage_size = params.get("storage_size", "1G") enable_auth = "yes" == params.get("enable_auth") use_auth_usage = "yes" == params.get("use_auth_usage") auth_sec_usage_type = params.get("auth_sec_usage_type", "iscsi") auth_sec_usage_target = params.get("auth_sec_usage_target", "libvirtiscsi") auth_sec_uuid = "" disk_auth_dict = {} size = "1" status_error = "yes" == params.get("status_error") define_error = "yes" == params.get("define_error") # Initialize one NbdExport object nbd = None img_file = os.path.join(data_dir.get_tmp_dir(), "%s_test.img" % vm_name) # Start VM and get all partitions in VM. if vm.is_dead(): vm.start() session = vm.wait_for_login() old_parts = utils_disk.get_parts_list(session) session.close() vm.destroy(gracefully=False) # Back up xml file. vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Additional disk images. disks_img = [] try: # Clean up dirty secrets in test environments if there are. utils_secret.clean_up_secrets() # Setup backend storage if backend_storage_type == "file": image_filename = params.get("image_filename", "raw.img") disk_path = os.path.join(data_dir.get_tmp_dir(), image_filename) if blockcopy_option in ['reuse_external']: device_source = libvirt.create_local_disk( backend_storage_type, disk_path, storage_size, device_format) else: device_source = disk_path disks_img.append({ "format": device_format, "source": disk_path, "path": disk_path }) disk_src_dict = { 'attrs': { 'file': device_source, 'type_name': 'file' } } checkout_device_source = image_filename elif backend_storage_type == "iscsi": iscsi_host = params.get("iscsi_host") iscsi_port = params.get("iscsi_port") if device_type == "block": device_source = libvirt.setup_or_cleanup_iscsi(is_setup=True) disk_src_dict = {'attrs': {'dev': device_source}} checkout_device_source = device_source elif device_type == "network": chap_user = params.get("chap_user", "redhat") chap_passwd = params.get("chap_passwd", "password") auth_sec_usage = params.get("auth_sec_usage", "libvirtiscsi") auth_sec_dict = { "sec_usage": "iscsi", "sec_target": auth_sec_usage } auth_sec_uuid = libvirt.create_secret(auth_sec_dict) # Set password of auth secret virsh.secret_set_value(auth_sec_uuid, chap_passwd, encode=True, debug=True) iscsi_target, lun_num = libvirt.setup_or_cleanup_iscsi( is_setup=True, is_login=False, image_size=storage_size, chap_user=chap_user, chap_passwd=chap_passwd, portal_ip=iscsi_host) # ISCSI auth attributes for disk xml disk_auth_dict = { "auth_user": chap_user, "secret_type": auth_sec_usage_type, "secret_usage": auth_sec_usage_target } device_source = "iscsi://%s:%s/%s/%s" % ( iscsi_host, iscsi_port, iscsi_target, lun_num) disk_src_dict = { "attrs": { "protocol": "iscsi", "name": "%s/%s" % (iscsi_target, lun_num) }, "hosts": [{ "name": iscsi_host, "port": iscsi_port }] } checkout_device_source = 'emulated-iscsi' elif backend_storage_type == "ceph": ceph_host_ip = params.get("ceph_host_ip", "EXAMPLE_HOSTS") ceph_mon_ip = params.get("ceph_mon_ip", "EXAMPLE_MON_HOST") ceph_host_port = params.get("ceph_host_port", "EXAMPLE_PORTS") ceph_disk_name = params.get("ceph_disk_name", "EXAMPLE_SOURCE_NAME") ceph_client_name = params.get("ceph_client_name") ceph_client_key = params.get("ceph_client_key") ceph_auth_user = params.get("ceph_auth_user") ceph_auth_key = params.get("ceph_auth_key") enable_auth = "yes" == params.get("enable_auth") size = "0.15" key_file = os.path.join(data_dir.get_tmp_dir(), "ceph.key") key_opt = "" # Prepare a blank params to confirm whether it needs delete the configure at the end of the test ceph_cfg = "" if not utils_package.package_install(["ceph-common"]): test.error("Failed to install ceph-common") # Create config file if it doesn't exist ceph_cfg = ceph.create_config_file(ceph_mon_ip) # If enable auth, prepare a local file to save key if ceph_client_name and ceph_client_key: with open(key_file, 'w') as f: f.write("[%s]\n\tkey = %s\n" % (ceph_client_name, ceph_client_key)) key_opt = "--keyring %s" % key_file auth_sec_dict = { "sec_usage": auth_sec_usage_type, "sec_name": "ceph_auth_secret" } auth_sec_uuid = libvirt.create_secret(auth_sec_dict) virsh.secret_set_value(auth_sec_uuid, ceph_auth_key, ignore_status=False, debug=True) disk_auth_dict = { "auth_user": ceph_auth_user, "secret_type": auth_sec_usage_type, "secret_uuid": auth_sec_uuid } else: test.error("No ceph client name/key provided.") device_source = "rbd:%s:mon_host=%s:keyring=%s" % ( ceph_disk_name, ceph_mon_ip, key_file) cmd = ("rbd -m {0} {1} info {2} && rbd -m {0} {1} rm " "{2}".format(ceph_mon_ip, key_opt, ceph_disk_name)) cmd_result = process.run(cmd, ignore_status=True, shell=True) logging.debug("pre clean up rbd disk if exists: %s", cmd_result) if blockcopy_option in ['reuse_external']: # Create an local image and make FS on it. libvirt.create_local_disk("file", img_file, storage_size, device_format) # Convert the image to remote storage disk_path = ("rbd:%s:mon_host=%s" % (ceph_disk_name, ceph_mon_ip)) if ceph_client_name and ceph_client_key: disk_path += (":id=%s:key=%s" % (ceph_auth_user, ceph_auth_key)) rbd_cmd = ( "rbd -m %s %s info %s 2> /dev/null|| qemu-img convert -O" " %s %s %s" % (ceph_mon_ip, key_opt, ceph_disk_name, device_format, img_file, disk_path)) process.run(rbd_cmd, ignore_status=False, shell=True) disk_src_dict = { "attrs": { "protocol": "rbd", "name": ceph_disk_name }, "hosts": [{ "name": ceph_host_ip, "port": ceph_host_port }] } checkout_device_source = ceph_disk_name elif backend_storage_type == "nbd": # Get server hostname. hostname = socket.gethostname().strip() # Setup backend storage nbd_server_host = hostname nbd_server_port = params.get("nbd_server_port") image_path = params.get("emulated_image", "/var/lib/libvirt/images/nbdtest.img") # Create NbdExport object nbd = NbdExport(image_path, image_format=device_format, port=nbd_server_port) nbd.start_nbd_server() # Prepare disk source xml source_attrs_dict = {"protocol": "nbd"} disk_src_dict = {} disk_src_dict.update({"attrs": source_attrs_dict}) disk_src_dict.update({ "hosts": [{ "name": nbd_server_host, "port": nbd_server_port }] }) device_source = "nbd://%s:%s/%s" % (nbd_server_host, nbd_server_port, image_path) checkout_device_source = image_path if blockcopy_option in ['pivot']: ignore_check = True logging.debug("device source is: %s", device_source) # Add disk xml. vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disk_xml = Disk(type_name=device_type) disk_xml.device = device disk_xml.target = {"dev": device_target, "bus": device_bus} driver_dict = {"name": "qemu", "type": device_format} disk_xml.driver = driver_dict disk_source = disk_xml.new_disk_source(**disk_src_dict) auth_in_source = True if disk_auth_dict: logging.debug("disk auth dict is: %s" % disk_auth_dict) disk_source.auth = disk_xml.new_auth(**disk_auth_dict) disk_xml.source = disk_source logging.debug("new disk xml is: %s", disk_xml) # Sync VM xml device_source_path = os.path.join(data_dir.get_tmp_dir(), "source.raw") tmp_device_source = libvirt.create_local_disk("file", path=device_source_path, size=size, disk_format="raw") s_attach = virsh.attach_disk(vm_name, tmp_device_source, device_target, "--config", debug=True) libvirt.check_exit_status(s_attach) try: vm.start() vm.wait_for_login().close() except xcepts.LibvirtXMLError as xml_error: if not define_error: test.fail("Failed to define VM:\n%s", str(xml_error)) except virt_vm.VMStartError as details: # VM cannot be started if status_error: logging.info("VM failed to start as expected: %s", str(details)) else: test.fail("VM should start but failed: %s" % str(details)) # Additional operations before set block threshold options = params.get("options", "--pivot --transient-job --verbose --wait") result = virsh.blockcopy(vm_name, device_target, "--xml %s" % disk_xml.xml, options=options, debug=True) libvirt.check_exit_status(result) check_source_image = None if blockcopy_option in ['pivot']: check_source_image = checkout_device_source else: check_source_image = tmp_device_source check_blockcopy_xml(vm_name, check_source_image, ignore_check) finally: # Delete snapshots. if virsh.domain_exists(vm_name): #To Delete snapshot, destroy vm first. if vm.is_alive(): vm.destroy() libvirt.clean_up_snapshots(vm_name, domxml=vmxml_backup) vmxml_backup.sync("--snapshots-metadata") if os.path.exists(img_file): libvirt.delete_local_disk("file", img_file) for img in disks_img: if os.path.exists(img["path"]): libvirt.delete_local_disk("file", img["path"]) # Clean up backend storage if backend_storage_type == "iscsi": libvirt.setup_or_cleanup_iscsi(is_setup=False) elif backend_storage_type == "ceph": # Remove ceph configure file if created. if ceph_cfg: os.remove(ceph_cfg) cmd = ("rbd -m {0} {1} info {2} && rbd -m {0} {1} rm " "{2}".format(ceph_mon_ip, key_opt, ceph_disk_name)) cmd_result = process.run(cmd, ignore_status=True, shell=True) logging.debug("result of rbd removal: %s", cmd_result.stdout_text) if os.path.exists(key_file): os.remove(key_file) elif backend_storage_type == "nbd": if nbd: try: nbd.cleanup() except Exception as ndbEx: logging.error("Clean Up nbd failed: %s" % str(ndbEx)) # Clean up secrets if auth_sec_uuid: virsh.secret_undefine(auth_sec_uuid)
finally: # Restore libvirtd conf and restart libvirtd libvirtd_conf.restore() libvirtd_utl.restart() if libvirtd_log_path and os.path.exists(libvirtd_log_path): os.unlink(libvirtd_log_path) # Recover VM may fail unexpectedly, we need using try/except to # proceed the following cleanup steps try: vm.destroy(gracefully=False) # It may take a long time to shutdown the VM which has # blockjob running utils_misc.wait_for( lambda: virsh.domstate(vm_name, ignore_status=True).exit_status, 180) if virsh.domain_exists(vm_name): if active_snap or with_shallow: option = "--snapshots-metadata" else: option = None original_xml.sync(option) else: original_xml.define() except Exception, e: logging.error(e) for disk in snapshot_external_disks: if os.path.exists(disk): os.remove(disk) # Clean up libvirt pool, which may be created by 'set_vm_disk' if disk_type == 'volume': virsh.pool_destroy(pool_name, ignore_status=True, debug=True)
logging.info("Undefine output: %s", output) # Recover libvirtd state. if libvirtd_state == "off": utils_libvirtd.libvirtd_start() # Shutdown VM. if virsh.domain_exists(vm.name, uri=uri): try: if vm.is_alive(): vm.destroy() except error.CmdError, detail: logging.error("Detail: %s", detail) # Check if VM exists. vm_exist = virsh.domain_exists(vm.name, uri=uri) # Check if xml file exists. xml_exist = False if (os.path.exists("/etc/libvirt/qemu/%s.xml" % vm_name) or os.path.exists("/etc/xen/%s" % vm_name)): xml_exist = True # Recover main VM. if not virsh.domain_exists(vm.name, uri=uri): s_define = virsh.define(xml_file) if s_define is not True or not virsh.domain_exists(vm.name, uri=uri): logging.error("Failed to define %s.", vm.name) # Check results. if status_error == 'yes':
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 run(test, params, env): """ Test storage pool and volumes with applications such as: install vms, attached to vms... """ pool_type = params.get("pool_type") pool_name = "test_%s_app" % pool_type pool_target = params.get("pool_target") emulated_img = params.get("emulated_image", "emulated-image") volume_count = int(params.get("volume_count", 1)) volume_size = params.get("volume_size", "1G") emulated_size = "%sG" % (volume_count * int(volume_size[:-1]) + 1) application = params.get("application", "install") disk_target = params.get("disk_target", "vdb") test_message = params.get("test_message", "") vm_name = params.get("main_vm", "avocado-vt-vm1") block_device = params.get("block_device", "/DEV/EXAMPLE") if application == "install": cdrom_path = os.path.join(data_dir.get_data_dir(), params.get("cdrom_cd1")) if not os.path.exists(cdrom_path): raise error.TestNAError("Can't find installation cdrom:%s" % cdrom_path) # Get a nonexist domain name vm_name = "vol_install_test" try: pvtest = utlv.PoolVolumeTest(test, params) pvtest.pre_pool(pool_name, pool_type, pool_target, emulated_img, image_size=emulated_size, pre_disk_vol=[volume_size], device_name=block_device) logging.debug("Current pools:\n%s", libvirt_storage.StoragePool().list_pools()) new_pool = libvirt_storage.PoolVolume(pool_name) if pool_type == "disk": volumes = new_pool.list_volumes() logging.debug("Current volumes:%s", volumes) else: volumes = create_volumes(new_pool, volume_count, volume_size) if application == "attach": vm = env.get_vm(vm_name) session = vm.wait_for_login() virsh.attach_disk(vm_name, volumes.values()[volume_count - 1], disk_target) vm_attach_device = "/dev/%s" % disk_target if session.cmd_status("which parted"): # No parted command, check device only if session.cmd_status("ls %s" % vm_attach_device): raise error.TestFail("Didn't find attached device:%s" % vm_attach_device) return # Test if attached disk can be used normally utlv.mk_part(vm_attach_device, session=session) session.cmd("mkfs.ext4 %s1" % vm_attach_device) session.cmd("mount %s1 /mnt" % vm_attach_device) session.cmd("echo %s > /mnt/test" % test_message) output = session.cmd_output("cat /mnt/test").strip() if output != test_message: raise error.TestFail("%s cannot be used normally!" % vm_attach_device) elif application == "install": # Get a nonexist domain name anyway while virsh.domain_exists(vm_name): vm_name += "_test" # Prepare installation parameters params["main_vm"] = vm_name vm = env.create_vm("libvirt", None, vm_name, params, test.bindir) env.register_vm(vm_name, vm) params["image_name"] = volumes.values()[volume_count - 1] params["image_format"] = "raw" params['force_create_image'] = "yes" params['remove_image'] = "yes" params['shutdown_cleanly'] = "yes" params['shutdown_cleanly_timeout'] = 120 params['guest_port_unattended_install'] = 12323 params['inactivity_watcher'] = "error" params['inactivity_treshold'] = 1800 params['image_verify_bootable'] = "no" params['unattended_delivery_method'] = "cdrom" params['drive_index_unattended'] = 1 params['drive_index_cd1'] = 2 params['boot_once'] = "d" params['medium'] = "cdrom" params['wait_no_ack'] = "yes" params['image_raw_device'] = "yes" params['backup_image_before_testing'] = "no" params['kernel_params'] = ("ks=cdrom nicdelay=60 " "console=ttyS0,115200 console=tty0") params['cdroms'] = "unattended cd1" params['redirs'] += " unattended_install" selinux_mode = None try: selinux_mode = utils_selinux.get_status() utils_selinux.set_status("permissive") try: unattended_install.run(test, params, env) except process.CmdError, detail: raise error.TestFail("Guest install failed:%s" % detail) finally: if selinux_mode is not None: utils_selinux.set_status(selinux_mode) env.unregister_vm(vm_name) finally: try: if application == "install": if virsh.domain_exists(vm_name): virsh.remove_domain(vm_name) elif application == "attach": virsh.detach_disk(vm_name, disk_target) finally: pvtest.cleanup_pool(pool_name, pool_type, pool_target, emulated_img, device_name=block_device)
def run(test, params, env): """ Test virsh undefine command. Undefine an inactive domain, or convert persistent to transient. 1.Prepare test environment. 2.Backup the VM's information to a xml file. 3.When the libvirtd == "off", stop the libvirtd service. 4.Perform virsh undefine operation. 5.Recover test environment.(libvirts service,VM) 6.Confirm the test result. """ vm_ref = params.get("undefine_vm_ref", "vm_name") extra = params.get("undefine_extra", "") option = params.get("undefine_option", "") libvirtd_state = params.get("libvirtd", "on") status_error = ("yes" == params.get("status_error", "no")) undefine_twice = ("yes" == params.get("undefine_twice", 'no')) local_ip = params.get("local_ip", "LOCAL.EXAMPLE.COM") local_pwd = params.get("local_pwd", "password") remote_ip = params.get("remote_ip", "REMOTE.EXAMPLE.COM") remote_user = params.get("remote_user", "user") remote_pwd = params.get("remote_pwd", "password") remote_prompt = params.get("remote_prompt", "#") pool_type = params.get("pool_type") pool_name = params.get("pool_name", "test") pool_target = params.get("pool_target") volume_size = params.get("volume_size", "1G") vol_name = params.get("vol_name", "test_vol") emulated_img = params.get("emulated_img", "emulated_img") emulated_size = "%sG" % (int(volume_size[:-1]) + 1) disk_target = params.get("disk_target", "vdb") wipe_data = "yes" == params.get("wipe_data", "no") if wipe_data: option += " --wipe-storage" nvram_o = None if platform.machine() == 'aarch64': nvram_o = " --nvram" option += nvram_o vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) vm_id = vm.get_id() vm_uuid = vm.get_uuid() # polkit acl related params uri = params.get("virsh_uri") unprivileged_user = params.get('unprivileged_user') if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = '******' if not libvirt_version.version_compare(1, 1, 1): if params.get('setup_libvirt_polkit') == 'yes': test.cancel("API acl test not supported in current" " libvirt version.") # Back up xml file.Xen host has no guest xml file to define a guset. backup_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Confirm how to reference a VM. if vm_ref == "vm_name": vm_ref = vm_name elif vm_ref == "id": vm_ref = vm_id elif vm_ref == "hex_vm_id": vm_ref = hex(int(vm_id)) elif vm_ref == "uuid": vm_ref = vm_uuid elif vm_ref.find("invalid") != -1: vm_ref = params.get(vm_ref) volume = None pvtest = None status3 = None elems = backup_xml.xmltreefile.findall('/devices/disk/source') existing_images = [elem.get('file') for elem in elems] # Backup images since remove-all-storage could remove existing libvirt # managed guest images if existing_images and option.count("remove-all-storage"): for img in existing_images: backup_img = img + '.bak' logging.info('Backup %s to %s', img, backup_img) shutil.copyfile(img, backup_img) try: save_file = "/var/lib/libvirt/qemu/save/%s.save" % vm_name if option.count("managedsave") and vm.is_alive(): virsh.managedsave(vm_name) if not vm.is_lxc(): snp_list = virsh.snapshot_list(vm_name) if option.count("snapshot"): snp_file_list = [] if not len(snp_list): virsh.snapshot_create(vm_name) logging.debug("Create a snapshot for test!") else: # Backup snapshots for domain for snp_item in snp_list: tmp_file = os.path.join(data_dir.get_tmp_dir(), snp_item + ".xml") virsh.snapshot_dumpxml(vm_name, snp_item, to_file=tmp_file) snp_file_list.append(tmp_file) else: if len(snp_list): test.cancel("This domain has snapshot(s), " "cannot be undefined!") if option.count("remove-all-storage"): pvtest = utlv.PoolVolumeTest(test, params) pvtest.pre_pool(pool_name, pool_type, pool_target, emulated_img, emulated_size=emulated_size) new_pool = libvirt_storage.PoolVolume(pool_name) if not new_pool.create_volume(vol_name, volume_size): test.fail("Creation of volume %s failed." % vol_name) volumes = new_pool.list_volumes() volume = volumes[vol_name] ret = virsh.attach_disk(vm_name, volume, disk_target, "--config", debug=True) if ret.exit_status != 0: test.error("Attach disk failed: %s" % ret.stderr) # Turn libvirtd into certain state. if libvirtd_state == "off": utils_libvirtd.libvirtd_stop() # Test virsh undefine command. output = "" if vm_ref != "remote": vm_ref = "%s %s" % (vm_ref, extra) cmdresult = virsh.undefine(vm_ref, option, unprivileged_user=unprivileged_user, uri=uri, ignore_status=True, debug=True) status = cmdresult.exit_status output = cmdresult.stdout.strip() if status: logging.debug("Error status, command output: %s", cmdresult.stderr.strip()) if undefine_twice: status2 = virsh.undefine(vm_ref, nvram_o, ignore_status=True).exit_status else: if remote_ip.count("EXAMPLE.COM") or local_ip.count("EXAMPLE.COM"): test.cancel("remote_ip and/or local_ip parameters" " not changed from default values") try: local_user = params.get("username", "root") uri = libvirt_vm.complete_uri(local_ip) # setup ssh auto login from remote machine to test machine # for the command to execute remotely ssh_key.setup_remote_ssh_key(remote_ip, remote_user, remote_pwd, hostname2=local_ip, user2=local_user, password2=local_pwd) session = remote.remote_login("ssh", remote_ip, "22", remote_user, remote_pwd, remote_prompt) cmd_undefine = "virsh -c %s undefine %s" % (uri, vm_name) status, output = session.cmd_status_output(cmd_undefine) logging.info("Undefine output: %s", output) except (process.CmdError, remote.LoginError, aexpect.ShellError) as de: logging.error("Detail: %s", de) status = 1 # Recover libvirtd state. if libvirtd_state == "off": utils_libvirtd.libvirtd_start() # Shutdown VM. if virsh.domain_exists(vm.name): try: if vm.is_alive(): vm.destroy(gracefully=False) except process.CmdError as detail: logging.error("Detail: %s", detail) # After vm.destroy, virsh.domain_exists returns True due to # timing issue and tests fails. time.sleep(2) # Check if VM exists. vm_exist = virsh.domain_exists(vm_name) # Check if xml file exists. xml_exist = False if vm.is_qemu() and os.path.exists( "/etc/libvirt/qemu/%s.xml" % vm_name): xml_exist = True if vm.is_lxc() and os.path.exists("/etc/libvirt/lxc/%s.xml" % vm_name): xml_exist = True if vm.is_xen() and os.path.exists("/etc/xen/%s" % vm_name): xml_exist = True # Check if save file exists if use --managed-save save_exist = os.path.exists(save_file) # Check if save file exists if use --managed-save volume_exist = volume and os.path.exists(volume) # Test define with acl control and recover domain. if params.get('setup_libvirt_polkit') == 'yes': if virsh.domain_exists(vm.name): virsh.undefine(vm_ref, nvram_o, ignore_status=True) cmd = "chmod 666 %s" % backup_xml.xml process.run(cmd, ignore_status=False, shell=True) s_define = virsh.define(backup_xml.xml, unprivileged_user=unprivileged_user, uri=uri, ignore_status=True, debug=True) status3 = s_define.exit_status finally: # Recover main VM. try: backup_xml.sync() except LibvirtXMLError: # sync() tries to undefines and define the xml to sync # but virsh_undefine test would have undefined already # may lead to error out backup_xml.define() # Recover existing guest images if existing_images and option.count("remove-all-storage"): for img in existing_images: backup_img = img + '.bak' logging.info('Recover image %s to %s', backup_img, img) shutil.move(backup_img, img) # Clean up pool if pvtest: pvtest.cleanup_pool(pool_name, pool_type, pool_target, emulated_img) # Recover VM snapshots. if option.count("snapshot") and (not vm.is_lxc()): logging.debug("Recover snapshots for domain!") for file_item in snp_file_list: virsh.snapshot_create(vm_name, file_item) # Check results. if status_error: if not status: if libvirtd_state == "off" and libvirt_version.version_compare( 5, 6, 0): logging.info( "From libvirt version 5.6.0 libvirtd is restarted " "and command should succeed") else: test.fail("virsh undefine return unexpected result.") if params.get('setup_libvirt_polkit') == 'yes': if status3 == 0: test.fail("virsh define with false acl permission" + " should failed.") else: if status: test.fail("virsh undefine failed.") if undefine_twice: if not status2: test.fail("Undefine the same VM twice succeeded.") if vm_exist: test.fail("VM still exists after undefine.") if xml_exist: test.fail("Xml file still exists after undefine.") if option.count("managedsave") and save_exist: test.fail("Save file still exists after undefine.") if option.count("remove-all-storage") and volume_exist: test.fail("Volume file '%s' still exists after" " undefine." % volume) if wipe_data and option.count("remove-all-storage"): if not output.count("Wiping volume '%s'" % disk_target): test.fail("Command didn't wipe volume storage!") if params.get('setup_libvirt_polkit') == 'yes': if status3: test.fail("virsh define with right acl permission" + " should succeeded")
def run(test, params, env): """ Test various options of virt-v2v. """ if utils_v2v.V2V_EXEC is None: raise ValueError('Missing command: virt-v2v') for v in params.itervalues(): if "V2V_EXAMPLE" in v: test.cancel("Please set real value for %s" % v) vm_name = params.get("main_vm", "EXAMPLE") new_vm_name = params.get("new_vm_name") input_mode = params.get("input_mode") v2v_options = params.get("v2v_options", "") hypervisor = params.get("hypervisor", "kvm") remote_host = params.get("remote_host", "EXAMPLE") vpx_dc = params.get("vpx_dc", "EXAMPLE") esx_ip = params.get("esx_ip", "EXAMPLE") output_mode = params.get("output_mode") output_storage = params.get("output_storage", "default") disk_img = params.get("input_disk_image", "") nfs_storage = params.get("storage") no_root = 'yes' == params.get('no_root', 'no') mnt_point = params.get("mnt_point") export_domain_uuid = params.get("export_domain_uuid", "") fake_domain_uuid = params.get("fake_domain_uuid") vdsm_image_uuid = params.get("vdsm_image_uuid") vdsm_vol_uuid = params.get("vdsm_vol_uuid") vdsm_vm_uuid = params.get("vdsm_vm_uuid") vdsm_ovf_output = params.get("vdsm_ovf_output") v2v_user = params.get("unprivileged_user", "") v2v_timeout = int(params.get("v2v_timeout", 1200)) status_error = "yes" == params.get("status_error", "no") su_cmd = "su - %s -c " % v2v_user output_uri = params.get("oc_uri", "") pool_name = params.get("pool_name", "v2v_test") pool_type = params.get("pool_type", "dir") pool_target = params.get("pool_target_path", "v2v_pool") emulated_img = params.get("emulated_image_path", "v2v-emulated-img") pvt = utlv.PoolVolumeTest(test, params) new_v2v_user = False address_cache = env.get('address_cache') params['vmcheck_flag'] = False checkpoint = params.get('checkpoint', '') def create_pool(user_pool=False, pool_name=pool_name, pool_target=pool_target): """ Create libvirt pool as the output storage """ if output_uri == "qemu:///session" or user_pool: target_path = os.path.join("/home", v2v_user, pool_target) cmd = su_cmd + "'mkdir %s'" % target_path process.system(cmd, verbose=True) cmd = su_cmd + "'virsh pool-create-as %s dir" % pool_name cmd += " --target %s'" % target_path process.system(cmd, verbose=True) else: pvt.pre_pool(pool_name, pool_type, pool_target, emulated_img) def cleanup_pool(user_pool=False, pool_name=pool_name, pool_target=pool_target): """ Clean up libvirt pool """ if output_uri == "qemu:///session" or user_pool: cmd = su_cmd + "'virsh pool-destroy %s'" % pool_name process.system(cmd, verbose=True) target_path = os.path.join("/home", v2v_user, pool_target) cmd = su_cmd + "'rm -rf %s'" % target_path process.system(cmd, verbose=True) else: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_img) def get_all_uuids(output): """ Get export domain uuid, image uuid and vol uuid from command output. """ tmp_target = re.findall(r"qemu-img\s'convert'\s.+\s'(\S+)'\n", output) if len(tmp_target) < 1: test.error("Fail to find tmp target file name when converting vm" " disk image") targets = tmp_target[0].split('/') return (targets[3], targets[5], targets[6]) def get_ovf_content(output): """ Find and read ovf file. """ export_domain_uuid, _, vol_uuid = get_all_uuids(output) export_vm_dir = os.path.join(mnt_point, export_domain_uuid, 'master/vms') ovf_content = "" if os.path.isdir(export_vm_dir): ovf_id = "ovf:id='%s'" % vol_uuid ret = process.system_output("grep -R \"%s\" %s" % (ovf_id, export_vm_dir)) ovf_file = ret.split(":")[0] if os.path.isfile(ovf_file): ovf_f = open(ovf_file, "r") ovf_content = ovf_f.read() ovf_f.close() else: logging.error("Can't find ovf file to read") return ovf_content def get_img_path(output): """ Get the full path of the converted image. """ img_name = vm_name + "-sda" if output_mode == "libvirt": img_path = virsh.vol_path(img_name, output_storage).stdout.strip() elif output_mode == "local": img_path = os.path.join(output_storage, img_name) elif output_mode in ["rhev", "vdsm"]: export_domain_uuid, image_uuid, vol_uuid = get_all_uuids(output) img_path = os.path.join(mnt_point, export_domain_uuid, 'images', image_uuid, vol_uuid) return img_path def check_vmtype(ovf, expected_vmtype): """ Verify vmtype in ovf file. """ if output_mode != "rhev": return if expected_vmtype == "server": vmtype_int = 1 elif expected_vmtype == "desktop": vmtype_int = 0 else: return if "<VmType>%s</VmType>" % vmtype_int in ovf: logging.info("Find VmType=%s in ovf file", expected_vmtype) else: test.fail("VmType check failed") def check_image(img_path, check_point, expected_value): """ Verify image file allocation mode and format """ if not img_path or not os.path.isfile(img_path): test.error("Image path: '%s' is invalid" % img_path) img_info = utils_misc.get_image_info(img_path) logging.debug("Image info: %s", img_info) if check_point == "allocation": if expected_value == "sparse": if img_info['vsize'] > img_info['dsize']: logging.info("%s is a sparse image", img_path) else: test.fail("%s is not a sparse image" % img_path) elif expected_value == "preallocated": if img_info['vsize'] <= img_info['dsize']: logging.info("%s is a preallocated image", img_path) else: test.fail("%s is not a preallocated image" % img_path) if check_point == "format": if expected_value == img_info['format']: logging.info("%s format is %s", img_path, expected_value) else: test.fail("%s format is not %s" % (img_path, expected_value)) def check_new_name(output, expected_name): """ Verify guest name changed to the new name. """ found = False if output_mode == "libvirt": found = virsh.domain_exists(expected_name) if output_mode == "local": found = os.path.isfile(os.path.join(output_storage, expected_name + "-sda")) if output_mode in ["rhev", "vdsm"]: ovf = get_ovf_content(output) found = "<Name>%s</Name>" % expected_name in ovf else: return if found: logging.info("Guest name renamed when converting it") else: test.fail("Rename guest failed") def check_nocopy(output): """ Verify no image created if convert command use --no-copy option """ img_path = get_img_path(output) if not os.path.isfile(img_path): logging.info("No image created with --no-copy option") else: test.fail("Find %s" % img_path) def check_connection(output, expected_uri): """ Check output connection uri used when converting guest """ init_msg = "Initializing the target -o libvirt -oc %s" % expected_uri if init_msg in output: logging.info("Find message: %s", init_msg) else: test.fail("Not find message: %s" % init_msg) def check_ovf_snapshot_id(ovf_content): """ Check if snapshot id in ovf file consists of '0's """ search = re.search("ovf:vm_snapshot_id='(.*?)'", ovf_content) if search: snapshot_id = search.group(1) logging.debug('vm_snapshot_id = %s', snapshot_id) if snapshot_id.count('0') >= 32: test.fail('vm_snapshot_id consists with "0"') else: test.fail('Fail to find snapshot_id') def check_source(output): """ Check if --print-source option print the correct info """ # Parse source info source = output.split('\n')[2:] for i in range(len(source)): if source[i].startswith('\t'): source[i-1] += source[i] source[i] = '' source_strip = [x.strip() for x in source if x.strip()] source_info = {} for line in source_strip: source_info[line.split(':')[0]] = line.split(':', 1)[1].strip() logging.debug('Source info to check: %s', source_info) checklist = ['nr vCPUs', 'hypervisor type', 'source name', 'memory', 'display', 'CPU features', 'disks', 'NICs'] for key in checklist: if key not in source_info: test.fail('%s info missing' % key) # Check single values fail = [] xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) check_map = {} check_map['nr vCPUs'] = xml.vcpu check_map['hypervisor type'] = xml.hypervisor_type check_map['source name'] = xml.vm_name check_map['memory'] = str(int(xml.max_mem) * 1024) + ' (bytes)' check_map['display'] = xml.get_graphics_devices()[0].type_name logging.info('KEY:\tSOURCE<-> XML') for key in check_map: logging.info('%-15s:%18s <-> %s', key, source_info[key], check_map[key]) if source_info[key] != str(check_map[key]): fail.append(key) # Check disk info disk = xml.get_disk_all().values()[0] bus, type = disk.find('target').get('bus'), disk.find('driver').get('type') path = disk.find('source').get('file') disks_info = "%s (%s) [%s]" % (path, type, bus) source_disks = source_info['disks'].split() source_disks_path = source_disks[0] source_disks_type = source_disks[1].strip('()') source_disks_bus = source_disks[2].strip('[]') logging.info('disks:%s<->%s', source_info['disks'], disks_info) if source_disks_path != path or source_disks_type != type or bus not in source_disks_bus: fail.append('disks') # Check nic info nic = xml.get_iface_all().values()[0] type = nic.get('type') mac = nic.find('mac').get('address') nic_source = nic.find('source') name = nic_source.get(type) nic_info = '%s "%s" mac: %s' % (type, name, mac) logging.info('NICs:%s<->%s', source_info['NICs'], nic_info) if nic_info.lower() not in source_info['NICs'].lower(): fail.append('NICs') # Check cpu features feature_list = xml.features.get_feature_list() logging.info('CPU features:%s<->%s', source_info['CPU features'], feature_list) if sorted(source_info['CPU features'].split(',')) != sorted(feature_list): fail.append('CPU features') if fail: test.fail('Source info not correct for: %s' % fail) def check_man_page(in_man, not_in_man): """ Check if content of man page or help info meets expectation """ man_page = process.run('man virt-v2v', verbose=False).stdout.strip() if in_man: logging.info('Checking man page of virt-v2v for "%s"', in_man) if in_man not in man_page: test.fail('"%s" not in man page' % in_man) if not_in_man: logging.info('Checking man page of virt-v2v for "%s"', not_in_man) if not_in_man in man_page: test.fail('"%s" not removed from man page' % not_in_man) def check_result(cmd, result, status_error): """ Check virt-v2v command result """ utlv.check_exit_status(result, status_error) output = result.stdout + result.stderr if status_error: if checkpoint == 'length_of_error': log_lines = output.split('\n') v2v_start = False for line in log_lines: if line.startswith('virt-v2v:'): v2v_start = True if line.startswith('libvirt:'): v2v_start = False if v2v_start and len(line) > 72: test.fail('Error log longer than 72 charactors: %s' % line) if checkpoint == 'disk_not_exist': vol_list = virsh.vol_list(pool_name) logging.info(vol_list) if vm_name in vol_list.stdout: test.fail('Disk exists for vm %s' % vm_name) else: if output_mode == "rhev" and checkpoint != 'quiet': ovf = get_ovf_content(output) logging.debug("ovf content: %s", ovf) check_ovf_snapshot_id(ovf) if '--vmtype' in cmd: expected_vmtype = re.findall(r"--vmtype\s(\w+)", cmd)[0] check_vmtype(ovf, expected_vmtype) if '-oa' in cmd and '--no-copy' not in cmd: expected_mode = re.findall(r"-oa\s(\w+)", cmd)[0] img_path = get_img_path(output) def check_alloc(): try: check_image(img_path, "allocation", expected_mode) return True except exceptions.TestFail: pass if not utils_misc.wait_for(check_alloc, timeout=600, step=10.0): test.fail('Allocation check failed.') if '-of' in cmd and '--no-copy' not in cmd and checkpoint != 'quiet': expected_format = re.findall(r"-of\s(\w+)", cmd)[0] img_path = get_img_path(output) check_image(img_path, "format", expected_format) if '-on' in cmd: expected_name = re.findall(r"-on\s(\w+)", cmd)[0] check_new_name(output, expected_name) if '--no-copy' in cmd: check_nocopy(output) if '-oc' in cmd: expected_uri = re.findall(r"-oc\s(\S+)", cmd)[0] check_connection(output, expected_uri) if output_mode == "rhev": if not utils_v2v.import_vm_to_ovirt(params, address_cache): test.fail("Import VM failed") else: params['vmcheck_flag'] = True if output_mode == "libvirt": if "qemu:///session" not in v2v_options and not no_root: virsh.start(vm_name, debug=True, ignore_status=False) if checkpoint == 'vmx': vmchecker = VMChecker(test, params, env) params['vmchecker'] = vmchecker params['vmcheck_flag'] = True ret = vmchecker.run() if len(ret) == 0: logging.info("All common checkpoints passed") if checkpoint == 'quiet': if len(output.strip()) != 0: test.fail('Output is not empty in quiet mode') if checkpoint == 'dependency': if 'libguestfs-winsupport' not in output: test.fail('libguestfs-winsupport not in dependency') if 'VMF' not in output: test.fail('OVMF/AAVMF not in dependency') if 'qemu-kvm-rhev' in output: test.fail('qemu-kvm-rhev is in dependency') if 'libX11' in output: test.fail('libX11 is in dependency') win_img = params.get('win_image') command = 'guestfish -a %s -i' if process.run(command % win_img, ignore_status=True).exit_status == 0: test.fail('Command "%s" success' % command % win_img) if checkpoint == 'no_dcpath': if '--dcpath' in output: test.fail('"--dcpath" is not removed') if checkpoint == 'debug_overlays': search = re.search('Overlay saved as(.*)', output) if not search: test.fail('Not find log of saving overlays') overlay_path = search.group(1).strip() logging.debug('Overlay file location: %s' % overlay_path) if os.path.isfile(overlay_path): logging.info('Found overlay file: %s' % overlay_path) else: test.fail('Overlay file not saved') if checkpoint.startswith('empty_nic_source'): target_str = '%s "eth0" mac: %s' % (params[checkpoint][0], params[checkpoint][1]) logging.info('Expect log: %s', target_str) if target_str not in result.stdout.lower(): test.fail('Expect log not found: %s' % target_str) if checkpoint == 'print_source': check_source(result.stdout) if checkpoint == 'machine_readable': if os.path.exists(params.get('example_file', '')): expect_output = open(params['example_file']).read().strip() logging.debug(expect_output) if expect_output != result.stdout.strip(): test.fail('machine readable content not correct') else: test.error('No content to compare with') if checkpoint == 'compress': img_path = get_img_path(output) logging.info('Image path: %s', img_path) disk_check = process.run('qemu-img check %s' % img_path).stdout logging.info(disk_check) compress_info = disk_check.split(',')[-1].split('%')[0].strip() compress_rate = float(compress_info) logging.info('%s%% compressed', compress_rate) if compress_rate < 0.1: test.fail('Disk image NOT compressed') if checkpoint == 'tail_log': messages = params['tail'].get_output() logging.info('Content of /var/log/messages during conversion:') logging.info(messages) msg_content = params['msg_content'] if msg_content in messages: test.fail('Found "%s" in /var/log/messages' % msg_content) log_check = utils_v2v.check_log(params, output) if log_check: test.fail(log_check) check_man_page(params.get('in_man'), params.get('not_in_man')) backup_xml = None vdsm_domain_dir, vdsm_image_dir, vdsm_vm_dir = ("", "", "") try: if checkpoint.startswith('empty_nic_source'): xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) iface = xml.get_devices('interface')[0] disks = xml.get_devices('disk') del iface.source iface.type_name = checkpoint.split('_')[-1] iface.source = {iface.type_name: ''} params[checkpoint] = [iface.type_name, iface.mac_address] logging.debug(iface.source) devices = vm_xml.VMXMLDevices() devices.extend(disks) devices.append(iface) xml.set_devices(devices) logging.info(xml.xmltreefile) params['input_xml'] = xml.xmltreefile.name # Build input options input_option = "" if input_mode is None: pass elif input_mode == "libvirt": uri_obj = utils_v2v.Uri(hypervisor) ic_uri = uri_obj.get_uri(remote_host, vpx_dc, esx_ip) if checkpoint == 'with_ic': ic_uri = 'qemu:///session' input_option = "-i %s -ic %s %s" % (input_mode, ic_uri, vm_name) if checkpoint == 'without_ic': input_option = '-i %s %s' % (input_mode, vm_name) # Build network&bridge option to avoid network error v2v_options += " -b %s -n %s" % (params.get("output_bridge"), params.get("output_network")) elif input_mode == "disk": input_option += "-i %s %s" % (input_mode, disk_img) elif input_mode == 'libvirtxml': input_xml = params.get('input_xml') input_option += '-i %s %s' % (input_mode, input_xml) elif input_mode in ['ova']: test.cancel("Unsupported input mode: %s" % input_mode) else: test.error("Unknown input mode %s" % input_mode) input_format = params.get("input_format", "") input_allo_mode = params.get("input_allo_mode") if input_format: input_option += " -if %s" % input_format if not status_error: logging.info("Check image before convert") check_image(disk_img, "format", input_format) if input_allo_mode: check_image(disk_img, "allocation", input_allo_mode) # Build output options output_option = "" if output_mode: output_option = "-o %s -os %s" % (output_mode, output_storage) if checkpoint == 'rhv': output_option = output_option.replace('rhev', 'rhv') output_format = params.get("output_format") if output_format and output_format != input_format: output_option += " -of %s" % output_format output_allo_mode = params.get("output_allo_mode") if output_allo_mode: output_option += " -oa %s" % output_allo_mode # Build vdsm related options if output_mode in ['vdsm', 'rhev']: if not os.path.isdir(mnt_point): os.mkdir(mnt_point) if not utils_misc.mount(nfs_storage, mnt_point, "nfs"): test.error("Mount NFS Failed") if output_mode == 'vdsm': v2v_options += " --vdsm-image-uuid %s" % vdsm_image_uuid v2v_options += " --vdsm-vol-uuid %s" % vdsm_vol_uuid v2v_options += " --vdsm-vm-uuid %s" % vdsm_vm_uuid v2v_options += " --vdsm-ovf-output %s" % vdsm_ovf_output vdsm_domain_dir = os.path.join(mnt_point, fake_domain_uuid) vdsm_image_dir = os.path.join(mnt_point, export_domain_uuid, "images", vdsm_image_uuid) vdsm_vm_dir = os.path.join(mnt_point, export_domain_uuid, "master/vms", vdsm_vm_uuid) # For vdsm_domain_dir, just create a dir to test BZ#1176591 os.makedirs(vdsm_domain_dir) os.makedirs(vdsm_image_dir) os.makedirs(vdsm_vm_dir) # Output more messages except quiet mode if checkpoint == 'quiet': v2v_options += ' -q' elif checkpoint not in ['length_of_error', 'empty_nic_source_network', 'empty_nic_source_bridge']: v2v_options += " -v -x" # Prepare for libvirt unprivileged user session connection if "qemu:///session" in v2v_options or no_root: try: pwd.getpwnam(v2v_user) except KeyError: # create new user process.system("useradd %s" % v2v_user, ignore_status=True) new_v2v_user = True user_info = pwd.getpwnam(v2v_user) logging.info("Convert to qemu:///session by user '%s'", v2v_user) if input_mode == "disk": # Copy image from souce and change the image owner and group disk_path = os.path.join(data_dir.get_tmp_dir(), os.path.basename(disk_img)) logging.info('Copy image file %s to %s', disk_img, disk_path) shutil.copyfile(disk_img, disk_path) input_option = string.replace(input_option, disk_img, disk_path) os.chown(disk_path, user_info.pw_uid, user_info.pw_gid) elif not no_root: test.cancel("Only support convert local disk") # Setup ssh-agent access to xen hypervisor if hypervisor == 'xen': user = params.get("xen_host_user", "root") passwd = params.get("xen_host_passwd", "redhat") logging.info("set up ssh-agent access ") ssh_key.setup_ssh_key(remote_host, user=user, port=22, password=passwd) utils_misc.add_identities_into_ssh_agent() # Check if xen guest exists uri = utils_v2v.Uri(hypervisor).get_uri(remote_host) if not virsh.domain_exists(vm_name, uri=uri): logging.error('VM %s not exists', vm_name) # If the input format is not define, we need to either define # the original format in the source metadata(xml) or use '-of' # to force the output format, see BZ#1141723 for detail. if '-of' not in v2v_options and checkpoint != 'xen_no_output_format': v2v_options += ' -of %s' % params.get("default_output_format", "qcow2") # Create password file for access to ESX hypervisor if hypervisor == 'esx': vpx_passwd = params.get("vpx_password") vpx_passwd_file = os.path.join(test.tmpdir, "vpx_passwd") logging.info("Building ESX no password interactive verification.") pwd_f = open(vpx_passwd_file, 'w') pwd_f.write(vpx_passwd) pwd_f.close() output_option += " --password-file %s" % vpx_passwd_file # Create libvirt dir pool if output_mode == "libvirt": create_pool() # Work around till bug fixed os.environ['LIBGUESTFS_BACKEND'] = 'direct' if checkpoint in ['with_ic', 'without_ic']: new_v2v_user = True v2v_options += ' -on %s' % new_vm_name create_pool(user_pool=True, pool_name='src_pool', pool_target='v2v_src_pool') create_pool(user_pool=True) logging.debug(virsh.pool_list(uri='qemu:///session')) sh_install_vm = params.get('sh_install_vm') if not sh_install_vm: test.error('Source vm installing script missing') with open(sh_install_vm) as fh: cmd_install_vm = fh.read().strip() process.run('su - %s -c "%s"' % (v2v_user, cmd_install_vm), timeout=10, shell=True) if checkpoint == 'vmx': mount_point = params.get('mount_point') if not os.path.isdir(mount_point): os.mkdir(mount_point) nfs_vmx = params.get('nfs_vmx') if not utils_misc.mount(nfs_vmx, mount_point, 'nfs', verbose=True): test.error('Mount nfs for vmx failed') vmx = params.get('vmx') input_option = '-i vmx %s' % vmx v2v_options += " -b %s -n %s" % (params.get("output_bridge"), params.get("output_network")) # Running virt-v2v command cmd = "%s %s %s %s" % (utils_v2v.V2V_EXEC, input_option, output_option, v2v_options) if v2v_user: cmd = su_cmd + "'%s'" % cmd if params.get('cmd_free') == 'yes': cmd = params.get('check_command') # Set timeout to kill v2v process before conversion succeed if checkpoint == 'disk_not_exist': v2v_timeout = 30 # Get tail content of /var/log/messages if checkpoint == 'tail_log': params['tail_log'] = os.path.join(data_dir.get_tmp_dir(), 'tail_log') params['tail'] = aexpect.Tail( command='tail -f /var/log/messages', output_func=utils_misc.log_line, output_params=(params['tail_log'],) ) cmd_result = process.run(cmd, timeout=v2v_timeout, verbose=True, ignore_status=True) if new_vm_name: vm_name = new_vm_name params['main_vm'] = new_vm_name check_result(cmd, cmd_result, status_error) finally: if hypervisor == "xen": process.run("ssh-agent -k") if hypervisor == "esx": process.run("rm -rf %s" % vpx_passwd_file) for vdsm_dir in [vdsm_domain_dir, vdsm_image_dir, vdsm_vm_dir]: if os.path.exists(vdsm_dir): shutil.rmtree(vdsm_dir) if os.path.exists(mnt_point): utils_misc.umount(nfs_storage, mnt_point, "nfs") os.rmdir(mnt_point) if output_mode == "local": image_name = vm_name + "-sda" img_file = os.path.join(output_storage, image_name) xml_file = img_file + ".xml" for local_file in [img_file, xml_file]: if os.path.exists(local_file): os.remove(local_file) if output_mode == "libvirt": if "qemu:///session" in v2v_options or no_root: cmd = su_cmd + "'virsh undefine %s'" % vm_name try: process.system(cmd) except: logging.error('Undefine "%s" failed', vm_name) if no_root: cleanup_pool(user_pool=True, pool_name='src_pool', pool_target='v2v_src_pool') cleanup_pool(user_pool=True) else: virsh.remove_domain(vm_name) cleanup_pool() vmcheck_flag = params.get("vmcheck_flag") if vmcheck_flag: vmcheck = utils_v2v.VMCheck(test, params, env) vmcheck.cleanup() if new_v2v_user: process.system("userdel -f %s" % v2v_user) if backup_xml: backup_xml.sync() if checkpoint == 'vmx': utils_misc.umount(params['nfs_vmx'], params['mount_point'], 'nfs') os.rmdir(params['mount_point'])
def run(test, params, env): """ Test svirt in virt-install. (1). Init variables. (2). Set selinux on host. (3). Set label of image. (4). run a virt-install command. (5). clean up. As this test only care whether the qemu-kvm process can access the image. It is not necessary to install a full os in a vm. Just verify the vm is alive after virt-install command is enough. Then we can save a lot of time and make this test independent from unattended_install. """ # Get general variables. status_error = "yes" == params.get("status_error", "no") host_sestatus = params.get("host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_install_vm_sec_type", "dynamic") sec_model = params.get("svirt_install_vm_sec_model", "selinux") sec_label = params.get("svirt_install_vm_sec_label", None) sec_relabel = params.get("svirt_install_vm_sec_relabel", "yes") # Set selinux status on host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the image label. disk_label = params.get("svirt_install_disk_label", None) vm_name = params.get("main_vm", None) # svirt will prevent accessing via a symble link. data_path = data_dir.get_data_dir() real_data_path = os.path.realpath(data_path) image_path = os.path.join(real_data_path, "svirt_image") if virsh.domain_exists(vm_name): virsh.remove_domain(vm_name) if not os.path.exists(image_path): utils_test.libvirt.create_local_disk("file", path=image_path) try: utils_selinux.set_context_of_file(image_path, disk_label) cmd = "virt-install --name %s --import --disk path=%s --ram '1024' " % (vm_name, image_path) cmd += " --security" if sec_type == "static": if sec_label is None: raise ValueError("Seclabel is not setted for static.") cmd += " type=static,label=%s" % (sec_label) elif sec_type == "dynamic": cmd += " type=dynamic" else: raise ValueError("Security type %s is not supported." % sec_type) if sec_relabel is not None: cmd += ",relabel=%s" % sec_relabel cmd += "&" utils.run(cmd, ignore_status=True) def _vm_alive(): return virsh.is_alive(vm_name) if utils_misc.wait_for(_vm_alive, timeout=5): if status_error: raise error.TestFail("Test succeeded in negative case.") else: if not status_error: raise error.TestFail("Test failed in positive case.") finally: # cleanup utils_selinux.set_status(backup_sestatus) if virsh.domain_exists(vm_name): virsh.remove_domain(vm_name) if not os.path.exists(image_path): utils_test.libvirt.delete_local_disk("file", path=image_path)
def run(test, params, env): """ Test command: virsh blockcopy. This command can copy a disk backing image chain to dest. 1. Positive testing 1.1 Copy a disk to a new image file. 1.2 Reuse existing destination copy. 1.3 Valid blockcopy timeout and bandwidth test. 2. Negative testing 2.1 Copy a disk to a non-exist directory. 2.2 Copy a disk with invalid options. 2.3 Do block copy for a persistent domain. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) target = params.get("target_disk", "") replace_vm_disk = "yes" == params.get("replace_vm_disk", "no") disk_source_protocol = params.get("disk_source_protocol") disk_type = params.get("disk_type") pool_name = params.get("pool_name") image_size = params.get("image_size") emu_image = params.get("emulated_image") copy_to_nfs = "yes" == params.get("copy_to_nfs", "no") mnt_path_name = params.get("mnt_path_name") options = params.get("blockcopy_options", "") bandwidth = params.get("blockcopy_bandwidth", "") bandwidth_byte = "yes" == params.get("bandwidth_byte", "no") reuse_external = "yes" == params.get("reuse_external", "no") persistent_vm = params.get("persistent_vm", "no") status_error = "yes" == params.get("status_error", "no") active_error = "yes" == params.get("active_error", "no") active_snap = "yes" == params.get("active_snap", "no") active_save = "yes" == params.get("active_save", "no") check_state_lock = "yes" == params.get("check_state_lock", "no") with_shallow = "yes" == params.get("with_shallow", "no") with_blockdev = "yes" == params.get("with_blockdev", "no") setup_libvirt_polkit = "yes" == params.get('setup_libvirt_polkit') bug_url = params.get("bug_url", "") timeout = int(params.get("timeout", 1200)) relative_path = params.get("relative_path") rerun_flag = 0 blkdev_n = None back_n = 'blockdev-backing-iscsi' snapshot_external_disks = [] # Skip/Fail early if with_blockdev and not libvirt_version.version_compare(1, 2, 13): raise exceptions.TestSkipError("--blockdev option not supported in " "current version") if not target: raise exceptions.TestSkipError("Require target disk to copy") if setup_libvirt_polkit and not libvirt_version.version_compare(1, 1, 1): raise exceptions.TestSkipError("API acl test not supported in current" " libvirt version") if copy_to_nfs and not libvirt_version.version_compare(1, 1, 1): raise exceptions.TestSkipError("Bug will not fix: %s" % bug_url) if bandwidth_byte and not libvirt_version.version_compare(1, 3, 3): raise exceptions.TestSkipError("--bytes option not supported in " "current version") if relative_path == "yes" and not libvirt_version.version_compare(3, 0, 0): test.cancel("Forbid using relative path or file name only is added since libvirt-3.0.0") # Check the source disk if vm_xml.VMXML.check_disk_exist(vm_name, target): logging.debug("Find %s in domain %s", target, vm_name) else: raise exceptions.TestFail("Can't find %s in domain %s" % (target, vm_name)) original_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) tmp_dir = data_dir.get_tmp_dir() # Prepare dest path params dest_path = params.get("dest_path", "") dest_format = params.get("dest_format", "") # Ugh... this piece of chicanery brought to you by the QemuImg which # will "add" the 'dest_format' extension during the check_format code. # So if we create the file with the extension and then remove it when # doing the check_format later, then we avoid erroneous failures. dest_extension = "" if dest_format != "": dest_extension = ".%s" % dest_format # Prepare for --reuse-external option if reuse_external: options += "--reuse-external --wait" # Set rerun_flag=1 to do blockcopy twice, and the first time created # file can be reused in the second time if no dest_path given # This will make sure the image size equal to original disk size if dest_path == "/path/non-exist": if os.path.exists(dest_path) and not os.path.isdir(dest_path): os.remove(dest_path) else: rerun_flag = 1 # Prepare other options if dest_format == "raw": options += " --raw" if with_blockdev: options += " --blockdev" if len(bandwidth): options += " --bandwidth %s" % bandwidth if bandwidth_byte: options += " --bytes" if with_shallow: options += " --shallow" # Prepare acl options uri = params.get("virsh_uri") unprivileged_user = params.get('unprivileged_user') if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = '******' extra_dict = {'uri': uri, 'unprivileged_user': unprivileged_user, 'debug': True, 'ignore_status': True, 'timeout': timeout} libvirtd_utl = utils_libvirtd.Libvirtd() libvirtd_conf = utils_config.LibvirtdConfig() libvirtd_conf["log_filters"] = '"3:json 1:libvirt 1:qemu"' libvirtd_log_path = os.path.join(data_dir.get_tmp_dir(), "libvirtd.log") libvirtd_conf["log_outputs"] = '"1:file:%s"' % libvirtd_log_path logging.debug("the libvirtd config file content is:\n %s" % libvirtd_conf) libvirtd_utl.restart() def check_format(dest_path, dest_extension, expect): """ Check the image format :param dest_path: Path of the copy to create :param expect: Expect image format """ # And now because the QemuImg will add the extension for us # we have to remove it here. path_noext = dest_path.strip(dest_extension) params['image_name'] = path_noext params['image_format'] = expect image = qemu_storage.QemuImg(params, "/", path_noext) if image.get_format() == expect: logging.debug("%s format is %s", dest_path, expect) else: raise exceptions.TestFail("%s format is not %s" % (dest_path, expect)) def _blockjob_and_libvirtd_chk(cmd_result): """ Raise TestFail when blockcopy fail with block-job-complete error or blockcopy hang with state change lock. This is a specific bug verify, so ignore status_error here. """ bug_url_ = "https://bugzilla.redhat.com/show_bug.cgi?id=1197592" err_msg = "internal error: unable to execute QEMU command" err_msg += " 'block-job-complete'" if err_msg in cmd_result.stderr: raise exceptions.TestFail("Hit on bug: %s" % bug_url_) err_pattern = "Timed out during operation: cannot acquire" err_pattern += " state change lock" ret = chk_libvirtd_log(libvirtd_log_path, err_pattern, "error") if ret: raise exceptions.TestFail("Hit on bug: %s" % bug_url_) def _make_snapshot(): """ Make external disk snapshot """ snap_xml = snapshot_xml.SnapshotXML() snapshot_name = "blockcopy_snap" snap_xml.snap_name = snapshot_name snap_xml.description = "blockcopy snapshot" # Add all disks into xml file. vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) disks = vmxml.devices.by_device_tag('disk') # Remove non-storage disk such as 'cdrom' for disk in disks: if disk.device != 'disk': disks.remove(disk) new_disks = [] src_disk_xml = disks[0] disk_xml = snap_xml.SnapDiskXML() disk_xml.xmltreefile = src_disk_xml.xmltreefile del disk_xml.device del disk_xml.address disk_xml.snapshot = "external" disk_xml.disk_name = disk_xml.target['dev'] # Only qcow2 works as external snapshot file format, update it # here driver_attr = disk_xml.driver driver_attr.update({'type': 'qcow2'}) disk_xml.driver = driver_attr new_attrs = disk_xml.source.attrs if 'file' in disk_xml.source.attrs: new_file = os.path.join(tmp_dir, "blockcopy_shallow.snap") snapshot_external_disks.append(new_file) new_attrs.update({'file': new_file}) hosts = None elif ('dev' in disk_xml.source.attrs or 'name' in disk_xml.source.attrs or 'pool' in disk_xml.source.attrs): if (disk_xml.type_name == 'block' or disk_source_protocol == 'iscsi'): disk_xml.type_name = 'block' if 'name' in new_attrs: del new_attrs['name'] del new_attrs['protocol'] elif 'pool' in new_attrs: del new_attrs['pool'] del new_attrs['volume'] del new_attrs['mode'] back_path = utl.setup_or_cleanup_iscsi(is_setup=True, is_login=True, image_size="1G", emulated_image=back_n) emulated_iscsi.append(back_n) cmd = "qemu-img create -f qcow2 %s 1G" % back_path process.run(cmd, shell=True) new_attrs.update({'dev': back_path}) hosts = None new_src_dict = {"attrs": new_attrs} if hosts: new_src_dict.update({"hosts": hosts}) disk_xml.source = disk_xml.new_disk_source(**new_src_dict) new_disks.append(disk_xml) snap_xml.set_disks(new_disks) snapshot_xml_path = snap_xml.xml logging.debug("The snapshot xml is: %s" % snap_xml.xmltreefile) options = "--disk-only --xmlfile %s " % snapshot_xml_path snapshot_result = virsh.snapshot_create( vm_name, options, debug=True) if snapshot_result.exit_status != 0: raise exceptions.TestFail(snapshot_result.stderr) snap_path = '' save_path = '' emulated_iscsi = [] nfs_cleanup = False try: # Prepare dest_path tmp_file = time.strftime("%Y-%m-%d-%H.%M.%S.img") tmp_file += dest_extension if not dest_path: if with_blockdev: blkdev_n = 'blockdev-iscsi' dest_path = utl.setup_or_cleanup_iscsi(is_setup=True, is_login=True, image_size=image_size, emulated_image=blkdev_n) emulated_iscsi.append(blkdev_n) # Make sure the new disk show up utils_misc.wait_for(lambda: os.path.exists(dest_path), 5) else: if copy_to_nfs: tmp_dir = "%s/%s" % (tmp_dir, mnt_path_name) dest_path = os.path.join(tmp_dir, tmp_file) # Domain disk replacement with desire type if replace_vm_disk: # Calling 'set_vm_disk' is bad idea as it left lots of cleanup jobs # after test, such as pool, volume, nfs, iscsi and so on # TODO: remove this function in the future if disk_source_protocol == 'iscsi': emulated_iscsi.append(emu_image) if disk_source_protocol == 'netfs': nfs_cleanup = True utl.set_vm_disk(vm, params, tmp_dir, test) new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) if with_shallow: _make_snapshot() # Prepare transient/persistent vm if persistent_vm == "no" and vm.is_persistent(): vm.undefine("--nvram") elif persistent_vm == "yes" and not vm.is_persistent(): new_xml.define() # Run blockcopy command to create destination file if rerun_flag == 1: options1 = "--wait %s --finish --verbose" % dest_format if with_blockdev: options1 += " --blockdev" if with_shallow: options1 += " --shallow" cmd_result = virsh.blockcopy(vm_name, target, dest_path, options1, **extra_dict) status = cmd_result.exit_status if status != 0: raise exceptions.TestFail("Run blockcopy command fail: %s" % cmd_result.stdout.strip() + cmd_result.stderr) elif not os.path.exists(dest_path): raise exceptions.TestFail("Cannot find the created copy") # Run the real testing command cmd_result = virsh.blockcopy(vm_name, target, dest_path, options, **extra_dict) # check BZ#1197592 _blockjob_and_libvirtd_chk(cmd_result) status = cmd_result.exit_status if not libvirtd_utl.is_running(): raise exceptions.TestFail("Libvirtd service is dead") if not status_error: if status == 0: ret = utils_misc.wait_for( lambda: check_xml(vm_name, target, dest_path, options), 5) if not ret: raise exceptions.TestFail("Domain xml not expected after" " blockcopy") if options.count("--bandwidth"): if options.count('--bytes'): bandwidth += 'B' else: bandwidth += 'M' if not utl.check_blockjob(vm_name, target, "bandwidth", bandwidth): raise exceptions.TestFail("Check bandwidth failed") val = options.count("--pivot") + options.count("--finish") # Don't wait for job finish when using --byte option val += options.count('--bytes') if val == 0: try: finish_job(vm_name, target, timeout) except JobTimeout as excpt: raise exceptions.TestFail("Run command failed: %s" % excpt) if options.count("--raw") and not with_blockdev: check_format(dest_path, dest_extension, dest_format) if active_snap: snap_path = "%s/%s.snap" % (tmp_dir, vm_name) snap_opt = "--disk-only --atomic --no-metadata " snap_opt += "vda,snapshot=external,file=%s" % snap_path ret = virsh.snapshot_create_as(vm_name, snap_opt, ignore_status=True, debug=True) utl.check_exit_status(ret, active_error) if active_save: save_path = "%s/%s.save" % (tmp_dir, vm_name) ret = virsh.save(vm_name, save_path, ignore_status=True, debug=True) utl.check_exit_status(ret, active_error) if check_state_lock: # Run blockjob pivot in subprocess as it will hang # for a while, run blockjob info again to check # job state command = "virsh blockjob %s %s --pivot" % (vm_name, target) session = aexpect.ShellSession(command) ret = virsh.blockjob(vm_name, target, "--info") err_info = "cannot acquire state change lock" if err_info in ret.stderr: raise exceptions.TestFail("Hit on bug: %s" % bug_url) utl.check_exit_status(ret, status_error) session.close() else: raise exceptions.TestFail(cmd_result.stdout.strip() + cmd_result.stderr) else: if status: logging.debug("Expect error: %s", cmd_result.stderr) else: # Commit id '4c297728' changed how virsh exits when # unexpectedly failing due to timeout from a fail (1) # to a success(0), so we need to look for a different # marker to indicate the copy aborted. As "stdout: Now # in mirroring phase" could be in stdout which fail the # check, so also do check in libvirtd log to confirm. if options.count("--timeout") and options.count("--wait"): log_pattern = "Copy aborted" if (re.search(log_pattern, cmd_result.stdout.strip()) or chk_libvirtd_log(libvirtd_log_path, log_pattern, "debug")): logging.debug("Found success a timed out block copy") else: raise exceptions.TestFail("Expect fail, but run " "successfully: %s" % bug_url) finally: # Recover VM may fail unexpectedly, we need using try/except to # proceed the following cleanup steps try: # Abort exist blockjob to avoid any possible lock error virsh.blockjob(vm_name, target, '--abort', ignore_status=True) vm.destroy(gracefully=False) # It may take a long time to shutdown the VM which has # blockjob running utils_misc.wait_for( lambda: virsh.domstate(vm_name, ignore_status=True).exit_status, 180) if virsh.domain_exists(vm_name): if active_snap or with_shallow: option = "--snapshots-metadata" else: option = None original_xml.sync(option) else: original_xml.define() except Exception as e: logging.error(e) for disk in snapshot_external_disks: if os.path.exists(disk): os.remove(disk) # Clean up libvirt pool, which may be created by 'set_vm_disk' if disk_type == 'volume': virsh.pool_destroy(pool_name, ignore_status=True, debug=True) # Restore libvirtd conf and restart libvirtd libvirtd_conf.restore() libvirtd_utl.restart() if libvirtd_log_path and os.path.exists(libvirtd_log_path): os.unlink(libvirtd_log_path) # Clean up NFS try: if nfs_cleanup: utl.setup_or_cleanup_nfs(is_setup=False) except Exception as e: logging.error(e) # Clean up iSCSI try: for iscsi_n in list(set(emulated_iscsi)): utl.setup_or_cleanup_iscsi(is_setup=False, emulated_image=iscsi_n) # iscsid will be restarted, so give it a break before next loop time.sleep(5) except Exception as e: logging.error(e) if os.path.exists(dest_path): os.remove(dest_path) if os.path.exists(snap_path): os.remove(snap_path) if os.path.exists(save_path): os.remove(save_path) # Restart virtlogd service to release VM log file lock try: path.find_command('virtlogd') process.run('systemctl reset-failed virtlogd') process.run('systemctl restart virtlogd ') except path.CmdNotFoundError: pass