示例#1
0
    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)
示例#4
0
    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
示例#5
0
    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)
示例#6
0
    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
示例#7
0
    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()
示例#9
0
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()
示例#10
0
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)
示例#11
0
        # 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: