def run(test, params, env): """ Test svirt in virt-clone. """ VIRT_CLONE = None try: VIRT_CLONE = utils_misc.find_command("virt-clone") except ValueError: raise error.TestNAError("No virt-clone command found.") # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_virt_clone_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_virt_clone_vm_sec_type", "dynamic") sec_model = params.get("svirt_virt_clone_vm_sec_model", "selinux") sec_label = params.get("svirt_virt_clone_vm_sec_label", None) sec_relabel = params.get("svirt_virt_clone_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_virt_clone_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) utils_selinux.set_context_of_file(filename=disk_path, context=img_label) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() clone_name = ("%s-clone" % vm.name) try: cmd = ("%s --original %s --name %s --auto-clone" % (VIRT_CLONE, vm.name, clone_name)) cmd_result = utils.run(cmd, ignore_status=True) if cmd_result.exit_status: raise error.TestFail("Failed to execute virt-clone command." "Detail: %s." % cmd_result) finally: # clean up for path, label in backup_labels_of_disks.items(): utils_selinux.set_context_of_file(filename=path, context=label) backup_xml.sync() utils_selinux.set_status(backup_sestatus) if not virsh.domstate(clone_name).exit_status: libvirt_vm.VM(clone_name, params, None, None).remove_with_storage()
def get_info(self, name): if name == 'libvirtd': if self.libvirtd.is_running(): status = 'running' else: status = 'stopped' if name == 'selinux': status = utils_selinux.get_status() return {'name': name, 'status': status}
def setup_or_cleanup_iscsi(is_setup, is_login=True, emulated_image="emulated_iscsi", image_size="1G"): """ Set up(and login iscsi target) or clean up iscsi service on localhost. :param is_setup: Boolean value, true for setup, false for cleanup :param is_login: Boolean value, true for login, false for not login :param emulated_image: name of iscsi device :param image_size: emulated image's size :return: iscsi device name or iscsi target """ try: utils_misc.find_command("tgtadm") utils_misc.find_command("iscsiadm") except ValueError: raise error.TestNAError("Missing command 'tgtadm' and/or 'iscsiadm'.") tmpdir = os.path.join(data_dir.get_root_dir(), 'tmp') emulated_path = os.path.join(tmpdir, emulated_image) emulated_target = "iqn.2001-01.com.virttest:%s.target" % emulated_image iscsi_params = {"emulated_image": emulated_path, "target": emulated_target, "image_size": image_size, "iscsi_thread_id": "virt"} _iscsi = iscsi.Iscsi(iscsi_params) if is_setup: sv_status = None if utils_misc.selinux_enforcing(): sv_status = utils_selinux.get_status() utils_selinux.set_status("permissive") _iscsi.export_target() if sv_status is not None: utils_selinux.set_status(sv_status) if is_login: _iscsi.login() # The device doesn't necessarily appear instantaneously, so give # about 5 seconds for it to appear before giving up iscsi_device = utils_misc.wait_for(_iscsi.get_device_name, 5, 0, 1, "Searching iscsi device name.") if iscsi_device: logging.debug("iscsi device: %s", iscsi_device) return iscsi_device if not iscsi_device: logging.error("Not find iscsi device.") # Cleanup and return "" - caller needs to handle that # _iscsi.export_target() will have set the emulated_id and # export_flag already on success... _iscsi.cleanup() utils.run("rm -f %s" % emulated_path) else: return emulated_target else: _iscsi.export_flag = True _iscsi.emulated_id = _iscsi.get_target_id() _iscsi.cleanup() utils.run("rm -f %s" % emulated_path) return ""
def test_sestatus(self): """ Test the method related with sestatus. """ status = utils_selinux.get_status() # b/c there is no assertIn method in re.py in python2.6. # use assertTrue. self.assertTrue(status in ['enforcing', 'permissive', 'disabled']) if utils_selinux.is_disabled(): self.assertRaises(utils_selinux.SelinuxError, utils_selinux.set_status, "enforcing") else: self.assertRaises(utils_selinux.SelinuxError, utils_selinux.set_status, "disabled")
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 run(test, params, env): """ Test for hotplug usb device. """ # get the params from params vm_name = params.get("main_vm", "virt-tests-vm1") vm = env.get_vm(vm_name) usb_type = params.get("usb_type", "kbd") attach_type = params.get("attach_type", "attach_device") attach_count = int(params.get("attach_count", "1")) if usb_type == "storage": model = params.get("model", "nec-xhci") index = params.get("index", "1") status_error = "yes" == params.get("status_error", "no") vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status("permissive") if usb_type == "storage": controllers = vm_xml.get_devices(device_type="controller") devices = vm_xml.get_devices() for dev in controllers: if dev.type == "usb" and dev.index == "1": devices.remove(dev) controller = Controller("controller") controller.type = "usb" controller.index = index controller.model = model devices.append(controller) vm_xml.set_devices(devices) try: session = vm.wait_for_login() except (LoginError, VMError, ShellError), e: raise error.TestFail("Test failed: %s" % str(e))
def setup_or_cleanup_nfs(is_setup, mount_dir="", is_mount=False, export_options="rw,no_root_squash", mount_src="nfs-export"): """ Set up or clean up nfs service on localhost. :param is_setup: Boolean value, true for setup, false for cleanup :param mount_dir: NFS mount point :param is_mount: Boolean value, true for mount, false for umount :param export_options: options for nfs dir :return: export nfs path or nothing """ tmpdir = os.path.join(data_dir.get_root_dir(), 'tmp') if not os.path.isabs(mount_src): mount_src = os.path.join(tmpdir, mount_src) if not mount_dir: mount_dir = os.path.join(tmpdir, 'nfs-mount') nfs_params = {"nfs_mount_dir": mount_dir, "nfs_mount_options": "rw", "nfs_mount_src": mount_src, "setup_local_nfs": "yes", "export_options": "rw,no_root_squash"} _nfs = nfs.Nfs(nfs_params) # Set selinux to permissive that the file in nfs # can be used freely if utils_misc.selinux_enforcing(): sv_status = utils_selinux.get_status() utils_selinux.set_status("permissive") if is_setup: _nfs.setup() if not is_mount: _nfs.umount() return mount_src else: _nfs.unexportfs_in_clean = True _nfs.cleanup() return ""
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Create a image to attached to VM. (3).Attach disk. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_attach_disk_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_attach_disk_vm_sec_type", "dynamic") sec_model = params.get("svirt_attach_disk_vm_sec_model", "selinux") sec_label = params.get("svirt_attach_disk_vm_sec_label", None) sec_relabel = params.get("svirt_attach_disk_vm_sec_relabel", "yes") sec_dict = { 'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel } # Get variables about pool vol with_pool_vol = 'yes' == params.get("with_pool_vol", "no") check_cap_rawio = "yes" == params.get("check_cap_rawio", "no") virt_use_nfs = params.get("virt_use_nfs", "off") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format") # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_attach_disk_disk_label') img_name = "svirt_disk" # Default label for the other disks. # To ensure VM is able to access other disks. default_label = params.get('svirt_attach_disk_disk_default_label', None) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the default label to other disks of vm. disks = vm.get_disk_devices() for disk in disks.values(): utils_selinux.set_context_of_file(filename=disk['source'], context=default_label) pvt = None qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # set qemu conf if check_cap_rawio: qemu_conf.user = '******' qemu_conf.group = 'root' logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() logging.debug("the domain xml is: %s" % vmxml.xmltreefile) if with_pool_vol: # Create dst pool for create attach vol img pvt = utlv.PoolVolumeTest(test, params) logging.debug("pool_type %s" % pool_type) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"]) if pool_type in ["iscsi", "disk"]: # iscsi and disk pool did not support create volume in libvirt, # logical pool could use libvirt to create volume but volume # format is not supported and will be 'raw' as default. pv = libvirt_storage.PoolVolume(pool_name) vols = pv.list_volumes().keys() if vols: vol_name = vols[0] else: raise error.TestNAError("No volume in pool: %s" % pool_name) else: vol_arg = { 'name': vol_name, 'format': vol_format, 'capacity': 1073741824, 'allocation': 1048576, } # Set volume xml file volxml = libvirt_xml.VolXML() newvol = volxml.new_vol(**vol_arg) vol_xml = newvol['xml'] # Run virsh_vol_create to create vol logging.debug("create volume from xml: %s" % newvol.xmltreefile) cmd_result = virsh.vol_create(pool_name, vol_xml, ignore_status=True, debug=True) if cmd_result.exit_status: raise error.TestNAError("Failed to create attach volume.") cmd_result = virsh.vol_path(vol_name, pool_name, debug=True) if cmd_result.exit_status: raise error.TestNAError("Failed to get volume path from pool.") img_path = cmd_result.stdout.strip() if pool_type in ["iscsi", "disk"]: extra = "--driver qemu --type lun --rawio --persistent" else: extra = "--persistent --subdriver qcow2" # set host_sestatus as nfs pool will reset it utils_selinux.set_status(host_sestatus) # set virt_use_nfs result = utils.run("setsebool virt_use_nfs %s" % virt_use_nfs) if result.exit_status: raise error.TestNAError("Failed to set virt_use_nfs value") else: # Init a QemuImg instance. params['image_name'] = img_name tmp_dir = data_dir.get_tmp_dir() image = qemu_storage.QemuImg(params, tmp_dir, img_name) # Create a image. img_path, result = image.create(params) # Set the context of the image. utils_selinux.set_context_of_file(filename=img_path, context=img_label) extra = "--persistent" # Do the attach action. result = virsh.attach_disk(vm_name, source=img_path, target="vdf", extra=extra, debug=True) if result.exit_status: raise error.TestFail("Failed to attach disk %s to VM." "Detail: %s." % (img_path, result.stderr)) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with set seclabel can access the image with the # set context. if status_error: raise error.TestFail('Test succeeded in negative case.') if check_cap_rawio: cap_list = ['CapPrm', 'CapEff', 'CapBnd'] cap_dict = {} pid = vm.get_pid() pid_status_path = "/proc/%s/status" % pid with open(pid_status_path) as f: for line in f: val_list = line.split(":") if val_list[0] in cap_list: cap_dict[val_list[0]] = int( val_list[1].strip(), 16) # bit and with rawio capabilitiy value to check cap_sys_rawio # is set cap_rawio_val = 0x0000000000020000 for i in cap_list: if not cap_rawio_val & cap_dict[i]: err_msg = "vm process with %s: 0x%x" % (i, cap_dict[i]) err_msg += " lack cap_sys_rawio capabilities" raise error.TestFail(err_msg) else: inf_msg = "vm process with %s: 0x%x" % (i, cap_dict[i]) inf_msg += " have cap_sys_rawio capabilities" logging.debug(inf_msg) except virt_vm.VMStartError, e: # Starting VM failed. # VM with set seclabel can not access the image with the # set context. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) try: virsh.detach_disk(vm_name, target="vdf", extra="--persistent", debug=True) except error.CmdError: raise error.TestFail("Detach disk 'vdf' from VM %s failed." % vm.name)
def export_target(self): """ Export target in localhost for emulated iscsi """ selinux_mode = None if not os.path.isfile(self.emulated_image): utils.system(self.create_cmd) else: emulated_image_size = os.path.getsize(self.emulated_image) / 1024 if emulated_image_size != self.emulated_expect_size: # No need to remvoe, rebuild is fine utils.system(self.create_cmd) cmd = "tgtadm --lld iscsi --mode target --op show" try: output = utils.system_output(cmd) except error.CmdError: utils.system("service tgtd restart") output = utils.system_output(cmd) if not re.findall("%s$" % self.target, output, re.M): logging.debug("Need to export target in host") # Set selinux to permissive mode to make sure iscsi target # export successfully if utils_selinux.is_enforcing(): selinux_mode = utils_selinux.get_status() utils_selinux.set_status("permissive") output = utils.system_output(cmd) used_id = re.findall("Target\s+(\d+)", output) emulated_id = 1 while str(emulated_id) in used_id: emulated_id += 1 self.emulated_id = str(emulated_id) cmd = "tgtadm --mode target --op new --tid %s" % self.emulated_id cmd += " --lld iscsi --targetname %s" % self.target utils.system(cmd) cmd = "tgtadm --lld iscsi --op bind --mode target " cmd += "--tid %s -I ALL" % self.emulated_id utils.system(cmd) else: target_strs = re.findall("Target\s+(\d+):\s+%s$" % self.target, output, re.M) self.emulated_id = target_strs[0].split(':')[0].split()[-1] cmd = "tgtadm --lld iscsi --mode target --op show" try: output = utils.system_output(cmd) except error.CmdError: # In case service stopped utils.system("service tgtd restart") output = utils.system_output(cmd) # Create a LUN with emulated image if re.findall(self.emulated_image, output, re.M): # Exist already logging.debug("Exported image already exists.") self.export_flag = True else: tgt_str = re.search(r'.*(Target\s+\d+:\s+%s\s*.*)$' % self.target, output, re.DOTALL) if tgt_str: luns = len(re.findall("\s+LUN:\s(\d+)", tgt_str.group(1), re.M)) else: luns = len(re.findall("\s+LUN:\s(\d+)", output, re.M)) cmd = "tgtadm --mode logicalunit --op new " cmd += "--tid %s --lld iscsi " % self.emulated_id cmd += "--lun %s " % luns cmd += "--backing-store %s" % self.emulated_image utils.system(cmd) self.export_flag = True # Restore selinux if selinux_mode is not None: utils_selinux.set_status(selinux_mode) if self.chap_flag: # Set CHAP authentication on the exported target self.set_chap_auth_target() # Set CHAP authentication for initiator to login target if self.portal_visible(): self.set_chap_auth_initiator()
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Create a image to attached to VM. (3).Attach disk. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_attach_disk_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_attach_disk_vm_sec_type", "dynamic") sec_model = params.get("svirt_attach_disk_vm_sec_model", "selinux") sec_label = params.get("svirt_attach_disk_vm_sec_label", None) sec_relabel = params.get("svirt_attach_disk_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} disk_seclabel = params.get("disk_seclabel", "no") # Get variables about pool vol with_pool_vol = 'yes' == params.get("with_pool_vol", "no") check_cap_rawio = "yes" == params.get("check_cap_rawio", "no") virt_use_nfs = params.get("virt_use_nfs", "off") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format", "qcow2") device_target = params.get("disk_target") device_bus = params.get("disk_target_bus") device_type = params.get("device_type", "file") # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_attach_disk_disk_label') sec_disk_dict = {'model': sec_model, 'label': img_label, 'relabel': sec_relabel} enable_namespace = 'yes' == params.get('enable_namespace', 'no') img_name = "svirt_disk" # Default label for the other disks. # To ensure VM is able to access other disks. default_label = params.get('svirt_attach_disk_disk_default_label', None) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the default label to other disks of vm. disks = vm.get_disk_devices() for disk in list(disks.values()): utils_selinux.set_context_of_file(filename=disk['source'], context=default_label) pvt = None qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() disk_xml = Disk(type_name=device_type) disk_xml.device = "disk" try: # set qemu conf if check_cap_rawio: qemu_conf.user = '******' qemu_conf.group = 'root' logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() if with_pool_vol: # Create dst pool for create attach vol img pvt = utlv.PoolVolumeTest(test, params) logging.debug("pool_type %s" % pool_type) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"]) if pool_type in ["iscsi", "disk"]: # iscsi and disk pool did not support create volume in libvirt, # logical pool could use libvirt to create volume but volume # format is not supported and will be 'raw' as default. pv = libvirt_storage.PoolVolume(pool_name) vols = list(pv.list_volumes().keys()) vol_format = "raw" if vols: vol_name = vols[0] else: test.cancel("No volume in pool: %s" % pool_name) else: vol_arg = {'name': vol_name, 'format': vol_format, 'capacity': 1073741824, 'allocation': 1048576, } # Set volume xml file volxml = libvirt_xml.VolXML() newvol = volxml.new_vol(**vol_arg) vol_xml = newvol['xml'] # Run virsh_vol_create to create vol logging.debug("create volume from xml: %s" % newvol.xmltreefile) cmd_result = virsh.vol_create(pool_name, vol_xml, ignore_status=True, debug=True) if cmd_result.exit_status: test.cancel("Failed to create attach volume.") cmd_result = virsh.vol_path(vol_name, pool_name, debug=True) if cmd_result.exit_status: test.cancel("Failed to get volume path from pool.") img_path = cmd_result.stdout.strip() if pool_type in ["iscsi", "disk"]: source_type = "dev" if pool_type == "iscsi": disk_xml.device = "lun" disk_xml.rawio = "yes" else: if not enable_namespace: qemu_conf.namespaces = '' logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() else: source_type = "file" # set host_sestatus as nfs pool will reset it utils_selinux.set_status(host_sestatus) # set virt_use_nfs result = process.run("setsebool virt_use_nfs %s" % virt_use_nfs, shell=True) if result.exit_status: test.cancel("Failed to set virt_use_nfs value") else: source_type = "file" # Init a QemuImg instance. params['image_name'] = img_name tmp_dir = data_dir.get_tmp_dir() image = qemu_storage.QemuImg(params, tmp_dir, img_name) # Create a image. img_path, result = image.create(params) # Set the context of the image. if sec_relabel == "no": utils_selinux.set_context_of_file(filename=img_path, context=img_label) disk_xml.target = {"dev": device_target, "bus": device_bus} disk_xml.driver = {"name": "qemu", "type": vol_format} if disk_seclabel == "yes": source_seclabel = [] sec_xml = seclabel.Seclabel() sec_xml.update(sec_disk_dict) source_seclabel.append(sec_xml) disk_source = disk_xml.new_disk_source(**{"attrs": {source_type: img_path}, "seclabels": source_seclabel}) else: disk_source = disk_xml.new_disk_source(**{"attrs": {source_type: img_path}}) # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() disk_xml.source = disk_source logging.debug(disk_xml) # Do the attach action. cmd_result = virsh.attach_device(domainarg=vm_name, filearg=disk_xml.xml, flagstr='--persistent') libvirt.check_exit_status(cmd_result, expect_error=False) logging.debug("the domain xml is: %s" % vmxml.xmltreefile) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with set seclabel can access the image with the # set context. if status_error: test.fail('Test succeeded in negative case.') if check_cap_rawio: cap_list = ['CapPrm', 'CapEff', 'CapBnd'] cap_dict = {} pid = vm.get_pid() pid_status_path = "/proc/%s/status" % pid with open(pid_status_path) as f: for line in f: val_list = line.split(":") if val_list[0] in cap_list: cap_dict[val_list[0]] = int(val_list[1].strip(), 16) # bit and with rawio capabilitiy value to check cap_sys_rawio # is set cap_rawio_val = 0x0000000000020000 for i in cap_list: if not cap_rawio_val & cap_dict[i]: err_msg = "vm process with %s: 0x%x" % (i, cap_dict[i]) err_msg += " lack cap_sys_rawio capabilities" test.fail(err_msg) else: inf_msg = "vm process with %s: 0x%x" % (i, cap_dict[i]) inf_msg += " have cap_sys_rawio capabilities" logging.debug(inf_msg) if pool_type == "disk": if libvirt_version.version_compare(3, 1, 0) and enable_namespace: vm_pid = vm.get_pid() output = process.system_output( "nsenter -t %d -m -- ls -Z %s" % (vm_pid, img_path)) else: output = process.system_output('ls -Z %s' % img_path) logging.debug("The default label is %s", default_label) logging.debug("The label after guest started is %s", to_text(output.strip().split()[-2])) if default_label not in to_text(output.strip().split()[-2]): test.fail("The label is wrong after guest started\n") except virt_vm.VMStartError as e: # Starting VM failed. # VM with set seclabel can not access the image with the # set context. if not status_error: test.fail("Test failed in positive case." "error: %s" % e) cmd_result = virsh.detach_device(domainarg=vm_name, filearg=disk_xml.xml) libvirt.check_exit_status(cmd_result, status_error) finally: # clean up vm.destroy() if not with_pool_vol: image.remove() if pvt: try: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_image) except exceptions.TestFail as detail: logging.error(str(detail)) backup_xml.sync() utils_selinux.set_status(backup_sestatus) if check_cap_rawio: qemu_conf.restore() libvirtd.restart()
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Label the VM and disk with proper label. (3).Start VM and check the context. (4).Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get( "svirt_undefine_define_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_undefine_define_vm_sec_type", "dynamic") sec_model = params.get("svirt_undefine_define_vm_sec_model", "selinux") sec_label = params.get("svirt_undefine_define_vm_sec_label", None) sec_relabel = params.get("svirt_undefine_define_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_undefine_define_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) utils_selinux.set_context_of_file(filename=disk_path, context=img_label) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() try: xml_file = (os.path.join(data_dir.get_tmp_dir(), "vmxml")) if vm.is_alive(): vm.destroy() virsh.dumpxml(vm.name, to_file=xml_file) cmd_result = virsh.undefine(vm.name) if cmd_result.exit_status: raise error.TestFail("Failed to undefine vm." "Detail: %s" % cmd_result) cmd_result = virsh.define(xml_file) if cmd_result.exit_status: raise error.TestFail("Failed to define vm." "Detail: %s" % cmd_result) finally: # clean up for path, label in backup_labels_of_disks.items(): utils_selinux.set_context_of_file(filename=path, context=label) backup_xml.sync() utils_selinux.set_status(backup_sestatus)
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Label the VM and disk with proper label. (3).Start VM and check the context. (4).Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_start_destroy_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_start_destroy_vm_sec_type", "dynamic") sec_model = params.get("svirt_start_destroy_vm_sec_model", "selinux") sec_label = params.get("svirt_start_destroy_vm_sec_label", None) sec_relabel = params.get("svirt_start_destroy_vm_sec_relabel", "yes") sec_dict = { 'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel } poweroff_with_destroy = ("destroy" == params.get( "svirt_start_destroy_vm_poweroff", "destroy")) # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_start_destroy_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) utils_selinux.set_context_of_file(filename=disk_path, context=img_label) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the context of the VM. vmxml.set_seclabel(sec_dict) vmxml.sync() try: # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with seclabel can access the image with the context. if status_error: raise error.TestFail("Test successed in negative case.") # Check the label of VM and image when VM is running. vm_context = utils_selinux.get_context_of_process(vm.get_pid()) if (sec_type == "static") and (not vm_context == sec_label): raise error.TestFail( "Label of VM is not expected after starting.\n" "Detail: vm_context=%s, sec_label=%s" % (vm_context, sec_label)) disk_context = utils_selinux.get_context_of_file( filename=disks.values()[0]['source']) if (sec_relabel == "no") and (not disk_context == img_label): raise error.TestFail("Label of disk is not expected after VM " "starting.\n" "Detail: disk_context=%s, img_label=%s." % (disk_context, img_label)) if sec_relabel == "yes": vmxml = VMXML.new_from_dumpxml(vm_name) imagelabel = vmxml.get_seclabel()['imagelabel'] if not disk_context == imagelabel: raise error.TestFail( "Label of disk is not relabeled by VM\n" "Detal: disk_context=%s, imagelabel=%s" % (disk_context, imagelabel)) # Check the label of disk after VM being destroyed. if poweroff_with_destroy: vm.destroy() else: vm.wait_for_login() vm.shutdown() img_label_after = utils_selinux.get_context_of_file( filename=disks.values()[0]['source']) if (not img_label_after == img_label): raise error.TestFail( "Bug: Label of disk is not restored in VM " "shuting down.\n" "Detail: img_label_after=%s, " "img_label_before=%s.\n" % (img_label_after, img_label)) except virt_vm.VMStartError, e: # Starting VM failed. # VM with seclabel can not access the image with the context. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up for path, label in backup_labels_of_disks.items(): utils_selinux.set_context_of_file(filename=path, context=label) backup_xml.sync() utils_selinux.set_status(backup_sestatus)
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 DAC setting in both domain xml and qemu.conf. (1) Init variables for test. (2) Set VM xml and qemu.conf with proper DAC label, also set monitor socket parent dir with propoer ownership and mode. (3) Start VM and check the context. """ # 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("vm_sec_type", "dynamic") vm_sec_model = params.get("vm_sec_model", "dac") vm_sec_label = params.get("vm_sec_label", None) vm_sec_relabel = params.get("vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': vm_sec_model, 'relabel': vm_sec_relabel} if vm_sec_label: sec_dict['label'] = vm_sec_label set_qemu_conf = "yes" == params.get("set_qemu_conf", "no") # Get per-img seclabel variables disk_type = params.get("disk_type") disk_target = params.get('disk_target') disk_src_protocol = params.get("disk_source_protocol") vol_name = params.get("vol_name") tmp_dir = data_dir.get_tmp_dir() pool_name = params.get("pool_name", "gluster-pool") brick_path = os.path.join(tmp_dir, pool_name) invalid_label = 'yes' == params.get("invalid_label", "no") relabel = params.get("per_img_sec_relabel") sec_label = params.get("per_img_sec_label") per_sec_model = params.get("per_sec_model", 'dac') per_img_dict = {'sec_model': per_sec_model, 'relabel': relabel, 'sec_label': sec_label} params.update(per_img_dict) # Get qemu.conf config variables qemu_user = params.get("qemu_user", 'qemu') qemu_group = params.get("qemu_group", 'qemu') dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) qemu_sock_mod = False qemu_sock_path = '/var/lib/libvirt/qemu/' qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: if set_qemu_conf: # Set qemu.conf for user and group if qemu_user: qemu_conf.user = qemu_user if qemu_group: qemu_conf.group = qemu_group if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() st = os.stat(qemu_sock_path) if not bool(st.st_mode & stat.S_IWGRP): # chmod g+w os.chmod(qemu_sock_path, st.st_mode | stat.S_IWGRP) qemu_sock_mod = True # Set the context of the VM. logging.debug("sec_dict is %s" % sec_dict) vmxml.set_seclabel([sec_dict]) vmxml.sync() # Get per-image seclabel in id string if sec_label: per_img_usr, per_img_grp = sec_label.split(':') sec_label_id = format_user_group_str(per_img_usr, per_img_grp) # Start VM to check the qemu process and image. try: # Set per-img sec context and start vm utlv.set_vm_disk(vm, params) # Start VM successfully. if status_error: if invalid_label: # invalid label should fail, more info in bug 1165485 raise error.TestNAError("The label or model not valid, " "check more info in bug: https://" "bugzilla.redhat.com/show_bug.cgi" "?id=1165485") else: raise error.TestFail("Test succeeded in negative case.") # Get vm process label when VM is running. vm_pid = vm.get_pid() pid_stat = os.stat("/proc/%d" % vm_pid) vm_process_uid = pid_stat.st_uid vm_process_gid = pid_stat.st_gid vm_context = "%s:%s" % (vm_process_uid, vm_process_gid) logging.debug("vm process label is: %s", vm_context) # Get vm image label when VM is running if disk_type != "network": disks = vm.get_blk_devices() f = os.open(disks[disk_target]['source'], 0) stat_re = os.fstat(f) disk_context = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) logging.debug("The disk dac label after vm start is: %s", disk_context) if sec_label and relabel == 'yes': if disk_context != sec_label_id: raise error.TestFail("The disk label is not equal to " "'%s'." % sec_label_id) except virt_vm.VMStartError, e: # Starting VM failed. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up if vm.is_alive(): vm.destroy(gracefully=False) backup_xml.sync() if qemu_sock_mod: st = os.stat(qemu_sock_path) os.chmod(qemu_sock_path, st.st_mode ^ stat.S_IWGRP) if set_qemu_conf: qemu_conf.restore() libvirtd.restart() utils_selinux.set_status(backup_sestatus) if disk_src_protocol == 'iscsi': utlv.setup_or_cleanup_iscsi(is_setup=False) elif disk_src_protocol == 'gluster': utlv.setup_or_cleanup_gluster(False, vol_name, brick_path) libvirtd.restart() elif disk_src_protocol == 'netfs': utlv.setup_or_cleanup_nfs(is_setup=False, restore_selinux=backup_sestatus)
vm_xml.VMXML.set_graphics_attr(vm_name, {'type': graphic}) if len(graphic_video) > 1: video_type = graphic_video[1] logging.info('Set video type to %s', video_type) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) video = vmxml.xmltreefile.find('devices').find('video').find('model') video.set('type', video_type) vmxml.sync() if checkpoint.startswith('listen'): listen_type = checkpoint.split('_')[-1] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) listen = vmxml.xmltreefile.find('devices').find('graphics').find('listen') listen.set('type', listen_type) vmxml.sync() if checkpoint == 'host_selinux_on': params['selinux_stat'] = utils_selinux.get_status() utils_selinux.set_status('enforcing') if checkpoint.startswith('selinux'): set_selinux(checkpoint[8:]) if checkpoint.startswith('host_firewalld'): service_mgr = service.ServiceManager() logging.info('Backing up firewall services status') params['bk_firewalld_status'] = service_mgr.status('firewalld') if 'start' in checkpoint: service_mgr.start('firewalld') if 'stop' in checkpoint: service_mgr.stop('firewalld') if checkpoint == 'guest_firewalld_status': get_firewalld_status() if checkpoint == 'remove_securetty': logging.info('Remove /etc/securetty file from guest')
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Config qemu conf if need (3).Label the VM and disk with proper label. (4).Start VM and check the context. (5).Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_start_destroy_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_start_destroy_vm_sec_type", "dynamic") sec_model = params.get("svirt_start_destroy_vm_sec_model", "selinux") sec_label = params.get("svirt_start_destroy_vm_sec_label", None) sec_baselabel = params.get("svirt_start_destroy_vm_sec_baselabel", None) security_driver = params.get("security_driver", None) security_default_confined = params.get("security_default_confined", None) security_require_confined = params.get("security_require_confined", None) no_sec_model = 'yes' == params.get("no_sec_model", 'no') xattr_check = 'yes' == params.get("xattr_check", 'no') sec_relabel = params.get("svirt_start_destroy_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'relabel': sec_relabel} sec_dict_list = [] def _set_sec_model(model): """ Set sec_dict_list base on given sec model type """ sec_dict_copy = sec_dict.copy() sec_dict_copy['model'] = model if sec_type != "none": if sec_type == "dynamic" and sec_baselabel: sec_dict_copy['baselabel'] = sec_baselabel else: sec_dict_copy['label'] = sec_label sec_dict_list.append(sec_dict_copy) if not no_sec_model: if "," in sec_model: sec_models = sec_model.split(",") for model in sec_models: _set_sec_model(model) else: _set_sec_model(sec_model) else: sec_dict_list.append(sec_dict) logging.debug("sec_dict_list is: %s" % sec_dict_list) poweroff_with_destroy = ("destroy" == params.get( "svirt_start_destroy_vm_poweroff", "destroy")) # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get variables about image. img_label = params.get('svirt_start_destroy_disk_label') # Backup disk Labels. disks = vm.get_disk_devices() backup_labels_of_disks = {} backup_ownership_of_disks = {} for disk in list(disks.values()): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) stat_re = os.stat(disk_path) backup_ownership_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) # Backup selinux of host. backup_sestatus = utils_selinux.get_status() qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() def _resolve_label(label_string): labels = label_string.split(":") label_type = labels[2] if len(labels) == 4: label_range = labels[3] elif len(labels) > 4: label_range = "%s:%s" % (labels[3], labels[4]) else: label_range = None return (label_type, label_range) def _check_label_equal(label1, label2): label1s = label1.split(":") label2s = label2.split(":") for i in range(len(label1s)): if label1s[i] != label2s[i]: return False return True try: # Set disk label (img_label_type, img_label_range) = _resolve_label(img_label) for disk in list(disks.values()): disk_path = disk['source'] dir_path = "%s(/.*)?" % os.path.dirname(disk_path) try: utils_selinux.del_defcon(img_label_type, pathregex=dir_path) except Exception as err: logging.debug("Delete label failed: %s", err) # Using semanage set context persistently utils_selinux.set_defcon(context_type=img_label_type, pathregex=dir_path, context_range=img_label_range) utils_selinux.verify_defcon(pathname=disk_path, readonly=False, forcedesc=True) if sec_relabel == "no" and sec_type == 'none': os.chown(disk_path, 107, 107) # Set selinux of host. utils_selinux.set_status(host_sestatus) # Set qemu conf if security_driver: qemu_conf.set_string('security_driver', security_driver) if security_default_confined: qemu_conf.security_default_confined = security_default_confined if security_require_confined: qemu_conf.security_require_confined = security_require_confined if (security_driver or security_default_confined or security_require_confined): logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Set the context of the VM. vmxml.set_seclabel(sec_dict_list) vmxml.sync() logging.debug("the domain xml is: %s" % vmxml.xmltreefile) # restart libvirtd libvirtd.restart() # Start VM to check the VM is able to access the image or not. try: # Need another guest to test the xattr added by libvirt if xattr_check: blklist = virsh.domblklist(vm_name, debug=True) target_disk = re.findall(r"[v,s]d[a-z]", blklist.stdout.strip())[0] guest_name = "%s_%s" % (vm_name, '1') cmd = "virt-clone --original %s --name %s " % (vm_name, guest_name) cmd += "--auto-clone --skip-copy=%s" % target_disk process.run(cmd, shell=True, verbose=True) vm.start() # Start VM successfully. # VM with seclabel can access the image with the context. if status_error: test.fail("Test succeeded in negative case.") # Start another vm with the same disk image. # The xattr will not be changed. if xattr_check: virsh.start(guest_name, ignore_status=True, debug=True) # Check the label of VM and image when VM is running. vm_context = utils_selinux.get_context_of_process(vm.get_pid()) if (sec_type == "static") and (not vm_context == sec_label): test.fail("Label of VM is not expected after " "starting.\n" "Detail: vm_context=%s, sec_label=%s" % (vm_context, sec_label)) disk_context = utils_selinux.get_context_of_file( filename=list(disks.values())[0]['source']) if (sec_relabel == "no") and (not disk_context == img_label): test.fail("Label of disk is not expected after VM " "starting.\n" "Detail: disk_context=%s, img_label=%s." % (disk_context, img_label)) if sec_relabel == "yes" and not no_sec_model: vmxml = VMXML.new_from_dumpxml(vm_name) imagelabel = vmxml.get_seclabel()[0]['imagelabel'] # the disk context is 'system_u:object_r:svirt_image_t:s0', # when VM started, the MLS/MCS Range will be added automatically. # imagelabel turns to be 'system_u:object_r:svirt_image_t:s0:cxx,cxxx' # but we shouldn't check the MCS range. if not _check_label_equal(disk_context, imagelabel): test.fail("Label of disk is not relabeled by " "VM\nDetal: disk_context=" "%s, imagelabel=%s" % (disk_context, imagelabel)) expected_results = "trusted.libvirt.security.ref_dac=\"1\"\n" expected_results += "trusted.libvirt.security.ref_selinux=\"1\"" cmd = "getfattr -m trusted.libvirt.security -d %s " % list( disks.values())[0]['source'] utils_test.libvirt.check_cmd_output(cmd, content=expected_results) # Check the label of disk after VM being destroyed. if poweroff_with_destroy: vm.destroy(gracefully=False) else: vm.wait_for_login() vm.shutdown() filename = list(disks.values())[0]['source'] img_label_after = utils_selinux.get_context_of_file(filename) stat_re = os.stat(filename) ownership_of_disk = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) logging.debug("The ownership of disk after guest starting is:\n") logging.debug(ownership_of_disk) logging.debug("The ownership of disk before guest starting is:\n") logging.debug(backup_ownership_of_disks[filename]) if not (sec_relabel == "no" and sec_type == 'none'): if not libvirt_version.version_compare(5, 6, 0): if img_label_after != img_label: # Bug 547546 - RFE: the security drivers must remember original # permissions/labels and restore them after # https://bugzilla.redhat.com/show_bug.cgi?id=547546 err_msg = "Label of disk is not restored in VM shutting down.\n" err_msg += "Detail: img_label_after=%s, " % img_label_after err_msg += "img_label_before=%s.\n" % img_label err_msg += "More info in https://bugzilla.redhat.com/show_bug" err_msg += ".cgi?id=547546" test.fail(err_msg) elif (img_label_after != img_label or ownership_of_disk != backup_ownership_of_disks[filename]): err_msg = "Label of disk is not restored in VM shutting down.\n" err_msg += "Detail: img_label_after=%s, %s " % ( img_label_after, ownership_of_disk) err_msg += "img_label_before=%s, %s\n" % ( img_label, backup_ownership_of_disks[filename]) test.fail(err_msg) # The xattr should be cleaned after guest shutoff. cmd = "getfattr -m trusted.libvirt.security -d %s " % list( disks.values())[0]['source'] utils_test.libvirt.check_cmd_output(cmd, content="") except virt_vm.VMStartError as e: # Starting VM failed. # VM with seclabel can not access the image with the context. if not status_error: test.fail("Test failed in positive case." "error: %s" % e) finally: # clean up for path, label in list(backup_labels_of_disks.items()): # Using semanage set context persistently dir_path = "%s(/.*)?" % os.path.dirname(path) (img_label_type, img_label_range) = _resolve_label(label) try: utils_selinux.del_defcon(img_label_type, pathregex=dir_path) except Exception as err: logging.debug("Delete label failed: %s", err) utils_selinux.set_defcon(context_type=img_label_type, pathregex=dir_path, context_range=img_label_range) utils_selinux.verify_defcon(pathname=path, readonly=False, forcedesc=True) for path, label in list(backup_ownership_of_disks.items()): label_list = label.split(":") os.chown(path, int(label_list[0]), int(label_list[1])) backup_xml.sync() if xattr_check: virsh.undefine(guest_name, ignore_status=True) utils_selinux.set_status(backup_sestatus) if (security_driver or security_default_confined or security_require_confined): qemu_conf.restore() libvirtd.restart()
def run(test, params, env): """ convert specific kvm guest to rhev """ 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: raise ValueError('Missing command: virt-v2v') hypervisor = params.get("hypervisor") vm_name = params.get('main_vm', 'EXAMPLE') target = params.get('target') remote_host = params.get('remote_host', 'EXAMPLE') input_mode = params.get("input_mode") output_mode = params.get('output_mode') output_format = params.get('output_format') source_user = params.get("username", "root") storage = params.get('output_storage') storage_name = params.get('storage_name') bridge = params.get('bridge') network = params.get('network') ntp_server = params.get('ntp_server') vpx_dc = params.get("vpx_dc") esx_ip = params.get("esx_hostname") address_cache = env.get('address_cache') 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 = utlv.PoolVolumeTest(test, params) v2v_opts = params.get('v2v_opts', '-v -x') v2v_timeout = int(params.get('v2v_timeout', 3600)) skip_check = 'yes' == params.get('skip_check', 'no') status_error = 'yes' == params.get('status_error', 'no') checkpoint = params.get('checkpoint', '') debug_kernel = 'debug_kernel' == checkpoint backup_list = ['floppy', 'floppy_devmap', 'fstab_cdrom', 'sata_disk', 'network_rtl8139', 'network_e1000', 'spice', 'spice_encrypt', 'spice_qxl', 'spice_cirrus', 'vnc_qxl', 'vnc_cirrus', 'blank_2nd_disk', 'listen_none', 'listen_socket', 'only_net', 'only_br'] error_list = [] # Prepare step for different hypervisor if hypervisor == "esx": source_ip = params.get("vpx_hostname") source_pwd = params.get("vpx_password") vpx_passwd_file = params.get("vpx_passwd_file") # Create password file to access ESX hypervisor with open(vpx_passwd_file, 'w') as f: f.write(source_pwd) elif hypervisor == "xen": source_ip = params.get("xen_hostname") source_pwd = params.get("xen_host_passwd") # Set up ssh access using ssh-agent and authorized_keys ssh_key.setup_ssh_key(source_ip, source_user, source_pwd) try: utils_misc.add_identities_into_ssh_agent() except Exception as e: process.run("ssh-agent -k") test.error("Fail to setup ssh-agent \n %s" % str(e)) elif hypervisor == "kvm": source_ip = None source_pwd = None else: test.cancel("Unspported hypervisor: %s" % hypervisor) # Create libvirt URI v2v_uri = utils_v2v.Uri(hypervisor) remote_uri = v2v_uri.get_uri(source_ip, vpx_dc, esx_ip) logging.debug("libvirt URI for converting: %s", remote_uri) # Make sure the VM exist before convert v2v_virsh = None close_virsh = False if hypervisor == 'kvm': v2v_virsh = virsh else: virsh_dargs = {'uri': remote_uri, 'remote_ip': source_ip, 'remote_user': source_user, 'remote_pwd': source_pwd, 'debug': True} v2v_virsh = virsh.VirshPersistent(**virsh_dargs) close_virsh = True if not v2v_virsh.domain_exists(vm_name): test.error("VM '%s' not exist" % vm_name) def log_fail(msg): """ Log error and update error list """ logging.error(msg) error_list.append(msg) def vm_shell(func): """ Decorator of shell session to vm """ def wrapper(*args, **kwargs): vm = libvirt_vm.VM(vm_name, params, test.bindir, env.get('address_cache')) if vm.is_dead(): logging.info('VM is down. Starting it now.') vm.start() session = vm.wait_for_login() kwargs['session'] = session kwargs['vm'] = vm func(*args, **kwargs) if session: session.close() vm.shutdown() return wrapper def check_disks(vmcheck): """ Check disk counts inside the VM """ # Initialize windows boot up os_type = params.get("os_type", "linux") expected_disks = int(params.get("ori_disks", "1")) logging.debug("Expect %s disks im VM after convert", expected_disks) # Get disk counts if os_type == "linux": cmd = "lsblk |grep disk |wc -l" disks = int(vmcheck.session.cmd(cmd).strip()) else: cmd = r"echo list disk > C:\list_disk.txt" vmcheck.session.cmd(cmd) cmd = r"diskpart /s C:\list_disk.txt" output = vmcheck.session.cmd(cmd).strip() logging.debug("Disks in VM: %s", output) disks = len(re.findall('Disk\s\d', output)) logging.debug("Find %s disks in VM after convert", disks) if disks == expected_disks: logging.info("Disk counts is expected") else: log_fail("Disk counts is wrong") def check_vmlinuz_initramfs(v2v_output): """ Check if vmlinuz matches initramfs on multi-kernel case """ logging.debug('Checking if vmlinuz matches initramfs') kernel_strs = re.findall('(\* kernel.*?\/boot\/config){1,}', v2v_output, re.DOTALL) if len(kernel_strs) == 0: test.error("Not find kernel information") # Remove duplicate items by set logging.debug('Boots and kernel info: %s' % set(kernel_strs)) for str_i in set(kernel_strs): # Fine all versions kernel_vers = re.findall('((?:\d+\.){1,}\d+-(?:\d+\.){1,}\w+)', str_i) logging.debug('kernel related versions: %s' % kernel_vers) # kernel_vers = [kernel, vmlinuz, initramfs] and they should be same if len(kernel_vers) < 3 or len(set(kernel_vers)) != 1: log_fail("kernel versions does not match: %s" % kernel_vers) def check_boot_kernel(vmcheck): """ Check if converted vm use the latest kernel """ _, current_kernel = vmcheck.run_cmd('uname -r') if 'debug' in current_kernel: log_fail('Current kernel is a debug kernel: %s' % current_kernel) # 'sort -V' can satisfy our testing, even though it's not strictly perfect. # The last one is always the latest kernel version kernel_normal_list = vmcheck.run_cmd('rpm -q kernel | sort -V')[1].strip().splitlines() status, kernel_debug = vmcheck.run_cmd('rpm -q kernel-debug') if status != 0: test.error('Not found kernel-debug package') all_kernel_list = kernel_normal_list + kernel_debug.strip().splitlines() logging.debug('All kernels: %s' % all_kernel_list) if len(all_kernel_list) < 3: test.error('Needs at least 2 normal kernels and 1 debug kernel in VM') # The latest non-debug kernel must be kernel_normal_list[-1] if current_kernel.strip() != kernel_normal_list[-1].lstrip('kernel-'): log_fail('Check boot kernel failed') def check_floppy_exist(vmcheck): """ Check if floppy exists after convertion """ blk = vmcheck.session.cmd('lsblk') logging.info(blk) if not re.search('fd0', blk): log_fail('Floppy not found') def attach_removable_media(type, source, dev): bus = {'cdrom': 'ide', 'floppy': 'fdc', 'disk': 'virtio'} args = {'driver': 'qemu', 'subdriver': 'raw', 'sourcetype': 'file', 'type': type, 'targetbus': bus[type]} if type == 'cdrom': args.update({'mode': 'readonly'}) config = '' # Join all options together to get command line for key in list(args.keys()): config += ' --%s %s' % (key, args[key]) config += ' --current' virsh.attach_disk(vm_name, source, dev, extra=config) def change_disk_bus(dest): """ Change all disks' bus type to $dest """ bus_list = ['ide', 'sata', 'virtio'] if dest not in bus_list: test.error('Bus type not support') dev_prefix = ['h', 's', 'v'] dev_table = dict(list(zip(bus_list, dev_prefix))) logging.info('Change disk bus to %s' % dest) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disks = vmxml.get_disk_all() index = 0 for disk in list(disks.values()): if disk.get('device') != 'disk': continue target = disk.find('target') target.set('bus', dest) target.set('dev', dev_table[dest] + 'd' + string.ascii_lowercase[index]) disk.remove(disk.find('address')) index += 1 vmxml.sync() def change_network_model(model): """ Change network model to $model """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) network_list = vmxml.get_iface_all() for node in list(network_list.values()): if node.get('type') == 'network': node.find('model').set('type', model) vmxml.sync() def attach_network_card(model): """ Attach network card based on model """ if model not in ('e1000', 'virtio', 'rtl8139'): test.error('Network model not support') options = {'type': 'network', 'source': 'default', 'model': model} line = '' for key in options: line += ' --' + key + ' ' + options[key] line += ' --current' logging.debug(virsh.attach_interface(vm_name, option=line)) def check_multi_netcards(mac_list, virsh_instance): """ Check if number and type of network cards meet expectation """ vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) iflist = vmxml.get_iface_all() logging.debug('MAC list before v2v: %s' % mac_list) logging.debug('MAC list after v2v: %s' % list(iflist.keys())) if set(mac_list).difference(list(iflist.keys())): log_fail('Missing network interface') for mac in iflist: if iflist[mac].find('model').get('type') != 'virtio': log_fail('Network not convert to virtio') @vm_shell def insert_floppy_devicemap(**kwargs): """ Add an entry of floppy to device.map """ session = kwargs['session'] line = '(fd0) /dev/fd0' devmap = '/boot/grub/device.map' if session.cmd_status('ls %s' % devmap): devmap = '/boot/grub2/device.map' cmd_exist = 'grep \'(fd0)\' %s' % devmap cmd_set = 'sed -i \'2i%s\' %s' % (line, devmap) if session.cmd_status(cmd_exist): session.cmd(cmd_set) def make_label(session): """ Label a volume, swap or root volume """ # swaplabel for rhel7 with xfs, e2label for rhel6 or ext* cmd_map = {'root': 'e2label %s ROOT', 'swap': 'swaplabel -L SWAPPER %s'} if not session.cmd_status('swaplabel --help'): blk = 'swap' elif not session.cmd_status('which e2label'): blk = 'root' else: test.error('No tool to make label') entry = session.cmd('blkid|grep %s' % blk).strip() path = entry.split()[0].strip(':') cmd_label = cmd_map[blk] % path if 'LABEL' not in entry: session.cmd(cmd_label) return blk @vm_shell def specify_fstab_entry(type, **kwargs): """ Specify entry in fstab file """ type_list = ['cdrom', 'uuid', 'label', 'sr0', 'invalid'] if type not in type_list: test.error('Not support %s in fstab' % type) session = kwargs['session'] # Specify cdrom device if type == 'cdrom': line = '/dev/cdrom /media/CDROM auto exec' if 'grub2' in utils_misc.get_bootloader_cfg(session): line += ',nofail' line += ' 0 0' logging.debug('fstab entry is "%s"', line) cmd = [ 'mkdir -p /media/CDROM', 'mount /dev/cdrom /media/CDROM', 'echo "%s" >> /etc/fstab' % line ] for i in range(len(cmd)): session.cmd(cmd[i]) elif type == 'sr0': line = params.get('fstab_content') session.cmd('echo "%s" >> /etc/fstab' % line) elif type == 'invalid': line = utils_misc.generate_random_string(6) session.cmd('echo "%s" >> /etc/fstab' % line) else: map = {'uuid': 'UUID', 'label': 'LABEL'} logging.info(type) if session.cmd_status('cat /etc/fstab|grep %s' % map[type]): # Specify device by UUID if type == 'uuid': entry = session.cmd( 'blkid -s UUID|grep swap').strip().split() # Replace path for UUID origin = entry[0].strip(':') replace = entry[1].replace('"', '') # Specify device by label elif type == 'label': blk = make_label(session) entry = session.cmd('blkid|grep %s' % blk).strip() # Remove " from LABEL="****" replace = entry.split()[1].strip().replace('"', '') # Replace the original id/path with label origin = entry.split()[0].strip(':') cmd_fstab = "sed -i 's|%s|%s|' /etc/fstab" % (origin, replace) session.cmd(cmd_fstab) fstab = session.cmd_output('cat /etc/fstab') logging.debug('Content of /etc/fstab:\n%s', fstab) def create_large_file(session, left_space): """ Create a large file to make left space of root less than $left_space MB """ cmd_df = "df -m / --output=avail" df_output = session.cmd(cmd_df).strip() logging.debug('Command output: %s', df_output) avail = int(df_output.strip().split('\n')[-1]) logging.info('Available space: %dM' % avail) if avail > left_space - 1: tmp_dir = data_dir.get_tmp_dir() if session.cmd_status('ls %s' % tmp_dir) != 0: session.cmd('mkdir %s' % tmp_dir) large_file = os.path.join(tmp_dir, 'file.large') cmd_create = 'dd if=/dev/zero of=%s bs=1M count=%d' % \ (large_file, avail - left_space + 2) session.cmd(cmd_create, timeout=v2v_timeout) logging.info('Available space: %sM' % session.cmd(cmd_df).strip()) @vm_shell def corrupt_rpmdb(**kwargs): """ Corrupt rpm db """ session = kwargs['session'] # If __db.* exist, remove them, then touch _db.001 to corrupt db. if not session.cmd_status('ls /var/lib/rpm/__db.001'): session.cmd('rm -f /var/lib/rpm/__db.*') session.cmd('touch /var/lib/rpm/__db.001') if not session.cmd_status('yum update'): test.error('Corrupt rpmdb failed') @vm_shell def grub_serial_terminal(**kwargs): """ Edit the serial and terminal lines of grub.conf """ session = kwargs['session'] vm = kwargs['vm'] grub_file = utils_misc.get_bootloader_cfg(session) if 'grub2' in grub_file: test.cancel('Skip this case on grub2') cmd = "sed -i '1iserial -unit=0 -speed=115200\\n" cmd += "terminal -timeout=10 serial console' %s" % grub_file session.cmd(cmd) @vm_shell def set_selinux(value, **kwargs): """ Set selinux stat of guest """ session = kwargs['session'] current_stat = session.cmd_output('getenforce').strip() logging.debug('Current selinux status: %s', current_stat) if current_stat != value: cmd = "sed -E -i 's/(^SELINUX=).*?/\\1%s/' /etc/selinux/config" % value logging.info('Set selinux stat with command %s', cmd) session.cmd(cmd) @vm_shell def get_firewalld_status(**kwargs): """ Return firewalld service status of vm """ session = kwargs['session'] # Example: Active: active (running) since Fri 2019-03-15 01:03:39 CST; 3min 48s ago firewalld_status = session.cmd('systemctl status firewalld.service|grep Active:', ok_status=[0, 3]).strip() # Exclude the time string because time changes if vm restarts firewalld_status = re.search('Active:\s\w*\s\(\w*\)', firewalld_status).group() logging.info('Status of firewalld: %s', firewalld_status) params[checkpoint] = firewalld_status def check_firewalld_status(vmcheck, expect_status): """ Check if status of firewalld meets expectation """ firewalld_status = vmcheck.session.cmd('systemctl status ' 'firewalld.service|grep Active:', ok_status=[0, 3]).strip() # Exclude the time string because time changes if vm restarts firewalld_status = re.search('Active:\s\w*\s\(\w*\)', firewalld_status).group() logging.info('Status of firewalld after v2v: %s', firewalld_status) if firewalld_status != expect_status: log_fail('Status of firewalld changed after conversion') @vm_shell def vm_cmd(cmd_list, **kwargs): """ Excecute a list of commands on guest. """ session = kwargs['session'] for cmd in cmd_list: logging.info('Send command "%s"', cmd) # 'chronyc waitsync' needs more than 2mins to sync clock, # We set timeout to 300s will not have side-effects for other # commands. status, output = session.cmd_status_output(cmd, timeout=300) logging.debug('Command output:\n%s', output) if status != 0: test.error('Command "%s" failed' % cmd) logging.info('All commands executed') def check_time_keep(vmcheck): """ Check time drift after convertion. """ logging.info('Check time drift') output = vmcheck.session.cmd('chronyc tracking') logging.debug(output) if 'Not synchronised' in output: log_fail('Time not synchronised') lst_offset = re.search('Last offset *?: *(.*) ', output).group(1) drift = abs(float(lst_offset)) logging.debug('Time drift is: %f', drift) if drift > 3: log_fail('Time drift exceeds 3 sec') def check_boot(): """ Check if guest can boot up after configuration """ try: vm = libvirt_vm.VM(vm_name, params, test.bindir, env.get('address_cache')) if vm.is_alive(): vm.shutdown() logging.info('Booting up %s' % vm_name) vm.start() vm.wait_for_login() vm.shutdown() logging.info('%s is down' % vm_name) except Exception as e: test.error('Bootup guest and login failed: %s', str(e)) def check_result(result, status_error): """ Check virt-v2v command result """ utlv.check_exit_status(result, status_error) output = result.stdout + result.stderr if skip_check: logging.info('Skip checking vm after conversion') elif not status_error: if output_mode == 'rhev': if not utils_v2v.import_vm_to_ovirt(params, address_cache, timeout=v2v_timeout): test.fail('Import VM failed') if 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 vmchecker = VMChecker(test, params, env) params['vmchecker'] = vmchecker if params.get('skip_check') != 'yes': ret = vmchecker.run() if len(ret) == 0: logging.info("All common checkpoints passed") vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=vmchecker.virsh_instance) logging.debug(vmxml) if checkpoint == 'multi_kernel': check_boot_kernel(vmchecker.checker) check_vmlinuz_initramfs(output) if checkpoint == 'floppy': # Convert to rhv will remove all removeable devices(floppy, cdrom) if output_mode in ['local', 'libvirt']: check_floppy_exist(vmchecker.checker) if checkpoint == 'multi_disks': check_disks(vmchecker.checker) if checkpoint == 'multi_netcards': check_multi_netcards(params['mac_address'], vmchecker.virsh_instance) if checkpoint.startswith(('spice', 'vnc')): if checkpoint == 'spice_encrypt': vmchecker.check_graphics(params[checkpoint]) else: graph_type = checkpoint.split('_')[0] vmchecker.check_graphics({'type': graph_type}) video_type = vmxml.get_devices('video')[0].model_type if video_type.lower() != 'qxl': log_fail('Video expect QXL, actual %s' % video_type) if checkpoint.startswith('listen'): listen_type = vmxml.get_devices('graphics')[0].listen_type logging.info('listen type is: %s', listen_type) if listen_type != checkpoint.split('_')[-1]: log_fail('listen type changed after conversion') if checkpoint.startswith('selinux'): status = vmchecker.checker.session.cmd( 'getenforce').strip().lower() logging.info('Selinux status after v2v:%s', status) if status != checkpoint[8:]: log_fail('Selinux status not match') if checkpoint == 'guest_firewalld_status': check_firewalld_status(vmchecker.checker, params[checkpoint]) if checkpoint in ['ntpd_on', 'sync_ntp']: check_time_keep(vmchecker.checker) # Merge 2 error lists error_list.extend(vmchecker.errors) log_check = utils_v2v.check_log(params, output) if log_check: log_fail(log_check) if len(error_list): test.fail('%d checkpoints failed: %s' % (len(error_list), error_list)) try: v2v_params = { 'target': target, 'hypervisor': hypervisor, 'main_vm': vm_name, 'input_mode': input_mode, 'network': network, 'bridge': bridge, 'storage': storage, 'hostname': source_ip, 'v2v_opts': v2v_opts, 'new_name': vm_name + utils_misc.generate_random_string(3)} if vpx_dc: v2v_params.update({"vpx_dc": vpx_dc}) if esx_ip: v2v_params.update({"esx_ip": esx_ip}) output_format = params.get('output_format') if output_format: v2v_params.update({'output_format': output_format}) # Build rhev related options if output_mode == 'rhev': # 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_mode == 'local': v2v_params['storage'] = data_dir.get_tmp_dir() if output_mode == 'libvirt': pvt.pre_pool(pool_name, pool_type, pool_target, '') # Set libguestfs environment variable os.environ['LIBGUESTFS_BACKEND'] = 'direct' # Save origin graphic type for result checking if source is KVM if hypervisor == 'kvm': ori_vm_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) params['ori_graphic'] = ori_vm_xml.xmltreefile.find( 'devices').find('graphics').get('type') backup_xml = None # Only kvm guest's xml needs to be backup currently if checkpoint in backup_list and hypervisor == 'kvm': backup_xml = ori_vm_xml if checkpoint == 'multi_disks': new_xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=v2v_virsh) disk_count = 0 for disk in list(new_xml.get_disk_all().values()): if disk.get('device') == 'disk': disk_count += 1 if disk_count <= 1: test.error('Not enough disk devices') params['ori_disks'] = disk_count if checkpoint == 'sata_disk': change_disk_bus('sata') if checkpoint.startswith('floppy'): img_path = data_dir.get_tmp_dir() + '/floppy.img' utlv.create_local_disk('floppy', img_path) attach_removable_media('floppy', img_path, 'fda') if checkpoint == 'floppy_devmap': insert_floppy_devicemap() if checkpoint.startswith('fstab'): if checkpoint == 'fstab_cdrom': img_path = data_dir.get_tmp_dir() + '/cdrom.iso' utlv.create_local_disk('iso', img_path) attach_removable_media('cdrom', img_path, 'hdc') specify_fstab_entry(checkpoint[6:]) if checkpoint == 'running': virsh.start(vm_name) logging.info('VM state: %s' % virsh.domstate(vm_name).stdout.strip()) if checkpoint == 'paused': virsh.start(vm_name, '--paused') logging.info('VM state: %s' % virsh.domstate(vm_name).stdout.strip()) if checkpoint == 'serial_terminal': grub_serial_terminal() check_boot() if checkpoint == 'no_space': @vm_shell def take_space(**kwargs): create_large_file(kwargs['session'], 20) take_space() if checkpoint.startswith('host_no_space'): session = aexpect.ShellSession('sh') create_large_file(session, 1000) if checkpoint == 'host_no_space_setcache': logging.info('Set LIBGUESTFS_CACHEDIR=/home') os.environ['LIBGUESTFS_CACHEDIR'] = '/home' if checkpoint == 'corrupt_rpmdb': corrupt_rpmdb() if checkpoint.startswith('network'): change_network_model(checkpoint[8:]) if checkpoint == 'multi_netcards': params['mac_address'] = [] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=v2v_virsh) network_list = vmxml.get_iface_all() for mac in network_list: if network_list[mac].get('type') in ['bridge', 'network']: params['mac_address'].append(mac) if len(params['mac_address']) < 2: test.error('Not enough network interface') logging.debug('MAC address: %s' % params['mac_address']) if checkpoint.startswith(('spice', 'vnc')): if checkpoint == 'spice_encrypt': spice_passwd = {'type': 'spice', 'passwd': params.get('spice_passwd', 'redhat')} vm_xml.VMXML.set_graphics_attr(vm_name, spice_passwd) params[checkpoint] = {'type': 'spice', 'passwdValidTo': '1970-01-01T00:00:01'} else: graphic_video = checkpoint.split('_') graphic = graphic_video[0] logging.info('Set graphic type to %s', graphic) vm_xml.VMXML.set_graphics_attr(vm_name, {'type': graphic}) if len(graphic_video) > 1: video_type = graphic_video[1] logging.info('Set video type to %s', video_type) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) video = vmxml.xmltreefile.find( 'devices').find('video').find('model') video.set('type', video_type) # cirrus doesn't support 'ram' and 'vgamem' attribute if video_type == 'cirrus': [video.attrib.pop(attr_i) for attr_i in [ 'ram', 'vgamem'] if attr_i in video.attrib] vmxml.sync() if checkpoint.startswith('listen'): listen_type = checkpoint.split('_')[-1] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) listen = vmxml.xmltreefile.find( 'devices').find('graphics').find('listen') listen.set('type', listen_type) vmxml.sync() if checkpoint == 'host_selinux_on': params['selinux_stat'] = utils_selinux.get_status() utils_selinux.set_status('enforcing') if checkpoint.startswith('selinux'): set_selinux(checkpoint[8:]) if checkpoint.startswith('host_firewalld'): service_mgr = service.ServiceManager() logging.info('Backing up firewall services status') params['bk_firewalld_status'] = service_mgr.status('firewalld') if 'start' in checkpoint: service_mgr.start('firewalld') if 'stop' in checkpoint: service_mgr.stop('firewalld') if checkpoint == 'guest_firewalld_status': get_firewalld_status() if checkpoint == 'remove_securetty': logging.info('Remove /etc/securetty file from guest') cmd = ['rm -f /etc/securetty'] vm_cmd(cmd) if checkpoint == 'ntpd_on': logging.info('Set service chronyd on') cmd = ['yum -y install chrony', 'systemctl start chronyd', 'chronyc add server %s' % ntp_server] vm_cmd(cmd) if checkpoint == 'sync_ntp': logging.info('Sync time with %s', ntp_server) cmd = ['yum -y install chrony', 'systemctl start chronyd', 'chronyc add server %s' % ntp_server, 'chronyc waitsync'] vm_cmd(cmd) if checkpoint == 'blank_2nd_disk': disk_path = os.path.join(data_dir.get_tmp_dir(), 'blank.img') logging.info('Create blank disk %s', disk_path) process.run('truncate -s 1G %s' % disk_path) logging.info('Attach blank disk to vm') attach_removable_media('disk', disk_path, 'vdc') logging.debug(virsh.dumpxml(vm_name)) if checkpoint in ['only_net', 'only_br']: logging.info('Detatch all networks') virsh.detach_interface(vm_name, 'network --current', debug=True) logging.info('Detatch all bridges') virsh.detach_interface(vm_name, 'bridge --current', debug=True) if checkpoint == 'only_net': logging.info('Attach network') virsh.attach_interface( vm_name, 'network default --current', debug=True) v2v_params.pop('bridge') if checkpoint == 'only_br': logging.info('Attatch bridge') virsh.attach_interface( vm_name, 'bridge virbr0 --current', debug=True) v2v_params.pop('network') if checkpoint == 'no_libguestfs_backend': os.environ.pop('LIBGUESTFS_BACKEND') if checkpoint == 'file_image': vm = env.get_vm(vm_name) disk = vm.get_first_disk_devices() logging.info('Disk type is %s', disk['type']) if disk['type'] != 'file': test.error('Guest is not with file image') v2v_result = utils_v2v.v2v_cmd(v2v_params) if v2v_params.get('new_name'): vm_name = params['main_vm'] = v2v_params['new_name'] check_result(v2v_result, status_error) finally: if close_virsh: v2v_virsh.close_session() if params.get('vmchecker'): params['vmchecker'].cleanup() if output_mode == 'libvirt': pvt.cleanup_pool(pool_name, pool_type, pool_target, '') if backup_xml: backup_xml.sync() if params.get('selinux_stat') and params['selinux_stat'] != 'disabled': utils_selinux.set_status(params['selinux_stat']) if 'bk_firewalld_status' in params: service_mgr = service.ServiceManager() if service_mgr.status('firewalld') != params['bk_firewalld_status']: if params['bk_firewalld_status']: service_mgr.start('firewalld') else: service_mgr.stop('firewalld') if checkpoint.startswith('host_no_space'): large_file = os.path.join(data_dir.get_tmp_dir(), 'file.large') if os.path.isfile(large_file): os.remove(large_file) # Cleanup constant files utils_v2v.cleanup_constant_files(params)
def run(test, params, env): """ Test DAC in adding nfs pool disk to VM. (1).Init variables for test. (2).Create nfs pool and vol. (3).Attach the nfs pool vol to VM. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("dac_nfs_disk_host_selinux", "enforcing") # Get qemu.conf config variables qemu_user = params.get("qemu_user") qemu_group = params.get("qemu_group") dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about pool vol virt_use_nfs = params.get("virt_use_nfs", "off") nfs_server_dir = params.get("nfs_server_dir", "nfs-server") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") export_options = params.get("export_options", "rw,async,no_root_squash,fsid=0") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format") bk_file_name = params.get("bk_file_name") # Get pool vol variables img_tup = ("img_user", "img_group", "img_mode") img_val = [] for i in img_tup: try: img_val.append(int(params.get(i))) except ValueError: test.cancel("%s value '%s' is not a number." % (i, params.get(i))) # False positive - img_val was filled in the for loop above. # pylint: disable=E0632 img_user, img_group, img_mode = img_val # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() vm_os_xml = vmxml.os # Backup domain disk label disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in list(disks.values()): disk_path = disk['source'] label = check_ownership(disk_path) if label: backup_labels_of_disks[disk_path] = label try: if vm_os_xml.nvram: nvram_path = vm_os_xml.nvram if not os.path.exists(nvram_path): # Need libvirt automatically generate the path vm.start() vm.destroy(gracefully=False) label = check_ownership(nvram_path) if label: backup_labels_of_disks[nvram_path] = label except xcepts.LibvirtXMLNotFoundError: logging.debug("vm xml don't have nvram element") # Backup selinux status of host. backup_sestatus = utils_selinux.get_status() pvt = None snapshot_name = None disk_snap_path = [] qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # chown domain disk to qemu:qemu to avoid fail on local disk for file_path in list(backup_labels_of_disks.keys()): if qemu_user == "root": os.chown(file_path, 0, 0) elif qemu_user == "qemu": os.chown(file_path, 107, 107) else: process.run('chown %s %s' % (qemu_user, file_path), shell=True) # Set selinux of host. if backup_sestatus == "disabled": test.cancel("SELinux is in Disabled mode." "It must be Enabled to" "run this test") utils_selinux.set_status(host_sestatus) # set qemu conf qemu_conf.user = qemu_user qemu_conf.group = qemu_user if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 logging.debug("the qemu.conf content is: %s", qemu_conf) libvirtd.restart() # Create dst pool for create attach vol img logging.debug("export_options is: %s", export_options) pvt = utlv.PoolVolumeTest(test, params) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"], export_options=export_options) # set virt_use_nfs result = process.run("setsebool virt_use_nfs %s" % virt_use_nfs, shell=True) if result.exit_status: test.cancel("Failed to set virt_use_nfs value") # Init a QemuImg instance and create img on nfs server dir. params['image_name'] = vol_name tmp_dir = test.tmpdir nfs_path = os.path.join(tmp_dir, nfs_server_dir) image = qemu_storage.QemuImg(params, nfs_path, vol_name) # Create a image. server_img_path, result = image.create(params) if params.get("image_name_backing_file"): params['image_name'] = bk_file_name params['has_backing_file'] = "yes" image = qemu_storage.QemuImg(params, nfs_path, bk_file_name) server_img_path, result = image.create(params) # Get vol img path vol_name = server_img_path.split('/')[-1] virsh.pool_refresh(pool_name, debug=True) cmd_result = virsh.vol_path(vol_name, pool_name, debug=True) if cmd_result.exit_status: test.cancel("Failed to get volume path from pool.") img_path = cmd_result.stdout.strip() # Do the attach action. extra = "--persistent --subdriver qcow2" result = virsh.attach_disk(vm_name, source=img_path, target="vdf", extra=extra, debug=True) if result.exit_status: test.fail("Failed to attach disk %s to VM." "Detail: %s." % (img_path, result.stderr)) # Change img ownership and mode on nfs server dir os.chown(server_img_path, img_user, img_group) os.chmod(server_img_path, img_mode) img_label_before = check_ownership(server_img_path) if img_label_before: logging.debug( "attached image ownership on nfs server before " "start: %s", img_label_before) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. img_label_after = check_ownership(server_img_path) if img_label_after: logging.debug( "attached image ownership on nfs server after" " start: %s", img_label_after) if status_error: test.fail('Test succeeded in negative case.') except virt_vm.VMStartError as e: # Starting VM failed. if not status_error: test.fail("Test failed in positive case." "error: %s" % e) if params.get("image_name_backing_file"): options = "--disk-only" snapshot_result = virsh.snapshot_create(vm_name, options, debug=True) if snapshot_result.exit_status: if not status_error: test.fail("Failed to create snapshot. Error:%s." % snapshot_result.stderr.strip()) snapshot_name = re.search("\d+", snapshot_result.stdout.strip()).group(0) if snapshot_name: disks_snap = vm.get_disk_devices() for disk in list(disks_snap.values()): disk_snap_path.append(disk['source']) virsh.snapshot_delete(vm_name, snapshot_name, "--metadata", debug=True) try: virsh.detach_disk(vm_name, target="vdf", extra="--persistent", debug=True) except process.CmdError: test.fail("Detach disk 'vdf' from VM %s failed." % vm.name) finally: # clean up vm.destroy() qemu_conf.restore() for path, label in list(backup_labels_of_disks.items()): label_list = label.split(":") os.chown(path, int(label_list[0]), int(label_list[1])) if snapshot_name: backup_xml.sync("--snapshots-metadata") else: backup_xml.sync() for i in disk_snap_path: if i and os.path.exists(i): os.unlink(i) if pvt: try: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_image) except test.fail as detail: logging.error(str(detail)) utils_selinux.set_status(backup_sestatus) libvirtd.restart()
def run(test, params, env): """ Test DAC in save/restore domain to nfs pool. (1).Init variables for test. (2).Create nfs pool (3).Start VM and check result. (4).Save domain to the nfs pool. (5).Restore domain from the nfs file. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("dac_nfs_save_restore_host_selinux", "enforcing") # Get qemu.conf config variables qemu_user = params.get("qemu_user") qemu_group = params.get("qemu_group") dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about pool vol virt_use_nfs = params.get("virt_use_nfs", "off") nfs_server_dir = params.get("nfs_server_dir", "nfs-server") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") export_options = params.get("export_options", "rw,async,no_root_squash") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format") bk_file_name = params.get("bk_file_name") # Get pool file variables pre_file = "yes" == params.get("pre_file", "yes") pre_file_name = params.get("pre_file_name", "dac_nfs_file") file_tup = ("file_user", "file_group", "file_mode") file_val = [] for i in file_tup: try: file_val.append(int(params.get(i))) except ValueError: raise error.TestNAError("%s value '%s' is not a number." % (i, params.get(i))) file_user, file_group, file_mode = file_val # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Backup domain disk label disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] f = os.open(disk_path, 0) stat_re = os.fstat(f) backup_labels_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) # Backup selinux status of host. backup_sestatus = utils_selinux.get_status() pvt = None qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # chown domain disk mode to avoid fail on local disk for disk in disks.values(): disk_path = disk['source'] if qemu_user == "root": os.chown(disk_path, 0, 0) elif qemu_user == "qemu": os.chown(disk_path, 107, 107) # Set selinux of host. utils_selinux.set_status(host_sestatus) # set qemu conf qemu_conf.user = qemu_user qemu_conf.group = qemu_user if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Create dst pool for save/restore logging.debug("export_options is: %s" % export_options) pvt = utlv.PoolVolumeTest(test, params) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"], export_options=export_options) # Set virt_use_nfs result = utils.run("setsebool virt_use_nfs %s" % virt_use_nfs) if result.exit_status: raise error.TestNAError("Failed to set virt_use_nfs value") # Create a file on nfs server dir. tmp_dir = data_dir.get_tmp_dir() nfs_path = os.path.join(tmp_dir, nfs_server_dir) server_file_path = os.path.join(nfs_path, pre_file_name) if pre_file and not os.path.exists(server_file_path): open(server_file_path, 'a').close() if not pre_file and os.path.exists(server_file_path): raise error.TestNAError("File %s already exist in pool %s" % (server_file_path, pool_name)) # Get nfs mount file path mnt_path = os.path.join(tmp_dir, pool_target) mnt_file_path = os.path.join(mnt_path, pre_file_name) # Change img ownership and mode on nfs server dir if pre_file: os.chown(server_file_path, file_user, file_group) os.chmod(server_file_path, file_mode) # Start VM. try: vm.start() # Start VM successfully. except virt_vm.VMStartError, e: # Starting VM failed. raise error.TestFail("Domain failed to start. " "error: %s" % e) label_before = check_ownership(server_file_path) if label_before: logging.debug("file ownership on nfs server before save: %s" % label_before) # Save domain to nfs pool file save_re = virsh.save(vm_name, mnt_file_path, debug=True) if save_re.exit_status: if not status_error: raise error.TestFail("Failed to save domain to nfs pool file.") else: if status_error: raise error.TestFail("Save domain to nfs pool file succeeded, " "expected Fail.") label_after = check_ownership(server_file_path) if label_after: logging.debug("file ownership on nfs server after save: %s" % label_after) # Restore domain from the nfs pool file if not save_re.exit_status: restore_re = virsh.restore(mnt_file_path, debug=True) if restore_re.exit_status: if not status_error: raise error.TestFail("Failed to restore domain from nfs " "pool file.") else: if status_error: raise error.TestFail("Restore domain from nfs pool file " "succeeded, expected Fail.") label_after_rs = check_ownership(server_file_path) if label_after_rs: logging.debug( "file ownership on nfs server after restore: %s" % label_after_rs)
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Create a image to attached to VM. (3).Attach disk. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_attach_disk_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_attach_disk_vm_sec_type", "dynamic") sec_model = params.get("svirt_attach_disk_vm_sec_model", "selinux") sec_label = params.get("svirt_attach_disk_vm_sec_label", None) sec_relabel = params.get("svirt_attach_disk_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} disk_seclabel = params.get("disk_seclabel", "no") # Get variables about pool vol with_pool_vol = 'yes' == params.get("with_pool_vol", "no") check_cap_rawio = "yes" == params.get("check_cap_rawio", "no") virt_use_nfs = params.get("virt_use_nfs", "off") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format", "qcow2") device_target = params.get("disk_target") device_bus = params.get("disk_target_bus") device_type = params.get("device_type", "file") # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_attach_disk_disk_label') sec_disk_dict = {'model': sec_model, 'label': img_label, 'relabel': sec_relabel} enable_namespace = 'yes' == params.get('enable_namespace', 'no') img_name = "svirt_disk" # Default label for the other disks. # To ensure VM is able to access other disks. default_label = params.get('svirt_attach_disk_disk_default_label', None) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the default label to other disks of vm. disks = vm.get_disk_devices() for disk in list(disks.values()): utils_selinux.set_context_of_file(filename=disk['source'], context=default_label) pvt = None qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() disk_xml = Disk(type_name=device_type) disk_xml.device = "disk" try: # set qemu conf if check_cap_rawio: qemu_conf.user = '******' qemu_conf.group = 'root' logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() if with_pool_vol: # Create dst pool for create attach vol img pvt = utlv.PoolVolumeTest(test, params) logging.debug("pool_type %s" % pool_type) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"]) if pool_type in ["iscsi", "disk"]: # iscsi and disk pool did not support create volume in libvirt, # logical pool could use libvirt to create volume but volume # format is not supported and will be 'raw' as default. pv = libvirt_storage.PoolVolume(pool_name) vols = list(pv.list_volumes().keys()) vol_format = "raw" if vols: vol_name = vols[0] else: test.cancel("No volume in pool: %s" % pool_name) else: vol_arg = {'name': vol_name, 'format': vol_format, 'capacity': 1073741824, 'allocation': 1048576, } # Set volume xml file volxml = libvirt_xml.VolXML() newvol = volxml.new_vol(**vol_arg) vol_xml = newvol['xml'] # Run virsh_vol_create to create vol logging.debug("create volume from xml: %s" % newvol.xmltreefile) cmd_result = virsh.vol_create(pool_name, vol_xml, ignore_status=True, debug=True) if cmd_result.exit_status: test.cancel("Failed to create attach volume.") cmd_result = virsh.vol_path(vol_name, pool_name, debug=True) if cmd_result.exit_status: test.cancel("Failed to get volume path from pool.") img_path = cmd_result.stdout.strip() if pool_type in ["iscsi", "disk"]: source_type = "dev" if pool_type == "iscsi": disk_xml.device = "lun" disk_xml.rawio = "yes" else: if not enable_namespace: qemu_conf.namespaces = '' logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() else: source_type = "file" # set host_sestatus as nfs pool will reset it utils_selinux.set_status(host_sestatus) # set virt_use_nfs result = process.run("setsebool virt_use_nfs %s" % virt_use_nfs, shell=True) if result.exit_status: test.cancel("Failed to set virt_use_nfs value") else: source_type = "file" # Init a QemuImg instance. params['image_name'] = img_name tmp_dir = data_dir.get_tmp_dir() image = qemu_storage.QemuImg(params, tmp_dir, img_name) # Create a image. img_path, result = image.create(params) # Set the context of the image. if sec_relabel == "no": utils_selinux.set_context_of_file(filename=img_path, context=img_label) disk_xml.target = {"dev": device_target, "bus": device_bus} disk_xml.driver = {"name": "qemu", "type": vol_format} if disk_seclabel == "yes": source_seclabel = [] sec_xml = seclabel.Seclabel() sec_xml.update(sec_disk_dict) source_seclabel.append(sec_xml) disk_source = disk_xml.new_disk_source(**{"attrs": {source_type: img_path}, "seclabels": source_seclabel}) else: disk_source = disk_xml.new_disk_source(**{"attrs": {source_type: img_path}}) # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() disk_xml.source = disk_source logging.debug(disk_xml) # Do the attach action. cmd_result = virsh.attach_device(domainarg=vm_name, filearg=disk_xml.xml, flagstr='--persistent') libvirt.check_exit_status(cmd_result, expect_error=False) logging.debug("the domain xml is: %s" % vmxml.xmltreefile) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with set seclabel can access the image with the # set context. if status_error: test.fail('Test succeeded in negative case.') if check_cap_rawio: cap_list = ['CapPrm', 'CapEff', 'CapBnd'] cap_dict = {} pid = vm.get_pid() pid_status_path = "/proc/%s/status" % pid with open(pid_status_path) as f: for line in f: val_list = line.split(":") if val_list[0] in cap_list: cap_dict[val_list[0]] = int(val_list[1].strip(), 16) # bit and with rawio capabilitiy value to check cap_sys_rawio # is set cap_rawio_val = 0x0000000000020000 for i in cap_list: if not cap_rawio_val & cap_dict[i]: err_msg = "vm process with %s: 0x%x" % (i, cap_dict[i]) err_msg += " lack cap_sys_rawio capabilities" test.fail(err_msg) else: inf_msg = "vm process with %s: 0x%x" % (i, cap_dict[i]) inf_msg += " have cap_sys_rawio capabilities" logging.debug(inf_msg) if pool_type == "disk": if libvirt_version.version_compare(3, 1, 0) and enable_namespace: vm_pid = vm.get_pid() output = process.system_output( "nsenter -t %d -m -- ls -Z %s" % (vm_pid, img_path)) else: output = process.system_output('ls -Z %s' % img_path) logging.debug("The default label is %s", default_label) logging.debug("The label after guest started is %s", astring.to_text(output.strip().split()[-2])) if default_label not in astring.to_text(output.strip().split()[-2]): test.fail("The label is wrong after guest started\n") except virt_vm.VMStartError as e: # Starting VM failed. # VM with set seclabel can not access the image with the # set context. if not status_error: test.fail("Test failed in positive case." "error: %s" % e) cmd_result = virsh.detach_device(domainarg=vm_name, filearg=disk_xml.xml) libvirt.check_exit_status(cmd_result, status_error) finally: # clean up vm.destroy() if not with_pool_vol: image.remove() if pvt: try: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_image) except exceptions.TestFail as detail: logging.error(str(detail)) backup_xml.sync() utils_selinux.set_status(backup_sestatus) if check_cap_rawio: qemu_conf.restore() libvirtd.restart()
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Config qemu conf if need (3).Label the VM and disk with proper label. (4).Start VM and check the context. (5).Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_start_destroy_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_start_destroy_vm_sec_type", "dynamic") sec_model = params.get("svirt_start_destroy_vm_sec_model", "selinux") sec_label = params.get("svirt_start_destroy_vm_sec_label", None) security_driver = params.get("security_driver", None) security_default_confined = params.get("security_default_confined", None) security_require_confined = params.get("security_require_confined", None) no_sec_model = 'yes' == params.get("no_sec_model", 'no') sec_relabel = params.get("svirt_start_destroy_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'relabel': sec_relabel} sec_dict_list = [] if not no_sec_model: if "," in sec_model: sec_models = sec_model.split(",") for model in sec_models: sec_dict['model'] = model if sec_type != "none": sec_dict['label'] = sec_label sec_dict_copy = sec_dict.copy() sec_dict_list.append(sec_dict_copy) else: sec_dict['model'] = sec_model if sec_type != "none": sec_dict['label'] = sec_label sec_dict_list.append(sec_dict) else: sec_dict_list.append(sec_dict) logging.debug("sec_dict_list is: %s" % sec_dict_list) poweroff_with_destroy = ("destroy" == params.get( "svirt_start_destroy_vm_poweroff", "destroy")) # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_start_destroy_disk_label') # Backup disk Labels. disks = vm.get_disk_devices() backup_labels_of_disks = {} backup_ownership_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) f = os.open(disk_path, 0) stat_re = os.fstat(f) backup_ownership_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) # Backup selinux of host. backup_sestatus = utils_selinux.get_status() qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # Set disk label for disk in disks.values(): disk_path = disk['source'] utils_selinux.set_context_of_file(filename=disk_path, context=img_label) os.chown(disk_path, 107, 107) # Set selinux of host. utils_selinux.set_status(host_sestatus) # Set qemu conf if security_driver: qemu_conf.set_string('security_driver', security_driver) if security_default_confined: qemu_conf.security_default_confined = security_default_confined if security_require_confined: qemu_conf.security_require_confined = security_require_confined if (security_driver or security_default_confined or security_require_confined): logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Set the context of the VM. vmxml.set_seclabel(sec_dict_list) vmxml.sync() logging.debug("the domain xml is: %s" % vmxml.xmltreefile) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with seclabel can access the image with the context. if status_error: raise error.TestFail("Test succeeded in negative case.") # Check the label of VM and image when VM is running. vm_context = utils_selinux.get_context_of_process(vm.get_pid()) if (sec_type == "static") and (not vm_context == sec_label): raise error.TestFail("Label of VM is not expected after " "starting.\n" "Detail: vm_context=%s, sec_label=%s" % (vm_context, sec_label)) disk_context = utils_selinux.get_context_of_file( filename=disks.values()[0]['source']) if (sec_relabel == "no") and (not disk_context == img_label): raise error.TestFail("Label of disk is not expected after VM " "starting.\n" "Detail: disk_context=%s, img_label=%s." % (disk_context, img_label)) if sec_relabel == "yes" and not no_sec_model: vmxml = VMXML.new_from_dumpxml(vm_name) imagelabel = vmxml.get_seclabel()[0]['imagelabel'] if not disk_context == imagelabel: raise error.TestFail("Label of disk is not relabeled by " "VM\nDetal: disk_context=" "%s, imagelabel=%s" % (disk_context, imagelabel)) # Check the label of disk after VM being destroyed. if poweroff_with_destroy: vm.destroy(gracefully=False) else: vm.wait_for_login() vm.shutdown() img_label_after = utils_selinux.get_context_of_file( filename=disks.values()[0]['source']) if (not img_label_after == img_label): # Bug 547546 - RFE: the security drivers must remember original # permissions/labels and restore them after # https://bugzilla.redhat.com/show_bug.cgi?id=547546 err_msg = "Label of disk is not restored in VM shuting down.\n" err_msg += "Detail: img_label_after=%s, " % img_label_after err_msg += "img_label_before=%s.\n" % img_label err_msg += "More info in https://bugzilla.redhat.com/show_bug" err_msg += ".cgi?id=547546" raise error.TestFail(err_msg) except virt_vm.VMStartError, e: # Starting VM failed. # VM with seclabel can not access the image with the context. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up for path, label in backup_labels_of_disks.items(): utils_selinux.set_context_of_file(filename=path, context=label) for path, label in backup_ownership_of_disks.items(): label_list = label.split(":") os.chown(path, int(label_list[0]), int(label_list[1])) backup_xml.sync() utils_selinux.set_status(backup_sestatus) if (security_driver or security_default_confined or security_require_confined): qemu_conf.restore() libvirtd.restart()
def run(test, params, env): """ Test DAC in adding nfs pool disk to VM. (1).Init variables for test. (2).Create nfs pool and vol. (3).Attach the nfs pool vol to VM. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("dac_nfs_disk_host_selinux", "enforcing") # Get qemu.conf config variables qemu_user = params.get("qemu_user") qemu_group = params.get("qemu_group") dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about pool vol virt_use_nfs = params.get("virt_use_nfs", "off") nfs_server_dir = params.get("nfs_server_dir", "nfs-server") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") export_options = params.get("export_options", "rw,async,no_root_squash") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format") bk_file_name = params.get("bk_file_name") # Get pool vol variables img_tup = ("img_user", "img_group", "img_mode") img_val = [] for i in img_tup: try: img_val.append(int(params.get(i))) except ValueError: test.cancel("%s value '%s' is not a number." % (i, params.get(i))) # False positive - img_val was filled in the for loop above. # pylint: disable=E0632 img_user, img_group, img_mode = img_val # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() vm_os_xml = vmxml.os # Backup domain disk label disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in list(disks.values()): disk_path = disk['source'] label = check_ownership(disk_path) if label: backup_labels_of_disks[disk_path] = label try: if vm_os_xml.nvram: nvram_path = vm_os_xml.nvram if not os.path.exists(nvram_path): # Need libvirt automatically generate the path vm.start() vm.destroy(gracefully=False) label = check_ownership(nvram_path) if label: backup_labels_of_disks[nvram_path] = label except xcepts.LibvirtXMLNotFoundError: logging.debug("vm xml don't have nvram element") # Backup selinux status of host. backup_sestatus = utils_selinux.get_status() pvt = None snapshot_name = None disk_snap_path = [] qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # chown domain disk to qemu:qemu to avoid fail on local disk for file_path in list(backup_labels_of_disks.keys()): if qemu_user == "root": os.chown(file_path, 0, 0) elif qemu_user == "qemu": os.chown(file_path, 107, 107) else: process.run('chown %s %s' % (qemu_user, file_path), shell=True) # Set selinux of host. if backup_sestatus == "disabled": test.cancel("SELinux is in Disabled mode." "It must be Enabled to" "run this test") utils_selinux.set_status(host_sestatus) # set qemu conf qemu_conf.user = qemu_user qemu_conf.group = qemu_user if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 logging.debug("the qemu.conf content is: %s", qemu_conf) libvirtd.restart() # Create dst pool for create attach vol img logging.debug("export_options is: %s", export_options) pvt = utlv.PoolVolumeTest(test, params) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"], export_options=export_options) # set virt_use_nfs result = process.run("setsebool virt_use_nfs %s" % virt_use_nfs, shell=True) if result.exit_status: test.cancel("Failed to set virt_use_nfs value") # Init a QemuImg instance and create img on nfs server dir. params['image_name'] = vol_name tmp_dir = data_dir.get_tmp_dir() nfs_path = os.path.join(tmp_dir, nfs_server_dir) image = qemu_storage.QemuImg(params, nfs_path, vol_name) # Create a image. server_img_path, result = image.create(params) if params.get("image_name_backing_file"): params['image_name'] = bk_file_name params['has_backing_file'] = "yes" image = qemu_storage.QemuImg(params, nfs_path, bk_file_name) server_img_path, result = image.create(params) # Get vol img path vol_name = server_img_path.split('/')[-1] virsh.pool_refresh(pool_name, debug=True) cmd_result = virsh.vol_path(vol_name, pool_name, debug=True) if cmd_result.exit_status: test.cancel("Failed to get volume path from pool.") img_path = cmd_result.stdout.strip() # Do the attach action. extra = "--persistent --subdriver qcow2" result = virsh.attach_disk(vm_name, source=img_path, target="vdf", extra=extra, debug=True) if result.exit_status: test.fail("Failed to attach disk %s to VM." "Detail: %s." % (img_path, result.stderr)) # Change img ownership and mode on nfs server dir os.chown(server_img_path, img_user, img_group) os.chmod(server_img_path, img_mode) img_label_before = check_ownership(server_img_path) if img_label_before: logging.debug("attached image ownership on nfs server before " "start: %s", img_label_before) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. img_label_after = check_ownership(server_img_path) if img_label_after: logging.debug("attached image ownership on nfs server after" " start: %s", img_label_after) if status_error: test.fail('Test succeeded in negative case.') except virt_vm.VMStartError as e: # Starting VM failed. if not status_error: test.fail("Test failed in positive case." "error: %s" % e) if params.get("image_name_backing_file"): options = "--disk-only" snapshot_result = virsh.snapshot_create(vm_name, options, debug=True) if snapshot_result.exit_status: if not status_error: test.fail("Failed to create snapshot. Error:%s." % snapshot_result.stderr.strip()) snapshot_name = re.search( "\d+", snapshot_result.stdout.strip()).group(0) if snapshot_name: disks_snap = vm.get_disk_devices() for disk in list(disks_snap.values()): disk_snap_path.append(disk['source']) virsh.snapshot_delete(vm_name, snapshot_name, "--metadata", debug=True) try: virsh.detach_disk(vm_name, target="vdf", extra="--persistent", debug=True) except process.CmdError: test.fail("Detach disk 'vdf' from VM %s failed." % vm.name) finally: # clean up vm.destroy() qemu_conf.restore() for path, label in list(backup_labels_of_disks.items()): label_list = label.split(":") os.chown(path, int(label_list[0]), int(label_list[1])) if snapshot_name: backup_xml.sync("--snapshots-metadata") else: backup_xml.sync() for i in disk_snap_path: if i and os.path.exists(i): os.unlink(i) if pvt: try: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_image) except test.fail as detail: logging.error(str(detail)) utils_selinux.set_status(backup_sestatus) libvirtd.restart()
def run(test, params, env): """ Test DAC in save/restore domain to nfs pool. (1).Init variables for test. (2).Create nfs pool (3).Start VM and check result. (4).Save domain to the nfs pool. (5).Restore domain from the nfs file. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("dac_nfs_save_restore_host_selinux", "enforcing") # Get qemu.conf config variables qemu_user = params.get("qemu_user") qemu_group = params.get("qemu_group") dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about pool vol virt_use_nfs = params.get("virt_use_nfs", "off") nfs_server_dir = params.get("nfs_server_dir", "nfs-server") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") export_options = params.get("export_options", "rw,async,no_root_squash") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format") bk_file_name = params.get("bk_file_name") # Get pool file variables pre_file = "yes" == params.get("pre_file", "yes") pre_file_name = params.get("pre_file_name", "dac_nfs_file") file_tup = ("file_user", "file_group", "file_mode") file_val = [] for i in file_tup: try: file_val.append(int(params.get(i))) except ValueError: test.cancel("%s value '%s' is not a number." % (i, params.get(i))) # False positive - file_val was filled in the for loop above. # pylint: disable=E0632 file_user, file_group, file_mode = file_val # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Backup domain disk label disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in list(disks.values()): disk_path = disk['source'] f = os.open(disk_path, 0) stat_re = os.fstat(f) backup_labels_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) # Backup selinux status of host. backup_sestatus = utils_selinux.get_status() pvt = None qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # chown domain disk mode to avoid fail on local disk for disk in list(disks.values()): disk_path = disk['source'] if qemu_user == "root": os.chown(disk_path, 0, 0) elif qemu_user == "qemu": os.chown(disk_path, 107, 107) # Set selinux of host. utils_selinux.set_status(host_sestatus) # set qemu conf qemu_conf.user = qemu_user qemu_conf.group = qemu_user if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Create dst pool for save/restore logging.debug("export_options is: %s" % export_options) pvt = utlv.PoolVolumeTest(test, params) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"], export_options=export_options) # Set virt_use_nfs result = process.run("setsebool virt_use_nfs %s" % virt_use_nfs, shell=True) if result.exit_status: test.cancel("Failed to set virt_use_nfs value") # Create a file on nfs server dir. tmp_dir = data_dir.get_tmp_dir() nfs_path = os.path.join(tmp_dir, nfs_server_dir) server_file_path = os.path.join(nfs_path, pre_file_name) if pre_file and not os.path.exists(server_file_path): open(server_file_path, 'a').close() if not pre_file and os.path.exists(server_file_path): test.cancel("File %s already exist in pool %s" % (server_file_path, pool_name)) # Get nfs mount file path mnt_path = os.path.join(tmp_dir, pool_target) mnt_file_path = os.path.join(mnt_path, pre_file_name) # Change img ownership and mode on nfs server dir if pre_file: os.chown(server_file_path, file_user, file_group) os.chmod(server_file_path, file_mode) # Start VM. try: vm.start() # Start VM successfully. except virt_vm.VMStartError as e: # Starting VM failed. test.fail("Domain failed to start. " "error: %s" % e) label_before = check_ownership(server_file_path) if label_before: logging.debug("file ownership on nfs server before save: %s" % label_before) # Save domain to nfs pool file save_re = virsh.save(vm_name, mnt_file_path, debug=True) if save_re.exit_status: if not status_error: test.fail("Failed to save domain to nfs pool file.") else: if status_error: test.fail("Save domain to nfs pool file succeeded, " "expected Fail.") label_after = check_ownership(server_file_path) if label_after: logging.debug("file ownership on nfs server after save: %s" % label_after) # Restore domain from the nfs pool file if not save_re.exit_status: restore_re = virsh.restore(mnt_file_path, debug=True) if restore_re.exit_status: if not status_error: test.fail("Failed to restore domain from nfs " "pool file.") else: if status_error: test.fail("Restore domain from nfs pool file " "succeeded, expected Fail.") label_after_rs = check_ownership(server_file_path) if label_after_rs: logging.debug("file ownership on nfs server after restore: %s" % label_after_rs) finally: # clean up for path, label in list(backup_labels_of_disks.items()): label_list = label.split(":") os.chown(path, int(label_list[0]), int(label_list[1])) if pvt: try: pvt.cleanup_pool(pool_name, pool_type, pool_target, emulated_image) except exceptions.TestFail as detail: logging.error(str(detail)) utils_selinux.set_status(backup_sestatus) qemu_conf.restore() libvirtd.restart()
def run(test, params, env): """ Test DAC in adding nfs pool disk to VM. (1).Init variables for test. (2).Create nfs pool and vol. (3).Attach the nfs pool vol to VM. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("dac_nfs_disk_host_selinux", "enforcing") # Get qemu.conf config variables qemu_user = params.get("qemu_user") qemu_group = params.get("qemu_group") dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about pool vol virt_use_nfs = params.get("virt_use_nfs", "off") nfs_server_dir = params.get("nfs_server_dir", "nfs-server") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") export_options = params.get("export_options", "rw,async,no_root_squash") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format") bk_file_name = params.get("bk_file_name") # Get pool vol variables img_tup = ("img_user", "img_group", "img_mode") img_val = [] for i in img_tup: try: img_val.append(int(params.get(i))) except ValueError: raise error.TestNAError("%s value '%s' is not a number." % (i, params.get(i))) img_user, img_group, img_mode = img_val # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Backup domain disk label disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] f = os.open(disk_path, 0) stat_re = os.fstat(f) backup_labels_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) # Backup selinux status of host. backup_sestatus = utils_selinux.get_status() pvt = None snapshot_name = None qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # chown domain disk to qemu:qemu to avoid fail on local disk for disk in disks.values(): disk_path = disk['source'] if qemu_user == "root": os.chown(disk_path, 0, 0) elif qemu_user == "qemu": os.chown(disk_path, 107, 107) # Set selinux of host. utils_selinux.set_status(host_sestatus) # set qemu conf qemu_conf.user = qemu_user qemu_conf.group = qemu_user if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Create dst pool for create attach vol img logging.debug("export_options is: %s" % export_options) pvt = utlv.PoolVolumeTest(test, params) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"], export_options=export_options) # set virt_use_nfs result = utils.run("setsebool virt_use_nfs %s" % virt_use_nfs) if result.exit_status: raise error.TestNAError("Failed to set virt_use_nfs value") # Init a QemuImg instance and create img on nfs server dir. params['image_name'] = vol_name tmp_dir = data_dir.get_tmp_dir() nfs_path = os.path.join(tmp_dir, nfs_server_dir) image = qemu_storage.QemuImg(params, nfs_path, vol_name) # Create a image. server_img_path, result = image.create(params) if params.get("image_name_backing_file"): params['image_name'] = bk_file_name params['has_backing_file'] = "yes" image = qemu_storage.QemuImg(params, nfs_path, bk_file_name) server_img_path, result = image.create(params) # Get vol img path vol_name = server_img_path.split('/')[-1] virsh.pool_refresh(pool_name, debug=True) cmd_result = virsh.vol_path(vol_name, pool_name, debug=True) if cmd_result.exit_status: raise error.TestNAError("Failed to get volume path from pool.") img_path = cmd_result.stdout.strip() # Do the attach action. extra = "--persistent --subdriver qcow2" result = virsh.attach_disk(vm_name, source=img_path, target="vdf", extra=extra, debug=True) if result.exit_status: raise error.TestFail("Failed to attach disk %s to VM." "Detail: %s." % (img_path, result.stderr)) # Change img ownership and mode on nfs server dir os.chown(server_img_path, img_user, img_group) os.chmod(server_img_path, img_mode) img_label_before = check_ownership(server_img_path) if img_label_before: logging.debug("attached image ownership on nfs server before " "start: %s" % img_label_before) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. img_label_after = check_ownership(server_img_path) if img_label_after: logging.debug("attached image ownership on nfs server after" " start: %s" % img_label_after) if status_error: raise error.TestFail('Test succeeded in negative case.') except virt_vm.VMStartError, e: # Starting VM failed. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) if params.get("image_name_backing_file"): options = "--disk-only" snapshot_result = virsh.snapshot_create(vm_name, options, debug=True) if snapshot_result.exit_status: if not status_error: raise error.TestFail( "Failed to create snapshot. Error:%s." % snapshot_result.stderr.strip()) snapshot_name = re.search("\d+", snapshot_result.stdout.strip()).group(0) if snapshot_name: virsh.snapshot_delete(vm_name, snapshot_name, "--metadata", debug=True) try: virsh.detach_disk(vm_name, target="vdf", extra="--persistent", debug=True) except error.CmdError: raise error.TestFail("Detach disk 'vdf' from VM %s failed." % vm.name)
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Create a image to attached to VM. (3).Attach disk. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_attach_disk_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_attach_disk_vm_sec_type", "dynamic") sec_model = params.get("svirt_attach_disk_vm_sec_model", "selinux") sec_label = params.get("svirt_attach_disk_vm_sec_label", None) sec_relabel = params.get("svirt_attach_disk_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} # Get variables about pool vol with_pool_vol = 'yes' == params.get("with_pool_vol", "no") check_cap_rawio = "yes" == params.get("check_cap_rawio", "no") virt_use_nfs = params.get("virt_use_nfs", "off") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format") # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_attach_disk_disk_label') img_name = "svirt_disk" # Default label for the other disks. # To ensure VM is able to access other disks. default_label = params.get('svirt_attach_disk_disk_default_label', None) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the default label to other disks of vm. disks = vm.get_disk_devices() for disk in disks.values(): utils_selinux.set_context_of_file(filename=disk['source'], context=default_label) pvt = None qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # set qemu conf if check_cap_rawio: qemu_conf.user = '******' qemu_conf.group = 'root' logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() logging.debug("the domain xml is: %s" % vmxml.xmltreefile) if with_pool_vol: # Create dst pool for create attach vol img pvt = utlv.PoolVolumeTest(test, params) logging.debug("pool_type %s" % pool_type) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"]) if pool_type in ["iscsi", "disk"]: # iscsi and disk pool did not support create volume in libvirt, # logical pool could use libvirt to create volume but volume # format is not supported and will be 'raw' as default. pv = libvirt_storage.PoolVolume(pool_name) vols = pv.list_volumes().keys() if vols: vol_name = vols[0] else: raise error.TestNAError("No volume in pool: %s" % pool_name) else: vol_arg = {'name': vol_name, 'format': vol_format, 'capacity': 1073741824, 'allocation': 1048576, } # Set volume xml file volxml = libvirt_xml.VolXML() newvol = volxml.new_vol(**vol_arg) vol_xml = newvol['xml'] # Run virsh_vol_create to create vol logging.debug("create volume from xml: %s" % newvol.xmltreefile) cmd_result = virsh.vol_create(pool_name, vol_xml, ignore_status=True, debug=True) if cmd_result.exit_status: raise error.TestNAError("Failed to create attach volume.") cmd_result = virsh.vol_path(vol_name, pool_name, debug=True) if cmd_result.exit_status: raise error.TestNAError("Failed to get volume path from pool.") img_path = cmd_result.stdout.strip() if pool_type in ["iscsi", "disk"]: extra = "--driver qemu --type lun --rawio --persistent" else: extra = "--persistent --subdriver qcow2" # set host_sestatus as nfs pool will reset it utils_selinux.set_status(host_sestatus) # set virt_use_nfs result = utils.run("setsebool virt_use_nfs %s" % virt_use_nfs) if result.exit_status: raise error.TestNAError("Failed to set virt_use_nfs value") else: # Init a QemuImg instance. params['image_name'] = img_name tmp_dir = data_dir.get_tmp_dir() image = qemu_storage.QemuImg(params, tmp_dir, img_name) # Create a image. img_path, result = image.create(params) # Set the context of the image. utils_selinux.set_context_of_file(filename=img_path, context=img_label) extra = "--persistent" # Do the attach action. result = virsh.attach_disk(vm_name, source=img_path, target="vdf", extra=extra, debug=True) if result.exit_status: raise error.TestFail("Failed to attach disk %s to VM." "Detail: %s." % (img_path, result.stderr)) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with set seclabel can access the image with the # set context. if status_error: raise error.TestFail('Test succeeded in negative case.') if check_cap_rawio: cap_list = ['CapPrm', 'CapEff', 'CapBnd'] cap_dict = {} pid = vm.get_pid() pid_status_path = "/proc/%s/status" % pid with open(pid_status_path) as f: for line in f: val_list = line.split(":") if val_list[0] in cap_list: cap_dict[val_list[0]] = int(val_list[1].strip(), 16) # bit and with rawio capabilitiy value to check cap_sys_rawio # is set cap_rawio_val = 0x0000000000020000 for i in cap_list: if not cap_rawio_val & cap_dict[i]: err_msg = "vm process with %s: 0x%x" % (i, cap_dict[i]) err_msg += " lack cap_sys_rawio capabilities" raise error.TestFail(err_msg) else: inf_msg = "vm process with %s: 0x%x" % (i, cap_dict[i]) inf_msg += " have cap_sys_rawio capabilities" logging.debug(inf_msg) except virt_vm.VMStartError, e: # Starting VM failed. # VM with set seclabel can not access the image with the # set context. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) try: virsh.detach_disk(vm_name, target="vdf", extra="--persistent", debug=True) except error.CmdError: raise error.TestFail("Detach disk 'vdf' from VM %s failed." % vm.name)
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Config qemu conf if need (3).Label the VM and disk with proper label. (4).Start VM and check the context. (5).Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_start_destroy_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_start_destroy_vm_sec_type", "dynamic") sec_model = params.get("svirt_start_destroy_vm_sec_model", "selinux") sec_label = params.get("svirt_start_destroy_vm_sec_label", None) sec_baselabel = params.get("svirt_start_destroy_vm_sec_baselabel", None) security_driver = params.get("security_driver", None) security_default_confined = params.get("security_default_confined", None) security_require_confined = params.get("security_require_confined", None) no_sec_model = 'yes' == params.get("no_sec_model", 'no') sec_relabel = params.get("svirt_start_destroy_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'relabel': sec_relabel} sec_dict_list = [] def _set_sec_model(model): """ Set sec_dict_list base on given sec model type """ sec_dict_copy = sec_dict.copy() sec_dict_copy['model'] = model if sec_type != "none": if sec_type == "dynamic" and sec_baselabel: sec_dict_copy['baselabel'] = sec_baselabel else: sec_dict_copy['label'] = sec_label sec_dict_list.append(sec_dict_copy) if not no_sec_model: if "," in sec_model: sec_models = sec_model.split(",") for model in sec_models: _set_sec_model(model) else: _set_sec_model(sec_model) else: sec_dict_list.append(sec_dict) logging.debug("sec_dict_list is: %s" % sec_dict_list) poweroff_with_destroy = ("destroy" == params.get( "svirt_start_destroy_vm_poweroff", "destroy")) # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_start_destroy_disk_label') # Backup disk Labels. disks = vm.get_disk_devices() backup_labels_of_disks = {} backup_ownership_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) f = os.open(disk_path, 0) stat_re = os.fstat(f) backup_ownership_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) # Backup selinux of host. backup_sestatus = utils_selinux.get_status() qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() def _resolve_label(label_string): labels = label_string.split(":") label_type = labels[2] if len(labels) == 4: label_range = labels[3] elif len(labels) > 4: label_range = "%s:%s" % (labels[3], labels[4]) else: label_range = None return (label_type, label_range) def _check_label_equal(label1, label2): label1s = label1.split(":") label2s = label2.split(":") for i in range(len(label1s)): if label1s[i] != label2s[i]: return False return True try: # Set disk label (img_label_type, img_label_range) = _resolve_label(img_label) for disk in disks.values(): disk_path = disk['source'] dir_path = "%s(/.*)?" % os.path.dirname(disk_path) # Using semanage set context persistently utils_selinux.set_defcon(context_type=img_label_type, pathregex=dir_path, context_range=img_label_range) o_r = utils_selinux.verify_defcon(pathname=disk_path, readonly=False, forcedesc=True) orig_label_type = backup_labels_of_disks[disk_path].split(":")[2] if o_r and (orig_label_type != img_label_type): raise error.TestFail("change disk label(%s) failed" % img_label_type) os.chown(disk_path, 107, 107) # Set selinux of host. utils_selinux.set_status(host_sestatus) # Set qemu conf if security_driver: qemu_conf.set_string('security_driver', security_driver) if security_default_confined: qemu_conf.security_default_confined = security_default_confined if security_require_confined: qemu_conf.security_require_confined = security_require_confined if (security_driver or security_default_confined or security_require_confined): logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Set the context of the VM. vmxml.set_seclabel(sec_dict_list) vmxml.sync() logging.debug("the domain xml is: %s" % vmxml.xmltreefile) # restart libvirtd libvirtd.restart() # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with seclabel can access the image with the context. if status_error: raise error.TestFail("Test succeeded in negative case.") # Check the label of VM and image when VM is running. vm_context = utils_selinux.get_context_of_process(vm.get_pid()) if (sec_type == "static") and (not vm_context == sec_label): raise error.TestFail("Label of VM is not expected after " "starting.\n" "Detail: vm_context=%s, sec_label=%s" % (vm_context, sec_label)) disk_context = utils_selinux.get_context_of_file( filename=disks.values()[0]['source']) if (sec_relabel == "no") and (not disk_context == img_label): raise error.TestFail("Label of disk is not expected after VM " "starting.\n" "Detail: disk_context=%s, img_label=%s." % (disk_context, img_label)) if sec_relabel == "yes" and not no_sec_model: vmxml = VMXML.new_from_dumpxml(vm_name) imagelabel = vmxml.get_seclabel()[0]['imagelabel'] # the disk context is 'system_u:object_r:svirt_image_t:s0', # when VM started, the MLS/MCS Range will be added automatically. # imagelabel turns to be 'system_u:object_r:svirt_image_t:s0:cxx,cxxx' # but we shouldn't check the MCS range. if not _check_label_equal(disk_context, imagelabel): raise error.TestFail("Label of disk is not relabeled by " "VM\nDetal: disk_context=" "%s, imagelabel=%s" % (disk_context, imagelabel)) # Check the label of disk after VM being destroyed. if poweroff_with_destroy: vm.destroy(gracefully=False) else: vm.wait_for_login() vm.shutdown() img_label_after = utils_selinux.get_context_of_file( filename=disks.values()[0]['source']) if (not img_label_after == img_label): # Bug 547546 - RFE: the security drivers must remember original # permissions/labels and restore them after # https://bugzilla.redhat.com/show_bug.cgi?id=547546 err_msg = "Label of disk is not restored in VM shuting down.\n" err_msg += "Detail: img_label_after=%s, " % img_label_after err_msg += "img_label_before=%s.\n" % img_label err_msg += "More info in https://bugzilla.redhat.com/show_bug" err_msg += ".cgi?id=547546" raise error.TestFail(err_msg) except virt_vm.VMStartError, e: # Starting VM failed. # VM with seclabel can not access the image with the context. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up for path, label in backup_labels_of_disks.items(): # Using semanage set context persistently dir_path = "%s(/.*)?" % os.path.dirname(path) (img_label_type, img_label_range) = _resolve_label(label) utils_selinux.set_defcon(context_type=img_label_type, pathregex=dir_path, context_range=img_label_range) utils_selinux.verify_defcon(pathname=path, readonly=False, forcedesc=True) for path, label in backup_ownership_of_disks.items(): label_list = label.split(":") os.chown(path, int(label_list[0]), int(label_list[1])) backup_xml.sync() utils_selinux.set_status(backup_sestatus) if (security_driver or security_default_confined or security_require_confined): qemu_conf.restore() libvirtd.restart()
def run(test, params, env): """ convert specific kvm guest to rhev """ 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: raise ValueError('Missing command: virt-v2v') vm_name = params.get('main_vm', 'EXAMPLE') target = params.get('target') remote_host = params.get('remote_host', 'EXAMPLE') output_mode = params.get('output_mode') output_format = params.get('output_format') output_storage = params.get('output_storage', 'default') bridge = params.get('bridge') network = params.get('network') ntp_server = params.get('ntp_server') address_cache = env.get('address_cache') 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 = utlv.PoolVolumeTest(test, params) v2v_timeout = int(params.get('v2v_timeout', 1200)) skip_check = 'yes' == params.get('skip_check', 'no') status_error = 'yes' == params.get('status_error', 'no') checkpoint = params.get('checkpoint', '') debug_kernel = 'debug_kernel' == checkpoint multi_kernel_list = ['multi_kernel', 'debug_kernel'] backup_list = [ 'virtio_on', 'virtio_off', 'floppy', 'floppy_devmap', 'fstab_cdrom', 'fstab_virtio', 'multi_disks', 'sata_disk', 'network_virtio', 'network_rtl8139', 'network_e1000', 'multi_netcards', 'spice', 'spice_encrypt', 'spice_qxl', 'spice_cirrus', 'vnc_qxl', 'vnc_cirrus', 'blank_2nd_disk', 'listen_none', 'listen_socket', 'only_net', 'only_br' ] error_list = [] def log_fail(msg): """ Log error and update error list """ logging.error(msg) error_list.append(msg) def vm_shell(func): """ Decorator of shell session to vm """ def wrapper(*args, **kwargs): vm = libvirt_vm.VM(vm_name, params, test.bindir, env.get('address_cache')) if vm.is_dead(): logging.info('VM is down. Starting it now.') vm.start() session = vm.wait_for_login() kwargs['session'] = session kwargs['vm'] = vm func(*args, **kwargs) if session: session.close() vm.shutdown() return wrapper def check_disks(vmcheck): """ Check disk counts inside the VM """ # Initialize windows boot up os_type = params.get("os_type", "linux") expected_disks = int(params.get("ori_disks", "1")) logging.debug("Expect %s disks im VM after convert", expected_disks) # Get disk counts if os_type == "linux": cmd = "lsblk |grep disk |wc -l" disks = int(vmcheck.session.cmd(cmd).strip()) else: cmd = r"echo list disk > C:\list_disk.txt" vmcheck.session.cmd(cmd) cmd = r"diskpart /s C:\list_disk.txt" output = vmcheck.session.cmd(cmd).strip() logging.debug("Disks in VM: %s", output) disks = len(re.findall('Disk\s\d', output)) logging.debug("Find %s disks in VM after convert", disks) if disks == expected_disks: logging.info("Disk counts is expected") else: log_fail("Disk counts is wrong") @vm_shell def check_vmlinuz_initramfs(v2v_result): """ Check if vmlinuz matches initramfs on multi-kernel case """ logging.info('Checking if vmlinuz matches initramfs') kernels = re.search( 'kernel packages in this guest:.*?(\(kernel.*?\).*?){2,}', v2v_result, re.DOTALL) try: lines = kernels.group(0) kernel_list = re.findall('\((.*?)\)', lines) for kernel in kernel_list: vmlinuz = re.search(r'/boot/vmlinuz-(.*?),', kernel).group(1) initramfs = \ re.search(r'/boot/initramfs-(.*?)\.img', kernel).group(1) logging.debug('vmlinuz version is: %s' % vmlinuz) logging.debug('initramfs version is: %s' % initramfs) if vmlinuz != initramfs: log_fail('vmlinuz not match with initramfs') except Exception as e: test.error('Error on find kernel info \n %s' % str(e)) def check_boot_kernel(vmcheck): """ Check if converted vm use the latest kernel """ current_kernel = vmcheck.session.cmd('uname -r').strip() logging.debug('Current kernel: %s' % current_kernel) if current_kernel == '3.10.0-799.el7.x86_64': logging.debug('The kernel is the latest kernel') else: log_fail('VM should choose lastest kernel not %s' % current_kernel) def check_floppy_exist(vmcheck): """ Check if floppy exists after convertion """ blk = vmcheck.session.cmd('lsblk') logging.info(blk) if not re.search('fd0', blk): log_fail('Floppy not found') def attach_removable_media(type, source, dev): bus = {'cdrom': 'ide', 'floppy': 'fdc', 'disk': 'virtio'} args = { 'driver': 'qemu', 'subdriver': 'raw', 'sourcetype': 'file', 'type': type, 'targetbus': bus[type] } if type == 'cdrom': args.update({'mode': 'readonly'}) config = '' # Join all options together to get command line for key in list(args.keys()): config += ' --%s %s' % (key, args[key]) config += ' --current' virsh.attach_disk(vm_name, source, dev, extra=config) def change_disk_bus(dest): """ Change all disks' bus type to $dest """ bus_list = ['ide', 'sata', 'virtio'] if dest not in bus_list: test.error('Bus type not support') dev_prefix = ['h', 's', 'v'] dev_table = dict(list(zip(bus_list, dev_prefix))) logging.info('Change disk bus to %s' % dest) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disks = vmxml.get_disk_all() index = 0 for disk in list(disks.values()): if disk.get('device') != 'disk': continue target = disk.find('target') target.set('bus', dest) target.set('dev', dev_table[dest] + 'd' + string.lowercase[index]) disk.remove(disk.find('address')) index += 1 vmxml.sync() def change_network_model(model): """ Change network model to $model """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) network_list = vmxml.get_iface_all() for node in list(network_list.values()): if node.get('type') == 'network': node.find('model').set('type', model) vmxml.sync() def attach_network_card(model): """ Attach network card based on model """ if model not in ('e1000', 'virtio', 'rtl8139'): test.error('Network model not support') options = {'type': 'network', 'source': 'default', 'model': model} line = '' for key in options: line += ' --' + key + ' ' + options[key] line += ' --current' logging.debug(virsh.attach_interface(vm_name, option=line)) def check_multi_netcards(mac_list, virsh_instance): """ Check if number and type of network cards meet expectation """ vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=virsh_instance) iflist = vmxml.get_iface_all() logging.debug('MAC list before v2v: %s' % mac_list) logging.debug('MAC list after v2v: %s' % list(iflist.keys())) if set(mac_list).difference(list(iflist.keys())): log_fail('Missing network interface') for mac in iflist: if iflist[mac].find('model').get('type') != 'virtio': log_fail('Network not convert to virtio') @vm_shell def insert_floppy_devicemap(**kwargs): """ Add an entry of floppy to device.map """ session = kwargs['session'] line = '(fd0) /dev/fd0' devmap = '/boot/grub/device.map' if session.cmd_status('ls %s' % devmap): devmap = '/boot/grub2/device.map' cmd_exist = 'grep \'(fd0)\' %s' % devmap cmd_set = 'sed -i \'2i%s\' %s' % (line, devmap) if session.cmd_status(cmd_exist): session.cmd(cmd_set) def make_label(session): """ Label a volume, swap or root volume """ # swaplabel for rhel7 with xfs, e2label for rhel6 or ext* cmd_map = { 'root': 'e2label %s ROOT', 'swap': 'swaplabel -L SWAPPER %s' } if not session.cmd_status('swaplabel --help'): blk = 'swap' elif not session.cmd_status('which e2label'): blk = 'root' else: test.error('No tool to make label') entry = session.cmd('blkid|grep %s' % blk).strip() path = entry.split()[0].strip(':') cmd_label = cmd_map[blk] % path if 'LABEL' not in entry: session.cmd(cmd_label) return blk @vm_shell def specify_fstab_entry(type, **kwargs): """ Specify entry in fstab file """ type_list = ['cdrom', 'uuid', 'label', 'virtio', 'sr0', 'invalid'] if type not in type_list: test.error('Not support %s in fstab' % type) session = kwargs['session'] # Specify cdrom device if type == 'cdrom': line = '/dev/cdrom /media/CDROM auto exec' if 'grub2' in utils_misc.get_bootloader_cfg(session): line += ',nofail' line += ' 0 0' logging.debug('fstab entry is "%s"', line) cmd = [ 'mkdir -p /media/CDROM', 'mount /dev/cdrom /media/CDROM', 'echo "%s" >> /etc/fstab' % line ] for i in range(len(cmd)): session.cmd(cmd[i]) elif type == 'sr0': line = params.get('fstab_content') session.cmd('echo "%s" >> /etc/fstab' % line) elif type == 'invalid': line = utils_misc.generate_random_string(6) session.cmd('echo "%s" >> /etc/fstab' % line) else: map = {'uuid': 'UUID', 'label': 'LABEL', 'virtio': '/vd'} logging.info(type) if session.cmd_status('cat /etc/fstab|grep %s' % map[type]): # Specify device by UUID if type == 'uuid': entry = session.cmd( 'blkid -s UUID|grep swap').strip().split() # Replace path for UUID origin = entry[0].strip(':') replace = entry[1].replace('"', '') # Specify virtio device elif type == 'virtio': entry = session.cmd('cat /etc/fstab|grep /boot').strip() # Get the ID (no matter what, usually UUID) origin = entry.split()[0] key = origin.split('=')[1] blkinfo = session.cmd('blkid|grep %s' % key).strip() # Replace with virtio disk path replace = blkinfo.split()[0].strip(':') # Specify device by label elif type == 'label': blk = make_label(session) entry = session.cmd('blkid|grep %s' % blk).strip() # Remove " from LABEL="****" replace = entry.split()[1].strip().replace('"', '') # Replace the original id/path with label origin = entry.split()[0].strip(':') cmd_fstab = "sed -i 's|%s|%s|' /etc/fstab" % (origin, replace) session.cmd(cmd_fstab) fstab = session.cmd_output('cat /etc/fstab') logging.debug('Content of /etc/fstab:\n%s', fstab) def create_large_file(session, left_space): """ Create a large file to make left space of root less than $left_space MB """ cmd_df = "df -m / --output=avail" df_output = session.cmd(cmd_df).strip() logging.debug('Command output: %s', df_output) avail = int(df_output.strip().split('\n')[-1]) logging.info('Available space: %dM' % avail) if avail > left_space - 1: tmp_dir = data_dir.get_tmp_dir() if session.cmd_status('ls %s' % tmp_dir) != 0: session.cmd('mkdir %s' % tmp_dir) large_file = os.path.join(tmp_dir, 'file.large') cmd_create = 'dd if=/dev/zero of=%s bs=1M count=%d' % \ (large_file, avail - left_space + 2) session.cmd(cmd_create, timeout=v2v_timeout) logging.info('Available space: %sM' % session.cmd(cmd_df).strip()) @vm_shell def corrupt_rpmdb(**kwargs): """ Corrupt rpm db """ session = kwargs['session'] # If __db.* exist, remove them, then touch _db.001 to corrupt db. if not session.cmd_status('ls /var/lib/rpm/__db.001'): session.cmd('rm -f /var/lib/rpm/__db.*') session.cmd('touch /var/lib/rpm/__db.001') if not session.cmd_status('yum update'): test.error('Corrupt rpmdb failed') @vm_shell def grub_serial_terminal(**kwargs): """ Edit the serial and terminal lines of grub.conf """ session = kwargs['session'] vm = kwargs['vm'] grub_file = utils_misc.get_bootloader_cfg(session) if 'grub2' in grub_file: test.cancel('Skip this case on grub2') cmd = "sed -i '1iserial -unit=0 -speed=115200\\n" cmd += "terminal -timeout=10 serial console' %s" % grub_file session.cmd(cmd) @vm_shell def set_selinux(value, **kwargs): """ Set selinux stat of guest """ session = kwargs['session'] current_stat = session.cmd_output('getenforce').strip() logging.debug('Current selinux status: %s', current_stat) if current_stat != value: cmd = "sed -E -i 's/(^SELINUX=).*?/\\1%s/' /etc/selinux/config" % value logging.info('Set selinux stat with command %s', cmd) session.cmd(cmd) @vm_shell def get_firewalld_status(**kwargs): """ Return firewalld service status of vm """ session = kwargs['session'] firewalld_status = session.cmd( 'systemctl status firewalld.service|grep Active:', ok_status=[0, 3]).strip() logging.info('Status of firewalld: %s', firewalld_status) params[checkpoint] = firewalld_status def check_firewalld_status(vmcheck, expect_status): """ Check if status of firewalld meets expectation """ firewalld_status = vmcheck.session.cmd( 'systemctl status ' 'firewalld.service|grep Active:', ok_status=[0, 3]).strip() logging.info('Status of firewalld after v2v: %s', firewalld_status) if firewalld_status != expect_status: log_fail('Status of firewalld changed after conversion') @vm_shell def vm_cmd(cmd_list, **kwargs): """ Excecute a list of commands on guest. """ session = kwargs['session'] for cmd in cmd_list: logging.info('Send command "%s"', cmd) status, output = session.cmd_status_output(cmd) logging.debug('Command output:\n%s', output) if status != 0: test.error('Command "%s" failed' % cmd) logging.info('All commands executed') def check_time_keep(vmcheck): """ Check time drift after convertion. """ logging.info('Check time drift') output = vmcheck.session.cmd('ntpdate -q %s' % ntp_server) logging.debug(output) drift = abs(float(output.split()[-2])) logging.debug('Time drift is: %f', drift) if drift > 3: log_fail('Time drift exceeds 3 sec') def check_boot(): """ Check if guest can boot up after configuration """ try: vm = libvirt_vm.VM(vm_name, params, test.bindir, env.get('address_cache')) if vm.is_alive(): vm.shutdown() logging.info('Booting up %s' % vm_name) vm.start() vm.wait_for_login() vm.shutdown() logging.info('%s is down' % vm_name) except Exception as e: test.error('Bootup guest and login failed: %s', str(e)) def check_result(result, status_error): """ Check virt-v2v command result """ utlv.check_exit_status(result, status_error) output = result.stdout + result.stderr if skip_check: logging.info('Skip checking vm after conversion') elif not status_error: if output_mode == 'rhev': if not utils_v2v.import_vm_to_ovirt( params, address_cache, timeout=v2v_timeout): test.fail('Import VM failed') if 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 vmchecker = VMChecker(test, params, env) params['vmchecker'] = vmchecker if params.get('skip_check') != 'yes': ret = vmchecker.run() if len(ret) == 0: logging.info("All common checkpoints passed") vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=vmchecker.virsh_instance) logging.debug(vmxml) if checkpoint == 'multi_kernel': check_boot_kernel(vmchecker.checker) if checkpoint == 'floppy': check_floppy_exist(vmchecker.checker) if checkpoint == 'multi_disks': check_disks(vmchecker.checker) if checkpoint == 'multi_netcards': check_multi_netcards(params['mac_address'], vmchecker.virsh_instance) if checkpoint.startswith(('spice', 'vnc')): if checkpoint == 'spice_encrypt': vmchecker.check_graphics(params[checkpoint]) else: graph_type = checkpoint.split('_')[0] vmchecker.check_graphics({'type': graph_type}) video_type = vmxml.get_devices('video')[0].model_type if video_type.lower() != 'qxl': log_fail('Video expect QXL, actual %s' % video_type) if checkpoint.startswith('listen'): listen_type = vmxml.get_devices('graphics')[0].listen_type logging.info('listen type is: %s', listen_type) if listen_type != checkpoint.split('_')[-1]: log_fail('listen type changed after conversion') if checkpoint.startswith('selinux'): status = vmchecker.checker.session.cmd( 'getenforce').strip().lower() logging.info('Selinux status after v2v:%s', status) if status != checkpoint[8:]: log_fail('Selinux status not match') if checkpoint == 'guest_firewalld_status': check_firewalld_status(vmchecker.checker, params[checkpoint]) if checkpoint in ['ntpd_on', 'sync_ntp']: check_time_keep(vmchecker.checker) # Merge 2 error lists error_list.extend(vmchecker.errors) log_check = utils_v2v.check_log(params, output) if log_check: log_fail(log_check) if len(error_list): test.fail('%d checkpoints failed: %s' % (len(error_list), error_list)) try: v2v_params = { 'hostname': remote_host, 'hypervisor': 'kvm', 'v2v_opts': '-v -x', 'storage': output_storage, 'network': network, 'bridge': bridge, 'target': target, 'main_vm': vm_name, 'input_mode': 'libvirt', 'new_name': vm_name + '_' + utils_misc.generate_random_string(3) } if output_format: v2v_params.update({'output_format': 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) if output_mode == 'local': v2v_params['storage'] = data_dir.get_tmp_dir() if output_mode == 'libvirt': pvt.pre_pool(pool_name, pool_type, pool_target, '') # Set libguestfs environment variable os.environ['LIBGUESTFS_BACKEND'] = 'direct' backup_xml = None if checkpoint in backup_list: backup_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) if checkpoint == 'multi_disks': attach_disk_path = os.path.join(data_dir.get_tmp_dir(), 'attach_disks') utlv.attach_disks(env.get_vm(vm_name), attach_disk_path, None, params) new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) disk_count = 0 for disk in list(new_xml.get_disk_all().values()): if disk.get('device') == 'disk': disk_count += 1 params['ori_disks'] = disk_count if checkpoint == 'virtio_on': change_disk_bus('virtio') if checkpoint == 'virtio_off': change_disk_bus('ide') if checkpoint == 'sata_disk': change_disk_bus('sata') if checkpoint.startswith('floppy'): img_path = data_dir.get_tmp_dir() + '/floppy.img' utlv.create_local_disk('floppy', img_path) attach_removable_media('floppy', img_path, 'fda') if checkpoint == 'floppy_devmap': insert_floppy_devicemap() if checkpoint.startswith('fstab'): if checkpoint == 'fstab_cdrom': img_path = data_dir.get_tmp_dir() + '/cdrom.iso' utlv.create_local_disk('iso', img_path) attach_removable_media('cdrom', img_path, 'hdc') if checkpoint == 'fstab_virtio': change_disk_bus('virtio') specify_fstab_entry(checkpoint[6:]) if checkpoint == 'running': virsh.start(vm_name) logging.info('VM state: %s' % virsh.domstate(vm_name).stdout.strip()) if checkpoint == 'paused': virsh.start(vm_name, '--paused') logging.info('VM state: %s' % virsh.domstate(vm_name).stdout.strip()) if checkpoint == 'serial_terminal': grub_serial_terminal() check_boot() if checkpoint == 'no_space': @vm_shell def take_space(**kwargs): create_large_file(kwargs['session'], 20) take_space() if checkpoint.startswith('host_no_space'): session = aexpect.ShellSession('sh') create_large_file(session, 1000) if checkpoint == 'host_no_space_setcache': logging.info('Set LIBGUESTFS_CACHEDIR=/home') os.environ['LIBGUESTFS_CACHEDIR'] = '/home' if checkpoint == 'corrupt_rpmdb': corrupt_rpmdb() if checkpoint.startswith('network'): change_network_model(checkpoint[8:]) if checkpoint == 'multi_netcards': attach_network_card('virtio') attach_network_card('e1000') params['mac_address'] = [] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) network_list = vmxml.get_iface_all() for mac in network_list: if network_list[mac].get('type') == 'network': params['mac_address'].append(mac) if len(params['mac_address']) < 2: test.error('Not enough network interface') logging.debug('MAC address: %s' % params['mac_address']) if checkpoint.startswith(('spice', 'vnc')): if checkpoint == 'spice_encrypt': spice_passwd = { 'type': 'spice', 'passwd': params.get('spice_passwd', 'redhat') } vm_xml.VMXML.set_graphics_attr(vm_name, spice_passwd) params[checkpoint] = { 'type': 'spice', 'passwdValidTo': '1970-01-01T00:00:01' } else: graphic_video = checkpoint.split('_') graphic = graphic_video[0] logging.info('Set graphic type to %s', graphic) vm_xml.VMXML.set_graphics_attr(vm_name, {'type': graphic}) if len(graphic_video) > 1: video_type = graphic_video[1] logging.info('Set video type to %s', video_type) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) video = vmxml.xmltreefile.find('devices').find( 'video').find('model') video.set('type', video_type) vmxml.sync() if checkpoint.startswith('listen'): listen_type = checkpoint.split('_')[-1] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) listen = vmxml.xmltreefile.find('devices').find('graphics').find( 'listen') listen.set('type', listen_type) vmxml.sync() if checkpoint == 'host_selinux_on': params['selinux_stat'] = utils_selinux.get_status() utils_selinux.set_status('enforcing') if checkpoint.startswith('selinux'): set_selinux(checkpoint[8:]) if checkpoint.startswith('host_firewalld'): service_mgr = service.ServiceManager() logging.info('Backing up firewall services status') params['bk_firewalld_status'] = service_mgr.status('firewalld') if 'start' in checkpoint: service_mgr.start('firewalld') if 'stop' in checkpoint: service_mgr.stop('firewalld') if checkpoint == 'guest_firewalld_status': get_firewalld_status() if checkpoint == 'remove_securetty': logging.info('Remove /etc/securetty file from guest') cmd = ['rm -f /etc/securetty'] vm_cmd(cmd) if checkpoint == 'ntpd_on': logging.info('Set service ntpd on') cmd = ['yum -y install ntp', 'systemctl start ntpd'] vm_cmd(cmd) if checkpoint == 'sync_ntp': logging.info('Sync time with %s', ntp_server) cmd = ['yum -y install ntpdate', 'ntpdate %s' % ntp_server] vm_cmd(cmd) if checkpoint == 'blank_2nd_disk': disk_path = os.path.join(data_dir.get_tmp_dir(), 'blank.img') logging.info('Create blank disk %s', disk_path) process.run('truncate -s 1G %s' % disk_path) logging.info('Attach blank disk to vm') attach_removable_media('disk', disk_path, 'vdc') logging.debug(virsh.dumpxml(vm_name)) if checkpoint in ['only_net', 'only_br']: logging.info('Detatch all networks') virsh.detach_interface(vm_name, 'network --current', debug=True) logging.info('Detatch all bridges') virsh.detach_interface(vm_name, 'bridge --current', debug=True) if checkpoint == 'only_net': logging.info('Attach network') virsh.attach_interface(vm_name, 'network default --current', debug=True) v2v_params.pop('bridge') if checkpoint == 'only_br': logging.info('Attatch bridge') virsh.attach_interface(vm_name, 'bridge virbr0 --current', debug=True) v2v_params.pop('network') if checkpoint == 'no_libguestfs_backend': os.environ.pop('LIBGUESTFS_BACKEND') if checkpoint == 'file_image': vm = env.get_vm(vm_name) disk = vm.get_first_disk_devices() logging.info('Disk type is %s', disk['type']) if disk['type'] != 'file': test.error('Guest is not with file image') virsh.dumpxml(vm_name, debug=True) v2v_result = utils_v2v.v2v_cmd(v2v_params) if v2v_params.get('new_name'): vm_name = params['main_vm'] = v2v_params['new_name'] check_result(v2v_result, status_error) finally: if params.get('vmchecker'): params['vmchecker'].cleanup() if output_mode == 'libvirt': pvt.cleanup_pool(pool_name, pool_type, pool_target, '') if backup_xml: backup_xml.sync() if params.get('selinux_stat') and params['selinux_stat'] != 'disabled': utils_selinux.set_status(params['selinux_stat']) if 'bk_firewalld_status' in params: service_mgr = service.ServiceManager() if service_mgr.status( 'firewalld') != params['bk_firewalld_status']: if params['bk_firewalld_status']: service_mgr.start('firewalld') else: service_mgr.stop('firewalld') if checkpoint.startswith('host_no_space'): large_file = os.path.join(data_dir.get_tmp_dir(), 'file.large') if os.path.isfile(large_file): os.remove(large_file)
def run(test, params, env): """ This case check error messages in libvirtd logging. Implemented test cases: with_iptables: Start libvirtd when using iptables service as firewall. with_firewalld: Start libvirtd when using firewalld service as firewall. no_firewall: Start libvirtd With both firewall services shut off. """ def _error_handler(line, errors): """ A callback function called when new error lines appears in libvirtd log, then this line is appended to list 'errors' :param errors: A list to contain all error lines. :param line: Newly found error line in libvirtd log. """ errors.append(line) def _check_errors(): """ Check for unexpected error messages in libvirtd log. """ logging.info('Checking errors in libvirtd log') accepted_error_patterns = [ 'Cannot access storage file', 'Failed to autostart storage pool', 'cannot open directory', ] if (not iptables_service and not firewalld_service and 'virt_t' not in libvirt_context): logging.info("virt_t is not in libvirtd process context. " "Failures for setting iptables rules will be ignored") # libvirtd process started without virt_t will failed to set # iptables rules which is expected here accepted_error_patterns.append( '/sbin/iptables .* unexpected exit status 1') logging.debug("Accepted errors are: %s", accepted_error_patterns) if errors: logging.debug("Found errors in libvirt log:") for line in errors: logging.debug(line) unexpected_errors = [] for line in errors: if any([re.search(p, line) for p in accepted_error_patterns]): logging.debug('Error "%s" is acceptable', line) else: unexpected_errors.append(line) if unexpected_errors: raise exceptions.TestFail( "Found unexpected errors in libvirt log:\n%s" % '\n'.join(unexpected_errors)) iptables_service = params.get('iptables_service', 'off') == 'on' firewalld_service = params.get('firewalld_service', 'off') == 'on' # In RHEL7 iptables service is provided by a separated package # In RHEL6 iptables-services and firewalld is not supported # So try to install all required packages but ignore failures logging.info('Preparing firewall related packages') software_mgr = software_manager.SoftwareManager() for pkg in ['iptables', 'iptables-services', 'firewalld']: if not software_mgr.check_installed(pkg): software_mgr.install(pkg) # Backup services status service_mgr = service.ServiceManager() logging.info('Backing up firewall services status') backup_iptables_status = service_mgr.status('iptables') backup_firewalld_status = service_mgr.status('firewalld') # iptables-service got deprecated in newer distros if iptables_service and backup_iptables_status is None: raise exceptions.TestSkipError('iptables service not found') # firewalld service could not exists on many distros if firewalld_service and backup_firewalld_status is None: raise exceptions.TestSkipError('firewalld service not found') try: if iptables_service and firewalld_service: raise exceptions.TestError( 'iptables service and firewalld service can not be started at ' 'the same time') # We should stop services first then start the other after. # Directly start one service will force the other service stop, # which will not be easy to handle. # Backup status should be compared with None to make sure that # service exists before action. logging.info('Changing firewall services status') if not iptables_service and backup_iptables_status is not None: process.run('iptables-save > /tmp/iptables.save', shell=True) service_mgr.stop('iptables') if not firewalld_service and backup_firewalld_status is not None: service_mgr.stop('firewalld') if iptables_service and backup_iptables_status is not None: service_mgr.start('iptables') if firewalld_service and backup_firewalld_status is not None: service_mgr.start('firewalld') errors = [] # Run libvirt session and collect errors in log. libvirtd_session = utils_libvirtd.LibvirtdSession( service_name="virtnetworkd", logging_handler=_error_handler, logging_params=(errors, ), logging_pattern=r'[-\d]+ [.:+\d]+ [:\d]+ error :', ) try: logging.info('Starting libvirtd session') libvirtd_session.start() time.sleep(3) libvirt_pid = libvirtd_session.tail.get_pid() sestatus = utils_selinux.get_status() if sestatus == "disabled": raise exceptions.TestSkipError("SELinux is in Disabled mode." "It must be in enforcing mode " "for test execution") libvirt_context = utils_selinux.get_context_of_process(libvirt_pid) logging.debug("The libvirtd process context is: %s", libvirt_context) finally: libvirtd_session.exit() _check_errors() finally: logging.info('Recovering services status') #Restart socket service after starting process at foreground utils_libvirtd.Libvirtd("virtnetworkd.socket").restart() # If service do not exists, then backup status and current status # will all be none and nothing will be done if service_mgr.status('iptables') != backup_iptables_status: if backup_iptables_status: service_mgr.start('iptables') process.run('iptables-restore < /tmp/iptables.save', shell=True) else: service_mgr.stop('iptables') if service_mgr.status('firewalld') != backup_firewalld_status: if backup_firewalld_status: service_mgr.start('firewalld') else: service_mgr.stop('firewalld') logging.info('Removing backup iptables') if os.path.exists("/tmp/iptables.save"): os.remove("/tmp/iptables.save")
def run(test, params, env): """ Test for hotplug usb device. """ # get the params from params vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) usb_type = params.get("usb_type", "kbd") attach_type = params.get("attach_type", "attach_device") attach_count = int(params.get("attach_count", "1")) if usb_type == "storage": model = params.get("model", "nec-xhci") index = params.get("index", "1") status_error = ("yes" == params.get("status_error", "no")) vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status("permissive") if usb_type == "storage": controllers = vm_xml.get_devices(device_type="controller") devices = vm_xml.get_devices() for dev in controllers: if dev.type == "usb" and dev.index == "1": devices.remove(dev) controller = Controller("controller") controller.type = "usb" controller.index = index controller.model = model devices.append(controller) vm_xml.set_devices(devices) try: session = vm.wait_for_login() except (LoginError, VMError, ShellError) as e: test.fail("Test failed: %s" % str(e)) def is_hotplug_ok(): try: output = session.cmd_output( "fdisk -l | grep -c '^Disk /dev/.* 1 M'") if int(output.strip()) != attach_count: return False else: return True except ShellTimeoutError as detail: test.fail("unhotplug failed: %s, " % detail) tmp_dir = os.path.join(data_dir.get_tmp_dir(), "usb_hotplug_files") if not os.path.isdir(tmp_dir): os.mkdir(tmp_dir) try: result = None dev_xml = None opt = "--hmp" for i in range(attach_count): if usb_type == "storage": path = os.path.join(tmp_dir, "%s.img" % i) libvirt.create_local_disk("file", path, size="1M", disk_format="qcow2") os.chmod(path, 0o666) if attach_type == "qemu_monitor": if usb_type == "storage": attach_cmd = "drive_add" attach_cmd += (" 0 id=drive-usb-%s,if=none,file=%s" % (i, path)) result = virsh.qemu_monitor_command(vm_name, attach_cmd, options=opt) if result.exit_status or (result.stdout.strip().find("OK") == -1): raise process.CmdError(result.command, result) attach_cmd = "device_add usb-storage," attach_cmd += ( "id=drive-usb-%s,bus=usb1.0,drive=drive-usb-%s" % (i, i)) else: attach_cmd = "device_add" attach_cmd += " usb-%s,bus=usb1.0,id=%s%s" % (usb_type, usb_type, i) result = virsh.qemu_monitor_command(vm_name, attach_cmd, options=opt) if result.exit_status: raise process.CmdError(result.command, result) else: attributes = {'type_name': "usb", 'bus': "1", 'port': "0"} if usb_type == "storage": dev_xml = Disk(type_name="file") dev_xml.device = "disk" dev_xml.source = dev_xml.new_disk_source( **{"attrs": { 'file': path }}) dev_xml.driver = { "name": "qemu", "type": 'qcow2', "cache": "none" } dev_xml.target = {"dev": 'sdb', "bus": "usb"} dev_xml.address = dev_xml.new_disk_address( **{"attrs": attributes}) else: if usb_type == "mouse": dev_xml = Input("mouse") elif usb_type == "tablet": dev_xml = Input("tablet") else: dev_xml = Input("keyboard") dev_xml.input_bus = "usb" dev_xml.address = dev_xml.new_input_address( **{"attrs": attributes}) result = virsh.attach_device(vm_name, dev_xml.xml) if result.exit_status: raise process.CmdError(result.command, result) if status_error and usb_type == "storage": if utils_misc.wait_for(is_hotplug_ok, timeout=30): # Sometimes we meet an error but the ret in $? is 0. test.fail("\nAttach device successfully in negative case." "\nExcept it fail when attach count exceed maximum." "\nDetail: %s" % result) for i in range(attach_count): attach_cmd = "device_del" if attach_type == "qemu_monitor": if usb_type == "storage": attach_cmd += (" drive-usb-%s" % i) else: if usb_type == "mouse": attach_cmd += " mouse" elif usb_type == "tablet": attach_cmd += " tablet" else: attach_cmd += " keyboard" result = virsh.qemu_monitor_command(vm_name, attach_cmd, options=opt) if result.exit_status: raise process.CmdError(result.command, result) else: result = virsh.detach_device(vm_name, dev_xml.xml) if result.exit_status: raise process.CmdError(result.command, result) except process.CmdError as e: if not status_error: # live attach of device 'input' is not supported ret = result.stderr.find("Operation not supported") if usb_type != "storage" and ret > -1: pass else: test.fail("failed to attach device.\nDetail: %s." % result) finally: session.close() if os.path.isdir(tmp_dir): shutil.rmtree(tmp_dir) utils_selinux.set_status(backup_sestatus) vm_xml_backup.sync()
def run_svirt_attach_disk(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Create a image to attached to VM. (3).Attach disk. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_attach_disk_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_attach_disk_vm_sec_type", "dynamic") sec_model = params.get("svirt_attach_disk_vm_sec_model", "selinux") sec_label = params.get("svirt_attach_disk_vm_sec_label", None) sec_relabel = params.get("svirt_attach_disk_vm_sec_relabel", "yes") sec_dict = { 'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel } # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_attach_disk_disk_label') img_name = "svirt_disk" # Default label for the other disks. # To ensure VM is able to access other disks. default_label = params.get('svirt_attach_disk_disk_default_label', None) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the default label to other disks of vm. disks = vm.get_disk_devices() for disk in disks.values(): utils_selinux.set_context_of_file(filename=disk['source'], context=default_label) # Init a QemuImg instance. params['image_name'] = img_name tmp_dir = data_dir.get_tmp_dir() image = qemu_storage.QemuImg(params, tmp_dir, img_name) # Create a image. img_path, result = image.create(params) # Set the context of the image. utils_selinux.set_context_of_file(filename=img_path, context=img_label) # Set the context of the VM. vmxml.set_seclabel(sec_dict) vmxml.sync() # Do the attach action. try: virsh.attach_disk(vm_name, source=img_path, target="vdf", extra="--persistent", ignore_status=False) except error.CmdError: raise error.TestFail("Attach disk %s to vdf on VM %s failed." % (img_path, vm.name)) # Check result. try: # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with set seclabel can access the image with the # set context. if status_error: raise error.TestFail('Test successed in negative case.') except virt_vm.VMStartError, e: # Starting VM failed. # VM with set seclabel can not access the image with the # set context. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up try: virsh.detach_disk(vm_name, target="vdf", extra="--persistent", ignore_status=False) except error.CmdError: raise error.TestFail("Detach disk 'vdf' from VM %s failed." % vm.name) image.remove() backup_xml.sync() utils_selinux.set_status(backup_sestatus)
def run_svirt_save_restore(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Label the VM and disk with proper label. (3).Save VM and check the context. (4).Restore VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_save_restore_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_save_restore_vm_sec_type", "dynamic") sec_model = params.get("svirt_save_restore_vm_sec_model", "selinux") sec_label = params.get("svirt_save_restore_vm_sec_label", None) sec_relabel = params.get("svirt_save_restore_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_save_restore_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) utils_selinux.set_context_of_file(filename=disk_path, context=img_label) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the context of the VM. vmxml.set_seclabel(sec_dict) vmxml.sync() # Init a path to save VM. save_path = os.path.join(test.tmpdir, "svirt_save") try: # Start VM to check the VM is able to access the image or not. try: vm.start() vm.save_to_file(path=save_path) vm.restore_from_file(path=save_path) # Save and restore VM successfully. if status_error: raise error.TestFail("Test successed in negative case.") except virt_vm.VMError, e: if not status_error: error_msg = "Test failed in positive case.\n error: %s\n" % e if str(e).count("getfd"): error_msg += ("More info pleass refer to" " https://bugzilla.redhat.com/show_bug.cgi?id=976632") raise error.TestFail(error_msg) finally: # clean up for path, label in backup_labels_of_disks.items(): utils_selinux.set_context_of_file(filename=path, context=label) backup_xml.sync() utils_selinux.set_status(backup_sestatus)
def run(test, params, env): """ Test for hotplug usb device. """ # get the params from params vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) usb_type = params.get("usb_type", "kbd") attach_type = params.get("attach_type", "attach_device") attach_count = int(params.get("attach_count", "1")) if usb_type == "storage": model = params.get("model", "nec-xhci") index = params.get("index", "1") status_error = ("yes" == params.get("status_error", "no")) vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status("permissive") if usb_type == "storage": controllers = vm_xml.get_devices(device_type="controller") devices = vm_xml.get_devices() for dev in controllers: if dev.type == "usb" and dev.index == "1": devices.remove(dev) controller = Controller("controller") controller.type = "usb" controller.index = index controller.model = model devices.append(controller) vm_xml.set_devices(devices) try: session = vm.wait_for_login() except (LoginError, VMError, ShellError) as e: test.fail("Test failed: %s" % str(e)) def is_hotplug_ok(): try: output = session.cmd_output("fdisk -l | grep -c '^Disk /dev/.* 1 M'") if int(output.strip()) != attach_count: return False else: return True except ShellTimeoutError as detail: test.fail("unhotplug failed: %s, " % detail) tmp_dir = os.path.join(data_dir.get_tmp_dir(), "usb_hotplug_files") if not os.path.isdir(tmp_dir): os.mkdir(tmp_dir) try: result = None dev_xml = None opt = "--hmp" for i in range(attach_count): if usb_type == "storage": path = os.path.join(tmp_dir, "%s.img" % i) libvirt.create_local_disk("file", path, size="1M", disk_format="qcow2") os.chmod(path, 0o666) if attach_type == "qemu_monitor": if usb_type == "storage": attach_cmd = "drive_add" attach_cmd += (" 0 id=drive-usb-%s,if=none,file=%s" % (i, path)) result = virsh.qemu_monitor_command(vm_name, attach_cmd, options=opt) if result.exit_status or (result.stdout.strip().find("OK") == -1): raise process.CmdError(result.command, result) attach_cmd = "device_add usb-storage," attach_cmd += ("id=drive-usb-%s,bus=usb1.0,drive=drive-usb-%s" % (i, i)) else: attach_cmd = "device_add" attach_cmd += " usb-%s,bus=usb1.0,id=%s%s" % (usb_type, usb_type, i) result = virsh.qemu_monitor_command(vm_name, attach_cmd, options=opt) if result.exit_status: raise process.CmdError(result.command, result) else: attributes = {'type_name': "usb", 'bus': "1", 'port': "0"} if usb_type == "storage": dev_xml = Disk(type_name="file") dev_xml.device = "disk" dev_xml.source = dev_xml.new_disk_source(**{"attrs": {'file': path}}) dev_xml.driver = {"name": "qemu", "type": 'qcow2', "cache": "none"} dev_xml.target = {"dev": 'sdb', "bus": "usb"} dev_xml.address = dev_xml.new_disk_address(**{"attrs": attributes}) else: if usb_type == "mouse": dev_xml = Input("mouse") elif usb_type == "tablet": dev_xml = Input("tablet") else: dev_xml = Input("keyboard") dev_xml.input_bus = "usb" dev_xml.address = dev_xml.new_input_address(**{"attrs": attributes}) result = virsh.attach_device(vm_name, dev_xml.xml) if result.exit_status: raise process.CmdError(result.command, result) if status_error and usb_type == "storage": if utils_misc.wait_for(is_hotplug_ok, timeout=30): # Sometimes we meet an error but the ret in $? is 0. test.fail("\nAttach device successfully in negative case." "\nExcept it fail when attach count exceed maximum." "\nDetail: %s" % result) for i in range(attach_count): attach_cmd = "device_del" if attach_type == "qemu_monitor": if usb_type == "storage": attach_cmd += (" drive-usb-%s" % i) else: if usb_type == "mouse": attach_cmd += " mouse" elif usb_type == "tablet": attach_cmd += " tablet" else: attach_cmd += " keyboard" result = virsh.qemu_monitor_command(vm_name, attach_cmd, options=opt) if result.exit_status: raise process.CmdError(result.command, result) else: result = virsh.detach_device(vm_name, dev_xml.xml) if result.exit_status: raise process.CmdError(result.command, result) except process.CmdError as e: if not status_error: # live attach of device 'input' is not supported ret = result.stderr.find("Operation not supported") if usb_type != "storage" and ret > -1: pass else: test.fail("failed to attach device.\nDetail: %s." % result) finally: session.close() if os.path.isdir(tmp_dir): shutil.rmtree(tmp_dir) utils_selinux.set_status(backup_sestatus) vm_xml_backup.sync()
def run(test, params, env): """ Test interafce xml options. 1.Prepare test environment,destroy or suspend a VM. 2.Edit xml and start the domain. 3.Perform test operation. 4.Recover test environment. 5.Confirm the test result. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) host_arch = platform.machine() virsh_dargs = {'debug': True, 'ignore_status': False} if not utils_package.package_install(["lsof"]): test.cancel("Failed to install dependency package lsof" " on host") def create_iface_xml(iface_mac): """ Create interface xml file """ iface = Interface(type_name=iface_type) source = ast.literal_eval(iface_source) if source: iface.source = source iface.model = iface_model if iface_model else "virtio" iface.mac_address = iface_mac driver_dict = {} driver_host = {} driver_guest = {} if iface_driver: driver_dict = ast.literal_eval(iface_driver) if iface_driver_host: driver_host = ast.literal_eval(iface_driver_host) if iface_driver_guest: driver_guest = ast.literal_eval(iface_driver_guest) iface.driver = iface.new_driver(driver_attr=driver_dict, driver_host=driver_host, driver_guest=driver_guest) if test_target: iface.target = {"dev": target_dev} logging.debug("Create new interface xml: %s", iface) return iface def modify_iface_xml(update, status_error=False): """ Modify interface xml options """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) xml_devices = vmxml.devices iface_index = xml_devices.index( xml_devices.by_device_tag("interface")[0]) iface = xml_devices[iface_index] if iface_model: iface.model = iface_model else: del iface.model if iface_type: iface.type_name = iface_type del iface.source source = ast.literal_eval(iface_source) if source: net_ifs = utils_net.get_net_if(state="UP") # Check source device is valid or not, # if it's not in host interface list, try to set # source device to first active interface of host if (iface.type_name == "direct" and 'dev' in source and source['dev'] not in net_ifs): logging.warn( "Source device %s is not a interface" " of host, reset to %s", source['dev'], net_ifs[0]) source['dev'] = net_ifs[0] iface.source = source backend = ast.literal_eval(iface_backend) if backend: iface.backend = backend driver_dict = {} driver_host = {} driver_guest = {} if iface_driver: driver_dict = ast.literal_eval(iface_driver) if iface_driver_host: driver_host = ast.literal_eval(iface_driver_host) if iface_driver_guest: driver_guest = ast.literal_eval(iface_driver_guest) iface.driver = iface.new_driver(driver_attr=driver_dict, driver_host=driver_host, driver_guest=driver_guest) if test_target: logging.debug("iface.target is %s" % target_dev) iface.target = {"dev": target_dev} if iface.address: del iface.address if set_ip: iface.ips = [ast.literal_eval(x) for x in set_ips] logging.debug("New interface xml file: %s", iface) if unprivileged_user: # Create disk image for unprivileged user disk_index = xml_devices.index( xml_devices.by_device_tag("disk")[0]) disk_xml = xml_devices[disk_index] logging.debug("source: %s", disk_xml.source) disk_source = disk_xml.source.attrs["file"] cmd = ("cp -fZ {0} {1} && chown {2}:{2} {1}" "".format(disk_source, dst_disk, unprivileged_user)) process.run(cmd, shell=True) disk_xml.source = disk_xml.new_disk_source( attrs={"file": dst_disk}) vmxml.devices = xml_devices # Remove all channels to avoid of permission problem channels = vmxml.get_devices(device_type="channel") for channel in channels: vmxml.del_device(channel) logging.info("Unprivileged users can't use 'dac' security driver," " removing from domain xml if present...") vmxml.del_seclabel([('model', 'dac')]) # Set vm memory to 2G if it's larger than 2G if vmxml.memory > 2097152: vmxml.memory = vmxml.current_mem = 2097152 vmxml.xmltreefile.write() logging.debug("New VM xml: %s", vmxml) process.run("chmod a+rw %s" % vmxml.xml, shell=True) virsh.define(vmxml.xml, **virsh_dargs) # Try to modify interface xml by update-device or edit xml elif update: iface.xmltreefile.write() ret = virsh.update_device(vm_name, iface.xml, ignore_status=True) libvirt.check_exit_status(ret, status_error) else: vmxml.devices = xml_devices vmxml.xmltreefile.write() try: vmxml.sync() if define_error: test.fail("Define VM succeed, but it should fail") except xcepts.LibvirtXMLError as e: if not define_error: test.fail("Define VM fail: %s" % e) def check_offloads_option(if_name, driver_options, session=None): """ Check interface offloads by ethtool output """ offloads = { "csum": "tx-checksumming", "gso": "generic-segmentation-offload", "tso4": "tcp-segmentation-offload", "tso6": "tx-tcp6-segmentation", "ecn": "tx-tcp-ecn-segmentation", "ufo": "udp-fragmentation-offload" } if session: ret, output = session.cmd_status_output("ethtool -k %s | head" " -18" % if_name) else: out = process.run("ethtool -k %s | head -18" % if_name, shell=True) ret, output = out.exit_status, out.stdout_text if ret: test.fail("ethtool return error code") logging.debug("ethtool output: %s", output) for offload in list(driver_options.keys()): if offload in offloads: if (output.count(offloads[offload]) and not output.count( "%s: %s" % (offloads[offload], driver_options[offload]))): test.fail("offloads option %s: %s isn't" " correct in ethtool output" % (offloads[offload], driver_options[offload])) def run_xml_test(iface_mac): """ Test for interface options in vm xml """ # Get the interface object according the mac address vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) iface_devices = vmxml.get_devices(device_type="interface") iface = None for iface_dev in iface_devices: if iface_dev.mac_address == iface_mac: iface = iface_dev if not iface: test.fail("Can't find interface with mac" " '%s' in vm xml" % iface_mac) driver_dict = {} if iface_driver: driver_dict = ast.literal_eval(iface_driver) for driver_opt in list(driver_dict.keys()): if not driver_dict[driver_opt] == iface.driver.driver_attr[ driver_opt]: test.fail("Can't see driver option %s=%s in vm xml" % (driver_opt, driver_dict[driver_opt])) else: logging.info("Find %s=%s in vm xml" % (driver_opt, driver_dict[driver_opt])) if iface_target: if ("dev" not in iface.target or not iface.target["dev"].startswith(iface_target)): test.fail("Can't see device target dev in vm xml") # Check macvtap mode by ip link command if iface_target == "macvtap" and "mode" in iface.source: cmd = "ip -d link show %s" % iface.target["dev"] output = process.run(cmd, shell=True).stdout_text logging.debug("ip link output: %s", output) mode = iface.source["mode"] if mode == "passthrough": mode = "passthru" if not re.search(r"macvtap\s+mode %s" % mode, output): test.fail("Failed to verify macvtap mode") # Check if the "target dev" is set successfully # 1. Target dev name with prefix as "vnet" will always be override; # 2. Target dev name with prefix as "macvtap" or "macvlan" with direct # type interface will be override; # 3. Other scenarios, the target dev should be set successfully. if test_target: if target_dev != iface.target["dev"]: if target_dev.startswith("vnet") or \ (iface_type == "direct" and (target_dev.startswith("macvtap") or target_dev.startswith("macvlan"))): logging.debug("target dev %s is override" % target_dev) else: test.fail("Failed to set target dev to %s", target_dev) else: logging.debug("target dev set successfully to %s", iface.target["dev"]) def run_cmdline_test(iface_mac, host_arch): """ Test qemu command line :param iface_mac: expected MAC :param host_arch: host architecture, e.g. x86_64 :raise avocado.core.exceptions.TestError: if preconditions are not met :raise avocado.core.exceptions.TestFail: if commandline doesn't match :return: None """ cmd = ("ps -ef | grep %s | grep -v grep " % vm_name) ret = process.run(cmd, shell=True) logging.debug("Command line %s", ret.stdout_text) if test_vhost_net: if not ret.stdout_text.count("vhost=on") and not rm_vhost_driver: test.fail("Can't see vhost options in" " qemu-kvm command line") if iface_model == "virtio": if host_arch == 's390x': model_option = "device virtio-net-ccw" else: model_option = "device virtio-net-pci" elif iface_model == 'rtl8139': model_option = "device rtl8139" else: test.error( "Don't know which device driver to expect on qemu cmdline" " for iface_model %s" % iface_model) iface_cmdline = re.findall( r"%s,(.+),mac=%s" % (model_option, iface_mac), ret.stdout_text) if not iface_cmdline: test.fail("Can't see %s with mac %s in command" " line" % (model_option, iface_mac)) cmd_opt = {} for opt in iface_cmdline[0].split(','): tmp = opt.rsplit("=") cmd_opt[tmp[0]] = tmp[1] logging.debug("Command line options %s", cmd_opt) driver_dict = {} # Test <driver> xml options. if iface_driver: iface_driver_dict = ast.literal_eval(iface_driver) for driver_opt in list(iface_driver_dict.keys()): if driver_opt == "name": continue elif driver_opt == "txmode": if iface_driver_dict["txmode"] == "iothread": driver_dict["tx"] = "bh" else: driver_dict["tx"] = iface_driver_dict["txmode"] elif driver_opt == "queues": driver_dict["mq"] = "on" if "pci" in model_option: driver_dict["vectors"] = str( int(iface_driver_dict["queues"]) * 2 + 2) else: driver_dict[driver_opt] = iface_driver_dict[driver_opt] # Test <driver><host/><driver> xml options. if iface_driver_host: driver_dict.update(ast.literal_eval(iface_driver_host)) # Test <driver><guest/><driver> xml options. if iface_driver_guest: driver_dict.update(ast.literal_eval(iface_driver_guest)) for driver_opt in list(driver_dict.keys()): if (driver_opt not in cmd_opt or not cmd_opt[driver_opt] == driver_dict[driver_opt]): test.fail("Can't see option '%s=%s' in qemu-kvm " " command line" % (driver_opt, driver_dict[driver_opt])) logging.info("Find %s=%s in qemu-kvm command line" % (driver_opt, driver_dict[driver_opt])) if test_backend: guest_pid = ret.stdout_text.rsplit()[1] cmd = "lsof %s | grep %s" % (backend["tap"], guest_pid) if process.system(cmd, ignore_status=True, shell=True): test.fail("Guest process didn't open backend file" " %s" % backend["tap"]) cmd = "lsof %s | grep %s" % (backend["vhost"], guest_pid) if process.system(cmd, ignore_status=True, shell=True): test.fail("Guest process didn't open backend file" " %s" % backend["vhost"]) def get_guest_ip(session, mac): """ Wrapper function to get guest ip address """ utils_net.restart_guest_network(session, mac) # Wait for IP address is ready utils_misc.wait_for(lambda: utils_net.get_guest_ip_addr(session, mac), 10) return utils_net.get_guest_ip_addr(session, mac) def check_user_network(session): """ Check user network ip address on guest """ vm_ips = [] vm_ips.append(get_guest_ip(session, iface_mac_old)) if attach_device: vm_ips.append(get_guest_ip(session, iface_mac)) logging.debug("IP address on guest: %s", vm_ips) if len(vm_ips) != len(set(vm_ips)): logging.debug( "Duplicated IP address on guest. Check bug: " "https://bugzilla.redhat.com/show_bug.cgi?id=1147238") for vm_ip in vm_ips: if not vm_ip or vm_ip != expect_ip: logging.debug("vm_ip is %s, expect_ip is %s", vm_ip, expect_ip) test.fail("Found wrong IP address" " on guest") # Check gateway address gateway = str(utils_net.get_default_gateway(False, session)) if expect_gw not in gateway: test.fail("The gateway on guest is %s, while expect is %s" % (gateway, expect_gw)) # Check dns server address ns_list = utils_net.get_guest_nameserver(session) if expect_ns not in ns_list: test.fail("The dns found is %s, which expect is %s" % (ns_list, expect_ns)) def check_mcast_network(session, add_session): """ Check multicast ip address on guests :param session: vm session :param add_session: additional vm session """ src_addr = ast.literal_eval(iface_source)['address'] vms_sess_dict = {vm_name: session, additional_vm.name: add_session} # Check mcast address on host cmd = "netstat -g | grep %s" % src_addr if process.run(cmd, ignore_status=True, shell=True).exit_status: test.fail("Can't find multicast ip address" " on host") vms_ip_dict = {} # Get ip address on each guest for vms in list(vms_sess_dict.keys()): vm_mac = vm_xml.VMXML.get_first_mac_by_name(vms) vm_ip = get_guest_ip(vms_sess_dict[vms], vm_mac) if not vm_ip: test.fail("Can't get multicast ip" " address on guest") vms_ip_dict.update({vms: vm_ip}) if len(set(vms_ip_dict.values())) != len(vms_sess_dict): test.fail("Got duplicated multicast ip address") logging.debug("Found ips on guest: %s", vms_ip_dict) # Run omping server on host if not utils_package.package_install(["omping"]): test.error("Failed to install omping" " on host") cmd = ("iptables -F;omping -m %s %s" % (src_addr, "192.168.122.1 %s" % ' '.join(list(vms_ip_dict.values())))) # Run a backgroup job waiting for connection of client bgjob = utils_misc.AsyncJob(cmd) # Run omping client on guests for vms in list(vms_sess_dict.keys()): # omping should be installed first if not utils_package.package_install(["omping"], vms_sess_dict[vms]): test.error("Failed to install omping" " on guest") cmd = ("iptables -F; omping -c 5 -T 5 -m %s %s" % (src_addr, "192.168.122.1 %s" % vms_ip_dict[vms])) ret, output = vms_sess_dict[vms].cmd_status_output(cmd) logging.debug("omping ret: %s, output: %s", ret, output) if (not output.count('multicast, xmt/rcv/%loss = 5/5/0%') or not output.count('unicast, xmt/rcv/%loss = 5/5/0%')): test.fail("omping failed on guest") # Kill the backgroup job bgjob.kill_func() def get_iface_model(iface_model, host_arch): """ Get iface_model. On s390x use default model 'virtio' if non-virtio given :param iface_model: value as by test configuration or default :param host_arch: host architecture, e.g. x86_64 :return: iface_model """ if 's390x' == host_arch and 'virtio' not in iface_model: return "virtio" else: return iface_model def check_vhostuser_guests(session1, session2): """ Check the vhostuser interface in guests param session1: Session of original guest param session2: Session of original additional guest """ logging.debug("iface details is %s" % libvirt.get_interface_details(vm_name)) vm1_mac = str(libvirt.get_interface_details(vm_name)[0]['mac']) vm2_mac = str(libvirt.get_interface_details(add_vm_name)[0]['mac']) utils_net.set_guest_ip_addr(session1, vm1_mac, guest1_ip) utils_net.set_guest_ip_addr(session2, vm2_mac, guest2_ip) ping_status, ping_output = utils_net.ping(dest=guest2_ip, count='3', timeout=5, session=session1) logging.info("output:%s" % ping_output) if ping_status != 0: if ping_expect_fail: logging.info("Can not ping guest2 as expected") else: test.fail("Can not ping guest2 from guest1") else: if ping_expect_fail: test.fail("Ping guest2 successfully not expected") else: logging.info("Can ping guest2 from guest1") def get_ovs_statis(ovs): """ Get ovs-vsctl interface statistics and format in dict param ovs: openvswitch instance """ ovs_statis_dict = {} ovs_iface_info = ovs.ovs_vsctl(["list", "interface"]).stdout_text.strip() ovs_iface_list = re.findall( 'name\s+: (\S+)\n.*?statistics\s+: {(.*?)}\n', ovs_iface_info, re.S) logging.info("ovs iface list is %s", ovs_iface_list) # Dict of iface name and statistics for iface_name in vhostuser_names.split(): for ovs_iface in ovs_iface_list: if iface_name == eval(ovs_iface[0]): format_statis = dict( re.findall(r'(\S*?)=(\d*?),', ovs_iface[1])) ovs_statis_dict[iface_name] = format_statis break return ovs_statis_dict status_error = "yes" == params.get("status_error", "no") start_error = "yes" == params.get("start_error", "no") define_error = "yes" == params.get("define_error", "no") unprivileged_user = params.get("unprivileged_user") # Interface specific attributes. iface_type = params.get("iface_type", "network") iface_source = params.get("iface_source", "{}") iface_driver = params.get("iface_driver") iface_model = get_iface_model(params.get("iface_model", "virtio"), host_arch) iface_target = params.get("iface_target") iface_backend = params.get("iface_backend", "{}") iface_driver_host = params.get("iface_driver_host") iface_driver_guest = params.get("iface_driver_guest") ovs_br_name = params.get("ovs_br_name") vhostuser_names = params.get("vhostuser_names") attach_device = params.get("attach_iface_device") expect_tx_size = params.get("expect_tx_size") guest1_ip = params.get("vhostuser_guest1_ip", "192.168.100.1") guest2_ip = params.get("vhostuser_guest2_ip", "192.168.100.2") change_option = "yes" == params.get("change_iface_options", "no") update_device = "yes" == params.get("update_iface_device", "no") additional_guest = "yes" == params.get("additional_guest", "no") serial_login = "******" == params.get("serial_login", "no") rm_vhost_driver = "yes" == params.get("rm_vhost_driver", "no") test_option_cmd = "yes" == params.get("test_iface_option_cmd", "no") test_option_xml = "yes" == params.get("test_iface_option_xml", "no") test_vhost_net = "yes" == params.get("test_vhost_net", "no") test_option_offloads = "yes" == params.get("test_option_offloads", "no") test_iface_user = "******" == params.get("test_iface_user", "no") test_iface_mcast = "yes" == params.get("test_iface_mcast", "no") test_libvirtd = "yes" == params.get("test_libvirtd", "no") restart_libvirtd = "yes" == params.get("restart_libvirtd", "no") restart_vm = "yes" == params.get("restart_vm", "no") test_guest_ip = "yes" == params.get("test_guest_ip", "no") test_backend = "yes" == params.get("test_backend", "no") check_guest_trans = "yes" == params.get("check_guest_trans", "no") set_ip = "yes" == params.get("set_user_ip", "no") set_ips = params.get("set_ips", "").split() expect_ip = params.get("expect_ip") expect_gw = params.get("expect_gw") expect_ns = params.get("expect_ns") test_target = "yes" == params.get("test_target", "no") target_dev = params.get("target_dev", None) # test params for vhostuser test huge_page = ast.literal_eval(params.get("huge_page", "{}")) numa_cell = ast.literal_eval(params.get("numa_cell", "{}")) additional_iface_source = ast.literal_eval( params.get("additional_iface_source", "{}")) vcpu_num = params.get("vcpu_num") cpu_mode = params.get("cpu_mode") hugepage_num = params.get("hugepage_num") log_pattern = params.get("log_pattern") # judgement params for vhostuer test need_vhostuser_env = "yes" == params.get("need_vhostuser_env", "no") ping_expect_fail = "yes" == params.get("ping_expect_fail", "no") check_libvirtd_log = "yes" == params.get("check_libvirtd_log", "no") check_statistics = "yes" == params.get("check_statistics", "no") enable_multiqueue = "yes" == params.get("enable_multiqueue", "no") queue_size = None if iface_driver: driver_dict = ast.literal_eval(iface_driver) if "queues" in driver_dict: queue_size = int(driver_dict.get("queues")) if iface_driver_host or iface_driver_guest or test_backend: if not libvirt_version.version_compare(1, 2, 8): test.cancel("Offloading/backend options not " "supported in this libvirt version") if iface_driver and "queues" in ast.literal_eval(iface_driver): if not libvirt_version.version_compare(1, 0, 6): test.cancel("Queues options not supported" " in this libvirt version") if unprivileged_user: if not libvirt_version.version_compare(1, 1, 1): test.cancel("qemu-bridge-helper not supported" " on this host") virsh_dargs["unprivileged_user"] = unprivileged_user # Create unprivileged user if needed cmd = ("grep {0} /etc/passwd || " "useradd {0}".format(unprivileged_user)) process.run(cmd, shell=True) # Need another disk image for unprivileged user to access dst_disk = "/tmp/%s.img" % unprivileged_user # Destroy VM first if vm.is_alive(): vm.destroy(gracefully=False) # Back up xml file. vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) iface_mac_old = vm_xml.VMXML.get_first_mac_by_name(vm_name) # iface_mac will update if attach a new interface iface_mac = iface_mac_old # Additional vm for test additional_vm = None libvirtd = utils_libvirtd.Libvirtd() libvirtd_log_path = None libvirtd_conf = None if check_libvirtd_log: libvirtd_log_path = os.path.join(test.tmpdir, "libvirtd.log") libvirtd_conf = utils_config.LibvirtdConfig() libvirtd_conf["log_outputs"] = '"1:file:%s"' % libvirtd_log_path libvirtd.restart() # Prepare vhostuser ovs = None if need_vhostuser_env: # Reserve selinux status selinux_mode = utils_selinux.get_status() # Reserve orig page size orig_size = utils_memory.get_num_huge_pages() ovs_dir = data_dir.get_tmp_dir() ovs = utils_net.setup_ovs_vhostuser(hugepage_num, ovs_dir, ovs_br_name, vhostuser_names, queue_size) try: # Build the xml and run test. try: # Prepare interface backend files if test_backend: if not os.path.exists("/dev/vhost-net"): process.run("modprobe vhost-net", shell=True) backend = ast.literal_eval(iface_backend) backend_tap = "/dev/net/tun" backend_vhost = "/dev/vhost-net" if not backend: backend["tap"] = backend_tap backend["vhost"] = backend_vhost if not start_error: # Create backend files for normal test if not os.path.exists(backend["tap"]): os.rename(backend_tap, backend["tap"]) if not os.path.exists(backend["vhost"]): os.rename(backend_vhost, backend["vhost"]) # Edit the interface xml. if change_option: modify_iface_xml(update=False) if define_error: return if test_target: logging.debug("Setting target device name to %s", target_dev) modify_iface_xml(update=False) if rm_vhost_driver: # remove vhost driver on host and # the character file /dev/vhost-net cmd = ("modprobe -r {0}; " "rm -f /dev/vhost-net".format("vhost_net")) if process.system(cmd, ignore_status=True, shell=True): test.error("Failed to remove vhost_net driver") else: # Load vhost_net driver by default cmd = "modprobe vhost_net" process.system(cmd, shell=True) # Attach a interface when vm is shutoff if attach_device == 'config': iface_mac = utils_net.generate_mac_address_simple() iface_xml_obj = create_iface_xml(iface_mac) iface_xml_obj.xmltreefile.write() ret = virsh.attach_device(vm_name, iface_xml_obj.xml, flagstr="--config", ignore_status=True) libvirt.check_exit_status(ret) # Add hugepage and update cpu for vhostuser testing if huge_page: vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) membacking = vm_xml.VMMemBackingXML() hugepages = vm_xml.VMHugepagesXML() pagexml = hugepages.PageXML() pagexml.update(huge_page) hugepages.pages = [pagexml] membacking.hugepages = hugepages vmxml.mb = membacking vmxml.vcpu = int(vcpu_num) cpu_xml = vm_xml.VMCPUXML() cpu_xml.xml = "<cpu><numa/></cpu>" cpu_xml.numa_cell = [numa_cell] cpu_xml.mode = cpu_mode if cpu_mode == "custom": vm_capability = capability_xml.CapabilityXML() cpu_xml.model = vm_capability.model vmxml.cpu = cpu_xml vmxml.sync() logging.debug("xmltreefile:%s", vmxml.xmltreefile) # Clone additional vm if additional_guest: add_vm_name = "%s_%s" % (vm_name, '1') # Clone additional guest timeout = params.get("clone_timeout", 360) utils_libguestfs.virt_clone_cmd(vm_name, add_vm_name, True, timeout=timeout) additional_vm = vm.clone(add_vm_name) # Update iface source if needed if additional_iface_source: add_vmxml = vm_xml.VMXML.new_from_dumpxml(add_vm_name) add_xml_devices = add_vmxml.devices add_iface_index = add_xml_devices.index( add_xml_devices.by_device_tag("interface")[0]) add_iface = add_xml_devices[add_iface_index] add_iface.source = additional_iface_source add_vmxml.devices = add_xml_devices add_vmxml.xmltreefile.write() add_vmxml.sync() logging.debug("add vm xmltreefile:%s", add_vmxml.xmltreefile) additional_vm.start() # additional_vm.wait_for_login() username = params.get("username") password = params.get("password") add_session = additional_vm.wait_for_serial_login( username=username, password=password) # Start the VM. if unprivileged_user: virsh.start(vm_name, **virsh_dargs) cmd = ("su - %s -c 'virsh console %s'" % (unprivileged_user, vm_name)) session = aexpect.ShellSession(cmd) session.sendline() remote.handle_prompts(session, params.get("username"), params.get("password"), r"[\#\$]\s*$", 60) # Get ip address on guest if not get_guest_ip(session, iface_mac): test.error("Can't get ip address on guest") else: # Will raise VMStartError exception if start fails vm.start() if serial_login: session = vm.wait_for_serial_login() else: session = vm.wait_for_login() if start_error: test.fail("VM started unexpectedly") # Attach a interface when vm is running if attach_device == 'live': iface_mac = utils_net.generate_mac_address_simple() iface_xml_obj = create_iface_xml(iface_mac) iface_xml_obj.xmltreefile.write() ret = virsh.attach_device(vm_name, iface_xml_obj.xml, flagstr="--live", ignore_status=True, debug=True) libvirt.check_exit_status(ret, status_error) # Need sleep here for attachment take effect time.sleep(5) # Update a interface options if update_device: modify_iface_xml(update=True, status_error=status_error) # Run tests for qemu-kvm command line options if test_option_cmd: run_cmdline_test(iface_mac, host_arch) # Run tests for vm xml if test_option_xml: run_xml_test(iface_mac) # Run tests for offloads options if test_option_offloads: if iface_driver_host: ifname_guest = utils_net.get_linux_ifname( session, iface_mac) check_offloads_option(ifname_guest, ast.literal_eval(iface_driver_host), session) if iface_driver_guest: ifname_host = libvirt.get_ifname_host(vm_name, iface_mac) check_offloads_option(ifname_host, ast.literal_eval(iface_driver_guest)) if test_iface_user: # Test user type network check_user_network(session) if test_iface_mcast: # Test mcast type network check_mcast_network(session, add_session) # Check guest ip address if test_guest_ip: if not get_guest_ip(session, iface_mac): test.fail("Guest can't get a" " valid ip address") # Check guest RX/TX ring if check_guest_trans: ifname_guest = utils_net.get_linux_ifname(session, iface_mac) ret, outp = session.cmd_status_output("ethtool -g %s" % ifname_guest) if ret: test.fail("ethtool return error code") logging.info("ethtool output is %s", outp) driver_dict = ast.literal_eval(iface_driver) if expect_tx_size: driver_dict['tx_queue_size'] = expect_tx_size for outp_p in outp.split("Current hardware"): if 'rx_queue_size' in driver_dict: if re.search( r"RX:\s*%s" % driver_dict['rx_queue_size'], outp_p): logging.info("Find RX setting RX:%s by ethtool", driver_dict['rx_queue_size']) else: test.fail("Cannot find matching rx setting") if 'tx_queue_size' in driver_dict: if re.search( r"TX:\s*%s" % driver_dict['tx_queue_size'], outp_p): logging.info("Find TX settint TX:%s by ethtool", driver_dict['tx_queue_size']) else: test.fail("Cannot find matching tx setting") if test_target: logging.debug("Check if the target dev is set") run_xml_test(iface_mac) # Check vhostuser guest if additional_iface_source: check_vhostuser_guests(session, add_session) # Check libvirtd log if check_libvirtd_log: find = 0 with open(libvirtd_log_path) as f: lines = "".join(f.readlines()) if log_pattern in lines: logging.info("Finding msg<%s> in libvirtd log", log_pattern) else: test.fail("Can not find msg:<%s> in libvirtd.log" % log_pattern) # Check statistics if check_statistics: session.sendline("ping %s" % guest2_ip) add_session.sendline("ping %s" % guest1_ip) time.sleep(5) vhost_name = vhostuser_names.split()[0] ovs_statis_dict = get_ovs_statis(ovs)[vhost_name] domif_info = {} domif_info = libvirt.get_interface_details(vm_name) virsh.domiflist(vm_name, debug=True) domif_stat_result = virsh.domifstat(vm_name, vhost_name) if domif_stat_result.exit_status != 0: test.fail("domifstat cmd fail with msg:%s" % domif_stat_result.stderr) else: domif_stat = domif_stat_result.stdout.strip() logging.debug("vhost_name is %s, domif_stat is %s", vhost_name, domif_stat) domif_stat_dict = dict( re.findall("%s (\S*) (\d*)" % vhost_name, domif_stat)) logging.debug("ovs_statis is %s, domif_stat is %s", ovs_statis_dict, domif_stat_dict) ovs_cmp_dict = { 'tx_bytes': ovs_statis_dict['rx_bytes'], 'tx_drop': ovs_statis_dict['rx_dropped'], 'tx_errs': ovs_statis_dict['rx_errors'], 'tx_packets': ovs_statis_dict['rx_packets'], 'rx_bytes': ovs_statis_dict['tx_bytes'], 'rx_drop': ovs_statis_dict['tx_dropped'] } logging.debug("ovs_cmp_dict is %s", ovs_cmp_dict) for dict_key in ovs_cmp_dict.keys(): if domif_stat_dict[dict_key] != ovs_cmp_dict[dict_key]: test.fail( "Find ovs %s result (%s) different with domifstate result (%s)" % (dict_key, ovs_cmp_dict[dict_key], domif_stat_dict[dict_key])) else: logging.info("ovs %s value %s is same with domifstate", dict_key, domif_stat_dict[dict_key]) # Check multi_queue if enable_multiqueue: ifname_guest = utils_net.get_linux_ifname(session, iface_mac) for comb_size in (queue_size, queue_size - 1): logging.info("Setting multiqueue size to %s" % comb_size) session.cmd_status("ethtool -L %s combined %s" % (ifname_guest, comb_size)) ret, outp = session.cmd_status_output("ethtool -l %s" % ifname_guest) logging.debug("ethtool cmd output:%s" % outp) if not ret: pre_comb = re.search( "Pre-set maximums:[\s\S]*?Combined:.*?(\d+)", outp).group(1) cur_comb = re.search( "Current hardware settings:[\s\S]*?Combined:.*?(\d+)", outp).group(1) if int(pre_comb) != queue_size or int(cur_comb) != int( comb_size): test.fail( "Fail to check the combined size: setting: %s," "Pre-set: %s, Current-set: %s, queue_size: %s" % (comb_size, pre_comb, cur_comb, queue_size)) else: logging.info( "Getting correct Pre-set and Current set value" ) else: test.error("ethtool list fail: %s" % outp) session.close() if additional_guest: add_session.close() # Restart libvirtd and guest, then test again if restart_libvirtd: libvirtd.restart() if restart_vm: vm.destroy(gracefully=True) vm.start() if test_option_xml: run_xml_test(iface_mac) # Detach hot/cold-plugged interface at last if attach_device and not status_error: ret = virsh.detach_device(vm_name, iface_xml_obj.xml, flagstr="", ignore_status=True, debug=True) libvirt.check_exit_status(ret) except virt_vm.VMStartError as e: logging.info(str(e)) if not start_error: test.fail('VM failed to start\n%s' % e) finally: # Recover VM. logging.info("Restoring vm...") # Restore interface backend files if test_backend: if not os.path.exists(backend_tap): os.rename(backend["tap"], backend_tap) if not os.path.exists(backend_vhost): os.rename(backend["vhost"], backend_vhost) if rm_vhost_driver: # Restore vhost_net driver process.system("modprobe vhost_net", shell=True) if unprivileged_user: virsh.remove_domain(vm_name, **virsh_dargs) process.run('rm -f %s' % dst_disk, shell=True) if additional_vm: virsh.remove_domain(additional_vm.name, "--remove-all-storage") # Kill all omping server process on host process.system("pidof omping && killall omping", ignore_status=True, shell=True) if vm.is_alive(): vm.destroy(gracefully=True) vmxml_backup.sync() if need_vhostuser_env: utils_net.clean_ovs_env(selinux_mode=selinux_mode, page_size=orig_size, clean_ovs=True) if libvirtd_conf: libvirtd_conf.restore() libvirtd.restart() if libvirtd_log_path and os.path.exists(libvirtd_log_path): os.unlink(libvirtd_log_path)
def export_target(self): """ Export target in localhost for emulated iscsi """ selinux_mode = None if not os.path.isfile(self.emulated_image): process.system(self.create_cmd) else: emulated_image_size = os.path.getsize(self.emulated_image) // 1024 if emulated_image_size != self.emulated_expect_size: # No need to remvoe, rebuild is fine process.system(self.create_cmd) cmd = "tgtadm --lld iscsi --mode target --op show" try: output = decode_to_text(process.system_output(cmd)) except process.CmdError: restart_tgtd() output = decode_to_text(process.system_output(cmd)) if not re.findall("%s$" % self.target, output, re.M): logging.debug("Need to export target in host") # Set selinux to permissive mode to make sure iscsi target # export successfully if utils_selinux.is_enforcing(): selinux_mode = utils_selinux.get_status() utils_selinux.set_status("permissive") output = decode_to_text(process.system_output(cmd)) used_id = re.findall("Target\s+(\d+)", output) emulated_id = 1 while str(emulated_id) in used_id: emulated_id += 1 self.emulated_id = str(emulated_id) cmd = "tgtadm --mode target --op new --tid %s" % self.emulated_id cmd += " --lld iscsi --targetname %s" % self.target process.system(cmd) cmd = "tgtadm --lld iscsi --op bind --mode target " cmd += "--tid %s -I ALL" % self.emulated_id process.system(cmd) else: target_strs = re.findall("Target\s+(\d+):\s+%s$" % self.target, output, re.M) self.emulated_id = target_strs[0].split(':')[0].split()[-1] cmd = "tgtadm --lld iscsi --mode target --op show" try: output = decode_to_text(process.system_output(cmd)) except process.CmdError: # In case service stopped restart_tgtd() output = decode_to_text(process.system_output(cmd)) # Create a LUN with emulated image if re.findall(self.emulated_image, output, re.M): # Exist already logging.debug("Exported image already exists.") self.export_flag = True else: tgt_str = re.search(r'.*(Target\s+\d+:\s+%s\s*.*)$' % self.target, output, re.DOTALL) if tgt_str: luns = len(re.findall("\s+LUN:\s(\d+)", tgt_str.group(1), re.M)) else: luns = len(re.findall("\s+LUN:\s(\d+)", output, re.M)) cmd = "tgtadm --mode logicalunit --op new " cmd += "--tid %s --lld iscsi " % self.emulated_id cmd += "--lun %s " % luns cmd += "--backing-store %s" % self.emulated_image process.system(cmd) self.export_flag = True self.luns = luns # Restore selinux if selinux_mode is not None: utils_selinux.set_status(selinux_mode) if self.chap_flag: # Set CHAP authentication on the exported target self.set_chap_auth_target() # Set CHAP authentication for initiator to login target if self.portal_visible(): self.set_chap_auth_initiator()
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" process.run(cmd, timeout=600, 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 export_target(self): """ Export target in localhost for emulated iscsi """ selinux_mode = None # create image disk if not os.path.isfile(self.emulated_image): process.system(self.create_cmd) else: emulated_image_size = os.path.getsize(self.emulated_image) // 1024 if emulated_image_size != self.emulated_expect_size: # No need to remvoe, rebuild is fine process.system(self.create_cmd) # confirm if the target exists and create iSCSI target cmd = "targetcli ls /iscsi 1" output = decode_to_text(process.system_output(cmd)) if not re.findall("%s$" % self.target, output, re.M): logging.debug("Need to export target in host") # Set selinux to permissive mode to make sure # iscsi target export successfully if utils_selinux.is_enforcing(): selinux_mode = utils_selinux.get_status() utils_selinux.set_status("permissive") # In fact, We've got two options here # # 1) Create a block backstore that usually provides the best # performance. We can use a block device like /dev/sdb or # a logical volume previously created, # (lvcreate -name lv_iscsi -size 1G vg) # 2) Create a fileio backstore, # which enables the local file system cache. # # This class Only works for emulated iscsi device, # So fileio backstore is enough and safe. # Create a fileio backstore device_cmd = ("targetcli /backstores/fileio/ create %s %s" % (self.device, self.emulated_image)) output = decode_to_text(process.system_output(device_cmd)) if "Created fileio" not in output: raise exceptions.TestFail("Failed to create fileio %s. (%s)" % (self.device, output)) # Create an IQN with a target named target_name target_cmd = "targetcli /iscsi/ create %s" % self.target output = decode_to_text(process.system_output(target_cmd)) if "Created target" not in output: raise exceptions.TestFail("Failed to create target %s. (%s)" % (self.target, output)) check_portal = "targetcli /iscsi/%s/tpg1/portals ls" % self.target portal_info = decode_to_text(process.system_output(check_portal)) if "0.0.0.0:3260" not in portal_info: # Create portal # 0.0.0.0 means binding to INADDR_ANY # and using default IP port 3260 portal_cmd = ("targetcli /iscsi/%s/tpg1/portals/ create %s" % (self.target, "0.0.0.0")) output = decode_to_text(process.system_output(portal_cmd)) if "Created network portal" not in output: raise exceptions.TestFail("Failed to create portal. (%s)" % output) if ("ipv6" == utils_net.IPAddress(self.portal_ip).version and self.portal_ip not in portal_info): # Ipv6 portal address can't be created by default, # create ipv6 portal if needed. portal_cmd = ("targetcli /iscsi/%s/tpg1/portals/ create %s" % (self.target, self.portal_ip)) output = decode_to_text(process.system_output(portal_cmd)) if "Created network portal" not in output: raise exceptions.TestFail("Failed to create portal. (%s)" % output) # Create lun lun_cmd = "targetcli /iscsi/%s/tpg1/luns/ " % self.target dev_cmd = "create /backstores/fileio/%s" % self.device output = decode_to_text(process.system_output(lun_cmd + dev_cmd)) luns = re.findall(r"Created LUN (\d+).", output) if not luns: raise exceptions.TestFail("Failed to create lun. (%s)" % output) self.luns = luns[0] # Set firewall if it's enabled output = decode_to_text( process.system_output("firewall-cmd --state", ignore_status=True)) if re.findall("^running", output, re.M): # firewall is running process.system("firewall-cmd --permanent --add-port=3260/tcp") process.system("firewall-cmd --reload") # Restore selinux if selinux_mode is not None: utils_selinux.set_status(selinux_mode) self.export_flag = True else: logging.info("Target %s has already existed!" % self.target) if self.chap_flag: # Set CHAP authentication on the exported target self.set_chap_auth_target() # Set CHAP authentication for initiator to login target if self.portal_visible(): self.set_chap_auth_initiator() else: # To enable that so-called "demo mode" TPG operation, # disable all authentication for the corresponding Endpoint. # which means grant access to all initiators, # so that they can access all LUNs in the TPG # without further authentication. auth_cmd = "targetcli /iscsi/%s/tpg1/ " % self.target attr_cmd = ("set attribute %s %s %s %s" % ("authentication=0", "demo_mode_write_protect=0", "generate_node_acls=1", "cache_dynamic_acls=1")) output = decode_to_text(process.system_output(auth_cmd + attr_cmd)) logging.info("Define access rights: %s" % output) # Discovery the target self.portal_visible() # Save configuration process.system("targetcli / saveconfig") # Restart iSCSI service restart_iscsid()
def export_target(self): """ Export target in localhost for emulated iscsi """ selinux_mode = None # create image disk if not os.path.isfile(self.emulated_image): utils.system(self.create_cmd) else: emulated_image_size = os.path.getsize(self.emulated_image) / 1024 if emulated_image_size != self.emulated_expect_size: # No need to remvoe, rebuild is fine utils.system(self.create_cmd) # confirm if the target exists and create iSCSI target cmd = "targetcli ls /iscsi 1" output = utils.system_output(cmd) if not re.findall("%s$" % self.target, output, re.M): logging.debug("Need to export target in host") # Set selinux to permissive mode to make sure # iscsi target export successfully if utils_selinux.is_enforcing(): selinux_mode = utils_selinux.get_status() utils_selinux.set_status("permissive") # In fact, We've got two options here # # 1) Create a block backstore that usually provides the best # performance. We can use a block device like /dev/sdb or # a logical volume previously created, # (lvcreate -name lv_iscsi -size 1G vg) # 2) Create a fileio backstore, # which enables the local file system cache. # # This class Only works for emulated iscsi device, # So fileio backstore is enough and safe. # Create a fileio backstore device_cmd = ("targetcli /backstores/fileio/ create %s %s" % (self.device, self.emulated_image)) output = utils.system_output(device_cmd) if "Created fileio" not in output: raise error.TestFail("Failed to create fileio %s. (%s)", self.device, output) # Create an IQN with a target named target_name target_cmd = "targetcli /iscsi/ create %s" % self.target output = utils.system_output(target_cmd) if "Created target" not in output: raise error.TestFail("Failed to create target %s. (%s)", self.target, output) check_portal = "targetcli /iscsi/%s/tpg1/portals ls" % self.target if "0.0.0.0:3260" not in utils.system_output(check_portal): # Create portal # 0.0.0.0 means binding to INADDR_ANY # and using default IP port 3260 portal_cmd = ("targetcli /iscsi/%s/tpg1/portals/ create %s" % (self.target, "0.0.0.0")) output = utils.system_output(portal_cmd) if "Created network portal" not in output: raise error.TestFail("Failed to create portal. (%s)", output) # Create lun lun_cmd = "targetcli /iscsi/%s/tpg1/luns/ " % self.target dev_cmd = "create /backstores/fileio/%s" % self.device output = utils.system_output(lun_cmd + dev_cmd) if "Created LUN" not in output: raise error.TestFail("Failed to create lun. (%s)", output) # Set firewall if it's enabled output = utils.system_output("firewall-cmd --state", ignore_status=True) if re.findall("^running", output, re.M): # firewall is running utils.system("firewall-cmd --permanent --add-port=3260/tcp") utils.system("firewall-cmd --reload") # Restore selinux if selinux_mode is not None: utils_selinux.set_status(selinux_mode) self.export_flag = True else: logging.info("Target %s has already existed!" % self.target) if self.chap_flag: # Set CHAP authentication on the exported target self.set_chap_auth_target() # Set CHAP authentication for initiator to login target if self.portal_visible(): self.set_chap_auth_initiator() else: # To enable that so-called "demo mode" TPG operation, # disable all authentication for the corresponding Endpoint. # which means grant access to all initiators, # so that they can access all LUNs in the TPG # without further authentication. auth_cmd = "targetcli /iscsi/%s/tpg1/ " % self.target attr_cmd = ("set attribute %s %s %s %s" % ("authentication=0", "demo_mode_write_protect=0", "generate_node_acls=1", "cache_dynamic_acls=1")) output = utils.system_output(auth_cmd + attr_cmd) logging.info("Define access rights: %s" % output) # Save configuration utils.system("targetcli / saveconfig")
def run(test, params, env): """ Test DAC setting in both domain xml and qemu.conf. (1) Init variables for test. (2) Set VM xml and qemu.conf with proper DAC label, also set monitor socket parent dir with propoer ownership and mode. (3) Start VM and check the context. """ # 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("vm_sec_type", "dynamic") vm_sec_model = params.get("vm_sec_model", "dac") vm_sec_label = params.get("vm_sec_label", None) vm_sec_relabel = params.get("vm_sec_relabel", "yes") sec_dict = { 'type': sec_type, 'model': vm_sec_model, 'relabel': vm_sec_relabel } if vm_sec_label: sec_dict['label'] = vm_sec_label set_qemu_conf = "yes" == params.get("set_qemu_conf", "no") # Get per-img seclabel variables disk_type = params.get("disk_type") disk_target = params.get('disk_target') disk_src_protocol = params.get("disk_source_protocol") vol_name = params.get("vol_name") tmp_dir = data_dir.get_tmp_dir() pool_name = params.get("pool_name", "gluster-pool") brick_path = os.path.join(tmp_dir, pool_name) invalid_label = 'yes' == params.get("invalid_label", "no") relabel = params.get("per_img_sec_relabel") sec_label = params.get("per_img_sec_label") per_sec_model = params.get("per_sec_model", 'dac') per_img_dict = { 'sec_model': per_sec_model, 'relabel': relabel, 'sec_label': sec_label } params.update(per_img_dict) # Get qemu.conf config variables qemu_user = params.get("qemu_user", 'qemu') qemu_group = params.get("qemu_group", 'qemu') dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) qemu_sock_mod = False qemu_sock_path = '/var/lib/libvirt/qemu/' qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: if set_qemu_conf: # Set qemu.conf for user and group if qemu_user: qemu_conf.user = qemu_user if qemu_group: qemu_conf.group = qemu_group if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() st = os.stat(qemu_sock_path) if not bool(st.st_mode & stat.S_IWGRP): # chmod g+w os.chmod(qemu_sock_path, st.st_mode | stat.S_IWGRP) qemu_sock_mod = True # Set the context of the VM. logging.debug("sec_dict is %s" % sec_dict) vmxml.set_seclabel([sec_dict]) vmxml.sync() # Get per-image seclabel in id string if sec_label: per_img_usr, per_img_grp = sec_label.split(':') sec_label_id = format_user_group_str(per_img_usr, per_img_grp) # Start VM to check the qemu process and image. try: # Set per-img sec context and start vm utlv.set_vm_disk(vm, params) # Start VM successfully. if status_error: if invalid_label: # invalid label should fail, more info in bug 1165485 raise error.TestNAError("The label or model not valid, " "check more info in bug: https://" "bugzilla.redhat.com/show_bug.cgi" "?id=1165485") else: raise error.TestFail("Test succeeded in negative case.") # Get vm process label when VM is running. vm_pid = vm.get_pid() pid_stat = os.stat("/proc/%d" % vm_pid) vm_process_uid = pid_stat.st_uid vm_process_gid = pid_stat.st_gid vm_context = "%s:%s" % (vm_process_uid, vm_process_gid) logging.debug("vm process label is: %s", vm_context) # Get vm image label when VM is running if disk_type != "network": disks = vm.get_blk_devices() f = os.open(disks[disk_target]['source'], 0) stat_re = os.fstat(f) disk_context = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) logging.debug("The disk dac label after vm start is: %s", disk_context) if sec_label and relabel == 'yes': if disk_context != sec_label_id: raise error.TestFail("The disk label is not equal to " "'%s'." % sec_label_id) except virt_vm.VMStartError, e: # Starting VM failed. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up if vm.is_alive(): vm.destroy(gracefully=False) backup_xml.sync() if qemu_sock_mod: st = os.stat(qemu_sock_path) os.chmod(qemu_sock_path, st.st_mode ^ stat.S_IWGRP) if set_qemu_conf: qemu_conf.restore() libvirtd.restart() utils_selinux.set_status(backup_sestatus) if disk_src_protocol == 'iscsi': utlv.setup_or_cleanup_iscsi(is_setup=False) elif disk_src_protocol == 'gluster': utlv.setup_or_cleanup_gluster(False, vol_name, brick_path) libvirtd.restart() elif disk_src_protocol == 'netfs': utlv.setup_or_cleanup_nfs(is_setup=False, restore_selinux=backup_sestatus)
def run_svirt_start_destroy(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Label the VM and disk with proper label. (3).Start VM and check the context. (4).Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_start_destroy_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_start_destroy_vm_sec_type", "dynamic") sec_model = params.get("svirt_start_destroy_vm_sec_model", "selinux") sec_label = params.get("svirt_start_destroy_vm_sec_label", None) sec_relabel = params.get("svirt_start_destroy_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_start_destroy_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) utils_selinux.set_context_of_file(filename=disk_path, context=img_label) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the context of the VM. vmxml.set_seclabel(sec_dict) vmxml.sync() try: # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with seclabel can access the image with the context. if status_error: raise error.TestFail("Test successed in negative case.") # Check the label of VM and image when VM is running. vm_context = utils_selinux.get_context_of_process(vm.get_pid()) if (sec_type == "static") and (not vm_context == sec_label): raise error.TestFail("Label of VM is not expected after starting.\n" "Detail: vm_context=%s, sec_label=%s" % (vm_context, sec_label)) disk_context = utils_selinux.get_context_of_file( filename=disks.values()[0]['source']) if (sec_relabel == "no") and (not disk_context == img_label): raise error.TestFail("Label of disk is not expected after VM " "starting.\n" "Detail: disk_context=%s, img_label=%s." % (disk_context, img_label)) if sec_relabel == "yes": vmxml = VMXML.new_from_dumpxml(vm_name) imagelabel = vmxml.get_seclabel()['imagelabel'] if not disk_context == imagelabel: raise error.TestFail("Label of disk is not relabeled by VM\n" "Detal: disk_context=%s, imagelabel=%s" % (disk_context, imagelabel)) # Check the label of disk after VM being destroyed. vm.destroy() img_label_after = utils_selinux.get_context_of_file( filename=disks.values()[0]['source']) if (not img_label_after == img_label): raise error.TestFail("Bug: Label of disk is not restored in VM " "shuting down.\n" "Detail: img_label_after=%s, " "img_label_before=%s.\n" % (img_label_after, img_label)) except virt_vm.VMStartError, e: # Starting VM failed. # VM with seclabel can not access the image with the context. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up for path, label in backup_labels_of_disks.items(): utils_selinux.set_context_of_file(filename=path, context=label) backup_xml.sync() utils_selinux.set_status(backup_sestatus)
def run(test, params, env): """ Test remote access with TCP, TLS connection """ test_dict = dict(params) vm_name = test_dict.get("main_vm") vm = env.get_vm(vm_name) start_vm = test_dict.get("start_vm", "no") # Server and client parameters server_ip = test_dict.get("server_ip") server_user = test_dict.get("server_user") server_pwd = test_dict.get("server_pwd") client_ip = test_dict.get("client_ip") client_user = test_dict.get("client_user") client_pwd = test_dict.get("client_pwd") server_cn = test_dict.get("server_cn") client_cn = test_dict.get("client_cn") target_ip = test_dict.get("target_ip", "") # generate remote IP if target_ip == "": if server_cn: target_ip = server_cn elif server_ip: target_ip = server_ip else: target_ip = target_ip remote_virsh_dargs = { 'remote_ip': server_ip, 'remote_user': server_user, 'remote_pwd': server_pwd, 'unprivileged_user': None, 'ssh_remote_auth': True } # Ceph disk parameters driver = test_dict.get("test_driver", "qemu") transport = test_dict.get("transport") plus = test_dict.get("conn_plus", "+") source_type = test_dict.get("vm_disk_source_type", "file") virsh_options = test_dict.get("virsh_options", "--verbose --live") vol_name = test_dict.get("vol_name") disk_src_protocol = params.get("disk_source_protocol") source_file = test_dict.get("disk_source_file") disk_format = test_dict.get("disk_format", "qcow2") mon_host = params.get("mon_host") ceph_key_opt = "" attach_disk = False # Disk XML file disk_xml = None # Define ceph_disk conditional variable ceph_disk = "yes" == test_dict.get("ceph_disk") # For --postcopy enable postcopy_options = test_dict.get("postcopy_options") if postcopy_options and not virsh_options.count(postcopy_options): virsh_options = "%s %s" % (virsh_options, postcopy_options) test_dict['virsh_options'] = virsh_options # For bi-directional and tls reverse test uri_port = test_dict.get("uri_port", ":22") uri_path = test_dict.get("uri_path", "/system") src_uri = test_dict.get("migration_source_uri", "qemu:///system") uri = "%s%s%s://%s%s%s" % (driver, plus, transport, target_ip, uri_port, uri_path) test_dict["desuri"] = uri # Make sure all of parameters are assigned a valid value check_parameters(test, test_dict) # Set up SSH key #ssh_key.setup_ssh_key(server_ip, server_user, server_pwd, port=22) remote_session = remote.wait_for_login('ssh', server_ip, '22', server_user, server_pwd, r"[\#\$]\s*$") remote_session.close() #ssh_key.setup_ssh_key(server_ip, server_user, server_pwd, port=22) # Set up remote ssh key and remote /etc/hosts file for bi-direction migration migr_vm_back = "yes" == test_dict.get("migrate_vm_back", "no") if migr_vm_back: ssh_key.setup_remote_ssh_key(server_ip, server_user, server_pwd) ssh_key.setup_remote_known_hosts_file(client_ip, server_ip, server_user, server_pwd) # Reset Vm state if needed if vm.is_alive() and start_vm == "no": vm.destroy(gracefully=False) # Back up xml file. vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Setup migration context migrate_setup = migration.MigrationTest() migrate_setup.migrate_pre_setup(test_dict["desuri"], params) # Install ceph-common on remote host machine. remote_ssh_session = remote.remote_login("ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$") if not utils_package.package_install(["ceph-common"], remote_ssh_session): test.error("Failed ot install required packages on remote host") remote_ssh_session.close() try: # Create a remote runner for later use runner_on_target = remote.RemoteRunner(host=server_ip, username=server_user, password=server_pwd) # Get initial Selinux config flex bit LOCAL_SELINUX_ENFORCING_STATUS = utils_selinux.get_status() logging.info("previous local enforce :%s", LOCAL_SELINUX_ENFORCING_STATUS) cmd_result = remote.run_remote_cmd('getenforce', params, runner_on_target) REMOTE_SELINUX_ENFORCING_STATUS = cmd_result.stdout_text logging.info("previous remote enforce :%s", REMOTE_SELINUX_ENFORCING_STATUS) if ceph_disk: logging.info( "Put local SELinux in permissive mode when test ceph migrating" ) utils_selinux.set_status("enforcing") logging.info("Put remote SELinux in permissive mode") cmd = "setenforce enforcing" cmd_result = remote.run_remote_cmd(cmd, params, runner_on_target) status, output = cmd_result.exit_status, cmd_result.stdout_text.strip( ) if status: test.Error("Failed to set SELinux " "in permissive mode") # Prepare ceph disk. key_file = os.path.join(data_dir.get_tmp_dir(), "ceph.key") test_dict['key_file'] = key_file test_dict['first_disk'] = vm.get_first_disk_devices() ceph_key_opt, secret_uuid = prepare_ceph_disk( test_dict, remote_virsh_dargs, test, runner_on_target) host_ip = test_dict.get('mon_host') disk_image = test_dict.get('disk_img') # Build auth information. auth_attrs = {} auth_attrs['auth_user'] = params.get("auth_user") auth_attrs['secret_type'] = params.get("secret_type") auth_attrs['secret_uuid'] = secret_uuid build_disk_xml(vm_name, disk_format, host_ip, disk_src_protocol, vol_name, disk_image, auth=auth_attrs) vm_xml_cxt = process.run("virsh dumpxml %s" % vm_name, shell=True).stdout_text logging.debug("The VM XML with ceph disk source: \n%s", vm_xml_cxt) try: if vm.is_dead(): vm.start() except virt_vm.VMStartError as e: logging.info("Failed to start VM") test.fail("Failed to start VM: %s" % vm_name) # Ensure the same VM name doesn't exist on remote host before migrating. destroy_vm_cmd = "virsh destroy %s" % vm_name remote.run_remote_cmd(cmd, params, runner_on_target) # Trigger migration migrate_vm(test, test_dict) 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 migrate_setup.migrate_pre_setup(src_uri, params) cmd = "virsh migrate %s %s %s" % (vm_name, virsh_options, src_uri) logging.debug("Start migrating: %s", cmd) cmd_result = remote.run_remote_cmd(cmd, params, runner_on_target) status, output = cmd_result.exit_status, cmd_result.stdout_text.strip( ) logging.info(output) if status: destroy_cmd = "virsh destroy %s" % vm_name remote.run_remote_cmd(destroy_cmd, params, runner_on_target) test.fail("Failed to run '%s' on remote: %s" % (cmd, output)) finally: logging.info("Recovery test environment") # Clean up of pre migration setup for local machine if migr_vm_back: migrate_setup.migrate_pre_setup(src_uri, params, cleanup=True) # Ensure VM can be cleaned up on remote host even migrating fail. destroy_vm_cmd = "virsh destroy %s" % vm_name remote.run_remote_cmd(destroy_vm_cmd, params, runner_on_target) logging.info("Recovery VM XML configration") vmxml_backup.sync() logging.debug("The current VM XML:\n%s", vmxml_backup.xmltreefile) # Clean up ceph environment. if disk_src_protocol == "rbd": # Clean up secret secret_list = get_secret_list() if secret_list: for secret_uuid in secret_list: virsh.secret_undefine(secret_uuid) # Clean up dirty secrets on remote host if testing involve in ceph auth. client_name = test_dict.get('client_name') client_key = test_dict.get("client_key") if client_name and client_key: try: remote_virsh = virsh.VirshPersistent(**remote_virsh_dargs) remote_dirty_secret_list = get_secret_list(remote_virsh) for dirty_secret_uuid in remote_dirty_secret_list: remote_virsh.secret_undefine(dirty_secret_uuid) except (process.CmdError, remote.SCPError) as detail: test.Error(detail) finally: remote_virsh.close_session() # Delete the disk if it exists. disk_src_name = "%s/%s" % (vol_name, test_dict.get('disk_img')) cmd = ("rbd -m {0} {1} info {2} && rbd -m {0} {1} rm " "{2}".format(mon_host, ceph_key_opt, disk_src_name)) process.run(cmd, ignore_status=True, shell=True) if LOCAL_SELINUX_ENFORCING_STATUS: logging.info("Restore SELinux in original mode") utils_selinux.set_status(LOCAL_SELINUX_ENFORCING_STATUS) if REMOTE_SELINUX_ENFORCING_STATUS: logging.info("Put remote SELinux in original mode") cmd = "yes yes | setenforce %s" % REMOTE_SELINUX_ENFORCING_STATUS remote.run_remote_cmd(cmd, params, runner_on_target) # Remove known hosts on local host cmd = "ssh-keygen -R %s" % server_ip process.run(cmd, ignore_status=True, shell=True) # Remove known hosts on remote host cmd = "ssh-keygen -R %s" % client_ip remote.run_remote_cmd(cmd, params, runner_on_target)
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Label the VM and disk with proper label. (3).Save VM and check the context. (4).Restore VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_save_restore_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_save_restore_vm_sec_type", "dynamic") sec_model = params.get("svirt_save_restore_vm_sec_model", "selinux") sec_label = params.get("svirt_save_restore_vm_sec_label", None) sec_relabel = params.get("svirt_save_restore_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_save_restore_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in list(disks.values()): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) utils_selinux.set_context_of_file(filename=disk_path, context=img_label) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() # Init a path to save VM. save_path = os.path.join(data_dir.get_tmp_dir(), "svirt_save") try: # Start VM to check the VM is able to access the image or not. try: vm.start() vm.save_to_file(path=save_path) vm.restore_from_file(path=save_path) # Save and restore VM successfully. if status_error: test.fail("Test succeeded in negative case.") except virt_vm.VMError as e: if not status_error: error_msg = "Test failed in positive case.\n error: %s\n" % e if str(e).count("getfd"): error_msg += ("More info pleass refer to" " https://bugzilla.redhat.com/show_bug.cgi?id=976632") test.fail(error_msg) finally: # clean up for path, label in list(backup_labels_of_disks.items()): utils_selinux.set_context_of_file(filename=path, context=label) backup_xml.sync() utils_selinux.set_status(backup_sestatus)
def run(test, params, env): """ Test DAC setting in both domain xml and qemu.conf. (1) Init variables for test. (2) Set VM xml and qemu.conf with proper DAC label, also set image and monitor socket parent dir with propoer ownership and mode. (3) Start VM and check the context. (4) Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("dac_start_destroy_host_selinux", "enforcing") qemu_group_user = "******" == params.get("qemu_group_user", "no") # Get variables about seclabel for VM. sec_type = params.get("dac_start_destroy_vm_sec_type", "dynamic") sec_model = params.get("dac_start_destroy_vm_sec_model", "dac") sec_label = params.get("dac_start_destroy_vm_sec_label", None) sec_relabel = params.get("dac_start_destroy_vm_sec_relabel", "yes") security_default_confined = params.get("security_default_confined", None) set_process_name = params.get("set_process_name", None) sec_dict = {'type': sec_type, 'model': sec_model, 'relabel': sec_relabel} if sec_label: sec_dict['label'] = sec_label set_sec_label = "yes" == params.get("set_sec_label", "no") set_qemu_conf = "yes" == params.get("set_qemu_conf", "no") qemu_no_usr_grp = "yes" == params.get("qemu_no_usr_grp", "no") # Get qemu.conf config variables qemu_user = params.get("qemu_user", None) qemu_group = params.get("qemu_group", None) dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get variables about image. img_label = params.get('dac_start_destroy_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} qemu_disk_mod = False if (not status_error): for disk in list(disks.values()): disk_path = disk['source'] f = os.open(disk_path, 0) stat_re = os.fstat(f) backup_labels_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) label_list = img_label.split(":") os.chown(disk_path, int(label_list[0]), int(label_list[1])) os.close(f) st = os.stat(disk_path) if not bool(st.st_mode & stat.S_IWGRP): # add group write mode to disk by chmod g+w os.chmod(disk_path, st.st_mode | stat.S_IWGRP) qemu_disk_mod = True # Set selinux of host. backup_sestatus = utils_selinux.get_status() if backup_sestatus == "disabled": test.cancel("SELinux is in Disabled " "mode. it must be in Enforcing " "mode to run this test") utils_selinux.set_status(host_sestatus) def _create_user(): """ Create a "vdsm_fake" in 'qemu' group for test """ logging.debug("create a user 'vdsm_fake' in 'qemu' group") cmd = "useradd vdsm_fake -G qemu -s /sbin/nologin" process.run(cmd, ignore_status=False, shell=True) create_qemu_user = False qemu_sock_mod = False qemu_sock_path = '/var/lib/libvirt/qemu/' qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # Check qemu_group_user if qemu_group_user: if set_qemu_conf: if "EXAMPLE" in qemu_user: if not check_qemu_grp_user("vdsm_fake", test): _create_user() create_qemu_user = True qemu_user = "******" qemu_group = "qemu" if set_sec_label: if sec_label: if "EXAMPLE" in sec_label: if not check_qemu_grp_user("vdsm_fake", test): _create_user() create_qemu_user = True sec_label = "vdsm_fake:qemu" sec_dict['label'] = sec_label st = os.stat(qemu_sock_path) if not bool(st.st_mode & stat.S_IWGRP): # chmod g+w os.chmod(qemu_sock_path, st.st_mode | stat.S_IWGRP) qemu_sock_mod = True if set_qemu_conf: # Transform qemu user and group to "uid:gid" qemu_user = qemu_user.replace("+", "") qemu_group = qemu_group.replace("+", "") qemu_conf_label_trans = format_user_group_str( qemu_user, qemu_group) # Set qemu.conf for user and group if qemu_user: qemu_conf.user = qemu_user if qemu_group: qemu_conf.group = qemu_group if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 if security_default_confined: qemu_conf.security_default_confined = security_default_confined if set_process_name: qemu_conf.set_process_name = set_process_name logging.debug("the qemu.conf content is: %s" % qemu_conf) if set_sec_label: # Transform seclabel to "uid:gid" if sec_label: sec_label = sec_label.replace("+", "") if ":" in sec_label: user, group = sec_label.split(":") sec_label_trans = format_user_group_str(user, group) # Set the context of the VM. logging.debug("sec_dict is %s" % sec_dict) vmxml.set_seclabel([sec_dict]) vmxml.sync() logging.debug("updated domain xml is: %s" % vmxml.xmltreefile) # Start VM to check the qemu process and image. try: libvirtd.restart() vm.start() # Start VM successfully. # VM with seclabel can access the image with the context. if status_error: test.fail("Test succeeded in negative case.") # Get vm process label when VM is running. vm_pid = vm.get_pid() pid_stat = os.stat("/proc/%d" % vm_pid) vm_process_uid = pid_stat.st_uid vm_process_gid = pid_stat.st_gid vm_context = "%s:%s" % (vm_process_uid, vm_process_gid) # Get vm image label when VM is running f = os.open(list(disks.values())[0]['source'], 0) stat_re = os.fstat(f) disk_context = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) # Check vm process and image DAC label after vm start if set_sec_label and sec_label: if ":" in sec_label: if vm_context != sec_label_trans: test.fail("Label of VM process is not " "expected after starting.\nDetail:" "vm_context=%s, sec_label_trans=%s" % (vm_context, sec_label_trans)) if sec_relabel == "yes": if dynamic_ownership: if disk_context != sec_label_trans: test.fail("Label of disk is not " + "expected" + " after VM starting.\n" + "Detail: disk_context" + "=%s" % disk_context + ", sec_label_trans=%s." % sec_label_trans) elif (set_qemu_conf and not security_default_confined and not qemu_no_usr_grp): if vm_context != qemu_conf_label_trans: test.fail("Label of VM process is not expected" " after starting.\nDetail: vm_context=" "%s, qemu_conf_label_trans=%s" % (vm_context, qemu_conf_label_trans)) if disk_context != qemu_conf_label_trans: if dynamic_ownership: test.fail("Label of disk is not expected " + "after VM starting.\nDetail: di" + "sk_context=%s, " % disk_context + "qemu_conf_label_trans=%s." % qemu_conf_label_trans) # check vm started with -name $vm_name,process=qemu:$vm_name if set_process_name: if libvirt_version.version_compare(1, 3, 5): chk_str = "-name guest=%s,process=qemu:%s" % (vm_name, vm_name) else: chk_str = "-name %s,process=qemu:%s" % (vm_name, vm_name) cmd = "ps -p %s -o command=" % vm_pid result = process.run(cmd, shell=True) if chk_str in result.stdout_text: logging.debug("%s found in vm process command: %s" % (chk_str, result.stdout_text)) else: test.fail("%s not in vm process command: %s" % (chk_str, result.stdout_text)) # Check the label of disk after VM being destroyed. vm.destroy() f = os.open(list(disks.values())[0]['source'], 0) stat_re = os.fstat(f) img_label_after = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) if libvirt_version.version_compare(5, 6, 0): if img_label_after != img_label: test.fail("Label of disk is img_label_after" ":%s" % img_label_after + ", it " "did not restore to %s in VM " "shutting down." % img_label) elif set_sec_label and sec_relabel == "yes": # As dynamic_ownership as 1 on non-share fs, current domain # image will restore to 0:0 when sec_relabel enabled. if dynamic_ownership: if not img_label_after == "0:0": test.fail("Label of disk is img_label_after" ":%s" % img_label_after + ", it " "did not restore to 0:0 in VM " "shutting down.") elif set_qemu_conf and not set_sec_label: # As dynamic_ownership as 1 on non-share fs, current domain # image will restore to 0:0 when only set qemu.conf. if dynamic_ownership: if not img_label_after == "0:0": test.fail("Label of disk is img_label_after" ":%s" % img_label_after + ", it " "did not restore to 0:0 in VM " "shutting down.") else: if (not img_label_after == img_label): test.fail("Bug: Label of disk is changed\n" "Detail: img_label_after=%s, " "img_label=%s.\n" % (img_label_after, img_label)) except virt_vm.VMStartError as e: # Starting VM failed. # VM with seclabel can not access the image with the context. if not status_error: err_msg = "Domain start failed as expected, check " err_msg += "more in https://bugzilla.redhat.com/show_bug" err_msg += ".cgi?id=856951" if set_sec_label: if sec_label: if sec_relabel == "yes" and sec_label_trans == "0:0": if set_qemu_conf and not qemu_no_usr_grp: if qemu_conf_label_trans == "107:107": logging.debug(err_msg) elif sec_relabel == "no" and sec_label_trans == "0:0": if not set_qemu_conf: logging.debug(err_msg) else: test.fail("Test failed in positive case." "error: %s" % e) finally: # clean up for path, label in list(backup_labels_of_disks.items()): label_list = label.split(":") os.chown(path, int(label_list[0]), int(label_list[1])) if qemu_disk_mod: st = os.stat(path) os.chmod(path, st.st_mode ^ stat.S_IWGRP) if set_sec_label: backup_xml.sync() if qemu_sock_mod: st = os.stat(qemu_sock_path) os.chmod(qemu_sock_path, st.st_mode ^ stat.S_IWGRP) if set_qemu_conf: qemu_conf.restore() libvirtd.restart() if create_qemu_user: cmd = "userdel -r vdsm_fake" output = process.run(cmd, ignore_status=True, shell=True) utils_selinux.set_status(backup_sestatus)
def run(test, params, env): """ Test DAC setting in both domain xml and qemu.conf. (1) Init variables for test. (2) Set VM xml and qemu.conf with proper DAC label, also set image and monitor socket parent dir with propoer ownership and mode. (3) Start VM and check the context. (4) Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("dac_start_destroy_host_selinux", "enforcing") qemu_group_user = "******" == params.get("qemu_group_user", "no") # Get variables about seclabel for VM. sec_type = params.get("dac_start_destroy_vm_sec_type", "dynamic") sec_model = params.get("dac_start_destroy_vm_sec_model", "dac") sec_label = params.get("dac_start_destroy_vm_sec_label", None) sec_relabel = params.get("dac_start_destroy_vm_sec_relabel", "yes") security_default_confined = params.get("security_default_confined", None) set_process_name = params.get("set_process_name", None) sec_dict = {'type': sec_type, 'model': sec_model, 'relabel': sec_relabel} if sec_label: sec_dict['label'] = sec_label set_sec_label = "yes" == params.get("set_sec_label", "no") set_qemu_conf = "yes" == params.get("set_qemu_conf", "no") # Get qemu.conf config variables qemu_user = params.get("qemu_user", None) qemu_group = params.get("qemu_group", None) dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('dac_start_destroy_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} qemu_disk_mod = False for disk in disks.values(): disk_path = disk['source'] f = os.open(disk_path, 0) stat_re = os.fstat(f) backup_labels_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) label_list = img_label.split(":") os.chown(disk_path, int(label_list[0]), int(label_list[1])) os.close(f) st = os.stat(disk_path) if not bool(st.st_mode & stat.S_IWGRP): # add group wirte mode to disk by chmod g+w os.chmod(disk_path, st.st_mode | stat.S_IWGRP) qemu_disk_mod = True # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) def _create_user(): """ Create a "vdsm_fake" in 'qemu' group for test """ logging.debug("create a user 'vdsm_fake' in 'qemu' group") cmd = "useradd vdsm_fake -G qemu -s /sbin/nologin" utils.run(cmd, ignore_status=False) create_qemu_user = False qemu_sock_mod = False qemu_sock_path = '/var/lib/libvirt/qemu/' qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # Check qemu_group_user if qemu_group_user: if set_qemu_conf: if "EXAMPLE" in qemu_user: if not check_qemu_grp_user("vdsm_fake"): _create_user() create_qemu_user = True qemu_user = "******" qemu_group = "qemu" if set_sec_label: if sec_label: if "EXAMPLE" in sec_label: if not check_qemu_grp_user("vdsm_fake"): _create_user() create_qemu_user = True sec_label = "vdsm_fake:qemu" sec_dict['label'] = sec_label st = os.stat(qemu_sock_path) if not bool(st.st_mode & stat.S_IWGRP): # chmod g+w os.chmod(qemu_sock_path, st.st_mode | stat.S_IWGRP) qemu_sock_mod = True if set_qemu_conf: # Transform qemu user and group to "uid:gid" qemu_user = qemu_user.replace("+", "") qemu_group = qemu_group.replace("+", "") qemu_conf_label_trans = format_user_group_str(qemu_user, qemu_group) # Set qemu.conf for user and group if qemu_user: qemu_conf.user = qemu_user if qemu_group: qemu_conf.group = qemu_group if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 if security_default_confined: qemu_conf.security_default_confined = security_default_confined if set_process_name: qemu_conf.set_process_name = set_process_name logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() if set_sec_label: # Transform seclabel to "uid:gid" if sec_label: sec_label = sec_label.replace("+", "") if ":" in sec_label: user, group = sec_label.split(":") sec_label_trans = format_user_group_str(user, group) # Set the context of the VM. logging.debug("sec_dict is %s" % sec_dict) vmxml.set_seclabel([sec_dict]) vmxml.sync() logging.debug("updated domain xml is: %s" % vmxml.xmltreefile) # Start VM to check the qemu process and image. try: vm.start() # Start VM successfully. # VM with seclabel can access the image with the context. if status_error: raise error.TestFail("Test succeeded in negative case.") # Get vm process label when VM is running. vm_pid = vm.get_pid() pid_stat = os.stat("/proc/%d" % vm_pid) vm_process_uid = pid_stat.st_uid vm_process_gid = pid_stat.st_gid vm_context = "%s:%s" % (vm_process_uid, vm_process_gid) # Get vm image label when VM is running f = os.open(disks.values()[0]['source'], 0) stat_re = os.fstat(f) disk_context = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) # Check vm process and image DAC label after vm start if set_sec_label and sec_label: if ":" in sec_label: if vm_context != sec_label_trans: raise error.TestFail("Label of VM processs is not " "expected after starting.\nDetail:" "vm_context=%s, sec_label_trans=%s" % (vm_context, sec_label_trans)) if sec_relabel == "yes": if dynamic_ownership: if disk_context != sec_label_trans: raise error.TestFail("Label of disk is not " + "expected" + " after VM starting.\n" + "Detail: disk_context" + "=%s" % disk_context + ", sec_label_trans=%s." % sec_label_trans) elif set_qemu_conf and not security_default_confined: if vm_context != qemu_conf_label_trans: raise error.TestFail("Label of VM processs is not expected" " after starting.\nDetail: vm_context=" "%s, qemu_conf_label_trans=%s" % (vm_context, qemu_conf_label_trans)) if disk_context != qemu_conf_label_trans: if dynamic_ownership: raise error.TestFail("Label of disk is not expected " + "after VM starting.\nDetail: di" + "sk_context=%s, " % disk_context + "qemu_conf_label_trans=%s." % qemu_conf_label_trans) # check vm started with -name $vm_name,process=qemu:$vm_name if set_process_name: chk_str = "-name %s,process=qemu:%s" % (vm_name, vm_name) cmd = "ps -p %s -o command=" % vm_pid result = utils.run(cmd) if chk_str in result.stdout: logging.debug("%s found in vm process command: %s" % (chk_str, result.stdout)) else: raise error.TestFail("%s not in vm process command: %s" % (chk_str, result.stdout)) # Check the label of disk after VM being destroyed. vm.destroy() f = os.open(disks.values()[0]['source'], 0) stat_re = os.fstat(f) img_label_after = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) if set_sec_label and sec_relabel == "yes": # As dynamic_ownership as 1 on non-share fs, current domain # image will restore to 0:0 when sec_relabel enabled. if dynamic_ownership: if not img_label_after == "0:0": raise error.TestFail("Label of disk is img_label_after" ":%s" % img_label_after + ", it " "did not restore to 0:0 in VM " "shuting down.") elif set_qemu_conf and not set_sec_label: # As dynamic_ownership as 1 on non-share fs, current domain # image will restore to 0:0 when only set qemu.conf. if dynamic_ownership: if not img_label_after == "0:0": raise error.TestFail("Label of disk is img_label_after" ":%s" % img_label_after + ", it " "did not restore to 0:0 in VM " "shuting down.") else: if (not img_label_after == img_label): raise error.TestFail("Bug: Label of disk is changed\n" "Detail: img_label_after=%s, " "img_label=%s.\n" % (img_label_after, img_label)) except virt_vm.VMStartError, e: # Starting VM failed. # VM with seclabel can not access the image with the context. if not status_error: err_msg = "Domain start fail not due to DAC setting, check " err_msg += "more in https://bugzilla.redhat.com/show_bug" err_msg += ".cgi?id=856951" if set_sec_label: if sec_label: if sec_relabel == "yes" and sec_label_trans == "0:0": if set_qemu_conf: if qemu_conf_label_trans == "107:107": raise error.TestNAError(err_msg) elif sec_relabel == "no" and sec_label_trans == "0:0": if not set_qemu_conf: raise error.TestNAError(err_msg) else: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up for path, label in backup_labels_of_disks.items(): label_list = label.split(":") os.chown(path, int(label_list[0]), int(label_list[1])) if qemu_disk_mod: st = os.stat(path) os.chmod(path, st.st_mode ^ stat.S_IWGRP) if set_sec_label: backup_xml.sync() if qemu_sock_mod: st = os.stat(qemu_sock_path) os.chmod(qemu_sock_path, st.st_mode ^ stat.S_IWGRP) if set_qemu_conf: qemu_conf.restore() libvirtd.restart() if create_qemu_user: cmd = "userdel -r vdsm_fake" output = utils.run(cmd, ignore_status=True) utils_selinux.set_status(backup_sestatus)
def run(test, params, env): """ convert specific kvm guest to rhev """ 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: raise ValueError('Missing command: virt-v2v') enable_legacy_policy = params_get(params, "enable_legacy_policy") == 'yes' version_required = params.get("version_required") hypervisor = params.get("hypervisor") vm_name = params.get('main_vm', 'EXAMPLE') target = params.get('target') remote_host = params.get('remote_host', 'EXAMPLE') input_mode = params.get("input_mode") output_mode = params.get('output_mode') output_format = params.get('output_format') source_user = params.get("username", "root") os_pool = storage = params.get('output_storage') bridge = params.get('bridge') network = params.get('network') ntp_server = params.get('ntp_server') vpx_dc = params.get("vpx_dc") esx_ip = params.get("esx_hostname") address_cache = env.get('address_cache') 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 = utlv.PoolVolumeTest(test, params) v2v_opts = '-v -x' if params.get('v2v_debug', 'on') in ['on', 'force_on'] else '' if params.get("v2v_opts"): # Add a blank by force v2v_opts += ' ' + params.get("v2v_opts") v2v_timeout = int(params.get('v2v_timeout', 3600)) skip_vm_check = params.get('skip_vm_check', 'no') status_error = 'yes' == params.get('status_error', 'no') checkpoint = params.get('checkpoint', '') debug_kernel = 'debug_kernel' == checkpoint backup_list = ['floppy', 'floppy_devmap', 'fstab_cdrom', 'sata_disk', 'network_rtl8139', 'network_e1000', 'spice', 'spice_encrypt', 'spice_qxl', 'spice_cirrus', 'vnc_qxl', 'vnc_cirrus', 'blank_2nd_disk', 'listen_none', 'listen_socket', 'only_net', 'only_br'] 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") # For VDDK input_transport = params.get("input_transport") vddk_libdir = params.get('vddk_libdir') # nfs mount source vddk_libdir_src = params.get('vddk_libdir_src') vddk_thumbprint = params.get('vddk_thumbprint') if version_required and not utils_v2v.multiple_versions_compare( version_required): test.cancel("Testing requires version: %s" % version_required) # Prepare step for different hypervisor if enable_legacy_policy: update_crypto_policy("LEGACY") if hypervisor == "esx": source_ip = params.get("vpx_hostname") source_pwd = params.get("vpx_password") vpx_passwd_file = params.get("vpx_passwd_file") # Create password file to access ESX hypervisor with open(vpx_passwd_file, 'w') as f: f.write(source_pwd) elif hypervisor == "xen": source_ip = params.get("xen_hostname") source_pwd = params.get("xen_host_passwd") # Set up ssh access using ssh-agent and authorized_keys xen_pubkey, xen_session = utils_v2v.v2v_setup_ssh_key( source_ip, source_user, source_pwd, auto_close=False) try: utils_misc.add_identities_into_ssh_agent() except Exception as e: process.run("ssh-agent -k") test.error("Fail to setup ssh-agent \n %s" % str(e)) elif hypervisor == "kvm": source_ip = None source_pwd = None else: test.cancel("Unsupported hypervisor: %s" % hypervisor) # Create libvirt URI v2v_uri = utils_v2v.Uri(hypervisor) remote_uri = v2v_uri.get_uri(source_ip, vpx_dc, esx_ip) LOG.debug("libvirt URI for converting: %s", remote_uri) # Make sure the VM exist before convert v2v_virsh = None close_virsh = False if hypervisor == 'kvm': v2v_virsh = virsh else: virsh_dargs = {'uri': remote_uri, 'remote_ip': source_ip, 'remote_user': source_user, 'remote_pwd': source_pwd, 'auto_close': True, 'debug': True} v2v_virsh = virsh.VirshPersistent(**virsh_dargs) LOG.debug('a new virsh session %s was created', v2v_virsh) close_virsh = True if not v2v_virsh.domain_exists(vm_name): test.error("VM '%s' not exist" % vm_name) def log_fail(msg): """ Log error and update error list """ LOG.error(msg) error_list.append(msg) def vm_shell(func): """ Decorator of shell session to vm """ def wrapper(*args, **kwargs): vm = libvirt_vm.VM(vm_name, params, test.bindir, env.get('address_cache')) if vm.is_dead(): LOG.info('VM is down. Starting it now.') vm.start() session = vm.wait_for_login() kwargs['session'] = session kwargs['vm'] = vm func(*args, **kwargs) if session: session.close() vm.shutdown() return wrapper def check_disks(vmcheck): """ Check disk counts inside the VM """ # Initialize windows boot up os_type = params.get("os_type", "linux") expected_disks = int(params.get("ori_disks", "1")) LOG.debug("Expect %s disks im VM after convert", expected_disks) # Get disk counts if os_type == "linux": cmd = "lsblk |grep disk |wc -l" disks = int(vmcheck.session.cmd(cmd).strip()) else: cmd = r"echo list disk > C:\list_disk.txt" vmcheck.session.cmd(cmd) cmd = r"diskpart /s C:\list_disk.txt" output = vmcheck.session.cmd(cmd).strip() LOG.debug("Disks in VM: %s", output) disks = len(re.findall(r'Disk\s\d', output)) LOG.debug("Find %s disks in VM after convert", disks) if disks == expected_disks: LOG.info("Disk counts is expected") else: log_fail("Disk counts is wrong") def check_vmlinuz_initramfs(v2v_output): """ Check if vmlinuz matches initramfs on multi-kernel case """ LOG.debug('Checking if vmlinuz matches initramfs') kernel_strs = re.findall( r'(\* kernel.*?\/boot\/config){1,}', v2v_output, re.DOTALL) if len(kernel_strs) == 0: test.error("Not find kernel information") # Remove duplicate items by set LOG.debug('Boots and kernel info: %s' % set(kernel_strs)) for str_i in set(kernel_strs): # Fine all versions kernel_vers = re.findall( r'((?:\d+\.){1,}\d+-(?:\d+\.){1,}\w+)', str_i) LOG.debug('kernel related versions: %s' % kernel_vers) # kernel_vers = [kernel, vmlinuz, initramfs] and they should be # same if len(kernel_vers) < 3 or len(set(kernel_vers)) != 1: log_fail("kernel versions does not match: %s" % kernel_vers) def check_boot_kernel(vmcheck): """ Check if converted vm use the latest kernel """ _, current_kernel = vmcheck.run_cmd('uname -r') if 'debug' in current_kernel: log_fail('Current kernel is a debug kernel: %s' % current_kernel) # 'sort -V' can satisfy our testing, even though it's not strictly perfect. # The last one is always the latest kernel version kernel_normal_list = vmcheck.run_cmd( 'rpm -q kernel | sort -V')[1].strip().splitlines() status, kernel_debug = vmcheck.run_cmd('rpm -q kernel-debug') if status != 0: test.error('Not found kernel-debug package') all_kernel_list = kernel_normal_list + kernel_debug.strip().splitlines() LOG.debug('All kernels: %s' % all_kernel_list) if len(all_kernel_list) < 3: test.error( 'Needs at least 2 normal kernels and 1 debug kernel in VM') # The latest non-debug kernel must be kernel_normal_list[-1] if current_kernel.strip() != kernel_normal_list[-1].lstrip('kernel-'): log_fail('Check boot kernel failed') def check_floppy_exist(vmcheck): """ Check if floppy exists after conversion """ blk = vmcheck.session.cmd('lsblk') LOG.info(blk) if not re.search('fd0', blk): log_fail('Floppy not found') def attach_removable_media(type, source, dev): bus = {'cdrom': 'ide', 'floppy': 'fdc', 'disk': 'virtio'} args = {'driver': 'qemu', 'subdriver': 'raw', 'sourcetype': 'file', 'type': type, 'targetbus': bus[type]} if type == 'cdrom': args.update({'mode': 'readonly'}) config = '' # Join all options together to get command line for key in list(args.keys()): config += ' --%s %s' % (key, args[key]) config += ' --current' virsh.attach_disk(vm_name, source, dev, extra=config) def change_disk_bus(dest): """ Change all disks' bus type to $dest """ bus_list = ['ide', 'sata', 'virtio'] if dest not in bus_list: test.error('Bus type not support') dev_prefix = ['h', 's', 'v'] dev_table = dict(list(zip(bus_list, dev_prefix))) LOG.info('Change disk bus to %s' % dest) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disks = vmxml.get_disk_all_by_expr('device==disk') index = 0 for disk in list(disks.values()): if disk.get('device') != 'disk': continue target = disk.find('target') target.set('bus', dest) target.set( 'dev', dev_table[dest] + 'd' + string.ascii_lowercase[index]) disk.remove(disk.find('address')) index += 1 vmxml.sync() def change_network_model(model): """ Change network model to $model """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) network_list = vmxml.get_iface_all() for node in list(network_list.values()): if node.get('type') == 'network': node.find('model').set('type', model) vmxml.sync() def attach_network_card(model): """ Attach network card based on model """ if model not in ('e1000', 'virtio', 'rtl8139'): test.error('Network model not support') options = {'type': 'network', 'source': 'default', 'model': model} line = '' for key in options: line += ' --' + key + ' ' + options[key] line += ' --current' LOG.debug(virsh.attach_interface(vm_name, option=line)) def check_multi_netcards(mac_list, vmxml): """ Check if number and type of network cards meet expectation """ xmltree = xml_utils.XMLTreeFile(vmxml) iface_nodes = xmltree.find('devices').findall('interface') iflist = {} for node in iface_nodes: mac_addr = node.find('mac').get('address') iflist[mac_addr] = node LOG.debug('MAC list before v2v: %s' % mac_list) LOG.debug('MAC list after v2v: %s' % list(iflist.keys())) if set(mac_list).difference(list(iflist.keys())): log_fail('Missing network interface') for mac in iflist: if iflist[mac].find('model').get('type') != 'virtio': log_fail('Network not convert to virtio') @vm_shell def insert_floppy_devicemap(**kwargs): """ Add an entry of floppy to device.map """ session = kwargs['session'] line = '(fd0) /dev/fd0' devmap = '/boot/grub/device.map' if session.cmd_status('ls %s' % devmap): devmap = '/boot/grub2/device.map' cmd_exist = 'grep \'(fd0)\' %s' % devmap cmd_set = 'sed -i \'2i%s\' %s' % (line, devmap) if session.cmd_status(cmd_exist): session.cmd(cmd_set) def make_label(session): """ Label a volume, swap or root volume """ # swaplabel for rhel7 with xfs, e2label for rhel6 or ext* cmd_map = {'root': 'e2label %s ROOT', 'swap': 'swaplabel -L SWAPPER %s'} if not session.cmd_status('swaplabel --help'): blk = 'swap' elif not session.cmd_status('which e2label'): blk = 'root' else: test.error('No tool to make label') entry = session.cmd('blkid|grep %s' % blk).strip() path = entry.split()[0].strip(':') cmd_label = cmd_map[blk] % path if 'LABEL' not in entry: session.cmd(cmd_label) return blk @vm_shell def specify_fstab_entry(type, **kwargs): """ Specify entry in fstab file """ type_list = ['cdrom', 'uuid', 'label', 'sr0', 'invalid'] if type not in type_list: test.error('Not support %s in fstab' % type) session = kwargs['session'] # Specify cdrom device if type == 'cdrom': line = '/dev/cdrom /media/CDROM auto exec' if 'grub2' in utils_misc.get_bootloader_cfg(session): line += ',nofail' line += ' 0 0' LOG.debug('fstab entry is "%s"', line) cmd = [ 'mkdir -p /media/CDROM', 'mount /dev/cdrom /media/CDROM', 'echo "%s" >> /etc/fstab' % line ] for i in range(len(cmd)): session.cmd(cmd[i]) elif type == 'sr0': line = params.get('fstab_content') session.cmd('echo "%s" >> /etc/fstab' % line) elif type == 'invalid': line = utils_misc.generate_random_string(6) session.cmd('echo "%s" >> /etc/fstab' % line) else: map = {'uuid': 'UUID', 'label': 'LABEL'} LOG.info(type) if session.cmd_status('cat /etc/fstab|grep %s' % map[type]): # Specify device by UUID if type == 'uuid': entry = session.cmd( 'blkid -s UUID|grep swap').strip().split() # Replace path for UUID origin = entry[0].strip(':') replace = entry[1].replace('"', '') # Specify device by label elif type == 'label': blk = make_label(session) entry = session.cmd('blkid|grep %s' % blk).strip() # Remove " from LABEL="****" replace = entry.split()[1].strip().replace('"', '') # Replace the original id/path with label origin = entry.split()[0].strip(':') cmd_fstab = "sed -i 's|%s|%s|' /etc/fstab" % (origin, replace) session.cmd(cmd_fstab) fstab = session.cmd_output('cat /etc/fstab') LOG.debug('Content of /etc/fstab:\n%s', fstab) def create_large_file(session, left_space): """ Create a large file to make left space of root less than $left_space MB """ cmd_guestfish = "guestfish get-cachedir" tmp_dir = session.cmd_output(cmd_guestfish).split()[-1] LOG.debug('Command output of tmp_dir: %s', tmp_dir) cmd_df = "df -m %s --output=avail" % tmp_dir df_output = session.cmd(cmd_df).strip() LOG.debug('Command output: %s', df_output) avail = int(df_output.strip().split('\n')[-1]) LOG.info('Available space: %dM' % avail) if avail <= left_space - 1: return None if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) large_file = os.path.join(tmp_dir, 'file.large') cmd_create = 'dd if=/dev/zero of=%s bs=1M count=%d' % \ (large_file, avail - left_space + 2) session.cmd(cmd_create, timeout=v2v_timeout) newAvail = int(session.cmd(cmd_df).strip().split('\n')[-1]) LOG.info('New Available space: %sM' % newAvail) return large_file @vm_shell def corrupt_rpmdb(**kwargs): """ Corrupt rpm db """ session = kwargs['session'] session.cmd('rm -f /var/lib/rpm/__db.*') session.cmd('touch /var/lib/rpm/__db.001') output = session.cmd_output('yum update --assumeno') LOG.debug(output) if 'rpmdb open failed' not in output: test.error('Prepare corrupt rpmdb failed') @vm_shell def grub_serial_terminal(**kwargs): """ Edit the serial and terminal lines of grub.conf """ session = kwargs['session'] vm = kwargs['vm'] grub_file = utils_misc.get_bootloader_cfg(session) if 'grub2' in grub_file: test.cancel('Skip this case on grub2') cmd = "sed -i '1iserial -unit=0 -speed=115200\\n" cmd += "terminal -timeout=10 serial console' %s" % grub_file session.cmd(cmd) @vm_shell def set_selinux(value, **kwargs): """ Set selinux stat of guest """ session = kwargs['session'] current_stat = session.cmd_output('getenforce').strip() LOG.debug('Current selinux status: %s', current_stat) if current_stat != value: cmd = "sed -E -i 's/(^SELINUX=).*?/\\1%s/' /etc/selinux/config" % value LOG.info('Set selinux stat with command %s', cmd) session.cmd(cmd) @vm_shell def get_firewalld_status(**kwargs): """ Return firewalld service status of vm """ session = kwargs['session'] # Example: Active: active (running) since Fri 2019-03-15 01:03:39 CST; # 3min 48s ago firewalld_status = session.cmd( 'systemctl status firewalld.service|grep Active:', ok_status=[ 0, 3]).strip() # Exclude the time string because time changes if vm restarts firewalld_status = re.search( r'Active:\s\w*\s\(\w*\)', firewalld_status).group() LOG.info('Status of firewalld: %s', firewalld_status) params[checkpoint] = firewalld_status def check_firewalld_status(vmcheck, expect_status): """ Check if status of firewalld meets expectation """ firewalld_status = vmcheck.session.cmd( 'systemctl status ' 'firewalld.service|grep Active:', ok_status=[ 0, 3]).strip() # Exclude the time string because time changes if vm restarts firewalld_status = re.search( r'Active:\s\w*\s\(\w*\)', firewalld_status).group() LOG.info('Status of firewalld after v2v: %s', firewalld_status) if firewalld_status != expect_status: log_fail('Status of firewalld changed after conversion') @vm_shell def vm_cmd(cmd_list, **kwargs): """ Execute a list of commands on guest. """ session = kwargs['session'] for cmd in cmd_list: LOG.info('Send command "%s"', cmd) # 'chronyc waitsync' needs more than 2mins to sync clock, # We set timeout to 300s will not have side-effects for other # commands. status, output = session.cmd_status_output(cmd, timeout=300) LOG.debug('Command output:\n%s', output) if status != 0: test.error('Command "%s" failed' % cmd) LOG.info('All commands executed') def check_time_keep(vmcheck): """ Check time drift after conversion. """ LOG.info('Check time drift') output = vmcheck.session.cmd('chronyc tracking') LOG.debug(output) if 'Not synchronised' in output: log_fail('Time not synchronised') lst_offset = re.search('Last offset *?: *(.*) ', output).group(1) drift = abs(float(lst_offset)) LOG.debug('Time drift is: %f', drift) if drift > 3: log_fail('Time drift exceeds 3 sec') def check_boot(): """ Check if guest can boot up after configuration """ try: vm = libvirt_vm.VM(vm_name, params, test.bindir, env.get('address_cache')) if vm.is_alive(): vm.shutdown() LOG.info('Booting up %s' % vm_name) vm.start() vm.wait_for_login() vm.shutdown() LOG.info('%s is down' % vm_name) except Exception as e: test.error('Bootup guest and login failed: %s' % str(e)) def check_result(result, status_error): """ Check virt-v2v command result """ utlv.check_exit_status(result, status_error) output = result.stdout_text + result.stderr_text if not status_error: if output_mode == 'json' and not check_json_output(params): test.fail('check json output failed') if output_mode == 'local' and not check_local_output(params): test.fail('check local output failed') if output_mode in ['null', 'json', 'local']: return vmchecker = VMChecker(test, params, env) params['vmchecker'] = vmchecker if output_mode == 'rhev': if not utils_v2v.import_vm_to_ovirt(params, address_cache, timeout=v2v_timeout): test.fail('Import VM failed') if 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 conversion if params.get('skip_vm_check') != 'yes': ret = vmchecker.run() if len(ret) == 0: LOG.info("All common checkpoints passed") LOG.debug(vmchecker.vmxml) if checkpoint == 'multi_kernel': check_boot_kernel(vmchecker.checker) check_vmlinuz_initramfs(output) if checkpoint == 'floppy': # Convert to rhv will remove all removable devices(floppy, # cdrom) if output_mode in ['local', 'libvirt']: check_floppy_exist(vmchecker.checker) if checkpoint == 'multi_disks': check_disks(vmchecker.checker) if checkpoint == 'multi_netcards': check_multi_netcards(params['mac_address'], vmchecker.vmxml) if checkpoint.startswith(('spice', 'vnc')): if checkpoint == 'spice_encrypt': vmchecker.check_graphics(params[checkpoint]) else: graph_type = checkpoint.split('_')[0] vmchecker.check_graphics({'type': graph_type}) video_type = vmchecker.xmltree.find( './devices/video/model').get('type') if utils_v2v.multiple_versions_compare(V2V_ADAPTE_SPICE_REMOVAL_VER): expect_video_type = 'vga' else: expect_video_type = 'qxl' if video_type.lower() != expect_video_type: log_fail('Video expect %s, actual %s' % (expect_video_type, video_type)) if checkpoint.startswith('listen'): listen_type = vmchecker.xmltree.find( './devices/graphics/listen').get('type') LOG.info('listen type is: %s', listen_type) if listen_type != checkpoint.split('_')[-1]: log_fail('listen type changed after conversion') if checkpoint.startswith('selinux'): status = vmchecker.checker.session.cmd( 'getenforce').strip().lower() LOG.info('Selinux status after v2v:%s', status) if status != checkpoint[8:]: log_fail('Selinux status not match') if checkpoint == 'check_selinuxtype': expect_output = vmchecker.checker.session.cmd( 'cat /etc/selinux/config') expect_selinuxtype = re.search( r'^SELINUXTYPE=\s*(\S+)$', expect_output, re.MULTILINE).group(1) actual_output = vmchecker.checker.session.cmd('sestatus') actual_selinuxtype = re.search( r'^Loaded policy name:\s*(\S+)$', actual_output, re.MULTILINE).group(1) if actual_selinuxtype != expect_selinuxtype: log_fail('Seliunx type not match') if checkpoint == 'guest_firewalld_status': check_firewalld_status(vmchecker.checker, params[checkpoint]) if checkpoint in ['ntpd_on', 'sync_ntp']: check_time_keep(vmchecker.checker) # Merge 2 error lists error_list.extend(vmchecker.errors) log_check = utils_v2v.check_log(params, output) if log_check: log_fail(log_check) if len(error_list): test.fail('%d checkpoints failed: %s' % (len(error_list), error_list)) try: v2v_sasl = None v2v_params = { 'target': target, 'hypervisor': hypervisor, 'main_vm': vm_name, 'input_mode': input_mode, 'network': network, 'bridge': bridge, 'os_storage': storage, 'os_pool': os_pool, 'hostname': source_ip, 'password': source_pwd, 'v2v_opts': v2v_opts, 'new_name': vm_name + utils_misc.generate_random_string(3), 'output_method': output_method, 'os_storage_name': storage_name, 'rhv_upload_opts': rhv_upload_opts, 'input_transport': input_transport, 'vcenter_host': source_ip, 'vcenter_password': source_pwd, 'vddk_thumbprint': vddk_thumbprint, 'vddk_libdir': vddk_libdir, 'vddk_libdir_src': vddk_libdir_src, 'params': params, } if vpx_dc: v2v_params.update({"vpx_dc": vpx_dc}) if esx_ip: v2v_params.update({"esx_ip": esx_ip}) output_format = params.get('output_format') if output_format: v2v_params.update({'of_format': output_format}) # Build rhev related options if output_mode == 'rhev': # Create different sasl_user name for different job params.update({'sasl_user': params.get("sasl_user") + utils_misc.generate_random_string(3)}) LOG.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) LOG.debug('A SASL session %s was created', v2v_sasl) 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) if output_mode == 'local': v2v_params['os_directory'] = data_dir.get_tmp_dir() if output_mode == 'libvirt': pvt.pre_pool(pool_name, pool_type, pool_target, '') # Set libguestfs environment variable utils_v2v.set_libguestfs_backend(params) # Save origin graphic type for result checking if source is KVM if hypervisor == 'kvm': ori_vm_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) params['ori_graphic'] = ori_vm_xml.xmltreefile.find( 'devices').find('graphics').get('type') params['vm_machine'] = ori_vm_xml.xmltreefile.find( './os/type').get('machine') backup_xml = None # Only kvm guest's xml needs to be backup currently if checkpoint in backup_list and hypervisor == 'kvm': backup_xml = ori_vm_xml if checkpoint == 'multi_disks': new_xml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=v2v_virsh) disk_count = len(new_xml.get_disk_all_by_expr('device==disk')) if disk_count <= 1: test.error('Not enough disk devices') params['ori_disks'] = disk_count if checkpoint == 'sata_disk': change_disk_bus('sata') if checkpoint.startswith('floppy'): if params['vm_machine'] and 'q35' in params['vm_machine'] and int( re.search(r'pc-q35-rhel(\d+)\.', params['vm_machine']).group(1)) >= 8: test.cancel( 'Device isa-fdc is not supported with machine type %s' % params['vm_machine']) img_path = data_dir.get_tmp_dir() + '/floppy.img' utlv.create_local_disk('floppy', img_path) attach_removable_media('floppy', img_path, 'fda') if checkpoint == 'floppy_devmap': insert_floppy_devicemap() if checkpoint.startswith('fstab'): if checkpoint == 'fstab_cdrom': img_path = data_dir.get_tmp_dir() + '/cdrom.iso' utlv.create_local_disk('iso', img_path) attach_removable_media('cdrom', img_path, 'hdc') specify_fstab_entry(checkpoint[6:]) if checkpoint == 'running': virsh.start(vm_name) LOG.info('VM state: %s' % virsh.domstate(vm_name).stdout.strip()) if checkpoint == 'paused': virsh.start(vm_name, '--paused') LOG.info('VM state: %s' % virsh.domstate(vm_name).stdout.strip()) if checkpoint == 'serial_terminal': grub_serial_terminal() check_boot() if checkpoint.startswith('host_no_space'): session = aexpect.ShellSession('sh') large_file = create_large_file(session, 800) if checkpoint == 'host_no_space_setcache': LOG.info('Set LIBGUESTFS_CACHEDIR=/home') os.environ['LIBGUESTFS_CACHEDIR'] = '/home' if checkpoint == 'corrupt_rpmdb': corrupt_rpmdb() if checkpoint.startswith('network'): change_network_model(checkpoint[8:]) if checkpoint == 'multi_netcards': params['mac_address'] = [] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml( vm_name, virsh_instance=v2v_virsh) network_list = vmxml.get_iface_all() for mac in network_list: if network_list[mac].get('type') in ['bridge', 'network']: params['mac_address'].append(mac) if len(params['mac_address']) < 2: test.error('Not enough network interface') LOG.debug('MAC address: %s' % params['mac_address']) if checkpoint.startswith(('spice', 'vnc')): if checkpoint == 'spice_encrypt': spice_passwd = {'type': 'spice', 'passwd': params.get('spice_passwd', 'redhat')} vm_xml.VMXML.set_graphics_attr(vm_name, spice_passwd) params[checkpoint] = {'type': 'spice', 'passwdValidTo': '1970-01-01T00:00:01'} else: graphic_video = checkpoint.split('_') graphic = graphic_video[0] LOG.info('Set graphic type to %s', graphic) vm_xml.VMXML.set_graphics_attr(vm_name, {'type': graphic}) if len(graphic_video) > 1: video_type = graphic_video[1] LOG.info('Set video type to %s', video_type) vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) video = vmxml.xmltreefile.find( 'devices').find('video').find('model') video.set('type', video_type) # cirrus doesn't support 'ram' and 'vgamem' attribute if video_type == 'cirrus': [video.attrib.pop(attr_i) for attr_i in [ 'ram', 'vgamem'] if attr_i in video.attrib] vmxml.sync() if checkpoint.startswith('listen'): listen_type = checkpoint.split('_')[-1] vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) listen = vmxml.xmltreefile.find( 'devices').find('graphics').find('listen') listen.set('type', listen_type) vmxml.sync() if checkpoint == 'host_selinux_on': params['selinux_stat'] = utils_selinux.get_status() utils_selinux.set_status('enforcing') if checkpoint.startswith('selinux'): set_selinux(checkpoint[8:]) if checkpoint.startswith('host_firewalld'): service_mgr = service.ServiceManager() LOG.info('Backing up firewall services status') params['bk_firewalld_status'] = service_mgr.status('firewalld') if 'start' in checkpoint: service_mgr.start('firewalld') if 'stop' in checkpoint: service_mgr.stop('firewalld') if checkpoint == 'guest_firewalld_status': get_firewalld_status() if checkpoint == 'remove_securetty': LOG.info('Remove /etc/securetty file from guest') cmd = ['rm -f /etc/securetty'] vm_cmd(cmd) if checkpoint == 'ntpd_on': LOG.info('Set service chronyd on') cmd = ['yum -y install chrony', 'systemctl start chronyd', 'chronyc add server %s' % ntp_server] vm_cmd(cmd) if checkpoint == 'sync_ntp': LOG.info('Sync time with %s', ntp_server) cmd = ['yum -y install chrony', 'systemctl start chronyd', 'chronyc add server %s' % ntp_server, 'chronyc waitsync'] vm_cmd(cmd) if checkpoint == 'blank_2nd_disk': disk_path = os.path.join(data_dir.get_tmp_dir(), 'blank.img') LOG.info('Create blank disk %s', disk_path) process.run('truncate -s 1G %s' % disk_path) LOG.info('Attach blank disk to vm') attach_removable_media('disk', disk_path, 'vdc') LOG.debug(virsh.dumpxml(vm_name)) if checkpoint in ['only_net', 'only_br']: LOG.info('Detatch all networks') virsh.detach_interface(vm_name, 'network --current', debug=True) LOG.info('Detatch all bridges') virsh.detach_interface(vm_name, 'bridge --current', debug=True) if checkpoint == 'only_net': LOG.info('Attach network') virsh.attach_interface( vm_name, 'network default --current', debug=True) if checkpoint == 'only_br': LOG.info('Attatch bridge') virsh.attach_interface( vm_name, 'bridge virbr0 --current', debug=True) if checkpoint == 'no_libguestfs_backend': os.environ.pop('LIBGUESTFS_BACKEND') if checkpoint == 'file_image': vm = env.get_vm(vm_name) disk = vm.get_first_disk_devices() LOG.info('Disk type is %s', disk['type']) if disk['type'] != 'file': test.error('Guest is not with file image') v2v_result = utils_v2v.v2v_cmd(v2v_params) if v2v_params.get('new_name'): vm_name = params['main_vm'] = v2v_params['new_name'] check_result(v2v_result, status_error) finally: if close_virsh and v2v_virsh: LOG.debug('virsh session %s is closing', v2v_virsh) v2v_virsh.close_session() if params.get('vmchecker'): params['vmchecker'].cleanup() if enable_legacy_policy: update_crypto_policy() if hypervisor == "xen": utils_v2v.v2v_setup_ssh_key_cleanup(xen_session, xen_pubkey) process.run('ssh-agent -k') if output_mode == 'rhev' and v2v_sasl: v2v_sasl.cleanup() LOG.debug('SASL session %s is closing', v2v_sasl) v2v_sasl.close_session() if output_mode == 'libvirt': pvt.cleanup_pool(pool_name, pool_type, pool_target, '') if backup_xml: backup_xml.sync() if params.get('selinux_stat') and params['selinux_stat'] != 'disabled': utils_selinux.set_status(params['selinux_stat']) if 'bk_firewalld_status' in params: service_mgr = service.ServiceManager() if service_mgr.status( 'firewalld') != params['bk_firewalld_status']: if params['bk_firewalld_status']: service_mgr.start('firewalld') else: service_mgr.stop('firewalld') if checkpoint.startswith('host_no_space'): if large_file and os.path.isfile(large_file): os.remove(large_file) # Cleanup constant files utils_v2v.cleanup_constant_files(params)
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 setup_or_cleanup_iscsi(is_setup, is_login=True, emulated_image="emulated_iscsi", image_size="1G"): """ Set up(and login iscsi target) or clean up iscsi service on localhost. :param is_setup: Boolean value, true for setup, false for cleanup :param is_login: Boolean value, true for login, false for not login :param emulated_image: name of iscsi device :param image_size: emulated image's size :return: iscsi device name or iscsi target """ try: utils_misc.find_command("tgtadm") utils_misc.find_command("iscsiadm") except ValueError: raise error.TestNAError("Missing command 'tgtadm' and/or 'iscsiadm'.") tmpdir = os.path.join(data_dir.get_root_dir(), 'tmp') emulated_path = os.path.join(tmpdir, emulated_image) emulated_target = "iqn.2001-01.com.virttest:%s.target" % emulated_image iscsi_params = { "emulated_image": emulated_path, "target": emulated_target, "image_size": image_size, "iscsi_thread_id": "virt" } _iscsi = iscsi.Iscsi(iscsi_params) if is_setup: sv_status = None if utils_selinux.is_enforcing(): sv_status = utils_selinux.get_status() utils_selinux.set_status("permissive") _iscsi.export_target() if sv_status is not None: utils_selinux.set_status(sv_status) if is_login: _iscsi.login() # The device doesn't necessarily appear instantaneously, so give # about 5 seconds for it to appear before giving up iscsi_device = utils_misc.wait_for(_iscsi.get_device_name, 5, 0, 1, "Searching iscsi device name.") if iscsi_device: logging.debug("iscsi device: %s", iscsi_device) return iscsi_device if not iscsi_device: logging.error("Not find iscsi device.") # Cleanup and return "" - caller needs to handle that # _iscsi.export_target() will have set the emulated_id and # export_flag already on success... _iscsi.cleanup() utils.run("rm -f %s" % emulated_path) else: return emulated_target else: _iscsi.export_flag = True _iscsi.emulated_id = _iscsi.get_target_id() _iscsi.cleanup() utils.run("rm -f %s" % emulated_path) return ""
def run(test, params, env): """ Test svirt in virt-clone. """ VIRT_CLONE = None try: VIRT_CLONE = utils_misc.find_command("virt-clone") except ValueError: raise error.TestNAError("No virt-clone command found.") # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_virt_clone_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_virt_clone_vm_sec_type", "dynamic") sec_model = params.get("svirt_virt_clone_vm_sec_model", "selinux") sec_label = params.get("svirt_virt_clone_vm_sec_label", None) sec_relabel = params.get("svirt_virt_clone_vm_sec_relabel", "yes") sec_dict = { 'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel } # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_virt_clone_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) utils_selinux.set_context_of_file(filename=disk_path, context=img_label) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() clone_name = ("%s-clone" % vm.name) try: cmd = ("%s --original %s --name %s --auto-clone" % (VIRT_CLONE, vm.name, clone_name)) cmd_result = utils.run(cmd, ignore_status=True) if cmd_result.exit_status: raise error.TestFail("Failed to execute virt-clone command." "Detail: %s." % cmd_result) finally: # clean up for path, label in backup_labels_of_disks.items(): utils_selinux.set_context_of_file(filename=path, context=label) backup_xml.sync() utils_selinux.set_status(backup_sestatus) if not virsh.domstate(clone_name).exit_status: libvirt_vm.VM(clone_name, params, None, None).remove_with_storage()
def run(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Label the VM and disk with proper label. (3).Start VM and check the context. (4).Destroy VM and check the context. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_undefine_define_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_undefine_define_vm_sec_type", "dynamic") sec_model = params.get("svirt_undefine_define_vm_sec_model", "selinux") sec_label = params.get("svirt_undefine_define_vm_sec_label", None) sec_relabel = params.get("svirt_undefine_define_vm_sec_relabel", "yes") sec_dict = { 'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel } poweroff_with_destroy = ("destroy" == params.get( "svirt_undefine_define_vm_poweroff", "destroy")) # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_undefine_define_disk_label') # Label the disks of VM with img_label. disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] backup_labels_of_disks[disk_path] = utils_selinux.get_context_of_file( filename=disk_path) utils_selinux.set_context_of_file(filename=disk_path, context=img_label) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the context of the VM. vmxml.set_seclabel([sec_dict]) vmxml.sync() try: xml_file = (os.path.join(data_dir.get_tmp_dir(), "vmxml")) if vm.is_alive(): vm.destroy() virsh.dumpxml(vm.name, to_file=xml_file) cmd_result = virsh.undefine(vm.name) if cmd_result.exit_status: raise error.TestFail("Failed to undefine vm." "Detail: %s" % cmd_result) cmd_result = virsh.define(xml_file) if cmd_result.exit_status: raise error.TestFail("Failed to define vm." "Detail: %s" % cmd_result) finally: # clean up for path, label in backup_labels_of_disks.items(): utils_selinux.set_context_of_file(filename=path, context=label) backup_xml.sync() utils_selinux.set_status(backup_sestatus)
def run_svirt_attach_disk(test, params, env): """ Test svirt in adding disk to VM. (1).Init variables for test. (2).Create a image to attached to VM. (3).Attach disk. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("svirt_attach_disk_host_selinux", "enforcing") # Get variables about seclabel for VM. sec_type = params.get("svirt_attach_disk_vm_sec_type", "dynamic") sec_model = params.get("svirt_attach_disk_vm_sec_model", "selinux") sec_label = params.get("svirt_attach_disk_vm_sec_label", None) sec_relabel = params.get("svirt_attach_disk_vm_sec_relabel", "yes") sec_dict = {'type': sec_type, 'model': sec_model, 'label': sec_label, 'relabel': sec_relabel} # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Get varialbles about image. img_label = params.get('svirt_attach_disk_disk_label') img_name = "svirt_disk" # Default label for the other disks. # To ensure VM is able to access other disks. default_label = params.get('svirt_attach_disk_disk_default_label', None) # Set selinux of host. backup_sestatus = utils_selinux.get_status() utils_selinux.set_status(host_sestatus) # Set the default label to other disks of vm. disks = vm.get_disk_devices() for disk in disks.values(): utils_selinux.set_context_of_file(filename=disk['source'], context=default_label) # Init a QemuImg instance. params['image_name'] = img_name tmp_dir = data_dir.get_tmp_dir() image = qemu_storage.QemuImg(params, tmp_dir, img_name) # Create a image. img_path, result = image.create(params) # Set the context of the image. utils_selinux.set_context_of_file(filename=img_path, context=img_label) # Set the context of the VM. vmxml.set_seclabel(sec_dict) vmxml.sync() # Do the attach action. try: virsh.attach_disk(vm_name, source=img_path, target="vdf", extra="--persistent", ignore_status=False) except error.CmdError: raise error.TestFail("Attach disk %s to vdf on VM %s failed." % (img_path, vm.name)) # Check result. try: # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. # VM with set seclabel can access the image with the # set context. if status_error: raise error.TestFail('Test successed in negative case.') except virt_vm.VMStartError, e: # Starting VM failed. # VM with set seclabel can not access the image with the # set context. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) finally: # clean up try: virsh.detach_disk(vm_name, target="vdf", extra="--persistent", ignore_status=False) except error.CmdError: raise error.TestFail("Detach disk 'vdf' from VM %s failed." % vm.name) image.remove() backup_xml.sync() utils_selinux.set_status(backup_sestatus)
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): test.cancel("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(test, 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, list(volumes.values())[volume_count - 1], disk_target, extra="--subdriver raw") 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): test.fail("Didn't find attached device:%s" % vm_attach_device) return # Test if attached disk can be used normally time.sleep(10) # Need seconds for the new disk to be recognized 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: test.fail("%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"] = list(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 as detail: test.fail("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) utils_misc.wait_for( lambda: not utlv.device_exists(vm, disk_target), 10) finally: pvtest.cleanup_pool(pool_name, pool_type, pool_target, emulated_img, device_name=block_device)
def run(test, params, env): """ Test DAC in adding nfs pool disk to VM. (1).Init variables for test. (2).Create nfs pool and vol. (3).Attach the nfs pool vol to VM. (4).Start VM and check result. """ # Get general variables. status_error = ('yes' == params.get("status_error", 'no')) host_sestatus = params.get("dac_nfs_disk_host_selinux", "enforcing") # Get qemu.conf config variables qemu_user = params.get("qemu_user") qemu_group = params.get("qemu_group") dynamic_ownership = "yes" == params.get("dynamic_ownership", "yes") # Get variables about pool vol virt_use_nfs = params.get("virt_use_nfs", "off") nfs_server_dir = params.get("nfs_server_dir", "nfs-server") pool_name = params.get("pool_name") pool_type = params.get("pool_type") pool_target = params.get("pool_target") export_options = params.get("export_options", "rw,async,no_root_squash,fsid=0") emulated_image = params.get("emulated_image") vol_name = params.get("vol_name") vol_format = params.get("vol_format") bk_file_name = params.get("bk_file_name") # Get pool vol variables img_tup = ("img_user", "img_group", "img_mode") img_val = [] for i in img_tup: try: img_val.append(int(params.get(i))) except ValueError: raise error.TestNAError("%s value '%s' is not a number." % (i, params.get(i))) img_user, img_group, img_mode = img_val # Get variables about VM and get a VM object and VMXML instance. vm_name = params.get("main_vm") vm = env.get_vm(vm_name) vmxml = VMXML.new_from_inactive_dumpxml(vm_name) backup_xml = vmxml.copy() # Backup domain disk label disks = vm.get_disk_devices() backup_labels_of_disks = {} for disk in disks.values(): disk_path = disk['source'] f = os.open(disk_path, 0) stat_re = os.fstat(f) backup_labels_of_disks[disk_path] = "%s:%s" % (stat_re.st_uid, stat_re.st_gid) os.close(f) # Backup selinux status of host. backup_sestatus = utils_selinux.get_status() pvt = None snapshot_name = None disk_snap_path = [] qemu_conf = utils_config.LibvirtQemuConfig() libvirtd = utils_libvirtd.Libvirtd() try: # chown domain disk to qemu:qemu to avoid fail on local disk for disk in disks.values(): disk_path = disk['source'] if qemu_user == "root": os.chown(disk_path, 0, 0) elif qemu_user == "qemu": os.chown(disk_path, 107, 107) # Set selinux of host. utils_selinux.set_status(host_sestatus) # set qemu conf qemu_conf.user = qemu_user qemu_conf.group = qemu_user if dynamic_ownership: qemu_conf.dynamic_ownership = 1 else: qemu_conf.dynamic_ownership = 0 logging.debug("the qemu.conf content is: %s" % qemu_conf) libvirtd.restart() # Create dst pool for create attach vol img logging.debug("export_options is: %s" % export_options) pvt = utlv.PoolVolumeTest(test, params) pvt.pre_pool(pool_name, pool_type, pool_target, emulated_image, image_size="1G", pre_disk_vol=["20M"], export_options=export_options) # set virt_use_nfs result = utils.run("setsebool virt_use_nfs %s" % virt_use_nfs) if result.exit_status: raise error.TestNAError("Failed to set virt_use_nfs value") # Init a QemuImg instance and create img on nfs server dir. params['image_name'] = vol_name tmp_dir = data_dir.get_tmp_dir() nfs_path = os.path.join(tmp_dir, nfs_server_dir) image = qemu_storage.QemuImg(params, nfs_path, vol_name) # Create a image. server_img_path, result = image.create(params) if params.get("image_name_backing_file"): params['image_name'] = bk_file_name params['has_backing_file'] = "yes" image = qemu_storage.QemuImg(params, nfs_path, bk_file_name) server_img_path, result = image.create(params) # Get vol img path vol_name = server_img_path.split('/')[-1] virsh.pool_refresh(pool_name, debug=True) cmd_result = virsh.vol_path(vol_name, pool_name, debug=True) if cmd_result.exit_status: raise error.TestNAError("Failed to get volume path from pool.") img_path = cmd_result.stdout.strip() # Do the attach action. extra = "--persistent --subdriver qcow2" result = virsh.attach_disk(vm_name, source=img_path, target="vdf", extra=extra, debug=True) if result.exit_status: raise error.TestFail("Failed to attach disk %s to VM." "Detail: %s." % (img_path, result.stderr)) # Change img ownership and mode on nfs server dir os.chown(server_img_path, img_user, img_group) os.chmod(server_img_path, img_mode) img_label_before = check_ownership(server_img_path) if img_label_before: logging.debug("attached image ownership on nfs server before " "start: %s" % img_label_before) # Start VM to check the VM is able to access the image or not. try: vm.start() # Start VM successfully. img_label_after = check_ownership(server_img_path) if img_label_after: logging.debug("attached image ownership on nfs server after" " start: %s" % img_label_after) if status_error: raise error.TestFail('Test succeeded in negative case.') except virt_vm.VMStartError, e: # Starting VM failed. if not status_error: raise error.TestFail("Test failed in positive case." "error: %s" % e) if params.get("image_name_backing_file"): options = "--disk-only" snapshot_result = virsh.snapshot_create(vm_name, options, debug=True) if snapshot_result.exit_status: if not status_error: raise error.TestFail("Failed to create snapshot. Error:%s." % snapshot_result.stderr.strip()) snapshot_name = re.search( "\d+", snapshot_result.stdout.strip()).group(0) if snapshot_name: disks_snap = vm.get_disk_devices() for disk in disks_snap.values(): disk_snap_path.append(disk['source']) virsh.snapshot_delete(vm_name, snapshot_name, "--metadata", debug=True) try: virsh.detach_disk(vm_name, target="vdf", extra="--persistent", debug=True) except error.CmdError: raise error.TestFail("Detach disk 'vdf' from VM %s failed." % vm.name)
def run(test, params, env): """ This case check error messages in libvirtd logging. Implemented test cases: with_iptables: Start libvirtd when using iptables service as firewall. with_firewalld: Start libvirtd when using firewalld service as firewall. no_firewall: Start libvirtd With both firewall services shut off. """ def _error_handler(line, errors): """ A callback function called when new error lines appares in libvirtd log, then this line is appended to list 'errors' :param errors: A list to contain all error lines. :param line: Newly found error line in libvirtd log. """ errors.append(line) def _check_errors(): """ Check for unexpected error messages in libvirtd log. """ logging.info('Checking errors in libvirtd log') accepted_error_patterns = [ 'Cannot access storage file', 'Failed to autostart storage pool', 'cannot open directory', ] if (not iptables_service and not firewalld_service and 'virt_t' not in libvirt_context): logging.info("virt_t is not in libvirtd process context. " "Failures for setting iptables rules will be ignored") # libvirtd process started without virt_t will failed to set # iptables rules which is expected here accepted_error_patterns.append( '/sbin/iptables .* unexpected exit status 1') logging.debug("Accepted errors are: %s", accepted_error_patterns) if errors: logging.debug("Found errors in libvirt log:") for line in errors: logging.debug(line) unexpected_errors = [] for line in errors: if any([re.search(p, line) for p in accepted_error_patterns]): logging.debug('Error "%s" is acceptable', line) else: unexpected_errors.append(line) if unexpected_errors: raise exceptions.TestFail( "Found unexpected errors in libvirt log:\n%s" % '\n'.join(unexpected_errors)) iptables_service = params.get('iptables_service', 'off') == 'on' firewalld_service = params.get('firewalld_service', 'off') == 'on' # In RHEL7 iptables service is provided by a separated package # In RHEL6 iptables-services and firewalld is not supported # So try to install all required packages but ignore failures logging.info('Preparing firewall related packages') software_mgr = software_manager.SoftwareManager() for pkg in ['iptables', 'iptables-services', 'firewalld']: if not software_mgr.check_installed(pkg): software_mgr.install(pkg) # Backup services status service_mgr = service.ServiceManager() logging.info('Backing up firewall services status') backup_iptables_status = service_mgr.status('iptables') backup_firewalld_status = service_mgr.status('firewalld') # iptables-service got deprecated in newer distros if iptables_service and backup_iptables_status is None: raise exceptions.TestSkipError('iptables service not found') # firewalld service could not exists on many distros if firewalld_service and backup_firewalld_status is None: raise exceptions.TestSkipError('firewalld service not found') try: if iptables_service and firewalld_service: raise exceptions.TestError( 'iptables service and firewalld service can not be started at ' 'the same time') # We should stop services first then start the other after. # Directly start one service will force the other service stop, # which will not be easy to handle. # Backup status should be compared with None to make sure that # service exists before action. logging.info('Changing firewall services status') if not iptables_service and backup_iptables_status is not None: process.run('iptables-save > /tmp/iptables.save', shell=True) service_mgr.stop('iptables') if not firewalld_service and backup_firewalld_status is not None: service_mgr.stop('firewalld') if iptables_service and backup_iptables_status is not None: service_mgr.start('iptables') if firewalld_service and backup_firewalld_status is not None: service_mgr.start('firewalld') errors = [] # Run libvirt session and collect errors in log. libvirtd_session = utils_libvirtd.LibvirtdSession( logging_handler=_error_handler, logging_params=(errors,), logging_pattern=r'[-\d]+ [.:+\d]+ [:\d]+ error :', ) try: logging.info('Starting libvirtd session') libvirtd_session.start() time.sleep(3) libvirt_pid = libvirtd_session.tail.get_pid() sestatus = utils_selinux.get_status() if sestatus == "disabled": raise exceptions.TestSkipError("SELinux is in Disabled mode." "It must be in enforcing mode " "for test execution") libvirt_context = utils_selinux.get_context_of_process(libvirt_pid) logging.debug( "The libvirtd process context is: %s", libvirt_context) finally: libvirtd_session.exit() _check_errors() finally: logging.info('Recovering services status') # If service do not exists, then backup status and current status # will all be none and nothing will be done if service_mgr.status('iptables') != backup_iptables_status: if backup_iptables_status: service_mgr.start('iptables') process.run('iptables-restore < /tmp/iptables.save', shell=True) else: service_mgr.stop('iptables') if service_mgr.status('firewalld') != backup_firewalld_status: if backup_firewalld_status: service_mgr.start('firewalld') else: service_mgr.stop('firewalld') logging.info('Removing backup iptables') if os.path.exists("/tmp/iptables.save"): os.remove("/tmp/iptables.save")