def setup_controller_xml(): """ Prepare controller devices of VM XML according to params. """ if cntlr_type is None: type = 'pci' else: type = cntlr_type curcntlr = 0 while curcntlr < cntlr_num: ctrl = Controller(type_name=type) if cntlr_model is not None: ctrl.model = cntlr_model if cntlr_model == 'pci-bridge': ctrl.model_name = {'name': 'pci-bridge'} if cntlr_index is not None: ctrl.index = cntlr_index elif with_index: if cntlr_model is not None and cntlr_model == 'pci-bridge': for i in range(1, int(match_new_addr()['bus'], 16) + 1): vm_xml.add_device(add_device('pci', str(i), 'pci-root')) ctrl.index = str(int(match_new_addr()['bus'], 16) + 1) else: ctrl.index = str(curcntlr) if target_index is not None: ctrl.target = {'index': target_index} elif with_index: if cntlr_model is not None and cntlr_model == 'pci-bridge': ctrl.target = { 'chassisNr': str(int(match_new_addr()['bus'], 16) + 1) } else: ctrl.target = {'index': str(curcntlr)} if addr_str is not None: ctrl.address = ctrl.new_controller_address( attrs=match_new_addr()) logging.debug("Controller XML is:%s", ctrl) vm_xml.add_device(ctrl) curcntlr += 1 if special_num: spe_num = int(special_num) ctrl = Controller(type_name=type) if cntlr_model is not None: ctrl.model = cntlr_model ctrl.index = spe_num ctrl.target = {'index': spe_num} if addr_str is not None: ctrl.address = ctrl.new_controller_address( attrs=match_new_addr()) logging.debug("Controller XML is:%s", ctrl) vm_xml.add_device(ctrl)
def setup_controller_xml(): """ Prepare controller devices of VM XML according to params. """ if cntlr_type is None: return ctrl = Controller(type_name=cntlr_type) if model is not None: ctrl.model = model if pcihole is not None: ctrl.pcihole64 = pcihole if vectors is not None: ctrl.vectors = vectors if index is not None: ctrl.index = index if addr_str is not None: match = re.match( r"(?P<bus>[0-9]*):(?P<slot>[0-9]*).(?P<function>[0-9])", addr_str) if match: addr_dict = match.groupdict() addr_dict['bus'] = hex(int(addr_dict['bus'])) addr_dict['slot'] = hex(int(addr_dict['slot'])) addr_dict['function'] = hex(int(addr_dict['function'])) addr_dict['domain'] = '0x0000' ctrl.address = ctrl.new_controller_address(attrs=addr_dict) logging.debug("Controller XML is:%s", ctrl) vm_xml.add_device(ctrl) if usb_cntlr_model is not None: ctrl = Controller(type_name='usb') ctrl.model = usb_cntlr_model if usb_cntlr_addr is not None: match = re.match( r"(?P<bus>[0-9]*):(?P<slot>[0-9]*).(?P<function>[0-9])", usb_cntlr_addr) if match: addr_dict = match.groupdict() addr_dict['bus'] = hex(int(addr_dict['bus'])) addr_dict['slot'] = hex(int(addr_dict['slot'])) addr_dict['function'] = hex(int(addr_dict['function'])) addr_dict['domain'] = '0x0000' ctrl.address = ctrl.new_controller_address(attrs=addr_dict) vm_xml.add_device(ctrl)
def setup_controller_xml(): """ Prepare controller devices of VM XML according to params. """ if cntlr_type is None: return ctrl = Controller(type_name=cntlr_type) if model is not None: ctrl.model = model if pcihole is not None: ctrl.pcihole64 = pcihole if vectors is not None: ctrl.vectors = vectors if index is not None: ctrl.index = index if addr_str is not None: match = re.match(r"(?P<bus>[0-9]*):(?P<slot>[0-9]*).(?P<function>[0-9])", addr_str) if match: addr_dict = match.groupdict() addr_dict['bus'] = hex(int(addr_dict['bus'])) addr_dict['slot'] = hex(int(addr_dict['slot'])) addr_dict['function'] = hex(int(addr_dict['function'])) addr_dict['domain'] = '0x0000' ctrl.address = ctrl.new_controller_address(attrs=addr_dict) logging.debug("Controller XML is:%s", ctrl) vm_xml.add_device(ctrl) if usb_cntlr_model is not None: ctrl = Controller(type_name='usb') ctrl.model = usb_cntlr_model if usb_cntlr_addr is not None: match = re.match(r"(?P<bus>[0-9]*):(?P<slot>[0-9]*).(?P<function>[0-9])", usb_cntlr_addr) if match: addr_dict = match.groupdict() addr_dict['bus'] = hex(int(addr_dict['bus'])) addr_dict['slot'] = hex(int(addr_dict['slot'])) addr_dict['function'] = hex(int(addr_dict['function'])) addr_dict['domain'] = '0x0000' ctrl.address = ctrl.new_controller_address(attrs=addr_dict) vm_xml.add_device(ctrl)
def setup_controller(nic_num, controller_index, ctl_models): """ Create controllers bond to numa node in the guest xml :param nic_num: number of nic card bond to numa node :param controller_index: index num used to create controllers :param ctl_models: contoller topo for numa bond """ index = controller_index if nic_num == 2: ctl_models.append('pcie-switch-upstream-port') ctl_models.append('pcie-switch-downstream-port') ctl_models.append('pcie-switch-downstream-port') for i in range(index): controller = Controller("controller") controller.type = "pci" controller.index = i if i == 0: controller.model = 'pcie-root' else: controller.model = 'pcie-root-port' vmxml.add_device(controller) set_address = False for model in ctl_models: controller = Controller("controller") controller.type = "pci" controller.index = index controller.model = model if set_address or model == "pcie-switch-upstream-port": attrs = { 'type': 'pci', 'domain': '0', 'slot': '0', 'bus': index - 1, 'function': '0' } controller.address = controller.new_controller_address( **{"attrs": attrs}) logging.debug(controller) if controller.model == "pcie-expander-bus": controller.node = "0" controller.target = {'busNr': '100'} set_address = True else: set_address = False logging.debug(controller) vmxml.add_device(controller) index += 1 return index - 1
def setup_controller_xml(index, addr_target=None): """ Prepare controller devices of VM XML. :param index: The index of controller :param addr_target: The controller address """ ctrl = Controller(type_name=cntlr_type) if model: ctrl.model = model if pcihole: ctrl.pcihole64 = pcihole if vectors: ctrl.vectors = vectors if index: ctrl.index = index if chassisNr: ctrl.target = {'chassisNr': chassisNr} if model_name: ctrl.model_name = {'name': model_name} if addr_target: match = re.match( r"(?P<bus>[0-9]*):(?P<slot>[0-9a-f]*).(?P<function>[0-9])", addr_target) if match: addr_dict = match.groupdict() addr_dict['bus'] = hex(int(addr_dict['bus'], 16)) addr_dict['slot'] = hex(int(addr_dict['slot'], 16)) addr_dict['function'] = hex(int(addr_dict['function'], 16)) addr_dict['domain'] = '0x0000' ctrl.address = ctrl.new_controller_address(attrs=addr_dict) logging.debug("Controller XML is:%s", ctrl) vm_xml.add_device(ctrl) if cmpnn_cntlr_model is not None: for num in range(int(cmpnn_cntlr_num)): ctrl = Controller(type_name=cntlr_type) ctrl.model = cmpnn_cntlr_model + str(num + 1) ctrl.index = index logging.debug("Controller XML is:%s", ctrl) vm_xml.add_device(ctrl)
def setup_controller(nic_num, controller_index, ctl_models): """ Create controllers bond to numa node in the guest xml :param nic_num: number of nic card bond to numa node :param controller_index: index num used to create controllers :param ctl_models: contoller topo for numa bond """ index = controller_index if nic_num == 2: ctl_models.append('pcie-switch-upstream-port') ctl_models.append('pcie-switch-downstream-port') ctl_models.append('pcie-switch-downstream-port') for i in range(index): controller = Controller("controller") controller.type = "pci" controller.index = i if i == 0: controller.model = 'pcie-root' else: controller.model = 'pcie-root-port' vmxml.add_device(controller) set_address = False for model in ctl_models: controller = Controller("controller") controller.type = "pci" controller.index = index controller.model = model if set_address or model == "pcie-switch-upstream-port": attrs = {'type': 'pci', 'domain': '0', 'slot': '0', 'bus': index - 1, 'function': '0'} controller.address = controller.new_controller_address(**{"attrs": attrs}) logging.debug(controller) if controller.model == "pcie-expander-bus": controller.node = "0" controller.target = {'busNr': '100'} set_address = True else: set_address = False logging.debug(controller) vmxml.add_device(controller) index += 1 return index - 1
def create_pci_device(pci_model, pci_model_name, **kwargs): """ Create a pci/pcie bridge :param pci_model: model of pci controller device :param pci_model_name: model name of pci controller device :param kwargs: other k-w args that needed to create device :return: the newly created device object """ pci_bridge = Controller('pci') pci_bridge.model = pci_model pci_bridge.model_name = {'name': pci_model_name} if 'index' in kwargs: pci_bridge.index = kwargs['index'] if 'address' in kwargs: pci_bridge.address = pci_bridge.new_controller_address( attrs=eval(kwargs['address'])) logging.debug('pci_bridge: %s', pci_bridge) return pci_bridge
def create_pci_device(pci_model, pci_model_name, **kwargs): """ Create a pci/pcie bridge :param pci_model: model of pci controller device :param pci_model_name: model name of pci controller device :param kwargs: other k-w args that needed to create device :return: the newly created device object """ pci_bridge = Controller('pci') pci_bridge.model = pci_model pci_bridge.model_name = {'name': pci_model_name} if 'index' in kwargs: pci_bridge.index = kwargs['index'] if 'address' in kwargs: pci_bridge.address = pci_bridge.new_controller_address( attrs=eval(kwargs['address'])) logging.debug('pci_bridge: %s', pci_bridge) return pci_bridge
def prepare_usb_controller(vmxml, index, addr): """ Add usb controllers into vm's xml. :param vmxml: The vm's xml. """ # Add disk usb controller(s) usb_controller = Controller("controller") usb_controller.type = "usb" usb_controller.index = str(index) usb_controller.model = 'qemu-xhci' addr_dict = { "domain": '0x0000', 'funtion': '0x0', 'bus': addr['bus'], 'slot': addr['slot'] } usb_controller.address = usb_controller.new_controller_address( **{"attrs": addr_dict}) vmxml.add_device(usb_controller) # Redefine domain vmxml.sync()
def run(test, params, env): """ please insert a usb disk into the host machine before test test libvirt usb feature based on the following matrix: the combination usage of machine type q35/i440fx, pci/pcie bus controller and usb controller bus controller on q35 machine: pcie-root,pcie-root-port,pcie-to-pci-bridge,pci-bridge pcie-root,pcie-root-port,pcie-switch-upstream-port, pcie-switch-downstream-port pcie-root,dmi-to-pci-bridge,pci-bridge bus controller on i440fx machine: pci-root,pci-bridge usb30_controller: nec-xhci qemu-xhci usb20_controller: ich9-ehci1,ich9-uhci1,ich9-uhci2,ich9-uhci3 Test scenarios: 1. by default, cold-plug/hot-unplug usb host device to/from guest 2. passthrough usb host device with vid/pid or bus/device hostdev 3. cold-plug/unplug usb host device to/from guest 4. hot-plug/unplug usb host device to/from guest 5. by default, cold-plug/hot-unplug usb redirdev device to/from guest 6. add usb redirdev device by type spicevm or tcp 7. hot-plug/unplug usb redirdev device to/from guest """ vm_name = params.get("main_vm") vm = env.get_vm(vm_name) usb_index = params.get("usb_index", "0") bus_controller = params.get("bus_controller", "") usb_model = params.get("usb_model", "") start_timeout = int(params.get("start_timeout", "60")) device_name = params.get("device_name", "") device_type = params.get("device_type", "") device_mode = params.get("device_mode", "") port_num = params.get("port_num", "") pkgs_host = params.get("pkgs_host", "") pkgs_guest = params.get("pkgs_guest", "") usb_hub = "yes" == params.get("usb_hub", "no") status_error = "yes" == params.get("status_error", "no") vid_pid = "yes" == params.get("vid_pid", "no") bus_dev = "yes" == params.get("bus_dev", "no") hotplug = "yes" == params.get("hotplug", "no") coldunplug = "yes" == params.get("coldunplug", "no") usb_alias = "yes" == params.get("usb_alias", "no") redirdev_alias = "yes" == params.get("redirdev_alias", "no") set_addr = params.get("set_addr", "yes") ctrl_addr_domain = params.get("ctrl_addr_domain", "") ctrl_addr_slot = params.get("ctrl_addr_slot", "") ctrl_addr_function = params.get("ctrl_addr_function", "") vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) vmxml_backup = vmxml.copy() def get_usb_source(lsusb_list, session=None): """ calculate a dict of the source xml of usb device based on the output from command lsusb :param lsusb_list: a list of the output from command lsusb :param session: a console session of guest :return: a dict of the source xml of usb device """ logging.debug("lsusb command result: {}".format(lsusb_list)) source_list = [] product_list = [] for line in lsusb_list: source = {} product = {} src = {} # filter out the usb hub device without vendor/product id if re.search("hub", line, re.IGNORECASE): continue if len(line.split()[5].split(':')) == 2: vendor_id, product_id = line.split()[5].split(':') if not (vendor_id and product_id): test.fail("vendor/product id is not available") # filter out the remaining usb hub devcie not catched above cmd = "lsusb -v -d {}:{}".format(vendor_id, product_id) if session: output = session.get_command_output(cmd) else: output = process.run(cmd).stdout_text if "hub" in output: continue product['vendor_id'] = "0x" + vendor_id product['product_id'] = "0x" + product_id product_list.append(product.copy()) if vid_pid: source = product.copy() if bus_dev: source['bus'] = int(line.split()[1]) source['device'] = int(line.split()[3].rstrip(':')) source_list.append(source.copy()) logging.debug("usb device product dict {}, source dict {}".format( product_list, source_list)) if not source_list or not product_list: test.fail("no available usb device in host") src['source'] = source_list src['product'] = product_list return src def usb_disk_check(session, src_guest): """ check usb storage disks passed from host with dd operation and product id :param session: a console session of guest :param src_guest: a dict of the source xml of usb device from guest """ # check and write the usb disk status, output = session.cmd_status_output("udevadm info /dev/sda") if status: test.fail("no available usb storage device") if session.cmd_status("dd if=/dev/zero of=/dev/sda bs=1M count=100", timeout=300): test.fail("usb storage device write fail") # check whether the guest got the right usb device output = output.strip().splitlines() for guest in src_guest['product']: pattern = "ID_MODEL_ID={}".format(guest['product_id'].lstrip("0x")) for line in output: if pattern in line: return test.fail("usb device {} is NOT found in output {}".format( src_guest['product'], output)) def usb_device_check(session, src_host): """ check usb devices passed from host with xml file, output of lsusb, and usb storage disk. :param session: a console session of guest :param src_host: a dict of the source xml of usb device from host """ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) output = session.get_command_output("lsusb") # check usb device xml for addr in src_host['source']: if device_name == "redirdev": pattern = 'redirdev bus="usb" type="{}"'.format(device_type) if device_name == "hostdev": if vid_pid: pattern = 'product id="{}"'.format(addr['product_id']) if bus_dev: pattern = 'address bus="{}" device="{}"'.format( int(addr['bus']), int(addr['device'])) if pattern not in str(vmxml): test.fail("the xml check of usb device fails") if device_name == "hostdev" or device_type == "tcp": # check the pid and vid of usb passthrough device in guest src_guest = get_usb_source(output.strip().splitlines(), session) for host in src_host['product']: flag = False for guest in src_guest['product']: if (guest['product_id'] == host['product_id'] and guest['vendor_id'] == host['vendor_id']): flag = True break if not flag: test.fail("the check of usb device in guest fails") # check usb disk /dev/sda usb_disk_check(session, src_guest) def check_alias(device_alias): """ check usb controller alias from qemu command line with xml config file :param device_alias: a {model:alias} dict of the usb controller or a {port:alias} dict of the usb redirdev device """ output = process.run("ps -ef | grep {}".format(vm_name), shell=True).stdout_text logging.debug('"ps -ef | grep {}" output {}'.format(vm_name, output)) if usb_alias: for model in usb_model.split(','): device = (model if model == "qemu-xhci" else ('-').join( [model.split('-')[0], "usb", model.split('-')[1]])) pattern = ("masterbus={}".format(device_alias['ich9-ehci1']) if "ich9-uhci" in model else "id={}".format( device_alias[model])) pattern = "-device {},".format(device) + pattern logging.debug("usb controller model {}, pattern {}".format( model, pattern)) if not re.search(pattern, output): test.fail("the check of controller alias fails") if redirdev_alias: for alias in device_alias.values(): pattern = "-device usb-redir,chardev=char{0},id={0}".format( alias) if not re.search(pattern, output): test.fail("the check of controller alias fails") try: # remove usb controller/device from xml controllers = vmxml.get_devices(device_type="controller") for dev in controllers: if dev.type == "usb" or dev.type == "pci": vmxml.del_device(dev) # clean device address when the address type of device is pci for element in vmxml.xmltreefile.findall("/devices/*/address"): if element.get('type') == "pci": vmxml.xmltreefile.remove(element) vmxml.xmltreefile.write() hubs = vmxml.get_devices(device_type="hub") for hub in hubs: if hub.type_name == "usb": vmxml.del_device(hub) # assemble the xml of pci/pcie bus for model in bus_controller.split(','): pci_bridge = Controller('pci') pci_bridge.type = "pci" pci_bridge.model = model vmxml.add_device(pci_bridge) # find the pci endpoint's name that usb controller will attach pci_endpoint = bus_controller.split(",")[-1] # find the pci's index that usb controller will attach pci_index_for_usb_controller = len(bus_controller.split(",")) - 1 device_alias = {} random_id = process.run("uuidgen").stdout_text.strip() # assemble the xml of usb controller for i, model in enumerate(usb_model.split(',')): controller = Controller("controller") controller.type = "usb" controller.index = usb_index controller.model = model if usb_alias: alias_str = "ua-usb" + str(i) + random_id device_alias[model] = alias_str alias = {"name": alias_str} if "ich9" not in model: controller.index = i controller.alias = alias # for 'usb_all' case, will not set addr if set_addr == "yes": ctrl_addr_dict = { 'type': 'pci', 'domain': ctrl_addr_domain, 'bus': '0x0' + str(pci_index_for_usb_controller), 'slot': ctrl_addr_slot, 'function': ctrl_addr_function } if "uhci" in controller.model: ctrl_addr_dict['function'] = "0x0" + str(i) # pcie-switch-downstream-port only supports slot 0 if pci_endpoint == "pcie-switch-downstream-port": ctrl_addr_dict['slot'] = "0x00" controller.address = controller.new_controller_address( attrs=ctrl_addr_dict) vmxml.add_device(controller) if usb_hub: hub = Hub("usb") vmxml.add_device(hub) # install essential package usbutils in host for pkg in pkgs_host.split(','): if not utils_package.package_install(pkg): test.fail("package {} installation fail".format(pkg)) # prepare to assemble the xml of usb device devs = vmxml.get_devices(device_name) for dev in devs: if dev.type == device_type: vmxml.del_device(dev) lsusb_list = process.run('lsusb').stdout_text.splitlines() src_host = get_usb_source(lsusb_list) dev_list = [] # assemble the xml of usb passthrough device if device_name == "hostdev": for addr in src_host['source']: device_xml = vmxml.get_device_class(device_name)() device_xml.type = device_type source_xml = device_xml.Source() device_xml.mode = device_mode device_xml.managed = 'no' if vid_pid: source_xml.vendor_id = addr['vendor_id'] source_xml.product_id = addr['product_id'] if bus_dev: source_xml.untyped_address = source_xml.new_untyped_address( **addr) device_xml.source = source_xml if hotplug: dev_list.append(device_xml) else: vmxml.add_device(device_xml) # assemble the xml of usb redirdev device if device_name == "redirdev": for i, addr in enumerate(src_host['product']): device_xml = vmxml.get_device_class(device_name)() device_xml.type = device_type device_xml.bus = "usb" if device_type == "tcp": source_xml = device_xml.Source() source_xml.mode = device_mode source_xml.host = "localhost" port = str(int(port_num) + i) source_xml.service = port source_xml.tls = "no" device_xml.source = source_xml # start usbredirserver vendor_id = addr['vendor_id'].lstrip("0x") product_id = addr['product_id'].lstrip("0x") ps = process.SubProcess( "usbredirserver -p {} {}:{}".format( port, vendor_id, product_id), shell=True) server_id = ps.start() if redirdev_alias: alias_str = "ua-redir" + str(i) + random_id device_alias[port] = alias_str alias = {"name": alias_str} device_xml.alias = alias if hotplug: dev_list.append(device_xml) else: vmxml.add_device(device_xml) # start guest vmxml.sync() vm.start() session = vm.wait_for_login(timeout=start_timeout) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) logging.debug("vm xml after starting up {}".format(vmxml)) # check usb controller in guest for model_type in usb_model.split(','): model_type = model_type.split('-')[-1].rstrip("1,2,3") logging.debug( "check usb controller {} in guest".format(model_type)) if session.cmd_status("dmesg | grep {}".format(model_type)): test.fail("usb controller check fail") if usb_alias or redirdev_alias: check_alias(device_alias) # install package usbutils in guest for pkg in pkgs_guest.split(','): if not utils_package.package_install(pkg, session): test.fail("package {} installation fails in guest".format(pkg)) # hotplug usb device if hotplug: for dev in dev_list: virsh.attach_device(vm_name, dev.xml, flagstr="--live", debug=True, ignore_status=False) if device_name == "hostdev": utils_misc.wait_for( lambda: not session.cmd_status( "lsusb | grep {}".format(dev.source.product_id)), 10) vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) logging.debug("vmxml after attaching {}".format(vmxml)) # check usb device usb_device_check(session, src_host) # detach usb device from guest devs = vmxml.get_devices(device_name) if coldunplug: vm.destroy() for dev in devs: if dev.type == device_type: if coldunplug: vmxml.del_device(dev) else: virsh.detach_device(vm_name, dev.xml, flagstr="--live", debug=True, ignore_status=False) # check the usb device element in xml after detaching if coldunplug: vmxml.sync() vm.start() vm.wait_for_login(timeout=start_timeout).close() vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) devs = vmxml.get_devices(device_name) for dev in devs: if dev.type == device_type: test.fail("detach usb device fail") finally: if 'session' in locals(): session.close() if 'server_id' in locals(): process.run("killall usbredirserver") vmxml_backup.sync()
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)
# After virtio 1.0 is enabled, lun type device need use virtio-scsi # instead of virtio, so addtional 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) vmxml.add_device(ctrl) vmxml.sync() try: # Start the VM and check status. vm.start() if status_error:
# After virtio 1.0 is enabled, lun type device need use virtio-scsi # instead of virtio, so addtional 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) vmxml.add_device(ctrl) vmxml.sync() try: # Start the VM and check status. vm.start() if status_error:
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)