def run(test, params, env): """ Test disk encryption option. 1.Prepare test environment, destroy or suspend a VM. 2.Prepare tgtd and secret config. 3.Edit disks xml and start the domain. 4.Perform test operation. 5.Recover test environment. 6.Confirm the test result. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) virsh_dargs = {'debug': True, 'ignore_status': True} def check_save_restore(save_file): """ Test domain save and restore. """ # Save the domain. ret = virsh.save(vm_name, save_file, **virsh_dargs) libvirt.check_exit_status(ret) # Restore the domain. ret = virsh.restore(save_file, **virsh_dargs) libvirt.check_exit_status(ret) def check_snapshot(): """ Test domain snapshot operation. """ snapshot1 = "s1" snapshot2 = "s2" ret = virsh.snapshot_create_as(vm_name, snapshot1) libvirt.check_exit_status(ret) ret = virsh.snapshot_create_as( vm_name, "%s --disk-only --diskspec vda," "file=/tmp/testvm-snap1" % snapshot2) libvirt.check_exit_status(ret, True) ret = virsh.snapshot_create_as( vm_name, "%s --memspec file=%s,snapshot=external" " --diskspec vda,file=/tmp/testvm-snap2" % (snapshot2, snapshot2)) libvirt.check_exit_status(ret, True) def check_in_vm(target, old_parts): """ Check mount/read/write disk in VM. :param vm. VM guest. :param target. Disk dev in VM. :return: True if check successfully. """ try: session = vm.wait_for_login() new_parts = libvirt.get_parts_list(session) added_parts = list(set(new_parts).difference(set(old_parts))) logging.info("Added parts:%s", added_parts) if len(added_parts) != 1: logging.error("The number of new partitions is invalid in VM") return False added_part = None if target.startswith("vd"): if added_parts[0].startswith("vd"): added_part = added_parts[0] elif target.startswith("hd"): if added_parts[0].startswith("sd"): added_part = added_parts[0] elif target.startswith("sd"): added_part = added_parts[0] if not added_part: logging.error("Cann't see added partition in VM") return False cmd = ("fdisk -l /dev/{0} && mkfs.ext4 -F /dev/{0} && " "mkdir -p test && mount /dev/{0} test && echo" " teststring > test/testfile && umount test".format( added_part)) s, o = session.cmd_status_output(cmd) logging.info("Check disk operation in VM:\n%s", o) if s != 0: return False return True except (remote.LoginError, virt_vm.VMError, aexpect.ShellError) as e: logging.error(str(e)) return False def check_qemu_cmd(): """ Check qemu-kvm command line options """ cmd = ("ps -ef | grep %s | grep -v grep " % vm_name) if driver_iothread: cmd += " | grep iothread=iothread%s" % driver_iothread if process.system(cmd, ignore_status=True, shell=True): test.fail("Can't see disk option '%s' " "in command line" % cmd) # Disk specific attributes. device = params.get("virt_disk_device", "disk") device_target = params.get("virt_disk_device_target", "vdd") device_format = params.get("virt_disk_device_format", "raw") device_type = params.get("virt_disk_device_type", "file") device_bus = params.get("virt_disk_device_bus", "virtio") # Controller specific attributes. cntlr_type = params.get('controller_type', None) cntlr_model = params.get('controller_model', None) cntlr_index = params.get('controller_index', None) controller_addr_options = params.get('controller_addr_options', None) driver_iothread = params.get("driver_iothread") # iscsi options. iscsi_target = params.get("iscsi_target") iscsi_host = params.get("iscsi_host") iscsi_port = params.get("iscsi_port") emulated_size = params.get("iscsi_image_size", "1") uuid = params.get("uuid", "") auth_uuid = "yes" == params.get("auth_uuid", "") auth_usage = "yes" == params.get("auth_usage", "") status_error = "yes" == params.get("status_error") define_error = "yes" == params.get("define_error", "no") test_save_snapshot = "yes" == params.get("test_save_snapshot", "no") test_qemu_cmd = "yes" == params.get("test_qemu_cmd", "no") check_partitions = "yes" == params.get("virt_disk_check_partitions", "yes") secret_uuid = "" # Start vm and get all partions in vm. if vm.is_dead(): vm.start() session = vm.wait_for_login() old_parts = libvirt.get_parts_list(session) session.close() vm.destroy(gracefully=False) # Back up xml file. vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: chap_user = "" chap_passwd = "" if auth_uuid or auth_usage: auth_place_in_location = params.get("auth_place_in_location") if 'source' in auth_place_in_location and not libvirt_version.version_compare( 3, 9, 0): test.cancel( "place auth in source is not supported in current libvirt version" ) auth_type = params.get("auth_type") secret_usage_target = params.get("secret_usage_target") secret_usage_type = params.get("secret_usage_type") chap_user = params.get("iscsi_user") chap_passwd = params.get("iscsi_password") sec_xml = secret_xml.SecretXML("no", "yes") sec_xml.description = "iSCSI secret" sec_xml.auth_type = auth_type sec_xml.auth_username = chap_user sec_xml.usage = secret_usage_type sec_xml.target = secret_usage_target sec_xml.xmltreefile.write() ret = virsh.secret_define(sec_xml.xml) libvirt.check_exit_status(ret) secret_uuid = re.findall(r".+\S+(\ +\S+)\ +.+\S+", ret.stdout.strip())[0].lstrip() logging.debug("Secret uuid %s", secret_uuid) if secret_uuid == "": test.error("Failed to get secret uuid") # Set secret value encoding = locale.getpreferredencoding() secret_string = base64.b64encode( chap_passwd.encode(encoding)).decode(encoding) ret = virsh.secret_set_value(secret_uuid, secret_string, **virsh_dargs) libvirt.check_exit_status(ret) # Setup iscsi target iscsi_target, lun_num = libvirt.setup_or_cleanup_iscsi( is_setup=True, is_login=False, image_size=emulated_size, chap_user=chap_user, chap_passwd=chap_passwd, portal_ip=iscsi_host) # If we use qcow2 disk format, should format iscsi disk first. if device_format == "qcow2": cmd = ( "qemu-img create -f qcow2 iscsi://%s:%s/%s/%s %s" % (iscsi_host, iscsi_port, iscsi_target, lun_num, emulated_size)) process.run(cmd, shell=True) # Add disk xml. vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disk_xml = Disk(type_name=device_type) disk_xml.device = device disk_xml.target = {"dev": device_target, "bus": device_bus} driver_dict = {"name": "qemu", "type": device_format} # For lun type device, iothread attribute need to be set in controller. if driver_iothread and device != "lun": driver_dict.update({"iothread": driver_iothread}) vmxml.iothreads = int(driver_iothread) elif driver_iothread: vmxml.iothreads = int(driver_iothread) disk_xml.driver = driver_dict # Check if we want to use a faked uuid. if not uuid: uuid = secret_uuid auth_dict = {} if auth_uuid: auth_dict = { "auth_user": chap_user, "secret_type": secret_usage_type, "secret_uuid": uuid } elif auth_usage: auth_dict = { "auth_user": chap_user, "secret_type": secret_usage_type, "secret_usage": secret_usage_target } disk_source = disk_xml.new_disk_source( **{ "attrs": { "protocol": "iscsi", "name": "%s/%s" % (iscsi_target, lun_num) }, "hosts": [{ "name": iscsi_host, "port": iscsi_port }] }) if auth_dict: disk_auth = disk_xml.new_auth(**auth_dict) if 'source' in auth_place_in_location: disk_source.auth = disk_auth if 'disk' in auth_place_in_location: disk_xml.auth = disk_auth disk_xml.source = disk_source # Sync VM xml. vmxml.add_device(disk_xml) # After virtio 1.0 is enabled, lun type device need use virtio-scsi # instead of virtio, so additional controller is needed. # Add controller. if device == "lun": ctrl = Controller(type_name=cntlr_type) if cntlr_model is not None: ctrl.model = cntlr_model if cntlr_index is not None: ctrl.index = cntlr_index ctrl_addr_dict = {} for addr_option in controller_addr_options.split(','): if addr_option != "": addr_part = addr_option.split('=') ctrl_addr_dict.update( {addr_part[0].strip(): addr_part[1].strip()}) ctrl.address = ctrl.new_controller_address(attrs=ctrl_addr_dict) # If driver_iothread is true, need add iothread attribute in controller. if driver_iothread: ctrl_driver_dict = {} ctrl_driver_dict.update({"iothread": driver_iothread}) ctrl.driver = ctrl_driver_dict logging.debug("Controller XML is:%s", ctrl) if cntlr_type: vmxml.del_controller(cntlr_type) else: vmxml.del_controller("scsi") vmxml.add_device(ctrl) try: # Start the VM and check status. vmxml.sync() vm.start() if status_error: test.fail("VM started unexpectedly.") # Check Qemu command line if test_qemu_cmd: check_qemu_cmd() except virt_vm.VMStartError as e: if status_error: if re.search(uuid, str(e)): pass else: test.fail("VM failed to start." "Error: %s" % str(e)) except xcepts.LibvirtXMLError as xml_error: if not define_error: test.fail("Failed to define VM:\n%s" % xml_error) else: # Check partitions in VM. if check_partitions: if not check_in_vm(device_target, old_parts): test.fail("Check disk partitions in VM failed") # Test domain save/restore/snapshot. if test_save_snapshot: save_file = os.path.join(data_dir.get_tmp_dir(), "%.save" % vm_name) check_save_restore(save_file) check_snapshot() if os.path.exists(save_file): os.remove(save_file) finally: # Delete snapshots. libvirt.clean_up_snapshots(vm_name, domxml=vmxml_backup) # Recover VM. if vm.is_alive(): vm.destroy(gracefully=False) vmxml_backup.sync("--snapshots-metadata") # Delete the tmp files. libvirt.setup_or_cleanup_iscsi(is_setup=False) # Clean up secret if secret_uuid: virsh.secret_undefine(secret_uuid)
vmxml.devices = xml_devices vmxml.define() # Add virtio_scsi controller. if virtio_scsi_controller: scsi_controller = Controller("controller") scsi_controller.type = "scsi" scsi_controller.index = "0" scsi_controller.model = "virtio-scsi" if virtio_scsi_controller_driver != "": driver_dict = {} for driver_option in virtio_scsi_controller_driver.split(','): if driver_option != "": d = driver_option.split('=') driver_dict.update({d[0].strip(): d[1].strip()}) scsi_controller.driver = driver_dict vmxml.add_device(scsi_controller) # Test usb devices. usb_devices = {} if add_usb_device: # Delete all usb devices first. controllers = vmxml.get_devices(device_type="controller") for ctrl in controllers: if ctrl.type == "usb": vmxml.del_device(ctrl) inputs = vmxml.get_devices(device_type="input") for input in inputs: if input.type_name == "tablet": vmxml.del_device(input)
# Add virtio_scsi controller. if virtio_scsi_controller: scsi_controller = Controller("controller") scsi_controller.type = "scsi" scsi_controller.index = "0" ctl_model = params.get("virtio_scsi_controller_model") if ctl_model: scsi_controller.model = ctl_model if virtio_scsi_controller_driver != "": driver_dict = {} for driver_option in virtio_scsi_controller_driver.split(','): if driver_option != "": d = driver_option.split('=') driver_dict.update({d[0].strip(): d[1].strip()}) scsi_controller.driver = driver_dict vmxml.del_controller("scsi") vmxml.add_device(scsi_controller) # Test usb devices. usb_devices = {} if add_usb_device: # Delete all usb devices first. controllers = vmxml.get_devices(device_type="controller") for ctrl in controllers: if ctrl.type == "usb": vmxml.del_device(ctrl) inputs = vmxml.get_devices(device_type="input") for input in inputs: if input.type_name == "tablet":
def run(test, params, env): """ Attach/Detach an iscsi network/volume disk to domain 1. For secret usage testing: 1.1. Setup an iscsi target with CHAP authentication. 1.2. Define a secret for iscsi target usage 1.3. Set secret value 2. Create 4. Create an iscsi network disk XML 5. Attach disk with the XML file and check the disk inside the VM 6. Detach the disk """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) disk_device = params.get("disk_device", "disk") disk_type = params.get("disk_type", "network") disk_src_protocol = params.get("disk_source_protocol", "iscsi") disk_src_host = params.get("disk_source_host", "127.0.0.1") disk_src_port = params.get("disk_source_port", "3260") disk_src_pool = params.get("disk_source_pool") disk_src_mode = params.get("disk_source_mode", "host") pool_type = params.get("pool_type", "iscsi") pool_src_host = params.get("pool_source_host", "127.0.0.1") pool_target = params.get("pool_target", "/dev/disk/by-path") disk_target = params.get("disk_target", "vdb") disk_target_bus = params.get("disk_target_bus", "virtio") disk_readonly = params.get("disk_readonly", "no") chap_auth = "yes" == params.get("chap_auth", "no") chap_user = params.get("chap_username", "") chap_passwd = params.get("chap_password", "") secret_usage_target = params.get("secret_usage_target") secret_ephemeral = params.get("secret_ephemeral", "no") secret_private = params.get("secret_private", "yes") status_error = "yes" == params.get("status_error", "no") vg_name = params.get("virt_disk_vg_name", "vg_test_0") lv_name = params.get("virt_disk_lv_name", "lv_test_0") driver_packed = params.get("driver_packed", "on") disk_packed = "yes" == params.get("disk_packed", "no") scsi_packed = "yes" == params.get("scsi_packed", "no") # Indicate the PPC platform on_ppc = False if platform.platform().count('ppc64'): on_ppc = True if disk_src_protocol == 'iscsi': if not libvirt_version.version_compare(1, 0, 4): test.cancel("'iscsi' disk doesn't support in" " current libvirt version.") if disk_type == "volume": if not libvirt_version.version_compare(1, 0, 5): test.cancel("'volume' type disk doesn't support in" " current libvirt version.") if pool_type == "iscsi-direct": if not libvirt_version.version_compare(4, 7, 0): test.cancel("iscsi-direct pool is not supported in" " current libvirt version.") if ((disk_packed or scsi_packed) and not libvirt_version.version_compare(6, 3, 0)): test.cancel("The virtio packed attribute is not supported in" " current libvirt version.") # Back VM XML vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) # Fix no more PCI slots issue in certain cases. vm_dump_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) machine_type = params.get("machine_type", "pc") if machine_type == 'q35': vm_dump_xml.remove_all_device_by_type('controller') machine_list = vm_dump_xml.os.machine.split("-") vm_dump_xml.set_os_attrs( **{"machine": machine_list[0] + "-q35-" + machine_list[2]}) q35_pcie_dict0 = { 'controller_model': 'pcie-root', 'controller_type': 'pci', 'controller_index': 0 } q35_pcie_dict1 = { 'controller_model': 'pcie-root-port', 'controller_type': 'pci' } vm_dump_xml.add_device(libvirt.create_controller_xml(q35_pcie_dict0)) # Add enough controllers to match multiple times disk attaching requirements for i in list(range(1, 12)): q35_pcie_dict1.update({'controller_index': "%d" % i}) vm_dump_xml.add_device( libvirt.create_controller_xml(q35_pcie_dict1)) vm_dump_xml.sync() virsh_dargs = {'debug': True, 'ignore_status': True} try: start_vm = "yes" == params.get("start_vm", "yes") if start_vm: if vm.is_dead(): vm.start() vm.wait_for_login() else: if not vm.is_dead(): vm.destroy() if chap_auth: # Create a secret xml to define it secret_xml = SecretXML(secret_ephemeral, secret_private) secret_xml.auth_type = "chap" secret_xml.auth_username = chap_user secret_xml.usage = disk_src_protocol secret_xml.target = secret_usage_target with open(secret_xml.xml) as f: logging.debug("Define secret by XML: %s", f.read()) # Define secret cmd_result = virsh.secret_define(secret_xml.xml, **virsh_dargs) libvirt.check_exit_status(cmd_result) # Get secret uuid try: secret_uuid = cmd_result.stdout.strip().split()[1] except IndexError: test.error("Fail to get new created secret uuid") # Set secret value encoding = locale.getpreferredencoding() secret_string = base64.b64encode( chap_passwd.encode(encoding)).decode(encoding) cmd_result = virsh.secret_set_value(secret_uuid, secret_string, **virsh_dargs) libvirt.check_exit_status(cmd_result) else: # Set chap_user and chap_passwd to empty to avoid setup # CHAP authentication when export iscsi target chap_user = "" chap_passwd = "" # Setup iscsi target if disk_type == "block": iscsi_target = libvirt.setup_or_cleanup_iscsi( is_setup=True, is_login=True, image_size="1G", chap_user=chap_user, chap_passwd=chap_passwd, portal_ip=disk_src_host) else: iscsi_target, lun_num = libvirt.setup_or_cleanup_iscsi( is_setup=True, is_login=False, image_size='1G', chap_user=chap_user, chap_passwd=chap_passwd, portal_ip=disk_src_host) # Create iscsi pool if disk_type == "volume": # Create an iscsi pool xml to create it pool_src_xml = pool_xml.SourceXML() pool_src_xml.host_name = pool_src_host pool_src_xml.device_path = iscsi_target poolxml = pool_xml.PoolXML(pool_type=pool_type) poolxml.name = disk_src_pool poolxml.set_source(pool_src_xml) poolxml.target_path = pool_target if chap_auth: pool_src_xml.auth_type = "chap" pool_src_xml.auth_username = chap_user pool_src_xml.secret_usage = secret_usage_target poolxml.set_source(pool_src_xml) if pool_type == "iscsi-direct": iscsi_initiator = params.get('iscsi_initiator') pool_src_xml.iqn_name = iscsi_initiator poolxml.set_source(pool_src_xml) # Create iscsi/iscsi-direct pool cmd_result = virsh.pool_create(poolxml.xml, **virsh_dargs) libvirt.check_exit_status(cmd_result) xml = virsh.pool_dumpxml(disk_src_pool) logging.debug("Pool '%s' XML:\n%s", disk_src_pool, xml) def get_vol(): """Get the volume info""" # Refresh the pool cmd_result = virsh.pool_refresh(disk_src_pool) libvirt.check_exit_status(cmd_result) # Get volume name cmd_result = virsh.vol_list(disk_src_pool, **virsh_dargs) libvirt.check_exit_status(cmd_result) vol_list = [] vol_list = re.findall(r"(\S+)\ +(\S+)", str(cmd_result.stdout.strip())) if len(vol_list) > 1: return vol_list[1] else: return None # Wait for a while so that we can get the volume info vol_info = utils_misc.wait_for(get_vol, 10) if vol_info: vol_name, vol_path = vol_info else: test.error("Failed to get volume info") # Snapshot doesn't support raw disk format, create a qcow2 volume # disk for snapshot operation. if pool_type == "iscsi": process.run('qemu-img create -f qcow2 %s %s' % (vol_path, '100M'), shell=True, verbose=True) else: # Get iscsi URL to create a qcow2 volume disk disk_path = ("iscsi://[%s]/%s/%s" % (disk_src_host, iscsi_target, lun_num)) blk_source = "/mnt/test.qcow2" process.run('qemu-img create -f qcow2 %s %s' % (blk_source, '100M'), shell=True, verbose=True) process.run('qemu-img convert -O qcow2 %s %s' % (blk_source, disk_path), shell=True, verbose=True) # Create block device if disk_type == "block": logging.debug("iscsi dev name: %s", iscsi_target) lv_utils.vg_create(vg_name, iscsi_target) device_source = libvirt.create_local_disk("lvm", size="10M", vgname=vg_name, lvname=lv_name) logging.debug("New created volume: %s", lv_name) # Create iscsi network disk XML disk_params = { 'device_type': disk_device, 'type_name': disk_type, 'target_dev': disk_target, 'target_bus': disk_target_bus, 'readonly': disk_readonly } disk_params_src = {} if disk_type == "network": disk_params_src = { 'source_protocol': disk_src_protocol, 'source_name': iscsi_target + "/%s" % lun_num, 'source_host_name': disk_src_host, 'source_host_port': disk_src_port } elif disk_type == "volume": if pool_type == "iscsi": disk_params_src = { 'source_pool': disk_src_pool, 'source_volume': vol_name, 'driver_type': 'qcow2', 'source_mode': disk_src_mode } # iscsi-direct pool don't include source_mode option else: disk_params_src = { 'source_pool': disk_src_pool, 'source_volume': vol_name, 'driver_type': 'qcow2' } elif disk_type == "block": disk_params_src = { 'source_file': device_source, 'driver_type': 'raw' } # Start guest with packed attribute in disk if disk_packed: disk_params_src['driver_packed'] = driver_packed # Start guest with packed attribute in scsi controller if scsi_packed: scsi_controller = Controller("controller") scsi_controller.type = "scsi" scsi_controller.model = "virtio-scsi" scsi_controller.driver = {'packed': driver_packed} vm_dump_xml.add_device(scsi_controller) vm_dump_xml.sync() else: test.cancel("Unsupported disk type in this test") disk_params.update(disk_params_src) if chap_auth and disk_type != "volume": disk_params_auth = { 'auth_user': chap_user, 'secret_type': disk_src_protocol, 'secret_usage': secret_xml.target } disk_params.update(disk_params_auth) disk_xml = libvirt.create_disk_xml(disk_params) attach_option = params.get("attach_option", "") cmd_result = virsh.attach_device(domainarg=vm_name, filearg=disk_xml, flagstr=attach_option, dargs=virsh_dargs) libvirt.check_exit_status(cmd_result, status_error) if vm.is_dead(): cmd_result = virsh.start(vm_name, **virsh_dargs) libvirt.check_exit_status(cmd_result) # Wait for domain is stable vm.wait_for_login().close() domain_operation = params.get("domain_operation", "") if domain_operation == "save": save_file = os.path.join(data_dir.get_tmp_dir(), "vm.save") cmd_result = virsh.save(vm_name, save_file, **virsh_dargs) libvirt.check_exit_status(cmd_result) cmd_result = virsh.restore(save_file) libvirt.check_exit_status(cmd_result) if os.path.exists(save_file): os.remove(save_file) elif domain_operation == "snapshot": # Run snapshot related commands: snapshot-create-as, snapshot-list # snapshot-info, snapshot-dumpxml, snapshot-create # virsh snapshot-revert is not supported on combined internal and external snapshots # see more details from,https://bugzilla.redhat.com/show_bug.cgi?id=1733173 snapshot_name1 = "snap1" snapshot_name2 = "snap2" cmd_result = virsh.snapshot_create_as(vm_name, snapshot_name1, **virsh_dargs) libvirt.check_exit_status(cmd_result) try: virsh.snapshot_list(vm_name, **virsh_dargs) except process.CmdError: test.fail("Failed getting snapshots list for %s" % vm_name) try: virsh.snapshot_info(vm_name, snapshot_name1, **virsh_dargs) except process.CmdError: test.fail("Failed getting snapshots info for %s" % vm_name) cmd_result = virsh.snapshot_dumpxml(vm_name, snapshot_name1, **virsh_dargs) libvirt.check_exit_status(cmd_result) cmd_result = virsh.snapshot_create(vm_name, **virsh_dargs) libvirt.check_exit_status(cmd_result) cmd_result = virsh.snapshot_current(vm_name, **virsh_dargs) libvirt.check_exit_status(cmd_result) virsh.snapshot_create_as(vm_name, snapshot_name2, ignore_status=False, debug=True) cmd_result = virsh.snapshot_revert(vm_name, snapshot_name1, **virsh_dargs) cmd_result = virsh.snapshot_list(vm_name, **virsh_dargs) if snapshot_name2 not in cmd_result: test.error("Snapshot %s not found" % snapshot_name2) elif domain_operation == "start_with_packed": expect_xml_line = "packed=\"%s\"" % driver_packed libvirt.check_dumpxml(vm, expect_xml_line) expect_qemu_line = "packed=%s" % driver_packed libvirt.check_qemu_cmd_line(expect_qemu_line) elif domain_operation == "": logging.debug("No domain operation provided, so skip it") else: logging.error("Unsupported operation %s in this case, so skip it", domain_operation) def find_attach_disk(expect=True): """ Find attached disk inside the VM """ found_disk = False if vm.is_dead(): test.error("Domain %s is not running" % vm_name) else: try: session = vm.wait_for_login() # Here the script needs wait for a while for the guest to # recognize the hotplugged disk on PPC if on_ppc: time.sleep(10) cmd = "grep %s /proc/partitions" % disk_target s, o = session.cmd_status_output(cmd) logging.info("%s output: %s", cmd, o) session.close() if s == 0: found_disk = True except (LoginError, VMError, ShellError) as e: logging.error(str(e)) if found_disk == expect: logging.debug("Check disk inside the VM PASS as expected") else: test.error("Check disk inside the VM FAIL") # Check disk inside the VM, expect is False if status_error=True find_attach_disk(not status_error) # Detach disk cmd_result = virsh.detach_disk(vm_name, disk_target, wait_remove_event=True) libvirt.check_exit_status(cmd_result, status_error) # Check disk inside the VM find_attach_disk(False) finally: # Clean up snapshot # Shut down before cleaning up snapshots if vm.is_alive(): vm.destroy() libvirt.clean_up_snapshots(vm_name, domxml=vmxml_backup) # Restore vm vmxml_backup.sync("--snapshots-metadata") # Destroy pool and undefine secret, which may not exist try: if disk_type == "volume": virsh.pool_destroy(disk_src_pool) if disk_type == "block": clean_up_lvm(iscsi_target, vg_name, lv_name) if chap_auth: virsh.secret_undefine(secret_uuid) except Exception: pass libvirt.setup_or_cleanup_iscsi(is_setup=False)
if cntlr_model is not None: ctrl.model = cntlr_model if cntlr_index is not None: ctrl.index = cntlr_index ctrl_addr_dict = {} for addr_option in controller_addr_options.split(','): if addr_option != "": addr_part = addr_option.split('=') ctrl_addr_dict.update({addr_part[0].strip(): addr_part[1].strip()}) ctrl.address = ctrl.new_controller_address(attrs=ctrl_addr_dict) # If driver_iothread is true, need add iothread attribute in controller. if driver_iothread: ctrl_driver_dict = {} ctrl_driver_dict.update({"iothread": driver_iothread}) ctrl.driver = ctrl_driver_dict logging.debug("Controller XML is:%s", ctrl) vmxml.add_device(ctrl) vmxml.sync() try: # Start the VM and check status. vm.start() if status_error: raise exceptions.TestFail("VM started unexpectedly.") # Check Qemu command line if test_qemu_cmd: check_qemu_cmd()
ctrl.model = cntlr_model if cntlr_index is not None: ctrl.index = cntlr_index ctrl_addr_dict = {} for addr_option in controller_addr_options.split(','): if addr_option != "": addr_part = addr_option.split('=') ctrl_addr_dict.update( {addr_part[0].strip(): addr_part[1].strip()}) ctrl.address = ctrl.new_controller_address(attrs=ctrl_addr_dict) # If driver_iothread is true, need add iothread attribute in controller. if driver_iothread: ctrl_driver_dict = {} ctrl_driver_dict.update({"iothread": driver_iothread}) ctrl.driver = ctrl_driver_dict logging.debug("Controller XML is:%s", ctrl) vmxml.add_device(ctrl) vmxml.sync() try: # Start the VM and check status. vm.start() if status_error: raise exceptions.TestFail("VM started unexpectedly.") # Check Qemu command line if test_qemu_cmd: check_qemu_cmd()
def run(test, params, env): """ Test disk encryption option. 1.Prepare test environment, destroy or suspend a VM. 2.Prepare tgtd and secret config. 3.Edit disks xml and start the domain. 4.Perform test operation. 5.Recover test environment. 6.Confirm the test result. """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) virsh_dargs = {'debug': True, 'ignore_status': True} def check_save_restore(save_file): """ Test domain save and restore. """ # Save the domain. ret = virsh.save(vm_name, save_file, **virsh_dargs) libvirt.check_exit_status(ret) # Restore the domain. ret = virsh.restore(save_file, **virsh_dargs) libvirt.check_exit_status(ret) def check_snapshot(): """ Test domain snapshot operation. """ snapshot1 = "s1" snapshot2 = "s2" ret = virsh.snapshot_create_as(vm_name, snapshot1) libvirt.check_exit_status(ret) ret = virsh.snapshot_create_as(vm_name, "%s --disk-only --diskspec vda," "file=/tmp/testvm-snap1" % snapshot2) libvirt.check_exit_status(ret, True) ret = virsh.snapshot_create_as(vm_name, "%s --memspec file=%s,snapshot=external" " --diskspec vda,file=/tmp/testvm-snap2" % (snapshot2, snapshot2)) libvirt.check_exit_status(ret, True) def check_in_vm(target, old_parts): """ Check mount/read/write disk in VM. :param vm. VM guest. :param target. Disk dev in VM. :return: True if check successfully. """ try: session = vm.wait_for_login() new_parts = libvirt.get_parts_list(session) added_parts = list(set(new_parts).difference(set(old_parts))) logging.info("Added parts:%s", added_parts) if len(added_parts) != 1: logging.error("The number of new partitions is invalid in VM") return False added_part = None if target.startswith("vd"): if added_parts[0].startswith("vd"): added_part = added_parts[0] elif target.startswith("hd"): if added_parts[0].startswith("sd"): added_part = added_parts[0] elif target.startswith("sd"): added_part = added_parts[0] if not added_part: logging.error("Cann't see added partition in VM") return False cmd = ("fdisk -l /dev/{0} && mkfs.ext4 -F /dev/{0} && " "mkdir -p test && mount /dev/{0} test && echo" " teststring > test/testfile && umount test" .format(added_part)) s, o = session.cmd_status_output(cmd) logging.info("Check disk operation in VM:\n%s", o) if s != 0: return False return True except (remote.LoginError, virt_vm.VMError, aexpect.ShellError) as e: logging.error(str(e)) return False def check_qemu_cmd(): """ Check qemu-kvm command line options """ cmd = ("ps -ef | grep %s | grep -v grep " % vm_name) if driver_iothread: cmd += " | grep iothread=iothread%s" % driver_iothread if process.system(cmd, ignore_status=True, shell=True): test.fail("Can't see disk option '%s' " "in command line" % cmd) def check_auth_plaintext(vm_name, password): """ Check if libvirt passed the plaintext of the chap authentication password to qemu. :param vm_name: The name of vm to be checked. :param password: The plaintext of password used for chap authentication. :return: True if using plaintext, False if not. """ cmd = ("ps -ef | grep -v grep | grep qemu-kvm | grep %s | grep %s" % (vm_name, password)) return process.system(cmd, ignore_status=True, shell=True) == 0 # Disk specific attributes. device = params.get("virt_disk_device", "disk") device_target = params.get("virt_disk_device_target", "vdd") device_format = params.get("virt_disk_device_format", "raw") device_type = params.get("virt_disk_device_type", "file") device_bus = params.get("virt_disk_device_bus", "virtio") # Controller specific attributes. cntlr_type = params.get('controller_type', None) cntlr_model = params.get('controller_model', None) cntlr_index = params.get('controller_index', None) controller_addr_options = params.get('controller_addr_options', None) driver_iothread = params.get("driver_iothread") # iscsi options. iscsi_target = params.get("iscsi_target") iscsi_host = params.get("iscsi_host") iscsi_port = params.get("iscsi_port") emulated_size = params.get("iscsi_image_size", "1") uuid = params.get("uuid", "") auth_uuid = "yes" == params.get("auth_uuid", "") auth_usage = "yes" == params.get("auth_usage", "") status_error = "yes" == params.get("status_error") define_error = "yes" == params.get("define_error", "no") test_save_snapshot = "yes" == params.get("test_save_snapshot", "no") test_qemu_cmd = "yes" == params.get("test_qemu_cmd", "no") check_partitions = "yes" == params.get("virt_disk_check_partitions", "yes") secret_uuid = "" # Start vm and get all partions in vm. if vm.is_dead(): vm.start() session = vm.wait_for_login() old_parts = libvirt.get_parts_list(session) session.close() vm.destroy(gracefully=False) # Back up xml file. vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) try: chap_user = "" chap_passwd = "" if auth_uuid or auth_usage: auth_place_in_location = params.get("auth_place_in_location") if 'source' in auth_place_in_location and not libvirt_version.version_compare(3, 9, 0): test.cancel("place auth in source is not supported in current libvirt version") auth_type = params.get("auth_type") secret_usage_target = params.get("secret_usage_target") secret_usage_type = params.get("secret_usage_type") chap_user = params.get("iscsi_user") chap_passwd = params.get("iscsi_password") sec_xml = secret_xml.SecretXML("no", "yes") sec_xml.description = "iSCSI secret" sec_xml.auth_type = auth_type sec_xml.auth_username = chap_user sec_xml.usage = secret_usage_type sec_xml.target = secret_usage_target sec_xml.xmltreefile.write() ret = virsh.secret_define(sec_xml.xml) libvirt.check_exit_status(ret) secret_uuid = re.findall(r".+\S+(\ +\S+)\ +.+\S+", ret.stdout.strip())[0].lstrip() logging.debug("Secret uuid %s", secret_uuid) if secret_uuid == "": test.error("Failed to get secret uuid") # Set secret value encoding = locale.getpreferredencoding() secret_string = base64.b64encode(chap_passwd.encode(encoding)).decode(encoding) ret = virsh.secret_set_value(secret_uuid, secret_string, **virsh_dargs) libvirt.check_exit_status(ret) # Setup iscsi target iscsi_target, lun_num = libvirt.setup_or_cleanup_iscsi(is_setup=True, is_login=False, image_size=emulated_size, chap_user=chap_user, chap_passwd=chap_passwd, portal_ip=iscsi_host) # If we use qcow2 disk format, should format iscsi disk first. if device_format == "qcow2": cmd = ("qemu-img create -f qcow2 iscsi://%s:%s/%s/%s %s" % (iscsi_host, iscsi_port, iscsi_target, lun_num, emulated_size)) process.run(cmd, shell=True) # Add disk xml. vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) disk_xml = Disk(type_name=device_type) disk_xml.device = device disk_xml.target = {"dev": device_target, "bus": device_bus} driver_dict = {"name": "qemu", "type": device_format} # For lun type device, iothread attribute need to be set in controller. if driver_iothread and device != "lun": driver_dict.update({"iothread": driver_iothread}) vmxml.iothreads = int(driver_iothread) elif driver_iothread: vmxml.iothreads = int(driver_iothread) disk_xml.driver = driver_dict # Check if we want to use a faked uuid. if not uuid: uuid = secret_uuid auth_dict = {} if auth_uuid: auth_dict = {"auth_user": chap_user, "secret_type": secret_usage_type, "secret_uuid": uuid} elif auth_usage: auth_dict = {"auth_user": chap_user, "secret_type": secret_usage_type, "secret_usage": secret_usage_target} disk_source = disk_xml.new_disk_source( **{"attrs": {"protocol": "iscsi", "name": "%s/%s" % (iscsi_target, lun_num)}, "hosts": [{"name": iscsi_host, "port": iscsi_port}]}) if auth_dict: disk_auth = disk_xml.new_auth(**auth_dict) if 'source' in auth_place_in_location: disk_source.auth = disk_auth if 'disk' in auth_place_in_location: disk_xml.auth = disk_auth disk_xml.source = disk_source # Sync VM xml. vmxml.add_device(disk_xml) # After virtio 1.0 is enabled, lun type device need use virtio-scsi # instead of virtio, so additional controller is needed. # Add controller. if device == "lun": ctrl = Controller(type_name=cntlr_type) if cntlr_model is not None: ctrl.model = cntlr_model if cntlr_index is not None: ctrl.index = cntlr_index ctrl_addr_dict = {} for addr_option in controller_addr_options.split(','): if addr_option != "": addr_part = addr_option.split('=') ctrl_addr_dict.update({addr_part[0].strip(): addr_part[1].strip()}) ctrl.address = ctrl.new_controller_address(attrs=ctrl_addr_dict) # If driver_iothread is true, need add iothread attribute in controller. if driver_iothread: ctrl_driver_dict = {} ctrl_driver_dict.update({"iothread": driver_iothread}) ctrl.driver = ctrl_driver_dict logging.debug("Controller XML is:%s", ctrl) if cntlr_type: vmxml.del_controller(cntlr_type) else: vmxml.del_controller("scsi") vmxml.add_device(ctrl) try: # Start the VM and check status. vmxml.sync() vm.start() if status_error: test.fail("VM started unexpectedly.") # Check Qemu command line if test_qemu_cmd: check_qemu_cmd() except virt_vm.VMStartError as e: if status_error: if re.search(uuid, str(e)): pass else: test.fail("VM failed to start." "Error: %s" % str(e)) except xcepts.LibvirtXMLError as xml_error: if not define_error: test.fail("Failed to define VM:\n%s" % xml_error) else: # Check partitions in VM. if check_partitions: if not check_in_vm(device_target, old_parts): test.fail("Check disk partitions in VM failed") # Test domain save/restore/snapshot. if test_save_snapshot: save_file = os.path.join(data_dir.get_tmp_dir(), "%.save" % vm_name) check_save_restore(save_file) check_snapshot() if os.path.exists(save_file): os.remove(save_file) # Test libvirt doesn't pass the plaintext of chap password to qemu, # this function is implemented in libvirt 4.3.0-1. if (libvirt_version.version_compare(4, 3, 0) and (auth_uuid or auth_usage) and chap_passwd): if(check_auth_plaintext(vm_name, chap_passwd)): test.fail("Libvirt should not pass plaintext of chap " "password to qemu-kvm.") finally: # Delete snapshots. libvirt.clean_up_snapshots(vm_name, domxml=vmxml_backup) # Recover VM. if vm.is_alive(): vm.destroy(gracefully=False) vmxml_backup.sync("--snapshots-metadata") # Delete the tmp files. libvirt.setup_or_cleanup_iscsi(is_setup=False) # Clean up secret if secret_uuid: virsh.secret_undefine(secret_uuid)