def check_device_was_created(test, uuid, adapter, domain): """ Check if the device was created successfully :param test: test object :param uuid: id for mediated device :param adapter: adapter of crypto device in host :param domain: domain of crypto device in host """ devices_cmd = ("cat /sys/devices/vfio_ap/matrix/%s/matrix" % uuid) status, output = utils_misc.cmd_status_output(devices_cmd, verbose=True) mdev_created_successfully = output == "%s.%s" % (adapter, domain) if not mdev_created_successfully: raise test.fail("mdev device was not create successfully through " "nodev-API")
def check_dasd_partition_table(session, device_target): """ Checks that the partition table can be read with 'fdasd' :param session: guest session, run command on host if None :param device_target: the expected target device name, e.g. 'vdb' """ cmd = "fdasd -p /dev/%s" % device_target err, out = cmd_status_output(cmd, shell=True, session=session) if err or not re.findall("reading vtoc.*ok", out): raise TestError("Couldn't get partition table. %s" % out) logging.debug("Confirmed partition table was read correctly:") logging.debug(out)
def make_dasd_part(path, session): """ Creates a partition spanning full disk on path :param path: dasd disk path, e.g. /dev/dasda :param session: guest session :return: True if partitioning succeeded """ cmd = "fdasd -a %s" % path err, out = cmd_status_output(cmd, shell=True, session=session) if err: raise TestError("Couldn't create partition. Status code '%s'. %s." % (err, out)) return True
def set_vf_mac(ethname, mac_addr, vf_idx=0, session=None): """ Set mac address for VF :param ethname: The name of the network interface :param mac_addr: The mac address to be set :param vf_idx: The index of VF :param session: The session object to the host :return: The command status and output """ cmd = "ip link set {0} vf {1} mac {2}".format(ethname, vf_idx, mac_addr) return utils_misc.cmd_status_output(cmd, shell=True, verbose=True, session=session)
def get_iface_name(pci_id, session=None): """ Get iface by the given pci :param pci_id: PCI ID of a device(eg. 0000:05:10.1) :param session: The session object to the host :return: The iface(eg. enp5s0f0) """ cmd = "ls /sys/bus/pci/devices/%s/net" % pci_id status, iface_name = utils_misc.cmd_status_output(cmd, shell=True, session=session) if status: raise exceptions.TestError("Unable to get iface name of %s." % pci_id) return iface_name
def format_dasd(path, session): """ Formats dasd disk and creates filesystem on path :param path: dasd disk path, e.g. /dev/dasda :param session: guest session :raises TestError: if disk can't be formatted :return: True if formatting succeeded """ cmd = "dasdfmt -b 4096 -M quick --force -p -y %s" % path err, out = cmd_status_output(cmd, shell=True, session=session) if err: raise TestError("Couldn't format disk. %s" % out) return True
def set_vf(pci_addr, vf_no=4, session=None): """ Enable VFs for PF :param pci_addr: The pci address :param vf_no: The value to be set :param session: The session object to the host :return: True if successful """ logging.debug("pci_addr is %s", pci_addr) cmd = "echo %s > %s/sriov_numvfs" % (vf_no, pci_addr) s, o = utils_misc.cmd_status_output(cmd, shell=True, verbose=True, session=session) return not s
def get_vf_mac(ethname, vf_idx=0, session=None): """ Get admin mac address for VF via 'ip' command. :param ethname: The name of the network interface :param vf_idx: The index of VF :param session: The session object to the host :return: VF's admin mac """ cmd = "ip link show %s |awk '/vf %d/ {print $4}'" % (ethname, vf_idx) status, vf_mac = utils_misc.cmd_status_output( cmd, shell=True, verbose=True, session=session) if status or not vf_mac: raise exceptions.TestError("Unable to get VF's mac address. status: %s," "stdout: %s." % (status, vf_mac)) return vf_mac.strip()
def set_online(chpids): """ Sets all two digit chip ids configured. :param chpids: string of concatenated chipds, e.g. "11122122" :raises OSError: if some command call fails """ ids = ChannelPaths._split(chpids) for i in ids: err, out = cmd_status_output("chchp -c 1 %s" % i, shell=True, timeout=CMD_TIMEOUT, verbose=VERBOSE) if err: raise OSError("Couldn't set all channel paths configured." " %s" % out)
def get_pci_from_iface(iface, session=None): """ Get pci by the given iface :param iface: The name of the network interface :param session: The session object to the host :return: Device's pci(eg. 0000:05:00.0) """ cmd = "ethtool -i %s | awk '/bus-info/ {print $NF}'" % iface.strip() status, pci = utils_misc.cmd_status_output(cmd, shell=True, verbose=True, session=session) if status: raise exceptions.TestError("Unable to get device's pci. status: %s, " "stdout: %s." % (status, pci)) return pci
def get_vf_pci_id(pf_pci, vf_index=0, session=None): """ Get pci_id of VF :param pf_pci: The pci id of PF :param vf_index: VF's index :param session: The session object to the host :return: VF's pci id """ cmd = "ls /sys/bus/pci/devices/{}/virtfn{}/net".format(pf_pci, vf_index) status, vf_name = utils_misc.cmd_status_output(cmd, shell=True, verbose=True, session=session) if status or not vf_name: raise exceptions.TestError( "Unable to get VF. status: %s, stdout: %s." % (status, vf_name)) return get_pci_from_iface(vf_name, session=session)
def set_vf(pci_addr, vf_no=4, session=None, timeout=60): """ Enable VFs for PF :param pci_addr: The pci address :param vf_no: The value to be set :param session: The session object to the host :param timeout: Time limit in seconds to wait for cmd to complete :return: True if successful """ LOG.debug("pci_addr is %s", pci_addr) cmd = "echo %s > %s/sriov_numvfs" % (vf_no, pci_addr) s, o = utils_misc.cmd_status_output(cmd, shell=True, timeout=timeout, verbose=True, session=session) return not s
def get_vf_pci_id(pf_pci, vf_index=0, session=None): """ Get pci_id of VF :param pf_pci: The pci id of PF :param vf_index: VF's index :param session: The session object to the host :return: VF's pci id """ cmd = "readlink /sys/bus/pci/devices/{}/virtfn{}".format(pf_pci, vf_index) status, tmp_vf = utils_misc.cmd_status_output(cmd, shell=True, verbose=True, session=session) if status or not tmp_vf: raise exceptions.TestError( "Unable to get VF. status: %s, stdout: %s." % (status, tmp_vf)) return os.path.basename(tmp_vf)
def virt_install_with_hostdev(vm_name, mdev_nodedev, target_address, disk_path): """ Runs virt-install with hostdev :param vm_name: guest name :param mdev_nodedev: mdev name as node device :param target_address: hostdev target address definition :param disk_path: path to the disk image for import """ cmd = ("virt-install --import --name %s" " --hostdev %s,%s" " --disk %s" " --vcpus 2 --memory 2048" " --nographics --noautoconsole" % (vm_name, mdev_nodedev, target_address, disk_path)) err, out = cmd_status_output(cmd, shell=True, verbose=True) if err: raise TestError("Couldn't install vm with hostdev: %s" % out)
def get_vcpu_line(vm_name, cmd, extra=''): """ Get the <vcpu xxx> line in the dumpxml :param vm_name: the vm name :param cmd: the command to get vcpu line :param extra: the extra option for virsh command :return: str, the line in dumpxml with <vcpu xxx> """ dumpxml_path = os.path.join(data_dir.get_tmp_dir(), '{}.dumpxml'.format(vm_name)) virsh.dumpxml(vm_name, extra=extra, to_file=dumpxml_path, ignore_status=False) _, output = utils_misc.cmd_status_output(cmd + dumpxml_path, ignore_status=False) os.remove(dumpxml_path) return output
def read_write(session): """ Writes, flushes and reads test file :param session: guest session :raises TestError: if read/write operation fails """ TESTFILE = "%s/testfile" % MOUNT cmd1 = "echo kaixo > %s" % TESTFILE cmd2 = "sync %s" % TESTFILE cmd3 = "cat %s" % TESTFILE err, out = None, None for cmd in [cmd1, cmd2, cmd3]: err, out = cmd_status_output(cmd, shell=True, session=session) if err: raise TestError("Some read/write operation failed. %s" % out) if cmd == cmd3 and "kaixo" not in out: raise TestError("Didn't get the written value '%s'" " from file '%s'" % ("kaixo", out))
def get_info(self): """ Gets crypto device info :return: CryptoDeviceInfo instance """ info = CryptoDeviceInfo() err, out = cmd_status_output("lszcrypt -V", shell=True, session=self.session, timeout=CMD_TIMEOUT, verbose=VERBOSE) if err: if NO_DEVICES not in out: raise OSError("Error when running lszcrypt: %s" % out) else: out = out.strip().split('\n')[2:] for entry in out: info.append(entry) return info
def set_standby(chpids): """ Sets all two digit chip ids standby. WARNING: Be careful of using this function. Setting all chipds of a device removes the device fully. A simple reboot won't restore them. :param chpids: string of concatenated chipds, e.g. "11122122" :raises OSError: if some command call fails """ ids = ChannelPaths._split(chpids) for i in ids: err, out = cmd_status_output("chchp -c 0 %s" % i, shell=True, timeout=CMD_TIMEOUT, verbose=VERBOSE) if err: raise OSError("Couldn't set all channel paths standby." " %s" % out)
def create_disk(disk_type, path=None, size="500M", disk_format="raw", extra='', session=None): """ Create disk on local or remote :param disk_type: Disk type :param path: The path of disk :param size: The size of disk :param disk_format: The format of disk :param extra: Extra parameters :param session: Session object to a remote host or guest :return: The path of disk :raise: TestError if the disk can't be created """ if session: if disk_type == "file": disk_cmd = ("qemu-img create -f %s %s %s %s" % (disk_format, extra, path, size)) else: # TODO: Add implementation for other types raise exceptions.TestError("Unknown disk type %s" % disk_type) status, stdout = utils_misc.cmd_status_output(disk_cmd, session=session) if status: raise exceptions.TestError( "Failed to create img on remote: cmd: {} " "status: {}, stdout: {}".format(disk_cmd, status, stdout)) return path else: return libvirt.create_local_disk(disk_type, path=path, size=size, disk_format=disk_format, extra=extra)
def get_info(self): """ Calls lscss and stores lines """ err, out = cmd_status_output("lscss", shell=True, session=self.session, timeout=CMD_TIMEOUT, verbose=VERBOSE) if err: raise OSError("Error when running lscss: %s" % out) # skip header and split according to HEADER self.devices = [[ x[:8], x[9:17], x[19:26], x[27:34], x[35:38], x[40:42], x[44:46], x[48:50], x[53:61], x[62:]] for x in out.split("\n")[2:]]
def get_device_path(disk_id): """ Gets the device path for the DASD disk :param disk_id: disk id cssid.ssid.devno, e.g. 0.0.5000 :return: absolute device path, e.g. '/dev/dasda' """ cmd = "lszdev %s" % disk_id err, out = cmd_status_output(cmd, shell=True) if err: raise TestError("Couldn't get device info. %s" % out) """ Expected output looks like: TYPE ID ON PERS NAMES dasd-eckd 0.0.5000 yes yes dasda """ try: info = out.split('\n') values = re.split(r"\s+", info[1]) name = values[-1] return "/dev/" + name except: raise TestError("Couldn't create device path from '%s', '%s', '%s'" % (out, info, values))
def check_cmd_in_guest(cmd_in_guest, vm_session, params, test): """ Execute a command within the guest and do checking :param cmd_in_guest: str, commands to execute in the VM :param vm_session: aexpect session for the VM :param params: dict, parameters to use hidden_attr's value should be a dict :param test: test object :raises: test.fail if checkpoints fail """ _, output = utils_misc.cmd_status_output(cmd_in_guest, shell=True, ignore_status=False, verbose=True, session=vm_session) logging.debug("Command '%s' result: %s", cmd_in_guest, output) hidden_attr = params.get('hidden_attr') if hidden_attr: (repl, found) = ('not', True) if hidden_attr['kvm_hidden_state'] == 'on' else ('', False) if output.count('KVM') == found: test.fail("'KVM' is %s expected when state is " "%s" % (repl, hidden_attr['kvm_hidden_state'])) logging.debug("Checking in check_cmd_in_guest() is successful.")
def run(test, params, env): """ Test storage migration 1) Do storage migration(copy-storage-all/copy-storage-inc) with TLS encryption - NBD transport 2) Cancel storage migration with TLS encryption 3) Copy only the top image for storage migration with backing chain :param test: test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def prepare_nfs_backingfile(vm, params): """ Create an image using nfs type backing_file :param vm: The guest :param params: the parameters used """ mnt_path_name = params.get("nfs_mount_dir", "nfs-mount") exp_opt = params.get("export_options", "rw,no_root_squash,fsid=0") exp_dir = params.get("export_dir", "nfs-export") backingfile_img = params.get("source_dist_img", "nfs-img") disk_format = params.get("disk_format", "qcow2") img_name = params.get("img_name", "test.img") precreation = "yes" == params.get("precreation", "yes") vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) disk_xml = vmxml.devices.by_device_tag('disk')[0] src_disk_format = disk_xml.xmltreefile.find('driver').get('type') first_disk = vm.get_first_disk_devices() blk_source = first_disk['source'] disk_img = os.path.join(os.path.dirname(blk_source), img_name) res = libvirt.setup_or_cleanup_nfs(True, mnt_path_name, is_mount=True, export_options=exp_opt, export_dir=exp_dir) mnt_path = res["mount_dir"] params["selinux_status_bak"] = res["selinux_status_bak"] if vm.is_alive(): vm.destroy(gracefully=False) disk_cmd = ("qemu-img convert -f %s -O %s %s %s/%s" % (src_disk_format, disk_format, blk_source, mnt_path, backingfile_img)) process.run(disk_cmd, ignore_status=False, verbose=True) local_image_list.append("%s/%s" % (mnt_path, backingfile_img)) logging.debug("Create a local image backing on NFS.") disk_cmd = ("qemu-img create -f %s -b %s/%s %s" % (disk_format, mnt_path, backingfile_img, disk_img)) process.run(disk_cmd, ignore_status=False, verbose=True) local_image_list.append(disk_img) if precreation: logging.debug("Create an image backing on NFS on remote host.") remote_session = remote.remote_login("ssh", server_ip, "22", server_user, server_pwd, r'[$#%]') utils_misc.make_dirs(os.path.dirname(blk_source), remote_session) status, stdout = utils_misc.cmd_status_output( disk_cmd, session=remote_session) logging.debug("status: {}, stdout: {}".format(status, stdout)) remote_image_list.append("%s/%s" % (mnt_path, backingfile_img)) remote_image_list.append(disk_img) remote_session.close() params.update({'disk_source_name': disk_img, 'disk_type': 'file', 'disk_source_protocol': 'file'}) libvirt.set_vm_disk(vm, params) migration_test = migration.MigrationTest() migration_test.check_parameters(params) # Local variables server_ip = params["server_ip"] = params.get("remote_ip") server_user = params["server_user"] = params.get("remote_user", "root") server_pwd = params["server_pwd"] = params.get("remote_pwd") client_ip = params["client_ip"] = params.get("local_ip") client_pwd = params["client_pwd"] = params.get("local_pwd") virsh_options = params.get("virsh_options", "") copy_storage_option = params.get("copy_storage_option") extra = params.get("virsh_migrate_extra", "") options = params.get("virsh_migrate_options", "--live --verbose") backingfile_type = params.get("backingfile_type") check_str_local_log = params.get("check_str_local_log", "") disk_format = params.get("disk_format", "qcow2") log_file = params.get("log_outputs", "/var/log/libvirt/libvirtd.log") daemon_conf_dict = eval(params.get("daemon_conf_dict", '{}')) cancel_migration = "yes" == params.get("cancel_migration", "no") migrate_again = "yes" == params.get("migrate_again", "no") precreation = "yes" == params.get("precreation", "yes") tls_recovery = "yes" == params.get("tls_auto_recovery", "yes") func_params_exists = "yes" == params.get("func_params_exists", "no") status_error = "yes" == params.get("status_error", "no") local_image_list = [] remote_image_list = [] tls_obj = None func_name = None daemon_conf = None mig_result = None remote_session = None vm_session = None # params for migration connection params["virsh_migrate_desturi"] = libvirt_vm.complete_uri( params.get("migrate_dest_host")) dest_uri = params.get("virsh_migrate_desturi") vm_name = params.get("migrate_main_vm") vm = env.get_vm(vm_name) vm.verify_alive() extra = "{} {}".format(extra, copy_storage_option) extra_args = {} if func_params_exists: extra_args.update({'func_params': params}) if cancel_migration: func_name = migration_test.do_cancel # For safety reasons, we'd better back up xmlfile. vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) orig_config_xml = vmxml.copy() try: if backingfile_type: if backingfile_type == "nfs": prepare_nfs_backingfile(vm, params) if extra.count("copy-storage-all") and precreation: blk_source = vm.get_first_disk_devices()['source'] vsize = utils_misc.get_image_info(blk_source).get("vsize") remote_session = remote.remote_login("ssh", server_ip, "22", server_user, server_pwd, r'[$#%]') utils_misc.make_dirs(os.path.dirname(blk_source), remote_session) disk_cmd = ("qemu-img create -f %s %s %s" % (disk_format, blk_source, vsize)) status, stdout = utils_misc.cmd_status_output( disk_cmd, session=remote_session) logging.debug("status: {}, stdout: {}".format(status, stdout)) remote_image_list.append(blk_source) remote_session.close() # Update libvirtd configuration if daemon_conf_dict: if os.path.exists(log_file): os.remove(log_file) daemon_conf = libvirt.customize_libvirt_config(daemon_conf_dict) if extra.count("--tls"): tls_obj = TLSConnection(params) if tls_recovery: tls_obj.auto_recover = True tls_obj.conn_setup() if not vm.is_alive(): vm.start() logging.debug("Guest xml after starting:\n%s", vm_xml.VMXML.new_from_dumpxml(vm_name)) # Check local guest network connection before migration vm_session = vm.wait_for_login(restart_network=True) migration_test.ping_vm(vm, params) # Execute migration process vms = [vm] migration_test.do_migration(vms, None, dest_uri, 'orderly', options, thread_timeout=900, ignore_status=True, virsh_opt=virsh_options, extra_opts=extra, func=func_name, **extra_args) mig_result = migration_test.ret migration_test.check_result(mig_result, params) if migrate_again and status_error: logging.debug("Sleeping 10 seconds before rerun migration") time.sleep(10) if cancel_migration: func_name = None params["status_error"] = "no" migration_test.do_migration(vms, None, dest_uri, 'orderly', options, thread_timeout=900, ignore_status=True, virsh_opt=virsh_options, extra_opts=extra, func=func_name, **extra_args) mig_result = migration_test.ret migration_test.check_result(mig_result, params) if int(mig_result.exit_status) == 0: migration_test.ping_vm(vm, params, uri=dest_uri) if check_str_local_log: libvirt.check_logfile(check_str_local_log, log_file) finally: logging.debug("Recover test environment") # Clean VM on destination and source try: migration_test.cleanup_dest_vm(vm, vm.connect_uri, dest_uri) if vm.is_alive(): vm.destroy(gracefully=False) except Exception as err: logging.error(err) logging.info("Recovery VM XML configration") orig_config_xml.sync() if daemon_conf: logging.debug("Recover the configurations") libvirt.customize_libvirt_config(None, is_recover=True, config_object=daemon_conf) if tls_obj: logging.debug("Clean up local objs") del tls_obj for source_file in local_image_list: libvirt.delete_local_disk("file", path=source_file) for img in remote_image_list: remote.run_remote_cmd("rm -rf %s" % img, params) if remote_session: remote_session.close()
def prepare_nfs_backingfile(vm, params): """ Create an image using nfs type backing_file :param vm: The guest :param params: the parameters used """ mnt_path_name = params.get("nfs_mount_dir", "nfs-mount") exp_opt = params.get("export_options", "rw,no_root_squash,fsid=0") exp_dir = params.get("export_dir", "nfs-export") backingfile_img = params.get("source_dist_img", "nfs-img") disk_format = params.get("disk_format", "qcow2") img_name = params.get("img_name", "test.img") precreation = "yes" == params.get("precreation", "yes") vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) disk_xml = vmxml.devices.by_device_tag('disk')[0] src_disk_format = disk_xml.xmltreefile.find('driver').get('type') first_disk = vm.get_first_disk_devices() blk_source = first_disk['source'] disk_img = os.path.join(os.path.dirname(blk_source), img_name) res = libvirt.setup_or_cleanup_nfs(True, mnt_path_name, is_mount=True, export_options=exp_opt, export_dir=exp_dir) mnt_path = res["mount_dir"] params["selinux_status_bak"] = res["selinux_status_bak"] if vm.is_alive(): vm.destroy(gracefully=False) disk_cmd = ("qemu-img convert -f %s -O %s %s %s/%s" % (src_disk_format, disk_format, blk_source, mnt_path, backingfile_img)) process.run(disk_cmd, ignore_status=False, verbose=True) local_image_list.append("%s/%s" % (mnt_path, backingfile_img)) logging.debug("Create a local image backing on NFS.") disk_cmd = ("qemu-img create -f %s -b %s/%s %s" % (disk_format, mnt_path, backingfile_img, disk_img)) process.run(disk_cmd, ignore_status=False, verbose=True) local_image_list.append(disk_img) if precreation: logging.debug("Create an image backing on NFS on remote host.") remote_session = remote.remote_login("ssh", server_ip, "22", server_user, server_pwd, r'[$#%]') utils_misc.make_dirs(os.path.dirname(blk_source), remote_session) status, stdout = utils_misc.cmd_status_output( disk_cmd, session=remote_session) logging.debug("status: {}, stdout: {}".format(status, stdout)) remote_image_list.append("%s/%s" % (mnt_path, backingfile_img)) remote_image_list.append(disk_img) remote_session.close() params.update({ 'disk_source_name': disk_img, 'disk_type': 'file', 'disk_source_protocol': 'file' }) libvirt.set_vm_disk(vm, params)
def run(test, params, env): """ Test virsh migrate command. """ def check_vm_network_accessed(session=None, ping_dest="www.baidu.com"): """ The operations to the VM need to be done before or after migration happens :param session: The session object to the host :param ping_dest: The destination to be ping :raise: test.fail when ping fails """ # Confirm local/remote VM can be accessed through network. logging.info("Check VM network connectivity") status, output = utils_test.ping(ping_dest, count=10, timeout=20, output_func=logging.debug, session=session) if status != 0: test.fail("Ping failed, status: %s," " output: %s" % (status, output)) def get_vm_ifaces(session=None): """ Get interfaces of vm :param session: The session object to the host :return: interfaces """ p_iface, v_iface = utils_net.get_remote_host_net_ifs(session) return p_iface def check_vm_iface_num(iface_list, exp_num=3): """ Check he number of interfaces :param iface_list: The interface list :param exp_num: The expected number :raise: test.fail when interfaces' number is not equal to exp_num """ if len(iface_list) != exp_num: test.fail("%d interfaces should be found on the vm, " "but find %s." % (exp_num, iface_list)) def create_or_del_networks(pf_name, params, remote_virsh_session=None, is_del=False): """ Create or delete network on local or remote :param params: Dictionary with the test parameters :param pf_name: The name of PF :param remote_virsh_session: The virsh session object to the remote host :param is_del: Whether the networks should be deleted :raise: test.fail when fails to define/start network """ net_hostdev_name = params.get("net_hostdev_name", "hostdev-net") net_hostdev_fwd = params.get("net_hostdev_fwd", '{"mode": "hostdev", "managed": "yes"}') net_bridge_name = params.get("net_bridge_name", "host-bridge") net_bridge_fwd = params.get("net_bridge_fwd", '{"mode": "bridge"}') bridge_name = params.get("bridge_name", "br0") net_dict = {"net_name": net_hostdev_name, "net_forward": net_hostdev_fwd, "net_forward_pf": '{"dev": "%s"}' % pf_name} bridge_dict = {"net_name": net_bridge_name, "net_forward": net_bridge_fwd, "net_bridge": '{"name": "%s"}' % bridge_name} if not is_del: for net_params in (net_dict, bridge_dict): net_dev = libvirt.create_net_xml(net_params.get("net_name"), net_params) if not remote_virsh_session: if net_dev.get_active(): net_dev.undefine() net_dev.define() net_dev.start() else: remote.scp_to_remote(server_ip, '22', server_user, server_pwd, net_dev.xml, net_dev.xml, limit="", log_filename=None, timeout=600, interface=None) remote_virsh_session.net_define(net_dev.xml, **virsh_args) remote_virsh_session.net_start(net_params.get("net_name"), **virsh_args) else: virsh_session = virsh if remote_virsh_session: virsh_session = remote_virsh_session for nname in (net_hostdev_name, net_bridge_name): if nname not in virsh_session.net_state_dict(): continue virsh_session.net_destroy(nname, debug=True, ignore_status=True) virsh_session.net_undefine(nname, debug=True, ignore_status=True) def check_vm_network_connection(net_name, expected_conn=0): """ Check network connections in network xml :param net_name: The network to be checked :param expected_conn: The expected value :raise: test.fail when fails """ output = virsh.net_dumpxml(net_name, debug=True).stdout_text if expected_conn == 0: reg_pattern = r"<network>" else: reg_pattern = r"<network connections='(\d)'>" res = re.findall(reg_pattern, output, re.I) if not res: test.fail("Unable to find expected connection in %s." % net_name) if expected_conn != 0: if expected_conn != int(res[0]): test.fail("Unable to get expected connection number." "Expected: %s, Actual %s" % (expected_conn, int(res[0]))) def get_hostdev_addr_from_xml(): """ Get VM hostdev address :return: pci driver id """ address_dict = {} for ifac in vm_xml.VMXML.new_from_dumpxml(vm_name).devices.by_device_tag("interface"): if ifac.type_name == "hostdev": address_dict = ifac.hostdev_address.attrs return libvirt.pci_info_from_address(address_dict, 16, "id") def check_vfio_pci(pci_path, status_error=False): """ Check if vf driver is vfio-pci :param pci_path: The absolute path of pci device :param status_error: Whether the driver should be vfio-pci """ cmd = "readlink %s/driver | awk -F '/' '{print $NF}'" % pci_path output = process.run(cmd, shell=True, verbose=True).stdout_text.strip() if (output == "vfio-pci") == status_error: test.fail("Get incorrect dirver %s, it should%s be vfio-pci." % (output, ' not' if status_error else '')) def update_iface_xml(vmxml): """ Update interfaces for guest :param vmxml: vm_xml.VMXML object """ vmxml.remove_all_device_by_type('interface') vmxml.sync() iface_dict = {"type": "network", "source": "{'network': 'host-bridge'}", "mac": mac_addr, "model": "virtio", "teaming": '{"type":"persistent"}', "alias": '{"name": "ua-backup0"}', "inbound": '{"average":"5"}', "outbound": '{"average":"5"}'} iface_dict2 = {"type": "network", "source": "{'network': 'hostdev-net'}", "mac": mac_addr, "model": "virtio", "teaming": '{"type":"transient", "persistent": "ua-backup0"}'} iface = interface.Interface('network') for ifc in (iface_dict, iface_dict2): iface.xml = libvirt.modify_vm_iface(vm.name, "get_xml", ifc) vmxml.add_device(iface) vmxml.sync() migration_test = migration.MigrationTest() migration_test.check_parameters(params) # Params for NFS shared storage shared_storage = params.get("migrate_shared_storage", "") if shared_storage == "": default_guest_asset = defaults.get_default_guest_os_info()['asset'] default_guest_asset = "%s.qcow2" % default_guest_asset shared_storage = os.path.join(params.get("nfs_mount_dir"), default_guest_asset) logging.debug("shared_storage:%s", shared_storage) # Params to update disk using shared storage params["disk_type"] = "file" params["disk_source_protocol"] = "netfs" params["mnt_path_name"] = params.get("nfs_mount_dir") # Local variables virsh_args = {"debug": True} virsh_options = params.get("virsh_options", "") server_ip = params.get("server_ip") server_user = params.get("server_user", "root") server_pwd = params.get("server_pwd") client_ip = params.get("client_ip") client_pwd = params.get("client_pwd") extra = params.get("virsh_migrate_extra") options = params.get("virsh_migrate_options") bridge_name = params.get("bridge_name", "br0") net_hostdev_name = params.get("net_hostdev_name", "hostdev-net") net_bridge_name = params.get("net_bridge_name", "host-bridge") driver = params.get("driver", "ixgbe") vm_tmp_file = params.get("vm_tmp_file", "/tmp/test.txt") cmd_during_mig = params.get("cmd_during_mig") net_failover_test = "yes" == params.get("net_failover_test", "no") cancel_migration = "yes" == params.get("cancel_migration", "no") try: vf_no = int(params.get("vf_no", "4")) except ValueError as e: test.error(e) migr_vm_back = "yes" == params.get("migrate_vm_back", "no") err_msg = params.get("err_msg") status_error = "yes" == params.get("status_error", "no") cmd_parms = {'server_ip': server_ip, 'server_user': server_user, 'server_pwd': server_pwd} remote_virsh_dargs = {'remote_ip': server_ip, 'remote_user': server_user, 'remote_pwd': server_pwd, 'unprivileged_user': None, 'ssh_remote_auth': True} destparams_dict = copy.deepcopy(params) remote_virsh_session = None vm_session = None vm = None mig_result = None func_name = None extra_args = {} default_src_vf = 0 default_dest_vf = 0 default_src_rp_filter = 1 default_dest_rp_filer = 1 if not libvirt_version.version_compare(6, 0, 0): test.cancel("This libvirt version doesn't support migration with " "net failover devices.") # params for migration connection params["virsh_migrate_desturi"] = libvirt_vm.complete_uri( params.get("migrate_dest_host")) params["virsh_migrate_connect_uri"] = libvirt_vm.complete_uri( params.get("migrate_source_host")) src_uri = params.get("virsh_migrate_connect_uri") dest_uri = params.get("virsh_migrate_desturi") vm_name = params.get("migrate_main_vm") vm = env.get_vm(vm_name) vm.verify_alive() # For safety reasons, we'd better back up xmlfile. new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) orig_config_xml = new_xml.copy() try: # Create a remote runner for later use runner_on_target = remote.RemoteRunner(host=server_ip, username=server_user, password=server_pwd) server_session = remote.wait_for_login('ssh', server_ip, '22', server_user, server_pwd, r"[\#\$]\s*$") if net_failover_test: src_pf, src_pf_pci = utils_sriov.find_pf(driver) logging.debug("src_pf is %s. src_pf_pci: %s", src_pf, src_pf_pci) params['pf_name'] = src_pf dest_pf, dest_pf_pci = utils_sriov.find_pf(driver, server_session) logging.debug("dest_pf is %s. dest_pf_pci: %s", dest_pf, dest_pf_pci) destparams_dict['pf_name'] = dest_pf src_pf_pci_path = utils_misc.get_pci_path(src_pf_pci) dest_pf_pci_path = utils_misc.get_pci_path(dest_pf_pci, server_session) cmd = "cat %s/sriov_numvfs" % (src_pf_pci_path) default_src_vf = process.run(cmd, shell=True, verbose=True).stdout_text cmd = "cat %s/sriov_numvfs" % (dest_pf_pci_path) status, default_dest_vf = utils_misc.cmd_status_output(cmd, shell=True, session=server_session) if status: test.error("Unable to get default sriov_numvfs on target!" "status: %s, output: %s" % (status, default_dest_vf)) if not utils_sriov.set_vf(src_pf_pci_path, vf_no): test.error("Failed to set vf on source.") if not utils_sriov.set_vf(dest_pf_pci_path, vf_no, session=server_session): test.error("Failed to set vf on target.") # Create PF and bridge connection on source and target host cmd = 'cat /proc/sys/net/ipv4/conf/all/rp_filter' default_src_rp_filter = process.run(cmd, shell=True, verbose=True).stdout_text status, default_dest_rp_filter = utils_misc.cmd_status_output(cmd, shell=True, session=server_session) if status: test.error("Unable to get default rp_filter on target!" "status: %s, output: %s" % (status, default_dest_rp_filter)) cmd = 'echo 0 >/proc/sys/net/ipv4/conf/all/rp_filter' process.run(cmd, shell=True, verbose=True) utils_misc.cmd_status_output(cmd, shell=True, session=server_session) utils_sriov.add_or_del_connection(params, is_del=False) utils_sriov.add_or_del_connection(destparams_dict, is_del=False, session=server_session) if not remote_virsh_session: remote_virsh_session = virsh.VirshPersistent(**remote_virsh_dargs) create_or_del_networks(dest_pf, params, remote_virsh_session=remote_virsh_session) remote_virsh_session.close_session() create_or_del_networks(src_pf, params) # Change network interface xml mac_addr = utils_net.generate_mac_address_simple() update_iface_xml(new_xml) # Change the disk of the vm libvirt.set_vm_disk(vm, params) if not vm.is_alive(): vm.start() # Check local guest network connection before migration if vm.serial_console is not None: vm.cleanup_serial_console() vm.create_serial_console() vm_session = vm.wait_for_serial_login(timeout=240) if net_failover_test: utils_net.restart_guest_network(vm_session) iface_list = get_vm_ifaces(vm_session) vm_ipv4, vm_ipv6 = utils_net.get_linux_ipaddr(vm_session, iface_list[0]) check_vm_network_accessed(ping_dest=vm_ipv4) if net_failover_test: check_vm_iface_num(iface_list) check_vm_network_connection(net_hostdev_name, 1) check_vm_network_connection(net_bridge_name, 1) hostdev_pci_id = get_hostdev_addr_from_xml() vf_path = utils_misc.get_pci_path(hostdev_pci_id) check_vfio_pci(vf_path) if cmd_during_mig: s, o = utils_misc.cmd_status_output(cmd_during_mig, shell=True, session=vm_session) if s: test.fail("Failed to run %s in vm." % cmd_during_mig) if extra.count("--postcopy"): func_name = virsh.migrate_postcopy extra_args.update({'func_params': params}) if cancel_migration: func_name = migration_test.do_cancel # Execute migration process vms = [vm] migration_test.do_migration(vms, None, dest_uri, 'orderly', options, thread_timeout=900, ignore_status=True, virsh_opt=virsh_options, func=func_name, extra_opts=extra, **extra_args) mig_result = migration_test.ret migration_test.check_result(mig_result, params) if int(mig_result.exit_status) == 0: server_session = remote.wait_for_login('ssh', server_ip, '22', server_user, server_pwd, r"[\#\$]\s*$") check_vm_network_accessed(server_session, vm_ipv4) server_session.close() if net_failover_test: # Check network connection check_vm_network_connection(net_hostdev_name) check_vm_network_connection(net_bridge_name) # VF driver should not be vfio-pci check_vfio_pci(vf_path, True) cmd_parms.update({'vm_ip': vm_ipv4, 'vm_pwd': params.get("password")}) vm_after_mig = remote.VMManager(cmd_parms) vm_after_mig.setup_ssh_auth() cmd = "ip link" cmd_result = vm_after_mig.run_command(cmd) libvirt.check_result(cmd_result) p_iface = re.findall(r"\d+:\s+(\w+):\s+.*", cmd_result.stdout_text) p_iface = [x for x in p_iface if x != 'lo'] check_vm_iface_num(p_iface) # Check the output of ping command cmd = 'cat %s' % vm_tmp_file cmd_result = vm_after_mig.run_command(cmd) libvirt.check_result(cmd_result) if re.findall('Destination Host Unreachable', cmd_result.stdout_text, re.M): test.fail("The network does not work well during " "the migration peirod. ping output: %s" % cmd_result.stdout_text) # Execute migration from remote if migr_vm_back: ssh_connection = utils_conn.SSHConnection(server_ip=client_ip, server_pwd=client_pwd, client_ip=server_ip, client_pwd=server_pwd) try: ssh_connection.conn_check() except utils_conn.ConnectionError: ssh_connection.conn_setup() ssh_connection.conn_check() # Pre migration setup for local machine migration_test.migrate_pre_setup(src_uri, params) cmd = "virsh migrate %s %s %s" % (vm_name, virsh_options, src_uri) logging.debug("Start migration: %s", cmd) cmd_result = remote.run_remote_cmd(cmd, params, runner_on_target) logging.info(cmd_result) if cmd_result.exit_status: test.fail("Failed to run '%s' on remote: %s" % (cmd, cmd_result)) logging.debug("migration back done") check_vm_network_accessed(ping_dest=vm_ipv4) if net_failover_test: if vm_session: vm_session.close() vm_session = vm.wait_for_login() iface_list = get_vm_ifaces(vm_session) check_vm_iface_num(iface_list) else: check_vm_network_accessed(ping_dest=vm_ipv4) if net_failover_test: iface_list = get_vm_ifaces(vm_session) check_vm_iface_num(iface_list) finally: logging.debug("Recover test environment") # Clean VM on destination migration_test.cleanup_dest_vm(vm, vm.connect_uri, dest_uri) if vm.is_alive(): vm.destroy(gracefully=False) logging.info("Recovery VM XML configration") orig_config_xml.sync() logging.debug("The current VM XML:\n%s", orig_config_xml.xmltreefile) server_session = remote.wait_for_login('ssh', server_ip, '22', server_user, server_pwd, r"[\#\$]\s*$") if 'src_pf' in locals(): cmd = 'echo %s >/proc/sys/net/ipv4/conf/all/rp_filter' % default_src_rp_filter process.run(cmd, shell=True, verbose=True) utils_sriov.add_or_del_connection(params, is_del=True) create_or_del_networks(src_pf, params, is_del=True) if 'dest_pf' in locals(): cmd = 'echo %s >/proc/sys/net/ipv4/conf/all/rp_filter' % default_dest_rp_filter utils_misc.cmd_status_output(cmd, shell=True, session=server_session) utils_sriov.add_or_del_connection(destparams_dict, session=server_session, is_del=True) remote_virsh_session = virsh.VirshPersistent(**remote_virsh_dargs) create_or_del_networks(dest_pf, params, remote_virsh_session, is_del=True) remote_virsh_session.close_session() if 'dest_pf_pci_path' in locals() and default_dest_vf != vf_no: utils_sriov.set_vf(dest_pf_pci_path, default_dest_vf, server_session) if 'src_pf_pci_path' in locals() and default_src_vf != vf_no: utils_sriov.set_vf(src_pf_pci_path, default_src_vf) # Clean up of pre migration setup for local machine if migr_vm_back: if 'ssh_connection' in locals(): ssh_connection.auto_recover = True migration_test.migrate_pre_setup(src_uri, params, cleanup=True) server_session.close() if remote_virsh_session: remote_virsh_session.close_session() logging.info("Remove local NFS image") source_file = params.get("source_file") if source_file: libvirt.delete_local_disk("file", path=source_file)
def get_forward_value(): """ Reads sysfs for forward value """ cmd = "cat /sys/kernel/debug/kvm/diag_9c_forward" return cmd_status_output(cmd, shell=True)
def get_forward_value(): """ Reads sysfs for forward value """ cmd = "cat %s" % FORWARD_VALUE_PATH return cmd_status_output(cmd, shell=True)
def run(test, params, env): """ Test the libvirt API to report deprecation status of machine-types and devices. """ libvirt_version.is_libvirt_feature_supported(params) vm_name = params.get("main_vm") deprecated_domain = params.get("deprecated_domain", "no") == "yes" check = params.get("check", "no") == "yes" vm = env.get_vm(vm_name) if vm.is_alive(): vm.destroy() backup_xml = libvirt_xml.VMXML.new_from_dumpxml(vm_name) deprecated_vm = backup_xml.copy() try: vm.start() vm.wait_for_login().close() if check: qmp_cmd = params.get("qmp_cmd") domain_tree = params.get("domain_tree") virsh_function = params.get("virsh_function") # Get a list of deprecated CPU architectures/machine types by # executing QMP command qmp_list = get_deprecated_name_list_qmp(vm_name, qmp_cmd) # and (dom)capabilities domain_list = get_deprecated_domain_capabilities_list( eval(virsh_function), domain_tree) check_deprecated_output(test, qmp_list, domain_list) if deprecated_domain: deprecated_list = prepare_deprecated_vm_xml_and_provide_deprecated_list( params, deprecated_vm) if not deprecated_list: test.cancel("There is no deprecated cpu or machine type in " "current qemu version, skipping the test.") # No "Messages" in the output since the default VM is still running. check_dominfo(test, vm_name, deprecated_list, empty=True) vm.destroy() # Update VM with a deprecated items and check dominfo deprecated_vm.sync() logging.debug("vm xml is %s", deprecated_vm) vm.start() vm.wait_for_login().close() check_dominfo(test, vm_name, deprecated_list) # Reboot the VM and check a dominfo again vm.reboot() check_dominfo(test, vm_name, deprecated_list) # Restart libvirtd and check a dominfo again libvirtd = utils_libvirtd.Libvirtd() libvirtd.restart() check_dominfo(test, vm_name, deprecated_list) # Save a VM to file and check a dominfo - No "Messages" deprecated_vm_file = "deprecated_vm" vm.save_to_file(deprecated_vm_file) check_dominfo(test, vm_name, deprecated_list, empty=True) # Restore a VM from file and check dominfo vm.restore_from_file(deprecated_vm_file) check_dominfo(test, vm_name, deprecated_list) # Destroy VM and check dominfo - No "Messages" vm.destroy() check_dominfo(test, vm_name, deprecated_list, empty=True) # Start the VM and shut it down internally - No "Messages" in # dominfo output vm.start() session = vm.wait_for_login() utils_misc.cmd_status_output("shutdown now", session=session) utils_misc.wait_for(lambda: vm.state() == 'shut off', 60) check_dominfo(test, vm_name, deprecated_list, empty=True) except (exceptions.TestFail, exceptions.TestCancel): raise except Exception as e: test.error('Unexpected error: {}'.format(e)) finally: if vm.is_alive: vm.destroy() backup_xml.sync()