Ejemplo n.º 1
0
def create_gluster_vol(params):
    vol_name = params.get("gluster_volume_name")
    force = params.get('force_recreate_gluster') == "yes"

    brick_path = params.get("gluster_brick")
    if not os.path.isabs(brick_path):  # do nothing when path is absolute
        base_dir = params.get("images_base_dir", data_dir.get_data_dir())
        brick_path = os.path.join(base_dir, brick_path)

    error_context.context("Host name lookup failed")
    hostname = socket.gethostname()
    if not hostname or hostname == "(none)":
        if_up = utils_net.get_net_if(state="UP")
        for i in if_up:
            ipv4_value = utils_net.get_net_if_addrs(i)["ipv4"]
            logging.debug("ipv4_value is %s", ipv4_value)
            if ipv4_value != []:
                ip_addr = ipv4_value[0]
                break
        hostname = ip_addr

    # Start the gluster dameon, if not started
    glusterd_start()
    # Check for the volume is already present, if not create one.
    if not is_gluster_vol_avail(vol_name) or force:
        return gluster_vol_create(vol_name, hostname, brick_path, force)
    else:
        return True
Ejemplo n.º 2
0
def create_gluster_uri(params, stripped=False):
    """
    Find/create gluster volume
    """
    vol_name = params.get("gluster_volume_name")

    error_context.context("Host name lookup failed")
    hostname = socket.gethostname()
    gluster_server = params.get("gluster_server")
    gluster_port = params.get("gluster_port", "0")
    if not gluster_server:
        gluster_server = hostname
    if not gluster_server or gluster_server == "(none)":
        if_up = utils_net.get_net_if(state="UP")
        ip_addr = utils_net.get_net_if_addrs(if_up[0])["ipv4"][0]
        gluster_server = ip_addr

    # Start the gluster dameon, if not started
    # Building gluster uri
    gluster_uri = None
    if stripped:
        gluster_uri = "%s:/%s" % (gluster_server, vol_name)
    else:
        gluster_uri = "gluster://%s:%s/%s/" % (gluster_server, gluster_port,
                                               vol_name)
    return gluster_uri
Ejemplo n.º 3
0
    def modify_iface_xml():
        """
        Modify interface xml options
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        if pxe_boot:
            # Config boot console for pxe boot
            osxml = vm_xml.VMOSXML()
            osxml.type = vmxml.os.type
            osxml.arch = vmxml.os.arch
            osxml.machine = vmxml.os.machine
            osxml.loader = "/usr/share/seabios/bios.bin"
            osxml.bios_useserial = "yes"
            osxml.bios_reboot_timeout = "-1"
            osxml.boots = ['network']
            del vmxml.os
            vmxml.os = osxml

        xml_devices = vmxml.devices
        iface_index = xml_devices.index(
            xml_devices.by_device_tag("interface")[0])
        iface = xml_devices[iface_index]
        iface_bandwidth = {}
        iface_inbound = ast.literal_eval(iface_bandwidth_inbound)
        iface_outbound = ast.literal_eval(iface_bandwidth_outbound)
        if iface_inbound:
            iface_bandwidth["inbound"] = iface_inbound
        if iface_outbound:
            iface_bandwidth["outbound"] = iface_outbound
        if iface_bandwidth:
            bandwidth = iface.new_bandwidth(**iface_bandwidth)
            iface.bandwidth = bandwidth

        iface_type = params.get("iface_type", "network")
        iface.type_name = iface_type
        source = ast.literal_eval(iface_source)
        if not source:
            source = {"network": "default"}
        net_ifs = utils_net.get_net_if(state="UP")
        # Check source device is valid or not,
        # if it's not in host interface list, try to set
        # source device to first active interface of host
        if (iface.type_name == "direct" and
            source.has_key('dev') and
                source['dev'] not in net_ifs):
            logging.warn("Source device %s is not a interface"
                         " of host, reset to %s",
                         source['dev'], net_ifs[0])
            source['dev'] = net_ifs[0]
        del iface.source
        iface.source = source
        iface_model = params.get("iface_model", "virtio")
        iface.model = iface_model
        logging.debug("New interface xml file: %s", iface)
        vmxml.devices = xml_devices
        vmxml.xmltreefile.write()
        vmxml.sync()
Ejemplo n.º 4
0
def get_host_ipv4_addr():
    """
    Get host ipv4 addr
    """
    if_up = utils_net.get_net_if(state="UP")
    for i in if_up:
        ipv4_value = utils_net.get_net_if_addrs(i)["ipv4"]
        logging.debug("ipv4_value is %s", ipv4_value)
        if ipv4_value != []:
            ip_addr = ipv4_value[0]
            break
    if ip_addr is not None:
        logging.info("ipv4 address is %s", ip_addr)
    else:
        raise error.TestFail("Fail to get ip address")
    return ip_addr
Ejemplo n.º 5
0
def run(test, params, env):
    """
    This test is for macvtap nic

    1. Check and backup environment
    2. Configure guest, add new nic and set a static ip address
    3. According to nic mode, start test
    4. Recover environment
    """
    vm_names = params.get("vms").split()
    remote_ip = params.get("remote_ip", "ENTER.YOUR.REMOTE.IP")
    iface_mode = params.get("mode", "vepa")
    eth_card_no = params.get("eth_card_no", "ENTER.YOUR.DEV.NAME")
    vm1_ip = params.get("vm1_ip", "ENTER.YOUR.GUEST1.IP")
    vm2_ip = params.get("vm2_ip", "ENTER.YOUR.GUEST2.IP")
    eth_config_file = params.get("eth_config_file",
                                 "ENTER.YOUR.CONFIG.FILE.PATH")
    #persistent_net_file = params.get("persistent_net_file",
    #                                 "ENTER.YOUR.RULE.FILE.PATH")

    #param_keys = ["remote_ip", "vm1_ip", "vm2_ip", "eth_card_no",
    #              "eth_config_file", "persistent_net_file"]
    #param_values = [remote_ip, vm1_ip, vm2_ip, eth_card_no,
    #               eth_config_file, persistent_net_file]
    param_keys = ["remote_ip", "vm1_ip", "vm2_ip", "eth_card_no",
                  "eth_config_file"]
    param_values = [remote_ip, vm1_ip, vm2_ip, eth_card_no,
                   eth_config_file]
    for key, value in zip(param_keys, param_values):
        if value.count("ENTER.YOUR"):
            raise error.TestNAError("Parameter '%s'(%s) is not configured."
                                    % (key, value))

    vm1 = env.get_vm(vm_names[0])
    vm2 = None
    if len(vm_names) > 1:
        vm2 = env.get_vm(vm_names[1])

    if eth_card_no not in utils_net.get_net_if():
        raise error.TestNAError("Device %s do not exists." % eth_card_no)
    try:
        iface_cls = utils_net.Interface(eth_card_no)
        origin_status = iface_cls.is_up()
        if not origin_status:
            iface_cls.up()
    except error.CmdError, detail:
        raise error.TestNAError(str(detail))
Ejemplo n.º 6
0
    def setup(self, test, params, env):
        self.br0_name = "br0-%s" % (utils_misc.generate_random_string(3))
        while self.br0_name in utils_net.get_net_if():
            self.br0_name = "br0-%s" % (utils_misc.generate_random_string(3))
        self.br0_ip = params.get("bridge_ip", "192.168.250.1")

        self.ovs = None

        error.context("Try to log into guest.")
        self.vms = [env.get_vm(vm) for vm in params.get("vms").split()]
        for vm in self.vms:
            vm.verify_alive()

        error.context("Start OpenVSwitch.")
        self.ovs = versionable_class.factory(openvswitch.OpenVSwitchSystem)()
        self.ovs.init_system()
        self.ovs.check()
        error.context("Add new bridge %s." % (self.br0_name))
        self.ovs.add_br(self.br0_name)
        utils_net.set_net_if_ip(self.br0_name, self.br0_ip)
        utils_net.bring_up_ifname(self.br0_name)
        self.dns_pidf = (utils_net.check_add_dnsmasq_to_br(self.br0_name,
                                                            test.tmpdir))
        error.context("Add new ports from vms %s to bridge %s." %
                        (self.vms, self.br0_name))

        for vm in self.vms:
            utils_net.change_iface_bridge(vm.virtnet[1],
                                           self.br0_name,
                                           self.ovs)


        logging.debug(self.ovs.status())
        self.host = ovs_utils.Machine(src=test.srcdir)
        self.mvms = [ovs_utils.Machine(vm) for vm in self.vms]
        self.machines = [self.host] + self.mvms

        #ForAllP(self.mvms).cmd("dhclinet")

        time.sleep(5)
        utils_misc.ForAllP(self.machines).fill_addrs()
Ejemplo n.º 7
0
def run(test, params, env):
    """
    Test interface devices update
    """
    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)
    network_name = params.get('network_name', 'default')
    new_network_name = params.get("net_name")
    expect_error = "yes" == params.get("status_error", "no")
    expect_err_msg = params.get("expect_err_msg")

    iface_driver = params.get("iface_driver")
    iface_driver_host = params.get("iface_driver_host")
    iface_driver_guest = params.get("iface_driver_guest")
    iface_model = params.get("iface_model")
    iface_mtu = params.get("iface_mtu")
    iface_rom = params.get("iface_rom")
    iface_filter = params.get("iface_filter")
    iface_boot = params.get('iface_boot')
    iface_coalesce = params.get('iface_coalesce')

    new_iface_driver = params.get("new_iface_driver")
    new_iface_driver_host = params.get("new_iface_driver_host")
    new_iface_driver_guest = params.get("new_iface_driver_guest")
    new_iface_model = params.get("new_iface_model")
    new_iface_rom = params.get("new_iface_rom")
    new_iface_inbound = params.get("new_iface_inbound")
    new_iface_outbound = params.get("new_iface_outbound")
    new_iface_link = params.get("new_iface_link")
    new_iface_source = params.get("new_iface_source")
    new_iface_target = params.get("new_iface_target")
    new_iface_addr = params.get("new_iface_addr")
    new_iface_filter = params.get("new_iface_filter")
    new_iface_mtu = params.get("new_iface_mtu")
    new_iface_type = params.get("new_iface_type")
    create_new_net = "yes" == params.get("create_new_net")
    new_iface_alias = params.get("new_iface_alias")
    new_iface_coalesce = params.get('new_iface_coalesce')
    cold_update = "yes" == params.get("cold_update", "no")
    del_addr = "yes" == params.get("del_address")
    del_rom = "yes" == params.get("del_rom")
    del_filter = "yes" == params.get("del_filter")
    check_libvirtd = "yes" == params.get("check_libvirtd")
    new_iface_filter_parameters = eval(
        params.get("new_iface_filter_parameters", "{}"))
    rules = eval(params.get("rules", "{}"))
    del_mac = "yes" == params.get("del_mac", "no")
    del_coalesce = 'yes' == params.get('del_coalesce', 'no')

    del_net_bandwidth = 'yes' == params.get('del_net_bandwidth', 'no')

    # Backup the vm xml for recover at last
    vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    netxml_backup = network_xml.NetworkXML.new_from_net_dumpxml(network_name)

    try:
        # Prepare network
        netxml = network_xml.NetworkXML.new_from_net_dumpxml(network_name)
        logging.debug('Network xml before update:\n%s', netxml)
        if del_net_bandwidth:
            netxml.del_element('/bandwidth')
        logging.debug('Network xml after update:\n%s', netxml)

        # According to the different os find different file for rom
        if (iface_rom and "file" in eval(iface_rom)
                and "%s" in eval(iface_rom)['file']):
            if rpm.RpmBackend().check_installed('ipxe-roms-qemu', '20200823'):
                logging.debug("Update the file path since " "ipxe-20200823-5:")
                iface_rom_new = iface_rom.replace('qemu-kvm', 'ipxe/qemu')
                iface_rom = iface_rom_new
            if os.path.exists(eval(iface_rom)['file'] % "pxe"):
                iface_rom = iface_rom % "pxe"
            elif os.path.exists(eval(iface_rom)['file'] % "efi"):
                iface_rom = iface_rom % "efi"
            else:
                logging.error("Can not find suitable rom file")
        iface_dict_bef = {}
        iface_dict_aft = {}
        names = locals()
        # Collect need update items in 2 dicts for both start vm before and after
        update_list_bef = [
            "driver", 'driver_host', 'driver_guest', "model", "mtu", "rom",
            "filter", 'boot', 'coalesce'
        ]
        for update_item_bef in update_list_bef:
            if names['iface_' + update_item_bef]:
                iface_dict_bef.update(
                    {update_item_bef: names['iface_' + update_item_bef]})

        update_list_aft = [
            "driver", "driver_host", "driver_guest", "model", "rom", "inbound",
            "outbound", "link", "source", "target", "addr", "filter", "mtu",
            "type", "alias", "filter_parameters", "coalesce"
        ]
        for update_item_aft in update_list_aft:
            if names["new_iface_" + update_item_aft]:
                iface_dict_aft.update(
                    {update_item_aft: names["new_iface_" + update_item_aft]})
        logging.info("iface_dict_bef is %s, iface_dict_aft is %s",
                     iface_dict_bef, iface_dict_aft)

        del_list = [
            "del_addr", "del_rom", "del_filter", "del_mac", "del_coalesce"
        ]
        for del_item in del_list:
            if names[del_item]:
                iface_dict_aft.update({del_item: names[del_item]})

        # Operations before updating vm's iface xml
        if iface_boot:
            disk_boot = params.get('disk_book', 1)
            vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
            # Remove os boot config
            vm_os = vmxml.os
            vm_os.del_boots()
            vmxml.os = vm_os
            # Add boot config to disk
            disk = vmxml.get_devices('disk')[0]
            target_dev = disk.target.get('dev', '')
            logging.debug('Will set boot order %s to device %s', disk_boot,
                          target_dev)
            vmxml.set_boot_order_by_target_dev(target_dev, disk_boot)
            vmxml.sync()

        # Update vm interface with items in iface_dict_bef and start it
        if iface_dict_bef:
            libvirt.modify_vm_iface(vm_name, "update_iface", iface_dict_bef)
        logging.info("vm xml is %s", vm.get_xml())

        if not cold_update:
            vm.start()

        if iface_mtu:
            # Do check for mtu size after start vm
            target_dev = libvirt.get_interface_details(vm_name)[0]['interface']
            cmd = "ip link show %s | grep 'mtu %s'" % (target_dev,
                                                       eval(iface_mtu)['size'])

            def check_mtu():
                """
                Check the mtu setting take effect for interface
                """
                ret = process.run(cmd, ignore_status=True, shell=True)
                if ret.exit_status:
                    test.fail("Can not find mtu setting in cmd result")

            check_mtu()
            utils_libvirtd.libvirtd_restart()
            check_mtu()

        # Create new network if need
        if create_new_net:
            new_net_xml = libvirt.create_net_xml(new_network_name, params)
            new_net_xml.sync()

        # Do update for iface_driver
        logging.info('Creating new iface xml.')
        new_iface_xml = libvirt.modify_vm_iface(vm_name, "get_xml",
                                                iface_dict_aft)
        bef_pid = process.getoutput("pidof -s libvirtd")
        ret = virsh.update_device(vm_name,
                                  new_iface_xml,
                                  ignore_status=True,
                                  debug=True)
        libvirt.check_exit_status(ret, expect_error)
        if check_libvirtd:
            aft_pid = process.getoutput("pidof -s libvirtd")
            if aft_pid != bef_pid:
                test.fail("libvirtd crash after update-device!")
            else:
                logging.info("libvirtd do not crash after update-device!")
        if expect_error:
            real_err_msg = ret.stderr.strip()
            if not re.search(expect_err_msg, real_err_msg, re.IGNORECASE):
                test.fail("The real error msg:'%s' does not match expect one:"
                          '%s' % (real_err_msg, expect_err_msg))
            else:
                logging.info("Get expect result: %s", real_err_msg)
        else:
            if new_iface_inbound:
                iface_bandwidth = {}
                iface_bandwidth = vm_xml.VMXML.get_iftune_params(vm_name)
                for bound_para in ["inbound", "outbound"]:
                    for tune_para in ["average", "peak", "burst"]:
                        get_value = iface_bandwidth.get(bound_para).get(
                            tune_para)
                        expect_value = eval(names["new_iface_" +
                                                  bound_para]).get(tune_para)
                        logging.info("Get value for %s:%s is %s, expect is %s",
                                     bound_para, tune_para, get_value,
                                     expect_value)
                        if get_value != expect_value:
                            test.fail("Get value is not equal to expect")
            vmxml_aft = vm_xml.VMXML.new_from_dumpxml(vm_name)
            iface_aft = list(vmxml_aft.get_iface_all().values())[0]
            if new_iface_link:
                iface_link_value = iface_aft.find('link').get('state')
                if iface_link_value == new_iface_link:
                    logging.info("Find link state is %s in xml",
                                 new_iface_link)

                    # Checking the statue in guest
                    mac_addr = iface_aft.find('mac').get('address')
                    state_map = "%s.*\n.*%s" % (iface_link_value.upper(),
                                                mac_addr)
                    session = vm.wait_for_serial_login()
                    logging.info("ip link output:%s",
                                 session.cmd_output("ip link"))
                    if_name = utils_net.get_net_if(runner=session.cmd_output,
                                                   state=state_map)[0]
                    if not check_iface_link(session, mac_addr, new_iface_link):
                        test.fail('iface link check inside vm failed.')
                    session.close()
                    if if_name:
                        logging.info("Find iface state %s for %s",
                                     iface_link_value, mac_addr)
                    else:
                        test.fail(
                            "Can not find iface with mac %s and state %s" %
                            (mac_addr, iface_link_value))
                else:
                    test.fail(
                        "Check fail to get link state, expect %s, but get %s" %
                        (iface_link_value, new_iface_link))
            if create_new_net and new_iface_source:
                iface_source_value = iface_aft.find('source').get('network')
                if iface_source_value == eval(new_iface_source)['network']:
                    logging.info("Get %s in xml as set", iface_source_value)
                else:
                    test.fail("Get source %s is not equal to set %s" %
                              (iface_source_value, new_iface_source))
            if new_iface_filter:
                iface_filter_value = iface_aft.find('filterref').get('filter')
                if iface_filter_value == new_iface_filter:
                    logging.info("Get %s in xml as set", iface_filter_value)
                else:
                    test.fail("Get filter %s is not equal to set %s" %
                              (iface_filter_value, new_iface_filter))
            if new_iface_filter_parameters:
                ebtables_outputs = process.run("ebtables -t nat -L",
                                               shell=True).stdout_text
                for rule in rules:
                    if rule not in ebtables_outputs:
                        test.fail(
                            "Can not find the corresponding rule after update filter with parameters!"
                        )
            if del_filter:
                # if the filter is deleted, it should not exists in the xml and the rules should be deleted as well
                iface_filter_value = iface_aft.find('filterref')
                if iface_filter_value is not None:
                    test.fail("After delete, the filter still exists: %s" %
                              iface_filter_value)
                ebtables_outputs = process.run("ebtables -t nat -L",
                                               shell=True).stdout_text
                logging.debug("after nwfilter deleted, ebtables rules are %s" %
                              ebtables_outputs)
                time.sleep(5)
                entries_num = re.findall(r'entries:\s+(\d)', ebtables_outputs)
                for i in entries_num:
                    if i != '0':
                        test.fail("After delete, the rules are still exists!")
            if new_iface_alias:
                iface_alias_value = iface_aft.find('alias').get('name')
                if iface_alias_value == eval(new_iface_alias)['name']:
                    logging.info("Get %s in xml as set", iface_alias_value)
                else:
                    test.fail("Get alias %s is not equal to set %s" %
                              (iface_alias_value, new_iface_alias))
            if 'update_coalesce' in params['name'] or new_iface_coalesce:
                iface_coalesce_val = iface_aft.find('coalesce').find(
                    'rx').find('frames').get('max')
                if iface_coalesce_val == str(eval(new_iface_coalesce)['max']):
                    logging.info('coalesce update check PASS.')
                else:
                    test.fail('coalesce value not updated.')
            if del_coalesce:
                if iface_aft.find('coalesce') is None:
                    logging.info('coalesce delete check PASS.')
                else:
                    test.fail('coalesce not deleted.')

    finally:
        vmxml_backup.sync()
        netxml_backup.sync()
        if create_new_net:
            new_net_xml.undefine()
Ejemplo n.º 8
0
def run(test, params, env):
    """
    Test 802.1Q vlan of NIC among guests and host with linux bridge backend.

    1) Configure vlan interface over host bridge interface.
    2) Create two VMs over vlan interface.
    3) Load 8021q module in guest.
    4) Configure ip address of guest with 192.168.*.*
    5) Test by ping between guest and host, should fail.
    6) Test by ping beween guests, should pass.
    7) Setup vlan in guests and using hard-coded ip address 192.168.*.*
    8) Test by ping between guest and host, should pass.
    9) Test by ping among guests, should pass.
    10) Test by netperf between guests and host.
    11) Test by netperf between guests.
    12) Delete vlan interface in host.

    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
    """

    def add_vlan(interface, v_id, session=None):
        """
        Create a vlan-device on interface.
        :params interface: Interface.
        :params v_id: Vlan id.
        :params session: VM session or none.
        """
        vlan_if = '%s.%s' % (interface, v_id)
        add_cmd = params["add_vlan_cmd"] % (interface, vlan_if, v_id)
        error_context.context("Create vlan interface '%s' on %s" %
                              (vlan_if, interface), logging.info)
        if session:
            session.cmd(add_cmd)
        else:
            process.system(add_cmd)
        return vlan_if

    def set_ip_vlan(vlan_if, vlan_ip, session=None):
        """
        Set ip address of vlan interface.
        :params vlan_if: Vlan interface.
        :params vlan_ip: Vlan internal ip.
        :params session: VM session or none.
        """
        error_context.context("Assign IP '%s' to vlan interface '%s'" %
                              (vlan_ip, vlan_if), logging.info)
        if session:
            session.cmd("ifconfig %s 0.0.0.0" % vlan_if)
            session.cmd("ifconfig %s down" % vlan_if)
            session.cmd("ifconfig %s %s up" % (vlan_if, vlan_ip))
        else:
            process.system("ifconfig %s %s up" % (vlan_if, vlan_ip))

    def set_mac_vlan(vlan_if, mac_str, session):
        """
        Give a new mac address for vlan interface in guest.
        :params: vlan_if: Vlan interface.
        :params: mac_str: New mac address for vlan.
        :params: session: VM session.
        """
        mac_cmd = "ip link set %s add %s up" % (vlan_if, mac_str)
        error_context.context("Give a new mac address '%s' for vlan interface "
                              "'%s'" % (mac_str, vlan_if), logging.info)
        session.cmd(mac_cmd)

    def set_arp_ignore(session):
        """
        Enable arp_ignore for all ipv4 device in guest
        """
        error_context.context("Enable arp_ignore for all ipv4 device in guest",
                              logging.info)
        ignore_cmd = "echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore"
        session.cmd(ignore_cmd)

    def ping_vlan(vm, dest, vlan_if, session):
        """
        Test ping between vlans, from guest to host/guest.
        :params vm: VM object
        :params dest: Dest ip to ping.
        :params vlan_if: Vlan interface.
        :params session: VM session.
        """
        error_context.context("Test ping from '%s' to '%s' on guest '%s'" %
                              (vlan_if, dest, vm.name))
        status, output = utils_test.ping(dest=dest, count=10,
                                         interface=vlan_if,
                                         session=session,
                                         timeout=30)
        if status:
            raise NetPingError(vlan_if, dest, output)

    def netperf_vlan(client='main_vm', server='localhost',
                     sub_type='netperf_stress'):
        """
        Test netperf stress among guests and host.
        :params client: Netperf client.
        :params server: Netperf server.
        :params sub_type: Sub_type to run.
        """
        params["netperf_client"] = client
        params["netperf_server"] = server
        error_context.context("Run netperf stress test among guests and host, "
                              "server: %s, client: %s" % (server, client),
                              logging.info)
        utils_test.run_virt_sub_test(test, params, env, sub_type)

    vms = []
    sessions = []
    ifname = []
    vm_ip = []
    vm_vlan_ip = []
    vm_vlan_if = []
    sub_type = params["sub_type"]
    host_br = params.get("netdst", "switch")
    host_vlan_id = params.get("host_vlan_id", "10")
    host_vlan_ip = params.get("host_vlan_ip", "192.168.10.10")
    subnet = params.get("subnet", "192.168")
    mac_str = params.get("mac_str").split(',')

    br_backend = utils_net.find_bridge_manager(host_br)
    if not isinstance(br_backend, utils_net.Bridge):
        test.cancel("Host does not use Linux Bridge")

    linux_modules.load_module("8021q")

    host_vlan_if = "%s.%s" % (host_br, host_vlan_id)
    if host_vlan_if not in utils_net.get_net_if():
        host_vlan_if = add_vlan(interface=host_br, v_id=host_vlan_id)
        if host_vlan_if in utils_net.get_net_if():
            set_ip_vlan(vlan_if=host_vlan_if, vlan_ip=host_vlan_ip)
            rm_host_vlan_cmd = params["rm_host_vlan_cmd"] % host_vlan_if
            funcatexit.register(env, params["type"], _system,
                                rm_host_vlan_cmd)
        else:
            test.cancel("Fail to set up vlan over bridge interface in host!")

    if params.get("start_vm", "yes") == "no":
        vm_main = env.get_vm(params["main_vm"])
        vm_main.create(params=params)
        vm2 = env.get_vm("vm2")
        vm2.create(params=params)
        vms.append(vm_main)
        vms.append(vm2)
    else:
        vms.append(env.get_vm([params["main_vm"]]))
        vms.append(env.get_vm('vm2'))

    for vm_ in vms:
        vm_.verify_alive()

    for vm_index, vm in enumerate(vms):
        error_context.context("Prepare test env on %s" % vm.name)
        session = vm.wait_for_serial_login()
        if not session:
            err_msg = "Could not log into guest %s" % vm.name
            test.error(err_msg)

        interface = utils_net.get_linux_ifname(session, vm.get_mac_address())

        error_context.context("Load 8021q module in guest %s" % vm.name,
                              logging.info)
        session.cmd_output_safe("modprobe 8021q")

        error_context.context("Setup vlan environment in guest %s" % vm.name,
                              logging.info)
        inter_ip = "%s.%s.%d" % (subnet, host_vlan_id, vm_index + 1)
        set_ip_vlan(interface, inter_ip, session=session)
        set_arp_ignore(session)
        params["vlan_nic"] = "%s.%s" % (interface, host_vlan_id)
        error_context.context("Test ping from guest '%s' to host with "
                              "interface '%s'" %
                              (vm.name, interface), logging.info)
        try:
            ping_vlan(vm, dest=host_vlan_ip, vlan_if=interface,
                      session=session)
        except NetPingError:
            logging.info("Guest ping fail to host as expected with "
                         "interface '%s'", interface)
        else:
            test.fail("Guest ping to host should fail with interface"
                      " '%s'" % interface)
        ifname.append(interface)
        vm_ip.append(inter_ip)
        sessions.append(session)

    # Ping succeed between guests
    error_context.context("Test ping between guests with interface %s"
                          % ifname[0], logging.info)
    ping_vlan(vms[0], dest=vm_ip[1], vlan_if=ifname[0], session=sessions[0])

    # set vlan tag for guest
    for vm_index, vm in enumerate(vms):
        session = sessions[vm_index]
        error_context.context("Add vlan interface on guest '%s'" % vm.name)
        session.cmd("ifconfig %s 0.0.0.0" % ifname[vm_index])
        vlan_if = add_vlan(interface=ifname[vm_index], v_id=host_vlan_id,
                           session=session)
        vm_vlan_if.append(vlan_if)
        set_mac_vlan(vlan_if, mac_str[vm_index], session=session)
        vlan_ip = "%s.%s.%d" % (subnet, host_vlan_id, vm_index + 11)
        set_ip_vlan(vlan_if, vlan_ip, session=session)
        vm_vlan_ip.append(vlan_ip)

        error_context.context("Test ping from interface '%s' on guest "
                              "'%s' to host." %
                              (vm_vlan_if[vm_index], vm.name), logging.info)
        ping_vlan(vm, dest=host_vlan_ip, vlan_if=vm_vlan_if[vm_index],
                  session=session)
        netperf_vlan(client=vm.name, server="localhost")

    error_context.context("Test ping and netperf between guests with "
                          "interface '%s'" %
                          vm_vlan_if[vm_index], logging.info)
    ping_vlan(vms[0], dest=vm_vlan_ip[1], vlan_if=vm_vlan_if[0],
              session=sessions[0])
    netperf_vlan(client=params["main_vm"], server='vm2')

    exithandlers = "exithandlers__%s" % sub_type
    sub_exit_timeout = int(params.get("sub_exit_timeout", 10))
    start_time = time.time()
    end_time = start_time + float(sub_exit_timeout)

    while time.time() < end_time:
        logging.debug("%s (%f secs)", sub_type + " is running",
                      (time.time() - start_time))
        if env.data.get(exithandlers):
            break
        time.sleep(1)

    for sess in sessions:
        if sess:
            sess.close()
Ejemplo n.º 9
0
    def modify_iface_xml(update, status_error=False):
        """
        Modify interface xml options
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        xml_devices = vmxml.devices
        iface_index = xml_devices.index(
            xml_devices.by_device_tag("interface")[0])
        iface = xml_devices[iface_index]
        if iface_model:
            iface.model = iface_model
        else:
            del iface.model
        if iface_type:
            iface.type_name = iface_type
        del iface.source
        source = ast.literal_eval(iface_source)
        if source:
            net_ifs = utils_net.get_net_if(state="UP")
            # Check source device is valid or not,
            # if it's not in host interface list, try to set
            # source device to first active interface of host
            if (iface.type_name == "direct" and 'dev' in source
                    and source['dev'] not in net_ifs):
                logging.warn(
                    "Source device %s is not a interface"
                    " of host, reset to %s", source['dev'], net_ifs[0])
                source['dev'] = net_ifs[0]
            iface.source = source
        backend = ast.literal_eval(iface_backend)
        if backend:
            iface.backend = backend
        driver_dict = {}
        driver_host = {}
        driver_guest = {}
        if iface_driver:
            driver_dict = ast.literal_eval(iface_driver)
        if iface_driver_host:
            driver_host = ast.literal_eval(iface_driver_host)
        if iface_driver_guest:
            driver_guest = ast.literal_eval(iface_driver_guest)
        iface.driver = iface.new_driver(driver_attr=driver_dict,
                                        driver_host=driver_host,
                                        driver_guest=driver_guest)
        if test_target:
            logging.debug("iface.target is %s" % target_dev)
            iface.target = {"dev": target_dev}
        if iface.address:
            del iface.address
        if set_ip:
            iface.ips = [ast.literal_eval(x) for x in set_ips]
        logging.debug("New interface xml file: %s", iface)
        if unprivileged_user:
            # Create disk image for unprivileged user
            disk_index = xml_devices.index(
                xml_devices.by_device_tag("disk")[0])
            disk_xml = xml_devices[disk_index]
            logging.debug("source: %s", disk_xml.source)
            disk_source = disk_xml.source.attrs["file"]
            cmd = ("cp -fZ {0} {1} && chown {2}:{2} {1}"
                   "".format(disk_source, dst_disk, unprivileged_user))
            process.run(cmd, shell=True)
            disk_xml.source = disk_xml.new_disk_source(
                attrs={"file": dst_disk})
            vmxml.devices = xml_devices
            # Remove all channels to avoid of permission problem
            channels = vmxml.get_devices(device_type="channel")
            for channel in channels:
                vmxml.del_device(channel)
            logging.info("Unprivileged users can't use 'dac' security driver,"
                         " removing from domain xml if present...")
            vmxml.del_seclabel([('model', 'dac')])

            # Set vm memory to 2G if it's larger than 2G
            if vmxml.memory > 2097152:
                vmxml.memory = vmxml.current_mem = 2097152

            vmxml.xmltreefile.write()
            logging.debug("New VM xml: %s", vmxml)
            process.run("chmod a+rw %s" % vmxml.xml, shell=True)
            virsh.define(vmxml.xml, **virsh_dargs)
        # Try to modify interface xml by update-device or edit xml
        elif update:
            iface.xmltreefile.write()
            ret = virsh.update_device(vm_name, iface.xml, ignore_status=True)
            libvirt.check_exit_status(ret, status_error)
        else:
            vmxml.devices = xml_devices
            vmxml.xmltreefile.write()
            try:
                vmxml.sync()
                if define_error:
                    test.fail("Define VM succeed, but it should fail")
            except xcepts.LibvirtXMLError as e:
                if not define_error:
                    test.fail("Define VM fail: %s" % e)
Ejemplo n.º 10
0
def run(test, params, env):
    """
    Test virsh {at|de}tach-interface command.

    1) Prepare test environment and its parameters
    2) Attach the required interface
    3) According test type(only attach or both attach and detach):
       a.Go on to test detach(if attaching is correct)
       b.Return GOOD or raise TestFail(if attaching is wrong)
    4) Check if attached interface is correct:
       a.Try to catch it in vm's XML file
       b.Try to catch it in vm
    5) Detach the attached interface
    6) Check result
    """

    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)
    backup_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

    # Test parameters
    uri = libvirt_vm.normalize_connect_uri(params.get("connect_uri",
                                                      "default"))
    vm_ref = params.get("at_detach_iface_vm_ref", "domname")
    options_suffix = params.get("at_detach_iface_options_suffix", "")
    status_error = "yes" == params.get("status_error", "no")
    start_vm = params.get("start_vm")
    # Should attach must be pass for detach test.
    correct_attach = "yes" == params.get("correct_attach", "no")
    readonly = ("yes" == params.get("readonly", "no"))

    # Interface specific attributes.
    iface_type = params.get("at_detach_iface_type", "network")
    iface_source = params.get("at_detach_iface_source", "default")
    iface_mode = params.get("at_detach_iface_mode", "vepa")
    iface_mac = params.get("at_detach_iface_mac", "created")
    iface_target = params.get("at_detach_iface_target")
    iface_model = params.get("at_detach_iface_model")
    iface_inbound = params.get("at_detach_iface_inbound")
    iface_outbound = params.get("at_detach_iface_outbound")
    iface_rom = params.get("at_detach_rom_bar")
    iface_link = params.get("at_detach_link_state")
    iface_boot = params.get("at_detach_boot_order")
    iface_driver = params.get("at_detach_iface_driver")
    iface_driver_host = params.get("at_detach_driver_host")
    iface_driver_guest = params.get("at_detach_driver_guest")
    iface_backend = params.get("at_detach_iface_backend")

    save_restore = params.get("save_restore", "no")
    restart_libvirtd = params.get("restart_libvirtd", "no")
    attach_cmd = params.get("attach_cmd", "attach-interface")
    virsh_dargs = {'ignore_status': True, 'debug': True, 'uri': uri}
    validate_xml_result = "yes" == params.get("check_xml_result", "no")
    paused_after_vm_start = "yes" == params.get("paused_after_vm_start", "no")
    machine_type = params.get("machine_type")

    # Get iface name if iface_type is direct
    if iface_type == "direct":
        iface_source = utils_net.get_net_if(state="UP")[0]
    # Get a bridge name for test if iface_type is bridge.
    # If there is no bridge other than virbr0, try to create one
    # or fail test
    if iface_type == "bridge":
        host_bridge = utils_net.Bridge()
        bridge_list = host_bridge.list_br()
        try:
            bridge_list.remove("virbr0")
        except AttributeError:
            pass  # If no virbr0, just pass is ok
        logging.debug("Useful bridges:%s", bridge_list)
        if len(bridge_list):
            iface_source = bridge_list[0]
        else:
            process.run('ip link add name br0 type bridge',
                        ignore_status=False)
            iface_source = 'br0'
            logging.debug("Added bridge br0")

    # Test both detach and attach, So collect info
    # both of them for result check.
    # When something wrong with interface, set it to 1
    fail_flag = 0
    result_info = []

    # Get a mac address if iface_mac is 'created'.
    if iface_mac == "created" or correct_attach:
        iface_mac = utils_net.generate_mac_address_simple()

    names = locals()
    iface_format = get_formatted_iface_dict(names, params.get("vm_arch_name"))

    # for rtl8139 model, need to add pcie bridge
    if iface_model == "rtl8139" and machine_type == "q35":
        add_pcie_controller(vm_name)
        if start_vm == "yes" and not vm.is_alive():
            vm.start()

    try:
        # Generate xml file if using attach-device command
        if attach_cmd == "attach-device":
            # Change boot order to disk
            libvirt.change_boot_order(vm_name, "disk", "1")
            vm.destroy()
            vm.start()
            # Generate attached xml
            new_iface = Interface(type_name=iface_type)
            xml_file_tmp = libvirt.modify_vm_iface(vm_name, "get_xml",
                                                   iface_format)
            new_iface.xml = xml_file_tmp
            new_iface.del_address()
            xml_file = new_iface.xml

        # To confirm vm's state and make sure os fully started
        if start_vm == "no":
            if vm.is_alive():
                vm.destroy()
        else:
            vm.wait_for_login().close()

        if paused_after_vm_start:
            vm.pause()

        # Set attach-interface domain
        dom_uuid = vm.get_uuid()
        dom_id = vm.get_id()

        if vm_ref == "domname":
            vm_ref = vm_name
        elif vm_ref == "domid":
            vm_ref = dom_id
        elif vm_ref == "domuuid":
            vm_ref = dom_uuid
        elif vm_ref == "hexdomid" and dom_id is not None:
            vm_ref = hex(int(dom_id))

        # Set attach-interface options and Start attach-interface test
        if correct_attach:
            options = set_options("network", "default", iface_mac, "",
                                  "attach", None, iface_model)
            if readonly:
                virsh_dargs.update({'readonly': True, 'debug': True})
            attach_result = virsh.attach_interface(vm_name, options,
                                                   **virsh_dargs)
        else:
            if attach_cmd == "attach-interface":
                options = set_options(iface_type, iface_source, iface_mac,
                                      options_suffix, "attach", iface_target,
                                      iface_model, iface_inbound,
                                      iface_outbound)
                attach_result = virsh.attach_interface(vm_ref, options,
                                                       **virsh_dargs)
            elif attach_cmd == "attach-device":
                attach_result = virsh.attach_device(vm_name,
                                                    xml_file,
                                                    ignore_status=True,
                                                    debug=True)
        attach_status = attach_result.exit_status
        logging.debug(attach_result)

        # If attach interface failed.
        if attach_status:
            if not status_error:
                fail_flag = 1
                result_info.append("Attach Failed: %s" % attach_result.stderr)
            elif status_error:
                # Here we just use it to exit, do not mean test failed
                fail_flag = 1
        # If attach interface succeeded.
        else:
            if status_error and not correct_attach:
                fail_flag = 1
                result_info.append("Attach Success with wrong command.")

        if fail_flag and start_vm == "yes":
            vm.destroy()
            if len(result_info):
                test.fail(result_info)
            else:
                # Exit because it is error_test for attach-interface.
                return

        if "print-xml" in options_suffix:
            iface_obj = Interface(type_name=iface_type)
            iface_obj.xml = attach_result.stdout.strip()
            if (iface_obj.type_name == iface_type
                    and iface_obj.source['dev'] == iface_source
                    and iface_obj.target['dev'] == iface_target
                    and iface_obj.model == iface_model
                    and iface_obj.bandwidth.inbound == eval(
                        iface_format['inbound'])
                    and iface_obj.bandwidth.outbound == eval(
                        iface_format['outbound'])):
                logging.info("Print ml all element check pass")
            else:
                test.fail("Print xml do not show as expected")

        # Check dumpxml file whether the interface is added successfully.
        status, ret = check_dumpxml_iface(vm_name, iface_format)
        if "print-xml" not in options_suffix:
            # Check validate_xml_result flag to determine whether apply check_interface_xml.
            if validate_xml_result:
                # If options_suffix contains config, it need dump inactive xml.
                is_active = True
                if options_suffix.count("config"):
                    is_active = False
                # Check dumping VM xml value.
                if not check_interface_xml(vm_name, iface_type, iface_source,
                                           iface_mac, is_active):
                    test.fail(
                        "Failed to find matched interface values in VM interface xml"
                    )
            if status:
                fail_flag = 1
                result_info.append(ret)
        else:
            if status == 0:
                test.fail(
                    "Attach interface effect in xml with print-xml option")
            else:
                return

        # Login to domain to check new interface.
        if not vm.is_alive():
            vm.start()
        elif vm.state() == "paused":
            vm.resume()
        vm.wait_for_login().close()

        status, ret = login_to_check(vm, iface_mac)
        if status:
            fail_flag = 1
            result_info.append(ret)

        # Check on host for direct type
        if iface_type == 'direct':
            cmd_result = process.run(
                "ip -d link show test").stdout_text.strip()
            logging.info("cmd output is %s", cmd_result)
            check_patten = (
                "%s@%s.*\n.*%s.*\n.*macvtap.*mode.*%s" %
                (iface_target, iface_source, iface_mac, iface_mode))
            logging.info("check patten is %s", check_patten)
            if not re.search(check_patten, cmd_result):
                logging.error("Can not find %s in ip link" % check_patten)
                fail_flag = 1
                result_info.append(cmd_result)

        # Do operation and check again
        if restart_libvirtd == "yes":
            libvirtd = utils_libvirtd.Libvirtd()
            libvirtd.restart()

        if save_restore == "yes":
            check_save_restore(vm_name)

        status, ret = check_dumpxml_iface(vm_name, iface_format)
        if status:
            fail_flag = 1
            result_info.append(ret)

        # Set detach-interface options
        options = set_options(iface_type, None, iface_mac, options_suffix,
                              "detach")

        # Start detach-interface test
        if save_restore == "yes" and vm_ref == dom_id:
            vm_ref = vm_name
        detach_result = virsh.detach_interface(vm_ref, options, **virsh_dargs)
        detach_status = detach_result.exit_status
        detach_msg = detach_result.stderr.strip()

        logging.debug(detach_result)

        if detach_status == 0 and status_error == 0:
            # If command with --config parameter, ignore below checking.
            if options_suffix.count("config"):
                return
            # Check the xml after detach and clean up if needed.
            time.sleep(5)
            status, _ = check_dumpxml_iface(vm_name, iface_format)
            if status == 0:
                detach_status = 1
                detach_msg = "xml still exist after detach"
                cleanup_options = "--type %s --mac %s" % (iface_type,
                                                          iface_mac)
                virsh.detach_interface(vm_ref, cleanup_options, **virsh_dargs)
            else:
                logging.info("After detach, the interface xml disappeared")

        # Check results.
        if status_error:
            if detach_status == 0:
                test.fail("Detach Success with wrong command.")
        else:
            if detach_status != 0:
                test.fail("Detach Failed: %s" % detach_msg)
            else:
                if fail_flag:
                    test.fail("Attach-Detach Success but "
                              "something wrong with its "
                              "functional use:%s" % result_info)
    finally:
        if vm.is_alive():
            vm.destroy()
        backup_xml.sync()
Ejemplo n.º 11
0
def run(test, params, env):
    """
    Test interface devices update
    """
    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)
    new_network_name = params.get("net_name")
    expect_error = "yes" == params.get("status_error", "no")
    expect_err_msg = params.get("expect_err_msg")

    iface_driver = params.get("iface_driver")
    iface_model = params.get("iface_model")
    iface_mtu = params.get("iface_mtu")
    iface_rom = params.get("iface_rom")

    new_iface_driver = params.get("new_iface_driver")
    new_iface_driver_host = params.get("new_iface_driver_host")
    new_iface_driver_guest = params.get("new_iface_driver_guest")
    new_iface_model = params.get("new_iface_model")
    new_iface_rom = params.get("new_iface_rom")
    new_iface_inbound = params.get("new_iface_inbound")
    new_iface_outbound = params.get("new_iface_outbound")
    new_iface_link = params.get("new_iface_link")
    new_iface_source = params.get("new_iface_source")
    new_iface_target = params.get("new_iface_target")
    new_iface_addr = params.get("new_iface_addr")
    new_iface_filter = params.get("new_iface_filter")
    new_iface_mtu = params.get("new_iface_mtu")
    new_iface_type = params.get("new_iface_type")
    create_new_net = "yes" == params.get("create_new_net")
    new_iface_alias = params.get("new_iface_alias")
    cold_update = "yes" == params.get("cold_update", "no")
    del_addr = "yes" == params.get("del_address")
    del_rom = "yes" == params.get("del_rom")

    # Backup the vm xml for recover at last
    vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

    try:
        # According to the different os find different file for rom
        if (iface_rom and "file" in eval(iface_rom)
                and "%s" in eval(iface_rom)['file']):
            if os.path.exists(eval(iface_rom)['file'] % "pxe"):
                iface_rom = iface_rom % "pxe"
            elif os.path.exists(eval(iface_rom)['file'] % "efi"):
                iface_rom = iface_rom % "efi"
            else:
                logging.error("Can not find suitable rom file")
        iface_dict_bef = {}
        iface_dict_aft = {}
        names = locals()
        # Collect need update items in 2 dicts for both start vm before and after
        update_list_bef = [
            "driver", "model", "mtu", "rom"
            ]
        for update_item_bef in update_list_bef:
            if names['iface_'+update_item_bef]:
                iface_dict_bef.update({update_item_bef: names['iface_'+update_item_bef]})

        update_list_aft = [
            "driver", "driver_host", "driver_guest", "model", "rom", "inbound",
            "outbound", "link", "source", "target", "addr", "filter", "mtu", "type",
            "alias"]
        for update_item_aft in update_list_aft:
            if names["new_iface_"+update_item_aft]:
                iface_dict_aft.update({update_item_aft: names["new_iface_"+update_item_aft]})
        logging.info("iface_dict_bef is %s, iface_dict_aft is %s",
                     iface_dict_bef, iface_dict_aft)

        del_list = ["del_addr", "del_rom"]
        for del_item in del_list:
            if names[del_item]:
                iface_dict_aft.update({del_item: "True"})

        # Update vm interface with items in iface_dict_bef and start it
        if iface_dict_bef:
            libvirt.modify_vm_iface(vm_name, "update_iface", iface_dict_bef)
        logging.info("vm xml is %s", vm.get_xml())

        if not cold_update:
            vm.start()

        if iface_mtu:
            # Do check for mtu size after start vm
            target_dev = libvirt.get_interface_details(vm_name)[0]['interface']
            cmd = "ip link show %s | grep 'mtu %s'" % (target_dev, eval(iface_mtu)['size'])

            def check_mtu():
                """
                Check the mtu setting take effect for interface
                """
                ret = process.run(cmd, ignore_status=True, shell=True)
                if ret.exit_status:
                    test.fail("Can not find mtu setting in cmd result")

            check_mtu()
            utils_libvirtd.libvirtd_restart()
            check_mtu()

        # Create new network if need
        if create_new_net:
            new_net_xml = libvirt.create_net_xml(new_network_name, params)
            new_net_xml.sync()

        # Do update for iface_driver
        new_iface_xml = libvirt.modify_vm_iface(vm_name, "get_xml", iface_dict_aft)
        ret = virsh.update_device(vm_name, new_iface_xml, ignore_status=True, debug=True)
        libvirt.check_exit_status(ret, expect_error)
        if expect_error:
            real_err_msg = ret.stderr.strip()
            if not re.search(expect_err_msg, real_err_msg, re.IGNORECASE):
                test.fail("The real error msg:'%s' does not match expect one:"
                          '%s' % (real_err_msg, expect_err_msg))
            else:
                logging.info("Get expect result: %s", real_err_msg)
        else:
            if new_iface_inbound:
                iface_bandwidth = {}
                iface_bandwidth = vm_xml.VMXML.get_iftune_params(vm_name)
                for bound_para in ["inbound", "outbound"]:
                    for tune_para in ["average", "peak", "burst"]:
                        get_value = iface_bandwidth.get(bound_para).get(tune_para)
                        expect_value = eval(names["new_iface_"+bound_para]).get(tune_para)
                        logging.info("Get value for %s:%s is %s, expect is %s",
                                     bound_para, tune_para, get_value, expect_value)
                        if get_value != expect_value:
                            test.fail("Get value is not equal to expect")
            vmxml_aft = vm_xml.VMXML.new_from_dumpxml(vm_name)
            iface_aft = list(vmxml_aft.get_iface_all().values())[0]
            if new_iface_link:
                iface_link_value = iface_aft.find('link').get('state')
                if iface_link_value == new_iface_link:
                    logging.info("Find link state is %s in xml", new_iface_link)

                    # Checking the statue in guest
                    mac_addr = iface_aft.find('mac').get('address')
                    state_map = "%s.*\n.*%s" % (iface_link_value.upper(), mac_addr)
                    session = vm.wait_for_serial_login()
                    logging.info("ip link output:%s", session.cmd_output("ip link"))
                    if_name = utils_net.get_net_if(runner=session.cmd_output, state=state_map)[0]
                    session.close()
                    if if_name:
                        logging.info("Find iface state %s for %s", iface_link_value, mac_addr)
                    else:
                        test.fail("Can not find iface with mac %s and state %s"
                                  % (mac_addr, iface_link_value))
                else:
                    test.fail("Check fail to get link state, expect %s, but get %s"
                              % (iface_link_value, new_iface_link))
            if create_new_net and new_iface_source:
                iface_source_value = iface_aft.find('source').get('network')
                if iface_source_value == eval(new_iface_source)['network']:
                    logging.info("Get %s in xml as set", iface_source_value)
                else:
                    test.fail("Get source %s is not equal to set %s"
                              % (iface_source_value, new_iface_source))
            if new_iface_filter:
                iface_filter_value = iface_aft.find('filterref').get('filter')
                if iface_filter_value == new_iface_filter:
                    logging.info("Get %s in xml as set", iface_filter_value)
                else:
                    test.fail("Get filter %s is not equal to set %s"
                              % (iface_filter_value, new_iface_filter))
            if new_iface_alias:
                iface_alias_value = iface_aft.find('alias').get('name')
                if iface_alias_value == eval(new_iface_alias)['name']:
                    logging.info("Get %s in xml as set", iface_alias_value)
                else:
                    test.fail("Get alias %s is not equal to set %s"
                              % (iface_alias_value, new_iface_alias))
    finally:
        vmxml_backup.sync()
        if create_new_net:
            new_net_xml.undefine()
def run(test, params, env):
    """
    Test virsh {at|de}tach-interface command.

    1) Prepare test environment and its parameters
    2) Attach the required interface
    3) According test type(only attach or both attach and detach):
       a.Go on to test detach(if attaching is correct)
       b.Return GOOD or raise TestFail(if attaching is wrong)
    4) Check if attached interface is correct:
       a.Try to catch it in vm's XML file
       b.Try to catch it in vm
    5) Detach the attached interface
    6) Check result
    """

    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)
    backup_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

    # Test parameters
    uri = libvirt_vm.normalize_connect_uri(params.get("connect_uri",
                                                      "default"))
    vm_ref = params.get("at_detach_iface_vm_ref", "domname")
    options_suffix = params.get("at_detach_iface_options_suffix", "")
    status_error = "yes" == params.get("status_error", "no")
    start_vm = params.get("start_vm")
    # Should attach must be pass for detach test.
    correct_attach = "yes" == params.get("correct_attach", "no")
    readonly = ("yes" == params.get("readonly", "no"))

    # Interface specific attributes.
    iface_type = params.get("at_detach_iface_type", "network")
    if iface_type == "bridge":
        try:
            utils_path.find_command("brctl")
        except utils_path.CmdNotFoundError:
            test.cancel("Command 'brctl' is missing. You must "
                        "install it.")

    iface_source = params.get("at_detach_iface_source", "default")
    iface_mode = params.get("at_detach_iface_mode", "vepa")
    iface_mac = params.get("at_detach_iface_mac", "created")
    iface_target = params.get("at_detach_iface_target")
    iface_model = params.get("at_detach_iface_model")
    iface_inbound = params.get("at_detach_iface_inbound")
    iface_outbound = params.get("at_detach_iface_outbound")
    iface_rom = params.get("at_detach_rom_bar")
    iface_link = params.get("at_detach_link_state")
    iface_boot = params.get("at_detach_boot_order")
    iface_driver = params.get("at_detach_iface_driver")
    iface_driver_host = params.get("at_detach_driver_host")
    iface_driver_guest = params.get("at_detach_driver_guest")
    iface_backend = params.get("at_detach_iface_backend")

    save_restore = params.get("save_restore", "no")
    restart_libvirtd = params.get("restart_libvirtd", "no")
    attach_cmd = params.get("attach_cmd", "attach-interface")
    virsh_dargs = {'ignore_status': True, 'debug': True, 'uri': uri}

    # Get iface name if iface_type is direct
    if iface_type == "direct":
        iface_source = utils_net.get_net_if(state="UP")[0]
    # Get a bridge name for test if iface_type is bridge.
    # If there is no bridge other than virbr0, raise TestCancel
    if iface_type == "bridge":
        host_bridge = utils_net.Bridge()
        bridge_list = host_bridge.list_br()
        try:
            bridge_list.remove("virbr0")
        except AttributeError:
            pass  # If no virbr0, just pass is ok
        logging.debug("Useful bridges:%s", bridge_list)
        # just choosing one bridge on host.
        if len(bridge_list):
            iface_source = bridge_list[0]
        else:
            test.cancel("No useful bridge on host "
                        "other than 'virbr0'.")

    # Test both detach and attach, So collect info
    # both of them for result check.
    # When something wrong with interface, set it to 1
    fail_flag = 0
    result_info = []

    # Get a mac address if iface_mac is 'created'.
    if iface_mac == "created" or correct_attach:
        iface_mac = utils_net.generate_mac_address_simple()

    # Record all iface parameters in iface_dict
    iface_dict = {}
    update_list = [
        "driver", "driver_host", "driver_guest", "model", "rom",
        "inbound", "outbound", "link", "target", "mac", "source",
        "boot", "backend", "type", "mode"
        ]
    names = locals()
    for update_item in update_list:
        if names["iface_"+update_item]:
            iface_dict.update({update_item: names["iface_"+update_item]})
        else:
            iface_dict.update({update_item: None})
    logging.info("iface_dict is %s", iface_dict)

    # Format the params
    iface_format = format_param(iface_dict)
    logging.info("iface_format is %s", iface_format)

    try:
        # Generate xml file if using attach-device command
        if attach_cmd == "attach-device":
            # Change boot order to disk
            libvirt.change_boot_order(vm_name, "disk", "1")
            vm.destroy()
            vm.start()
            # Generate attached xml
            xml_file_tmp = libvirt.modify_vm_iface(vm_name, "get_xml", iface_format)
            new_iface = Interface(type_name=iface_type)
            new_iface.xml = xml_file_tmp
            new_iface.del_address()
            xml_file = new_iface.xml

        # To confirm vm's state and make sure os fully started
        if start_vm == "no":
            if vm.is_alive():
                vm.destroy()
        else:
            vm.wait_for_login().close()

        # Set attach-interface domain
        dom_uuid = vm.get_uuid()
        dom_id = vm.get_id()

        if vm_ref == "domname":
            vm_ref = vm_name
        elif vm_ref == "domid":
            vm_ref = dom_id
        elif vm_ref == "domuuid":
            vm_ref = dom_uuid
        elif vm_ref == "hexdomid" and dom_id is not None:
            vm_ref = hex(int(dom_id))

        # Set attach-interface options and Start attach-interface test
        if correct_attach:
            options = set_options("network", "default", iface_mac, "", "attach")
            if readonly:
                virsh_dargs.update({'readonly': True, 'debug': True})
            attach_result = virsh.attach_interface(vm_name, options,
                                                   **virsh_dargs)
        else:
            if attach_cmd == "attach-interface":
                options = set_options(iface_type, iface_source, iface_mac,
                                      options_suffix, "attach", iface_target,
                                      iface_model, iface_inbound, iface_outbound)
                attach_result = virsh.attach_interface(vm_ref, options, **virsh_dargs)
            elif attach_cmd == "attach-device":
                attach_result = virsh.attach_device(vm_name, xml_file,
                                                    ignore_status=True, debug=True)
        attach_status = attach_result.exit_status
        logging.debug(attach_result)

        # If attach interface failed.
        if attach_status:
            if not status_error:
                fail_flag = 1
                result_info.append("Attach Failed: %s" % attach_result.stderr)
            elif status_error:
                # Here we just use it to exit, do not mean test failed
                fail_flag = 1
        # If attach interface succeeded.
        else:
            if status_error and not correct_attach:
                fail_flag = 1
                result_info.append("Attach Success with wrong command.")

        if fail_flag and start_vm == "yes":
            vm.destroy()
            if len(result_info):
                test.fail(result_info)
            else:
                # Exit because it is error_test for attach-interface.
                return

        if "print-xml" in options_suffix:
            iface_obj = Interface(type_name=iface_type)
            iface_obj.xml = attach_result.stdout.strip()
            if (iface_obj.type_name == iface_type
                    and iface_obj.source['dev'] == iface_source
                    and iface_obj.target['dev'] == iface_target
                    and iface_obj.model == iface_model
                    and iface_obj.bandwidth.inbound == eval(iface_format['inbound'])
                    and iface_obj.bandwidth.outbound == eval(iface_format['outbound'])):
                logging.info("Print ml all element check pass")
            else:
                test.fail("Print xml do not show as expected")

        # Check dumpxml file whether the interface is added successfully.
        status, ret = check_dumpxml_iface(vm_name, iface_format)
        if "print-xml" not in options_suffix:
            if status:
                fail_flag = 1
                result_info.append(ret)
        else:
            if status == 0:
                test.fail("Attach interface effect in xml with print-xml option")
            else:
                return

        # Login to domain to check new interface.
        if not vm.is_alive():
            vm.start()
        elif vm.state() == "paused":
            vm.resume()

        status, ret = login_to_check(vm, iface_mac)
        if status:
            fail_flag = 1
            result_info.append(ret)

        # Check on host for direct type
        if iface_type == 'direct':
            cmd_result = process.run("ip -d link show test").stdout_text.strip()
            logging.info("cmd output is %s", cmd_result)
            check_patten = ("%s@%s.*\n.*%s.*\n.*macvtap.*mode.*%s"
                            % (iface_target, iface_source, iface_mac, iface_mode))
            logging.info("check patten is %s", check_patten)
            if not re.search(check_patten, cmd_result):
                logging.error("Can not find %s in ip link" % check_patten)
                fail_flag = 1
                result_info.append(cmd_result)

        # Do operation and check again
        if restart_libvirtd == "yes":
            libvirtd = utils_libvirtd.Libvirtd()
            libvirtd.restart()

        if save_restore == "yes":
            check_save_restore(vm_name)

        status, ret = check_dumpxml_iface(vm_name, iface_format)
        if status:
            fail_flag = 1
            result_info.append(ret)

        # Set detach-interface options
        options = set_options(iface_type, None, iface_mac,
                              options_suffix, "detach")

        # Start detach-interface test
        if save_restore == "yes" and vm_ref == dom_id:
            vm_ref = vm_name
        detach_result = virsh.detach_interface(vm_ref, options, **virsh_dargs)
        detach_status = detach_result.exit_status
        detach_msg = detach_result.stderr.strip()

        logging.debug(detach_result)

        if detach_status == 0 and status_error == 0:
            # Check the xml after detach and clean up if needed.
            time.sleep(5)
            status, _ = check_dumpxml_iface(vm_name, iface_format)
            if status == 0:
                detach_status = 1
                detach_msg = "xml still exist after detach"
                cleanup_options = "--type %s --mac %s" % (iface_type, iface_mac)
                virsh.detach_interface(vm_ref, cleanup_options, **virsh_dargs)
            else:
                logging.info("After detach, the interface xml disappeared")

        # Check results.
        if status_error:
            if detach_status == 0:
                test.fail("Detach Success with wrong command.")
        else:
            if detach_status != 0:
                test.fail("Detach Failed: %s" % detach_msg)
            else:
                if fail_flag:
                    test.fail("Attach-Detach Success but "
                              "something wrong with its "
                              "functional use:%s" % result_info)
    finally:
        if vm.is_alive():
            vm.destroy()
        backup_xml.sync()
Ejemplo n.º 13
0
def run(test, params, env):
    """
    Test bridge support from network

    1) create a linux bridge and connect a physical interface to it
    2) define nwfilter with "vdsm-no-mac-spoofing"
    3) redefine the vm with the new create bridge and filter
    4) check if guest can get public ip after vm start
    5) check if guest and host can ping each other
    6) check if guest and host can ping outside
    7) start another vm connected to the same bridge
    8) check if the 2 guests can ping each other
    """

    def create_bridge(br_name, iface_name):
        """
        Create a linux bridge by virsh cmd:
        1. Stop NetworkManager and Start network service
        2. virsh iface-bridge <iface> <name> [--no-stp]

        :param br_name: bridge name
        :param iface_name: physical interface name
        :return: bridge created or raise exception
        """
        # Make sure the bridge not exist
        if libvirt.check_iface(br_name, "exists", "--all"):
            test.cancel("The bridge %s already exist" % br_name)

        # Create bridge
        utils_package.package_install('tmux')
        cmd = 'tmux -c "ip link add name {0} type bridge; ip link set {1} up;' \
              ' ip link set {1} master {0}; ip link set {0} up;' \
              ' pkill dhclient; sleep 6; dhclient {0}; ifconfig {1} 0"'.format(br_name, iface_name)
        process.run(cmd, shell=True, verbose=True)

    def define_nwfilter(filter_name):
        """
        Define nwfilter vdsm-no-mac-spoofing with content like:
        <filter name='vdsm-no-mac-spoofing' chain='root'>
            <filterref filter='no-mac-spoofing'/>
            <filterref filter='no-arp-mac-spoofing'/>
        </filter>

        :param filter_name: the name of nwfilter
        :return: filter created or raise exception
        """
        filter_uuid = params.get("filter_uuid", "11111111-b071-6127-b4ec-111111111111")
        filter_params = {"filter_name": "vdsm-no-mac-spoofing",
                         "filter_chain": "root",
                         "filter_uuid": filter_uuid,
                         "filterref_name_1": "no-mac-spoofing",
                         "filterref_name_2": "no-arp-mac-spoofing"}
        filter_xml = libvirt.create_nwfilter_xml(filter_params).xml
        # Run command
        result = virsh.nwfilter_define(filter_xml, ignore_status=True, debug=True)
        if result.exit_status:
            test.fail("Failed to define nwfilter with %s" % filter_xml)

    def modify_iface_xml(br_name, nwfilter, vm_name):
        """
        Modify interface xml with the new bridge and the nwfilter

        :param br_name: bridge name
        :param nwfilter: nwfilter name
        :param vm_name: vm name
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        iface_xml = vmxml.get_devices('interface')[0]
        vmxml.del_device(iface_xml)
        iface_xml = Interface(type_name='bridge')
        iface_xml.source = {'bridge': br_name}
        iface_xml.model = 'virtio'
        iface_xml.filterref = iface_xml.new_filterref(name=nwfilter)
        logging.debug("new interface xml is: %s" % iface_xml)
        vmxml.add_device(iface_xml)
        vmxml.sync()

    def ping(src_ip, dest_ip, ping_count, timeout, session=None):
        """
        Wrap of ping

        :param src_ip: source address
        :param dest_ip: destination address
        :param ping_count: count of icmp packet
        :param timeout: timeout for the ping command
        :param session: local execution or session to execute the ping command
        :return: ping succeed or raise exception
        """
        status, output = utils_net.ping(dest=dest_ip, count=ping_count,
                                        interface=src_ip, timeout=timeout,
                                        session=session)
        if status:
            test.fail("Fail to ping %s from %s" % (dest_ip, src_ip))

    def check_net_functions(guest_ip, ping_count, ping_timeout, guest_session, host_ip, remote_url, endpoint_ip):
        # make sure host network works well
        # host ping remote url
        ping(host_ip, remote_url, ping_count, ping_timeout)
        # host ping guest
        ping(host_ip, guest_ip, ping_count, ping_timeout)
        # guest ping host
        ping(guest_ip, host_ip, ping_count, ping_timeout, session=guest_session)
        # guest ping remote url
        ping(guest_ip, remote_url, ping_count, ping_timeout, session=guest_session)
        # guest ping endpoint
        ping(guest_ip, endpoint_ip, ping_count, ping_timeout, session=guest_session)

    # Get test params
    bridge_name = params.get("bridge_name", "test_br0")
    filter_name = params.get("filter_name", "vdsm-no-mac-spoofing")
    ping_count = params.get("ping_count", "5")
    ping_timeout = float(params.get("ping_timeout", "10"))
    iface_name = utils_net.get_net_if(state="UP")[0]
    bridge_script = NETWORK_SCRIPT + bridge_name
    iface_script = NETWORK_SCRIPT + iface_name
    iface_script_bk = os.path.join(data_dir.get_tmp_dir(), "iface-%s.bk" % iface_name)

    vms = params.get("vms").split()
    if len(vms) <= 1:
        test.cancel("Need two VMs to test")
    else:
        vm1_name = vms[0]
        vm2_name = vms[1]

    vm1 = env.get_vm(vm1_name)
    vm2 = env.get_vm(vm2_name)

    # Back up the interface script
    process.run("cp %s %s" % (iface_script, iface_script_bk),
                shell=True, verbose=True)
    # Back up vm xml
    vm1_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm1_name)
    vm2_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm2_name)

    # Stop NetworkManager service
    NM_service = service.Factory.create_service("NetworkManager")
    NM_status = NM_service.status()
    if not NM_status:
        NM_service.start()

    try:
        create_bridge(bridge_name, iface_name)
        define_nwfilter(filter_name)
        modify_iface_xml(bridge_name, filter_name, vm1_name)

        if vm1.is_alive():
            vm1.destroy()

        vm1.start()
        # Check if vm can get ip with the new create bridge
        session1 = session2 = None
        try:
            utils_net.update_mac_ip_address(vm1, timeout=120)
            vm1_ip = vm1.get_address()
        except Exception as errs:
            test.fail("vm1 can't get IP with the new create bridge: %s" % errs)

        # Check guest's network function
        host_ip = utils_net.get_ip_address_by_interface(bridge_name)
        remote_url = params.get("remote_ip", "www.google.com")
        # make sure the guest has got ip address
        session1 = vm1.wait_for_login()
        session1.cmd("pkill -9 dhclient", ignore_all_errors=True)
        session1.cmd("dhclient %s " % iface_name, ignore_all_errors=True)
        output = session1.cmd_output("ifconfig || ip a")
        logging.debug("guest1 ip info %s" % output)

        # Start vm2 connect to the same bridge
        modify_iface_xml(bridge_name, filter_name, vm2_name)
        if vm2.is_alive():
            vm2.destroy()
        vm2.start()

        # Check if vm1 and vm2 can ping each other
        try:
            utils_net.update_mac_ip_address(vm2, timeout=120)
            vm2_ip = vm2.get_address()
        except Exception as errs:
            test.fail("vm2 can't get IP with the new create bridge: %s" % errs)
        session2 = vm2.wait_for_login()
        # make sure guest has got ip address
        session2.cmd("pkill -9 dhclient", ignore_all_errors=True)
        session2.cmd("dhclient %s " % iface_name, ignore_all_errors=True)
        output2 = session2.cmd_output("ifconfig || ip a")
        logging.debug("guest ip info %s" % output2)
        # check 2 guests' network functions
        check_net_functions(vm1_ip, ping_count, ping_timeout, session1,
                            host_ip, remote_url, vm2_ip)
        check_net_functions(vm2_ip, ping_count, ping_timeout, session2,
                            host_ip, remote_url, vm1_ip)
    finally:
        logging.debug("Start to restore")
        vm1_xml_bak.sync()
        vm2_xml_bak.sync()
        virsh.nwfilter_undefine(filter_name, ignore_status=True)
        if libvirt.check_iface(bridge_name, "exists", "--all"):
            virsh.iface_unbridge(bridge_name, timeout=60, debug=True)
        if os.path.exists(iface_script_bk):
            process.run("mv %s %s" % (iface_script_bk, iface_script),
                        shell=True, verbose=True)
        if os.path.exists(bridge_script):
            process.run("rm -rf %s" % bridge_script, shell=True, verbose=True)
        cmd = 'tmux -c "ip link set {1} nomaster;  ip link delete {0};' \
              'pkill dhclient; sleep 6; dhclient {1}"'.format(bridge_name, iface_name)
        process.run(cmd, shell=True, verbose=True)
        # reload network configuration
        NM_service.restart()
        # recover NetworkManager
        if NM_status is True:
            NM_service.start()
Ejemplo n.º 14
0
def run(test, params, env):
    """
    Test bridge support from network

    1) create a linux bridge and connect a physical interface to it
    2) define nwfilter with "vdsm-no-mac-spoofing"
    3) redefine the vm with the new create bridge and filter
    4) check if guest can get public ip after vm start
    5) check if guest and host can ping each other
    6) check if guest and host can ping outside
    7) start another vm connected to the same bridge
    8) check if the 2 guests can ping each other
    """
    def create_bridge(br_name, iface_name):
        """
        Create a linux bridge by virsh cmd:
        1. Stop NetworkManager and Start network service
        2. virsh iface-bridge <iface> <name> [--no-stp]

        :param br_name: bridge name
        :param iface_name: physical interface name
        :return: bridge created or raise exception
        """
        # Make sure the bridge not exist
        if libvirt.check_iface(br_name, "exists", "--all"):
            test.cancel("The bridge %s already exist" % br_name)

        # Create bridge
        # This cmd run a long time, so set timeout=240
        result = virsh.iface_bridge(iface_name,
                                    br_name,
                                    "--no-stp",
                                    debug=True,
                                    timeout=240)
        if result.exit_status:
            test.fail("Failed to create bridge:\n%s" % result.stderr)

    def define_nwfilter(filter_name):
        """
        Define nwfilter vdsm-no-mac-spoofing with content like:
        <filter name='vdsm-no-mac-spoofing' chain='root'>
            <filterref filter='no-mac-spoofing'/>
            <filterref filter='no-arp-mac-spoofing'/>
        </filter>

        :param filter_name: the name of nwfilter
        :return: filter created or raise exception
        """
        filter_uuid = params.get("filter_uuid",
                                 "11111111-b071-6127-b4ec-111111111111")
        filter_params = {
            "filter_name": "vdsm-no-mac-spoofing",
            "filter_chain": "root",
            "filter_uuid": filter_uuid,
            "filterref_name_1": "no-mac-spoofing",
            "filterref_name_2": "no-arp-mac-spoofing"
        }
        filter_xml = libvirt.create_nwfilter_xml(filter_params).xml
        # Run command
        result = virsh.nwfilter_define(filter_xml,
                                       ignore_status=True,
                                       debug=True)
        if result.exit_status:
            test.fail("Failed to define nwfilter with %s" % filter_xml)

    def modify_iface_xml(br_name, nwfilter, vm_name):
        """
        Modify interface xml with the new bridge and the nwfilter

        :param br_name: bridge name
        :param nwfilter: nwfilter name
        :param vm_name: vm name
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        iface_xml = vmxml.get_devices('interface')[0]
        vmxml.del_device(iface_xml)
        iface_xml.source = {'bridge': br_name}
        iface_xml.filterref = iface_xml.new_filterref(name=nwfilter)
        logging.debug("new interface xml is: %s" % iface_xml)
        vmxml.add_device(iface_xml)
        vmxml.sync()

    def ping(src_ip, dest_ip, ping_count, timeout, session=None):
        """
        Wrap of ping

        :param src_ip: source address
        :param dest_ip: destination address
        :param ping_count: count of icmp packet
        :param timeout: timeout for the ping command
        :param session: local execution or session to execute the ping command
        :return: ping succeed or raise exception
        """
        status, output = utils_net.ping(dest=dest_ip,
                                        count=ping_count,
                                        interface=src_ip,
                                        timeout=timeout,
                                        session=session)
        if status:
            test.fail("Fail to ping %s from %s" % (dest_ip, src_ip))

    # Get test params
    bridge_name = params.get("bridge_name", "br0")
    filter_name = params.get("filter_name", "vdsm-no-mac-spoofing")
    ping_count = params.get("ping_count", "5")
    ping_timeout = float(params.get("ping_timeout", "10"))
    iface_name = utils_net.get_net_if(state="UP")[0]
    bridge_script = NETWORK_SCRIPT + bridge_name
    iface_script = NETWORK_SCRIPT + iface_name
    iface_script_bk = os.path.join(data_dir.get_tmp_dir(),
                                   "iface-%s.bk" % iface_name)

    vms = params.get("vms").split()
    if len(vms) <= 1:
        test.cancel("Need two VMs to test")
    else:
        vm1_name = vms[0]
        vm2_name = vms[1]

    vm1 = env.get_vm(vm1_name)
    vm2 = env.get_vm(vm2_name)

    # Back up the interface script
    process.run("cp %s %s" % (iface_script, iface_script_bk), shell=True)
    # Back up vm xml
    vm1_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm1_name)
    vm2_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm2_name)

    # Stop NetworkManager service
    NM_service = service.Factory.create_service("NetworkManager")
    NM_status = NM_service.status()
    if NM_status is True:
        NM_service.stop()

    # Start network service
    NW_service = service.Factory.create_service("network")
    NW_status = NW_service.status()
    if NW_status is None:
        logging.debug("network service not found")
        if not utils_package.package_install('network-scripts') or \
                not utils_package.package_install('initscripts'):
            test.cancel("Failed to install network service")
    if NW_status is not True:
        logging.debug("network service is not running")
        NW_service.start()

    try:
        create_bridge(bridge_name, iface_name)
        define_nwfilter(filter_name)
        modify_iface_xml(bridge_name, filter_name, vm1_name)

        if vm1.is_alive():
            vm1.destroy()

        vm1.start()
        # Check if vm can get ip with the new create bridge
        session1 = session2 = None
        try:
            utils_net.update_mac_ip_address(vm1, timeout=120)
            vm1_ip = vm1.get_address()
        except Exception as errs:
            test.fail("vm1 can't get IP with the new create bridge: %s" % errs)

        # Check guest and host can ping each other
        host_ip = utils_net.get_ip_address_by_interface(bridge_name)
        remote_ip = params.get("remote_ip", "www.baidu.com")
        ping(host_ip, vm1_ip, ping_count, ping_timeout)
        ping(host_ip, remote_ip, ping_count, ping_timeout)
        session1 = vm1.wait_for_login()
        ping(vm1_ip, host_ip, ping_count, ping_timeout, session=session1)
        ping(vm1_ip, remote_ip, ping_count, ping_timeout, session=session1)

        # Start vm2 connect to the same bridge
        modify_iface_xml(bridge_name, filter_name, vm2_name)
        if vm2.is_alive():
            vm2.destroy()
        vm2.start()

        # Check if vm1 and vm2 can ping each other
        try:
            utils_net.update_mac_ip_address(vm2, timeout=120)
            vm2_ip = vm2.get_address()
        except Exception as errs:
            test.fail("vm2 can't get IP with the new create bridge: %s" % errs)
        session2 = vm2.wait_for_login()
        ping(vm2_ip, vm1_ip, ping_count, ping_timeout, session=session2)
        ping(vm1_ip, vm2_ip, ping_count, ping_timeout, session=session1)
    finally:
        logging.debug("Start to restore")
        vm1_xml_bak.sync()
        vm2_xml_bak.sync()
        virsh.nwfilter_undefine(filter_name, ignore_status=True)
        if libvirt.check_iface(bridge_name, "exists", "--all"):
            virsh.iface_unbridge(bridge_name, timeout=60, debug=True)
        if os.path.exists(iface_script_bk):
            process.run("mv %s %s" % (iface_script_bk, iface_script),
                        shell=True)
        if os.path.exists(bridge_script):
            process.run("rm -rf %s" % bridge_script, shell=True)
        # reload network configuration
        NW_service.restart()
        # recover NetworkManager
        if NM_status is True:
            NM_service.start()
Ejemplo n.º 15
0
def run(test, params, env):
    """
    Test interafce xml options.

    1.Prepare test environment,destroy or suspend a VM.
    2.Edit xml and start the domain.
    3.Perform test operation.
    4.Recover test environment.
    5.Confirm the test result.
    """
    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)

    def prepare_pxe_boot():
        """
        Prepare tftp server and pxe boot files
        """
        pkg_list = ["syslinux", "tftp-server",
                    "tftp", "ipxe-roms-qemu", "wget"]
        # Try to install required packages
        if not utils_package.package_install(pkg_list):
            test.error("Failed ot install required packages")
        boot_initrd = params.get("boot_initrd", "EXAMPLE_INITRD")
        boot_vmlinuz = params.get("boot_vmlinuz", "EXAMPLE_VMLINUZ")
        if boot_initrd.count("EXAMPLE") or boot_vmlinuz.count("EXAMPLE"):
            test.cancel("Please provide initrd/vmlinuz URL")
        # Download pxe boot images
        process.system("wget %s -O %s/initrd.img" % (boot_initrd, tftp_root))
        process.system("wget %s -O %s/vmlinuz" % (boot_vmlinuz, tftp_root))
        process.system("cp -f /usr/share/syslinux/pxelinux.0 {0};"
                       " mkdir -m 777 -p {0}/pxelinux.cfg".format(tftp_root), shell=True)
        pxe_file = "%s/pxelinux.cfg/default" % tftp_root
        boot_txt = """
DISPLAY boot.txt
DEFAULT rhel
LABEL rhel
        kernel vmlinuz
        append initrd=initrd.img
PROMPT 1
TIMEOUT 3"""
        with open(pxe_file, 'w') as p_file:
            p_file.write(boot_txt)

    def modify_iface_xml():
        """
        Modify interface xml options
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        if pxe_boot:
            # Config boot console for pxe boot
            osxml = vm_xml.VMOSXML()
            osxml.type = vmxml.os.type
            osxml.arch = vmxml.os.arch
            osxml.machine = vmxml.os.machine
            osxml.loader = "/usr/share/seabios/bios.bin"
            osxml.bios_useserial = "yes"
            osxml.bios_reboot_timeout = "-1"
            osxml.boots = ['network']
            del vmxml.os
            vmxml.os = osxml

        xml_devices = vmxml.devices
        iface_index = xml_devices.index(
            xml_devices.by_device_tag("interface")[0])
        iface = xml_devices[iface_index]
        iface_bandwidth = {}
        iface_inbound = ast.literal_eval(iface_bandwidth_inbound)
        iface_outbound = ast.literal_eval(iface_bandwidth_outbound)
        if iface_inbound:
            iface_bandwidth["inbound"] = iface_inbound
        if iface_outbound:
            iface_bandwidth["outbound"] = iface_outbound
        if iface_bandwidth:
            bandwidth = iface.new_bandwidth(**iface_bandwidth)
            iface.bandwidth = bandwidth

        iface_type = params.get("iface_type", "network")
        iface.type_name = iface_type
        source = ast.literal_eval(iface_source)
        if not source:
            source = {"network": "default"}
        net_ifs = utils_net.get_net_if(state="UP")
        # Check source device is valid or not,
        # if it's not in host interface list, try to set
        # source device to first active interface of host
        if (iface.type_name == "direct" and
            source.has_key('dev') and
                source['dev'] not in net_ifs):
            logging.warn("Source device %s is not a interface"
                         " of host, reset to %s",
                         source['dev'], net_ifs[0])
            source['dev'] = net_ifs[0]
        del iface.source
        iface.source = source
        iface_model = params.get("iface_model", "virtio")
        iface.model = iface_model
        logging.debug("New interface xml file: %s", iface)
        vmxml.devices = xml_devices
        vmxml.xmltreefile.write()
        vmxml.sync()

    def run_dnsmasq_default_test(key, value=None, exists=True):
        """
        Test dnsmasq configuration.
        """
        conf_file = "/var/lib/libvirt/dnsmasq/default.conf"
        if not os.path.exists(conf_file):
            test.cancel("Can't find default.conf file")

        configs = ""
        with open(conf_file) as f:
            configs = f.read()
        logging.debug("configs in file %s: %s", conf_file, configs)
        if value:
            config = "%s=%s" % (key, value)
        else:
            config = key

        if not configs.count(config):
            if exists:
                test.fail("Can't find %s=%s in configuration file" % (key, value))
        else:
            if not exists:
                test.fail("Found %s=%s in configuration file" % (key, value))

    def run_dnsmasq_addnhosts_test(hostip, hostnames):
        """
        Test host ip and names configuration
        """
        conf_file = "/var/lib/libvirt/dnsmasq/default.addnhosts"
        hosts_re = ".*".join(hostnames)
        configs = ""
        with open(conf_file) as f:
            configs = f.read()
        logging.debug("configs in file %s: %s", conf_file, configs)
        if not re.search(r"%s.*%s" % (hostip, hosts_re), configs, re.M):
            test.fail("Can't find '%s' in configuration file" % hostip)

    def run_dnsmasq_host_test(iface_mac, guest_ip, guest_name):
        """
        Test host name and ip configuration for dnsmasq
        """
        conf_file = "/var/lib/libvirt/dnsmasq/default.hostsfile"
        config = "%s,%s,%s" % (iface_mac, guest_ip, guest_name)
        configs = ""
        with open(conf_file) as f:
            configs = f.read()
        logging.debug("configs in file %s: %s", conf_file, configs)
        if not configs.count(config):
            test.fail("Can't find host configuration in file %s" % conf_file)

    def check_class_rules(ifname, rule_id, bandwidth):
        """
        Check bandwidth settings via 'tc class' output
        """
        cmd = "tc class show dev %s" % ifname
        class_output = process.system_output(cmd)
        logging.debug("Bandwidth class output: %s", class_output)
        class_pattern = (r"class htb %s.*rate (\d+)Kbit ceil"
                         " (\d+)Kbit burst (\d+)(K?M?)b.*" % rule_id)
        se = re.search(class_pattern, class_output, re.M)
        if not se:
            test.fail("Can't find outbound setting for htb %s" % rule_id)
        logging.debug("bandwidth from tc output:%s" % str(se.groups()))
        ceil = None
        if bandwidth.has_key("floor"):
            ceil = int(bandwidth["floor"]) * 8
        elif bandwidth.has_key("average"):
            ceil = int(bandwidth["average"]) * 8
        if ceil:
            assert int(se.group(1)) == ceil
        if bandwidth.has_key("peak"):
            assert int(se.group(2)) == int(bandwidth["peak"]) * 8
        if bandwidth.has_key("burst"):
            if se.group(4) == 'M':
                tc_burst = int(se.group(3)) * 1024
            else:
                tc_burst = int(se.group(3))
            assert tc_burst == int(bandwidth["burst"])

    def check_filter_rules(ifname, bandwidth):
        """
        Check bandwidth settings via 'tc filter' output
        """
        cmd = "tc -d filter show dev %s parent ffff:" % ifname
        filter_output = process.system_output(cmd)
        logging.debug("Bandwidth filter output: %s", filter_output)
        if not filter_output.count("filter protocol all pref"):
            test.fail("Can't find 'protocol all' settings in filter rules")
        filter_pattern = ".*police.*rate (\d+)Kbit burst (\d+)(K?M?)b.*"
        se = re.search(r"%s" % filter_pattern, filter_output, re.M)
        if not se:
            test.fail("Can't find any filter policy")
        logging.debug("bandwidth from tc output:%s" % str(se.groups()))
        logging.debug("bandwidth from setting:%s" % str(bandwidth))
        if bandwidth.has_key("average"):
            assert int(se.group(1)) == int(bandwidth["average"]) * 8
        if bandwidth.has_key("burst"):
            if se.group(3) == 'M':
                tc_burst = int(se.group(2)) * 1024
            else:
                tc_burst = int(se.group(2))
            assert tc_burst == int(bandwidth["burst"])

    def check_host_routes():
        """
        Check network routes on host
        """
        for rt in routes:
            try:
                route = ast.literal_eval(rt)
                addr = "%s/%s" % (route["address"], route["prefix"])
                cmd = "ip route list %s" % addr
                if route.has_key("family") and route["family"] == "ipv6":
                    cmd = "ip -6 route list %s" % addr
                output = process.system_output(cmd)
                match_obj = re.search(r"via (\S+).*metric (\d+)", output)
                if match_obj:
                    via_addr = match_obj.group(1)
                    metric = match_obj.group(2)
                    logging.debug("via address %s for %s, matric is %s"
                                  % (via_addr, addr, metric))
                    assert via_addr == route["gateway"]
                    if route.has_key("metric"):
                        assert metric == route["metric"]
            except KeyError:
                pass

    def run_bandwidth_test(check_net=False, check_iface=False):
        """
        Test bandwidth option for network or interface by tc command.
        """
        iface_inbound = ast.literal_eval(iface_bandwidth_inbound)
        iface_outbound = ast.literal_eval(iface_bandwidth_outbound)
        net_inbound = ast.literal_eval(net_bandwidth_inbound)
        net_outbound = ast.literal_eval(net_bandwidth_outbound)
        net_bridge_name = ast.literal_eval(net_bridge)["name"]
        iface_name = libvirt.get_ifname_host(vm_name, iface_mac)

        try:
            if check_net and net_inbound:
                # Check qdisc rules
                cmd = "tc -d qdisc show dev %s" % net_bridge_name
                qdisc_output = process.system_output(cmd)
                logging.debug("Bandwidth qdisc output: %s", qdisc_output)
                if not qdisc_output.count("qdisc ingress ffff:"):
                    test.fail("Can't find ingress setting")
                check_class_rules(net_bridge_name, "1:1",
                                  {"average": net_inbound["average"],
                                   "peak": net_inbound["peak"]})
                check_class_rules(net_bridge_name, "1:2", net_inbound)

            # Check filter rules on bridge interface
            if check_net and net_outbound:
                check_filter_rules(net_bridge_name, net_outbound)

            # Check class rules on interface inbound settings
            if check_iface and iface_inbound:
                check_class_rules(iface_name, "1:1",
                                  {'average': iface_inbound['average'],
                                   'peak': iface_inbound['peak'],
                                   'burst': iface_inbound['burst']})
                if iface_inbound.has_key("floor"):
                    if not libvirt_version.version_compare(1, 0, 1):
                        test.cancel("Not supported Qos options 'floor'")

                    check_class_rules(net_bridge_name, "1:3",
                                      {'floor': iface_inbound["floor"]})

            # Check filter rules on interface outbound settings
            if check_iface and iface_outbound:
                check_filter_rules(iface_name, iface_outbound)
        except AssertionError:
            stacktrace.log_exc_info(sys.exc_info())
            test.fail("Failed to check network bandwidth")

    def check_name_ip(session):
        """
        Check dns resolving on guest
        """
        # Check if bind-utils is installed
        if not utils_package.package_install(['bind-utils'], session):
            test.error("Failed to install bind-utils on guest")
        # Run host command to check if hostname can be resolved
        if not guest_ipv4 and not guest_ipv6:
            test.fail("No ip address found from parameters")
        guest_ip = guest_ipv4 if guest_ipv4 else guest_ipv6
        cmd = "host %s | grep %s" % (guest_name, guest_ip)
        if session.cmd_status(cmd):
            test.fail("Can't resolve name %s on guest" % guest_name)

    def check_ipt_rules(check_ipv4=True, check_ipv6=False):
        """
        Check iptables for network/interface
        """
        br_name = ast.literal_eval(net_bridge)["name"]
        net_forward = ast.literal_eval(params.get("net_forward", "{}"))
        net_ipv4 = params.get("net_ipv4")
        net_ipv6 = params.get("net_ipv6")
        ipt_rules = ("FORWARD -i {0} -o {0} -j ACCEPT".format(br_name),
                     "FORWARD -o %s -j REJECT --reject-with icmp" % br_name,
                     "FORWARD -i %s -j REJECT --reject-with icmp" % br_name)
        net_dev_in = ""
        net_dev_out = ""
        if net_forward.has_key("dev"):
            net_dev_in = " -i %s" % net_forward["dev"]
            net_dev_out = " -o %s" % net_forward["dev"]
        if check_ipv4:
            ipv4_rules = list(ipt_rules)
            ctr_rule = ""
            nat_rules = []
            if net_forward.has_key("mode") and net_forward["mode"] == "nat":
                nat_port = ast.literal_eval(params.get("nat_port"))
                p_start = nat_port["start"]
                p_end = nat_port["end"]
                ctr_rule = " -m .* RELATED,ESTABLISHED"
                nat_rules = [("POSTROUTING -s {0} ! -d {0} -p tcp -j MASQUERADE"
                              " --to-ports {1}-{2}".format(net_ipv4, p_start, p_end)),
                             ("POSTROUTING -s {0} ! -d {0} -p udp -j MASQUERADE"
                              " --to-ports {1}-{2}".format(net_ipv4, p_start, p_end)),
                             ("POSTROUTING -s {0} ! -d {0} -p udp"
                              " -j MASQUERADE".format(net_ipv4))]
            if nat_rules:
                ipv4_rules.extend(nat_rules)
            if (net_ipv4 and net_forward.has_key("mode") and
                    net_forward["mode"] in ["nat", "route"]):
                rules = [("FORWARD -d %s%s -o %s%s -j ACCEPT"
                          % (net_ipv4, net_dev_in, br_name, ctr_rule)),
                         ("FORWARD -s %s -i %s%s -j ACCEPT"
                          % (net_ipv4, br_name, net_dev_out))]
                ipv4_rules.extend(rules)

            output = process.system_output('iptables-save')
            logging.debug("iptables: %s", output)
            for ipt in ipv4_rules:
                if not re.findall(r"%s" % ipt, output, re.M):
                    test.fail("Can't find iptable rule:\n%s" % ipt)
        if check_ipv6:
            ipv6_rules = list(ipt_rules)
            if (net_ipv6 and net_forward.has_key("mode") and
                    net_forward["mode"] in ["nat", "route"]):
                rules = [("FORWARD -d %s%s -o %s -j ACCEPT"
                          % (net_ipv6, net_dev_in, br_name)),
                         ("FORWARD -s %s -i %s%s -j ACCEPT"
                          % (net_ipv6, br_name, net_dev_out))]
                ipv6_rules.extend(rules)
            output = process.system_output("ip6tables-save")
            logging.debug("iptables: %s", output)
            for ipt in ipv6_rules:
                if not output.count(ipt):
                    test.fail("Can't find ipbtable rule:\n%s" % ipt)

    def run_ip_test(session, ip_ver):
        """
        Check iptables on host and ipv6 address on guest
        """
        if ip_ver == "ipv6":
            # Clean up iptables rules for guest to get ipv6 address
            session.cmd_status("ip6tables -F")

        # It may take some time to get the ip address
        def get_ip_func():
            return utils_net.get_guest_ip_addr(session, iface_mac,
                                               ip_version=ip_ver)
        utils_misc.wait_for(get_ip_func, 5)
        if not get_ip_func():
            utils_net.restart_guest_network(session, iface_mac,
                                            ip_version=ip_ver)
            utils_misc.wait_for(get_ip_func, 5)
        vm_ip = get_ip_func()
        logging.debug("Guest has ip: %s", vm_ip)
        if not vm_ip:
            test.fail("Can't find ip address on guest")
        ip_gateway = net_ip_address
        if ip_ver == "ipv6":
            ip_gateway = net_ipv6_address
            # Cleanup ip6talbes on host for ping6 test
            process.system("ip6tables -F")
        if ip_gateway and not routes:
            ping_s, _ = ping(dest=ip_gateway, count=5,
                             timeout=10, session=session)
            if ping_s:
                test.fail("Failed to ping gateway address: %s" % ip_gateway)

    def run_guest_libvirt(session):
        """
        Check guest libvirt network
        """
        # Try to install required packages
        if not utils_package.package_install(['libvirt'], session):
            test.error("Failed ot install libvirt package on guest")
        # Try to load tun module first
        session.cmd("lsmod | grep tun || modprobe  tun")
        # Check network state on guest
        cmd = ("service libvirtd restart; virsh net-info default"
               " | grep 'Active:.*yes'")
        if session.cmd_status(cmd):
            test.fail("'default' network isn't in active state")
        # Try to destroy&start default network on guest
        for opt in ['net-destroy', 'net-start']:
            cmd = "virsh %s default" % opt
            status, output = session.cmd_status_output(cmd)
            logging.debug("Run %s on guest exit %s, output %s"
                          % (cmd, status, output))
            if status:
                test.fail(output)
        if not utils_package.package_remove("libvirt*", session):
            test.error("Failed to remove libvirt packages on guest")

    start_error = "yes" == params.get("start_error", "no")
    define_error = "yes" == params.get("define_error", "no")
    restart_error = "yes" == params.get("restart_error", "no")

    # network specific attributes.
    net_name = params.get("net_name", "default")
    net_bridge = params.get("net_bridge", "{'name':'virbr0'}")
    net_domain = params.get("net_domain")
    net_ip_address = params.get("net_ip_address")
    net_ipv6_address = params.get("net_ipv6_address")
    net_dns_forward = params.get("net_dns_forward")
    net_dns_txt = params.get("net_dns_txt")
    net_dns_srv = params.get("net_dns_srv")
    net_dns_hostip = params.get("net_dns_hostip")
    net_dns_hostnames = params.get("net_dns_hostnames", "").split()
    dhcp_start_ipv4 = params.get("dhcp_start_ipv4")
    dhcp_end_ipv4 = params.get("dhcp_end_ipv4")
    guest_name = params.get("guest_name")
    guest_ipv4 = params.get("guest_ipv4")
    guest_ipv6 = params.get("guest_ipv6")
    tftp_root = params.get("tftp_root")
    pxe_boot = "yes" == params.get("pxe_boot", "no")
    routes = params.get("routes", "").split()
    net_bandwidth_inbound = params.get("net_bandwidth_inbound", "{}")
    net_bandwidth_outbound = params.get("net_bandwidth_outbound", "{}")
    iface_bandwidth_inbound = params.get("iface_bandwidth_inbound", "{}")
    iface_bandwidth_outbound = params.get("iface_bandwidth_outbound", "{}")
    iface_num = params.get("iface_num", "1")
    iface_source = params.get("iface_source", "{}")
    multiple_guests = params.get("multiple_guests")
    create_network = "yes" == params.get("create_network", "no")
    attach_iface = "yes" == params.get("attach_iface", "no")
    serial_login = "******" == params.get("serial_login", "no")
    change_iface_option = "yes" == params.get("change_iface_option", "no")
    test_bridge = "yes" == params.get("test_bridge", "no")
    test_dnsmasq = "yes" == params.get("test_dnsmasq", "no")
    test_dhcp_range = "yes" == params.get("test_dhcp_range", "no")
    test_dns_host = "yes" == params.get("test_dns_host", "no")
    test_qos_bandwidth = "yes" == params.get("test_qos_bandwidth", "no")
    test_pg_bandwidth = "yes" == params.get("test_portgroup_bandwidth", "no")
    test_qos_remove = "yes" == params.get("test_qos_remove", "no")
    test_ipv4_address = "yes" == params.get("test_ipv4_address", "no")
    test_ipv6_address = "yes" == params.get("test_ipv6_address", "no")
    test_guest_libvirt = "yes" == params.get("test_guest_libvirt", "no")
    username = params.get("username")
    password = params.get("password")

    # Destroy VM first
    if vm.is_alive():
        vm.destroy(gracefully=False)

    # Back up xml file.
    netxml_backup = NetworkXML.new_from_net_dumpxml("default")
    iface_mac = vm_xml.VMXML.get_first_mac_by_name(vm_name)
    params["guest_mac"] = iface_mac
    vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    vms_list = []
    if "floor" in ast.literal_eval(iface_bandwidth_inbound):
        if not libvirt_version.version_compare(1, 0, 1):
            test.cancel("Not supported Qos options 'floor'")

    # Enabling IPv6 forwarding with RA routes without accept_ra set to 2
    # is likely to cause routes loss
    sysctl_cmd = 'sysctl net.ipv6.conf.all.accept_ra'
    original_accept_ra = process.system_output(sysctl_cmd + ' -n')
    if test_ipv6_address and original_accept_ra != '2':
        process.system(sysctl_cmd + '=2')

    # Build the xml and run test.
    try:
        if test_dnsmasq:
            # Check the settings before modifying network xml
            if net_dns_forward == "no":
                run_dnsmasq_default_test("domain-needed", exists=False)
                run_dnsmasq_default_test("local", "//", exists=False)
            if net_domain:
                run_dnsmasq_default_test("domain", net_domain, exists=False)
                run_dnsmasq_default_test("expand-hosts", exists=False)

        # Prepare pxe boot directory
        if pxe_boot:
            prepare_pxe_boot()
        # Edit the network xml or create a new one.
        if create_network:
            net_ifs = utils_net.get_net_if(state="UP")
            # Check forward device is valid or not,
            # if it's not in host interface list, try to set
            # forward device to first active interface of host
            forward = ast.literal_eval(params.get("net_forward",
                                                  "{}"))
            if (forward.has_key('mode') and forward['mode'] in
                ['passthrough', 'private', 'bridge', 'macvtap'] and
                forward.has_key('dev') and
                    forward['dev'] not in net_ifs):
                logging.warn("Forward device %s is not a interface"
                             " of host, reset to %s",
                             forward['dev'], net_ifs[0])
                forward['dev'] = net_ifs[0]
                params["net_forward"] = str(forward)
            forward_iface = params.get("forward_iface")
            if forward_iface:
                interface = [x for x in forward_iface.split()]
                # The guest will use first interface of the list,
                # check if it's valid or not, if it's not in host
                # interface list, try to set forward interface to
                # first active interface of host.
                if interface[0] not in net_ifs:
                    logging.warn("Forward interface %s is not a "
                                 " interface of host, reset to %s",
                                 interface[0], net_ifs[0])
                    interface[0] = net_ifs[0]
                    params["forward_iface"] = " ".join(interface)

            netxml = libvirt.create_net_xml(net_name, params)
            try:
                netxml.sync()
            except xcepts.LibvirtXMLError, details:
                logging.info(str(details))
                if define_error:
                    pass
                else:
                    test.fail("Failed to define network")
        # Edit the interface xml.
        if change_iface_option:
            modify_iface_xml()
        # Attach interface if needed
        if attach_iface:
            iface_type = params.get("iface_type", "network")
            iface_model = params.get("iface_model", "virtio")
            for i in range(int(iface_num)):
                logging.info("Try to attach interface loop %s" % i)
                options = ("%s %s --model %s --config" %
                           (iface_type, net_name, iface_model))
                ret = virsh.attach_interface(vm_name, options,
                                             ignore_status=True)
                if ret.exit_status:
                    logging.error("Command output %s" %
                                  ret.stdout.strip())
                    test.fail("Failed to attach-interface")

        if multiple_guests:
            # Clone more vms for testing
            for i in range(int(multiple_guests)):
                guest_name = "%s_%s" % (vm_name, i)
                timeout = params.get("clone_timeout", 360)
                utils_libguestfs.virt_clone_cmd(vm_name, guest_name,
                                                True, timeout=timeout)
                vms_list.append(vm.clone(guest_name))

        if test_bridge:
            bridge = ast.literal_eval(net_bridge)
            br_if = utils_net.Interface(bridge['name'])
            if not br_if.is_up():
                test.fail("Bridge interface isn't up")
        if test_dnsmasq:
            # Check the settings in dnsmasq config file
            if net_dns_forward == "no":
                run_dnsmasq_default_test("domain-needed")
                run_dnsmasq_default_test("local", "//")
            if net_domain:
                run_dnsmasq_default_test("domain", net_domain)
                run_dnsmasq_default_test("expand-hosts")
            if net_bridge:
                bridge = ast.literal_eval(net_bridge)
                run_dnsmasq_default_test("interface", bridge['name'])
                if bridge.has_key('stp') and bridge['stp'] == 'on':
                    if bridge.has_key('delay'):
                        br_delay = float(bridge['delay'])
                        cmd = ("brctl showstp %s | grep 'bridge forward delay'"
                               % bridge['name'])
                        out = process.system_output(
                            cmd, shell=True, ignore_status=False)
                        logging.debug("brctl showstp output: %s", out)
                        pattern = (r"\s*forward delay\s+(\d+.\d+)\s+bridge"
                                   " forward delay\s+(\d+.\d+)")
                        match_obj = re.search(pattern, out, re.M)
                        if not match_obj or len(match_obj.groups()) != 2:
                            test.fail("Can't see forward delay messages from command")
                        elif (float(match_obj.groups()[0]) != br_delay or
                                float(match_obj.groups()[1]) != br_delay):
                            test.fail("Foward delay setting can't take effect")
            if dhcp_start_ipv4 and dhcp_end_ipv4:
                run_dnsmasq_default_test("dhcp-range", "%s,%s"
                                         % (dhcp_start_ipv4, dhcp_end_ipv4))
            if guest_name and guest_ipv4:
                run_dnsmasq_host_test(iface_mac, guest_ipv4, guest_name)

        if test_dns_host:
            if net_dns_txt:
                dns_txt = ast.literal_eval(net_dns_txt)
                run_dnsmasq_default_test("txt-record", "%s,%s" %
                                         (dns_txt["name"],
                                          dns_txt["value"]))
            if net_dns_srv:
                dns_srv = ast.literal_eval(net_dns_srv)
                run_dnsmasq_default_test("srv-host", "_%s._%s.%s,%s,%s,%s,%s" %
                                         (dns_srv["service"], dns_srv["protocol"],
                                          dns_srv["domain"], dns_srv["target"],
                                          dns_srv["port"], dns_srv["priority"],
                                          dns_srv["weight"]))
            if net_dns_hostip and net_dns_hostnames:
                run_dnsmasq_addnhosts_test(net_dns_hostip, net_dns_hostnames)

        # Run bandwidth test for network
        if test_qos_bandwidth:
            run_bandwidth_test(check_net=True)
        # Check routes if needed
        if routes:
            check_host_routes()

        try:
            # Start the VM.
            vm.start()
            if start_error:
                test.fail("VM started unexpectedly")
            if pxe_boot:
                # Just check network boot messages here
                vm.serial_console.read_until_output_matches(
                    ["Loading vmlinuz", "Loading initrd.img"],
                    utils_misc.strip_console_codes)
                output = vm.serial_console.get_stripped_output()
                logging.debug("Boot messages: %s", output)

            else:
                if serial_login:
                    session = vm.wait_for_serial_login(username=username,
                                                       password=password)
                else:
                    session = vm.wait_for_login()

                if test_dhcp_range:
                    dhcp_range = int(params.get("dhcp_range", "252"))
                    utils_net.restart_guest_network(session, iface_mac)
                    vm_ip = utils_net.get_guest_ip_addr(session, iface_mac)
                    logging.debug("Guest has ip: %s", vm_ip)
                    if not vm_ip and dhcp_range:
                        test.fail("Guest has invalid ip address")
                    elif vm_ip and not dhcp_range:
                        test.fail("Guest has ip address: %s" % vm_ip)
                    dhcp_range = dhcp_range - 1
                    for vms in vms_list:
                        # Start other VMs.
                        vms.start()
                        sess = vms.wait_for_serial_login()
                        vms_mac = vms.get_virsh_mac_address()
                        # restart guest network to get ip addr
                        utils_net.restart_guest_network(sess, vms_mac)
                        vms_ip = utils_net.get_guest_ip_addr(sess,
                                                             vms_mac)
                        if not vms_ip and dhcp_range:
                            test.fail("Guest has invalid ip address")
                        elif vms_ip and not dhcp_range:
                            # Get IP address on guest should return Null
                            # if it exceeds the dhcp range
                            test.fail("Guest has ip address: %s" % vms_ip)
                        dhcp_range = dhcp_range - 1
                        if vms_ip:
                            ping_s, _ = ping(dest=vm_ip, count=5,
                                             timeout=10, session=sess)
                            if ping_s:
                                test.fail("Failed to ping, src: %s, "
                                          "dst: %s" % (vms_ip, vm_ip))
                        sess.close()

                # Check dnsmasq settings if take affect in guest
                if guest_ipv4:
                    check_name_ip(session)

                # Run bandwidth test for interface
                if test_qos_bandwidth:
                    run_bandwidth_test(check_iface=True)
                # Run bandwidth test for portgroup
                if test_pg_bandwidth:
                    pg_bandwidth_inbound = params.get(
                        "portgroup_bandwidth_inbound", "").split()
                    pg_bandwidth_outbound = params.get(
                        "portgroup_bandwidth_outbound", "").split()
                    pg_name = params.get("portgroup_name", "").split()
                    pg_default = params.get("portgroup_default", "").split()
                    iface_inbound = ast.literal_eval(iface_bandwidth_inbound)
                    iface_outbound = ast.literal_eval(iface_bandwidth_outbound)
                    iface_name = libvirt.get_ifname_host(vm_name, iface_mac)
                    if_source = ast.literal_eval(iface_source)
                    if if_source.has_key("portgroup"):
                        pg = if_source["portgroup"]
                    else:
                        pg = "default"
                    for (name, df, bw_ib, bw_ob) in zip(pg_name, pg_default,
                                                        pg_bandwidth_inbound,
                                                        pg_bandwidth_outbound):
                        if pg == name:
                            inbound = ast.literal_eval(bw_ib)
                            outbound = ast.literal_eval(bw_ob)
                        elif pg == "default" and df == "yes":
                            inbound = ast.literal_eval(bw_ib)
                            outbound = ast.literal_eval(bw_ob)
                        else:
                            continue
                        # Interface bandwidth settings will
                        # overwriting portgroup settings
                        if iface_inbound:
                            inbound = iface_inbound
                        if iface_outbound:
                            outbound = iface_outbound
                        check_class_rules(iface_name, "1:1", inbound)
                        check_filter_rules(iface_name, outbound)
                if test_qos_remove:
                    # Remove the bandwidth settings in network xml
                    logging.debug("Removing network bandwidth settings...")
                    netxml_backup.sync()
                    vm.destroy(gracefully=False)
                    # Should fail to start vm
                    vm.start()
                    if restart_error:
                        test.fail("VM started unexpectedly")
                if test_ipv6_address:
                    check_ipt_rules(check_ipv6=True)
                    run_ip_test(session, "ipv6")
                if test_ipv4_address:
                    check_ipt_rules(check_ipv4=True)
                    run_ip_test(session, "ipv4")

                if test_guest_libvirt:
                    run_guest_libvirt(session)

                session.close()
        except virt_vm.VMStartError as details:
            logging.info(str(details))
            if not (start_error or restart_error):
                test.fail('VM failed to start:\n%s' % details)
Ejemplo n.º 16
0
def run(test, params, env):
    """
    Test virsh iface-bridge and iface-unbridge commands.

    (1) Bridge an existing network device(iface-bridge).
    (2) Unbridge a network device(iface-unbridge).
    """

    bridge_name = params.get("bridge_name")
    ping_ip = params.get("ping_ip", "")
    ping_count = int(params.get("ping_count", "3"))
    ping_timeout = int(params.get("ping_timeout", "5"))
    bridge_option = params.get("bridge_option")
    unbridge_option = params.get("unbridge_option")
    bridge_delay = "yes" == params.get("bridge_delay", "no")
    delay_num = params.get("delay_num", "0")
    create_bridge = "yes" == params.get("create_bridge", "yes")
    bridge_status_error = "yes" == params.get("bridge_status_error", "no")
    unbridge_status_error = "yes" == params.get("unbridge_status_error", "no")
    iface_name = params.get("iface_name")
    if iface_name == "HOST_INTERFACE":
        # Get the first active nic to test
        iface_name = utils_net.get_net_if(state="UP")[0]
        iface_ip = utils_net.get_ip_address_by_interface(iface_name)

    iface_script = NETWORK_SCRIPT + iface_name
    iface_script_bk = os.path.join(data_dir.get_tmp_dir(),
                                   "iface-%s.bk" % iface_name)
    bridge_script = NETWORK_SCRIPT + bridge_name
    check_iface = "yes" == params.get("check_iface", "yes")

    if check_iface:
        # Make sure the interface exists
        if not libvirt.check_iface(iface_name, "exists", "--all"):
            test.cancel("Interface '%s' not exists" % iface_name)

        # Back up the interface script
        process.run("cp %s %s" % (iface_script, iface_script_bk), shell=True)

    # Make sure the bridge name not exists
    net_bridge = utils_net.Bridge()
    if bridge_name in net_bridge.list_br():
        test.cancel("Bridge '%s' already exists" % bridge_name)

    # Stop NetworkManager service
    NM_service = None
    try:
        NM = utils_path.find_command("NetworkManager")
    except utils_path.CmdNotFoundError:
        logging.debug("No NetworkManager service.")
        NM = None
    if NM is not None:
        NM_service = service.Factory.create_service("NetworkManager")
        NM_is_running = NM_service.status()
        if NM_is_running:
            logging.debug("NM_is_running:%s", NM_is_running)
            logging.debug("Stop NetworkManager...")
            NM_service.stop()

    # Start network service
    NW_service = service.Factory.create_service("network")
    NW_status = NW_service.status()
    if NW_status is None:
        logging.debug("network service not found")
        if (not utils_package.package_install('network-scripts')
                or not utils_package.package_install('initscripts')):
            test.cancel("Failed to install network service")
    if NW_status is not True:
        logging.debug("network service is not running")
        logging.debug("Start network service...")
        NW_service.start()

    def unbridge_check():
        """
        Check the result after do unbridge.
        """
        list_option = "--all"
        if libvirt.check_iface(bridge_name, "exists", list_option):
            test.fail("%s is still present." % bridge_name)
        if "no-start" in unbridge_option:
            list_option = "--inactive"
        if not libvirt.check_iface(iface_name, "exists", list_option):
            test.fail("%s is not present." % iface_name)

    if bridge_delay:
        bridge_option += " --delay %s" % delay_num
    # Run test
    try:
        if create_bridge:
            # Create bridge
            # Set timeout as the cmd run a long time
            result = virsh.iface_bridge(iface_name,
                                        bridge_name,
                                        bridge_option,
                                        timeout=240,
                                        debug=True)
            libvirt.check_exit_status(result, bridge_status_error)
            if not bridge_status_error:
                # Get the new create bridge IP address
                try:
                    br_ip = utils_net.get_ip_address_by_interface(bridge_name)
                except Exception:
                    br_ip = ""
                # check IP of new bridge
                if check_iface and br_ip and br_ip != iface_ip:
                    test.fail("bridge IP(%s) isn't the same as iface IP(%s)." %
                              (br_ip, iface_ip))
                # check the status of STP feature
                if "no-start" not in bridge_option:
                    if "no-stp" not in bridge_option:
                        if "yes" != net_bridge.get_stp_status(bridge_name):
                            test.fail("Fail to enable STP.")
                # Do ping test only bridge has IP address and ping_ip not empty
                if br_ip and ping_ip:
                    if not libvirt.check_iface(bridge_name,
                                               "ping",
                                               ping_ip,
                                               count=ping_count,
                                               timeout=ping_timeout):
                        test.fail("Fail to ping %s from %s." %
                                  (ping_ip, bridge_name))
                else:
                    # Skip ping test
                    logging.debug("Skip ping test as %s has no IP address",
                                  bridge_name)
                list_option = ""
                if "no-start" in bridge_option:
                    list_option = "--inactive"
                if libvirt.check_iface(bridge_name, "exists", list_option):
                    # Unbridge
                    result = virsh.iface_unbridge(bridge_name,
                                                  unbridge_option,
                                                  timeout=60)
                    libvirt.check_exit_status(result, unbridge_status_error)
                    if not unbridge_status_error:
                        unbridge_check()
                else:
                    test.fail("%s is not present." % bridge_name)
        else:
            # Unbridge without creating bridge, only for negative test now
            result = virsh.iface_unbridge(bridge_name, unbridge_option)
            libvirt.check_exit_status(result, unbridge_status_error)
            if not unbridge_status_error:
                unbridge_check()
    finally:
        if create_bridge and check_iface:
            if libvirt.check_iface(bridge_name, "exists", "--all"):
                virsh.iface_unbridge(bridge_name, timeout=60)
            if os.path.exists(iface_script_bk):
                process.run("mv %s %s" % (iface_script_bk, iface_script),
                            shell=True)
            if os.path.exists(bridge_script):
                process.run("rm -rf %s" % bridge_script, shell=True)
            # Clear the new create bridge if it still exists
            try:
                utils_net.bring_down_ifname(bridge_name)
                process.run("ip link del dev %s" % bridge_name, shell=True)
            except utils_net.TAPBringDownError:
                pass
            # Reload network configuration
            NW_service.restart()
            # Recover NetworkManager
            if NM_is_running:
                NM_service.start()
Ejemplo n.º 17
0
def run(test, params, env):
    """
    Test bridge support from network

    1) create a linux bridge and connect a physical interface to it
    2) define nwfilter with "vdsm-no-mac-spoofing"
    3) redefine the vm with the new create bridge and filter
    4) check if guest can get public ip after vm start
    5) check if guest and host can ping each other
    6) check if guest and host can ping outside
    7) start another vm connected to the same bridge
    8) check if the 2 guests can ping each other
    """

    def create_bridge(br_name, iface_name):
        """
        Create a linux bridge by virsh cmd:
        1. Stop NetworkManager and Start network service
        2. virsh iface-bridge <iface> <name> [--no-stp]

        :param br_name: bridge name
        :param iface_name: physical interface name
        :return: bridge created or raise exception
        """
        # Make sure the bridge not exist
        if libvirt.check_iface(br_name, "exists", "--all"):
            test.cancel("The bridge %s already exist" % br_name)

        # Create bridge
        # This cmd run a long time, so set timeout=240
        result = virsh.iface_bridge(iface_name, br_name, "--no-stp", debug=True, timeout=240)
        if result.exit_status:
            test.fail("Failed to create bridge:\n%s" % result.stderr)

    def define_nwfilter(filter_name):
        """
        Define nwfilter vdsm-no-mac-spoofing with content like:
        <filter name='vdsm-no-mac-spoofing' chain='root'>
            <filterref filter='no-mac-spoofing'/>
            <filterref filter='no-arp-mac-spoofing'/>
        </filter>

        :param filter_name: the name of nwfilter
        :return: filter created or raise exception
        """
        filter_uuid = params.get("filter_uuid", "11111111-b071-6127-b4ec-111111111111")
        filter_params = {"filter_name": "vdsm-no-mac-spoofing",
                         "filter_chain": "root",
                         "filter_uuid": filter_uuid,
                         "filterref_name_1": "no-mac-spoofing",
                         "filterref_name_2": "no-arp-mac-spoofing"}
        filter_xml = libvirt.create_nwfilter_xml(filter_params).xml
        # Run command
        result = virsh.nwfilter_define(filter_xml, ignore_status=True, debug=True)
        if result.exit_status:
            test.fail("Failed to define nwfilter with %s" % filter_xml)

    def modify_iface_xml(br_name, nwfilter, vm_name):
        """
        Modify interface xml with the new bridge and the nwfilter

        :param br_name: bridge name
        :param nwfilter: nwfilter name
        :param vm_name: vm name
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        iface_xml = vmxml.get_devices('interface')[0]
        vmxml.del_device(iface_xml)
        iface_xml.source = {'bridge': br_name}
        iface_xml.filterref = iface_xml.new_filterref(name=nwfilter)
        logging.debug("new interface xml is: %s" % iface_xml)
        vmxml.add_device(iface_xml)
        vmxml.sync()

    def ping(src_ip, dest_ip, ping_count, timeout, session=None):
        """
        Wrap of ping

        :param src_ip: source address
        :param dest_ip: destination address
        :param ping_count: count of icmp packet
        :param timeout: timeout for the ping command
        :param session: local execution or session to execute the ping command
        :return: ping succeed or raise exception
        """
        status, output = utils_net.ping(dest=dest_ip, count=ping_count,
                                        interface=src_ip, timeout=timeout,
                                        session=session)
        if status:
            test.fail("Fail to ping %s from %s" % (dest_ip, src_ip))

    # Get test params
    bridge_name = params.get("bridge_name", "br0")
    filter_name = params.get("filter_name", "vdsm-no-mac-spoofing")
    ping_count = params.get("ping_count", "5")
    ping_timeout = float(params.get("ping_timeout", "10"))
    iface_name = utils_net.get_net_if(state="UP")[0]
    bridge_script = NETWORK_SCRIPT + bridge_name
    iface_script = NETWORK_SCRIPT + iface_name
    iface_script_bk = os.path.join(data_dir.get_tmp_dir(), "iface-%s.bk" % iface_name)

    vms = params.get("vms").split()
    if len(vms) <= 1:
        test.cancel("Need two VMs to test")
    else:
        vm1_name = vms[0]
        vm2_name = vms[1]

    vm1 = env.get_vm(vm1_name)
    vm2 = env.get_vm(vm2_name)

    # Back up the interface script
    process.run("cp %s %s" % (iface_script, iface_script_bk), shell=True)
    # Back up vm xml
    vm1_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm1_name)
    vm2_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm2_name)

    # Stop NetworkManager service
    NM_service = service.Factory.create_service("NetworkManager")
    NM_status = NM_service.status()
    if NM_status is True:
        NM_service.stop()

    # Start network service
    NW_service = service.Factory.create_service("network")
    NW_status = NW_service.status()
    if NW_status is None:
        logging.debug("network service not found")
        if not utils_package.package_install('network-scripts') or \
                not utils_package.package_install('initscripts'):
            test.cancel("Failed to install network service")
    if NW_status is not True:
        logging.debug("network service is not running")
        NW_service.start()

    try:
        create_bridge(bridge_name, iface_name)
        define_nwfilter(filter_name)
        modify_iface_xml(bridge_name, filter_name, vm1_name)

        if vm1.is_alive():
            vm1.destroy()

        vm1.start()
        # Check if vm can get ip with the new create bridge
        session1 = session2 = None
        try:
            utils_net.update_mac_ip_address(vm1, timeout=120)
            vm1_ip = vm1.get_address()
        except Exception as errs:
            test.fail("vm1 can't get IP with the new create bridge: %s" % errs)

        # Check guest and host can ping each other
        host_ip = utils_net.get_ip_address_by_interface(bridge_name)
        remote_ip = params.get("remote_ip", "www.baidu.com")
        ping(host_ip, vm1_ip, ping_count, ping_timeout)
        ping(host_ip, remote_ip, ping_count, ping_timeout)
        session1 = vm1.wait_for_login()
        ping(vm1_ip, host_ip, ping_count, ping_timeout, session=session1)
        ping(vm1_ip, remote_ip, ping_count, ping_timeout, session=session1)

        # Start vm2 connect to the same bridge
        modify_iface_xml(bridge_name, filter_name, vm2_name)
        if vm2.is_alive():
            vm2.destroy()
        vm2.start()

        # Check if vm1 and vm2 can ping each other
        try:
            utils_net.update_mac_ip_address(vm2, timeout=120)
            vm2_ip = vm2.get_address()
        except Exception as errs:
            test.fail("vm2 can't get IP with the new create bridge: %s" % errs)
        session2 = vm2.wait_for_login()
        ping(vm2_ip, vm1_ip, ping_count, ping_timeout, session=session2)
        ping(vm1_ip, vm2_ip, ping_count, ping_timeout, session=session1)
    finally:
        logging.debug("Start to restore")
        vm1_xml_bak.sync()
        vm2_xml_bak.sync()
        virsh.nwfilter_undefine(filter_name, ignore_status=True)
        if libvirt.check_iface(bridge_name, "exists", "--all"):
            virsh.iface_unbridge(bridge_name, timeout=60, debug=True)
        if os.path.exists(iface_script_bk):
            process.run("mv %s %s" % (iface_script_bk, iface_script), shell=True)
        if os.path.exists(bridge_script):
            process.run("rm -rf %s" % bridge_script, shell=True)
        # reload network configuration
        NW_service.restart()
        # recover NetworkManager
        if NM_status is True:
            NM_service.start()
Ejemplo n.º 18
0
def run(test, params, env):
    """
    Test network/interface function on 2 vms:

        - Test settings on 2 vms
        - Run ping check on 2 vms including pinging each other
        ...

    """
    vms = params.get('vms').split()
    vm_list = [env.get_vm(v_name) for v_name in vms]
    if len(vm_list) != 2:
        test.cancel('More or less than 2 vms is currently unsupported')

    feature = params.get('feature', '')
    case = params.get('case', '')
    check_ping = 'yes' == params.get('check_ping')
    expect_ping_host = 'yes' == params.get('expect_ping_host', 'no')
    expect_ping_out = 'yes' == params.get('expect_ping_out', 'no')
    expect_ping_vm = 'yes' == params.get('expect_ping_vm', 'no')
    out_ip = params.get('out_ip', 'www.redhat.com')
    live_update = 'yes' == params.get('live_update', 'no')
    set_all = 'yes' == params.get('set_all', 'no')

    rand_id = '_' + utils_misc.generate_random_string(3)
    bridge_name = params.get('bridge_name', 'test_br0') + rand_id
    iface_name = utils_net.get_net_if(state="UP")[0]
    test_net = 'net_isolated' + rand_id
    bridge_created = False

    vmxml_backup_list = []
    for vm_i in vm_list:
        vmxml_backup_list.append(vm_xml.VMXML.new_from_inactive_dumpxml(vm_i.name))

    try:
        # Test feature: port isolated
        if feature == 'port_isolated':
            if not libvirt_version.version_compare(6, 2, 0):
                test.cancel('Libvirt version should be'
                            ' > 6.2.0 to support port isolated')

            if case.startswith('set_iface'):
                create_bridge(bridge_name, iface_name)
                bridge_created = True
                iface_type = case.split('_')[-1]
                if iface_type == 'network':
                    net_dict = {'net_forward': "{'mode': 'bridge'}",
                                'net_bridge': "{'name': '%s'}" % bridge_name}
                    prepare_network(test_net, **net_dict)
                    updated_iface_dict = {
                        'type': iface_type,
                        'source': "{'network': '%s'}" % test_net,
                    }
                elif iface_type == 'bridge':
                    updated_iface_dict = {
                        'type': iface_type,
                        'source': "{'bridge': '%s'}" % bridge_name,
                    }
                else:
                    test.error('Unsupported iface type: %s' % iface_type)

                # Set 2 vms to isolated=yes or set one to 'yes', the other to 'no'
                isolated_settings = ['yes'] * 2 if set_all else ['yes', 'no']
                for i in (0, 1):
                    vm_i = vm_list[i]
                    new_iface_dict = dict(
                        list(updated_iface_dict.items()) +
                        [('port', "{'isolated': '%s'}" % isolated_settings[i])]
                    )
                    libvirt.modify_vm_iface(vm_i.name, 'update_iface',
                                            new_iface_dict)
                    logging.debug(virsh.dumpxml(vm_i.name).stdout_text)

            if case == 'update_iface':
                if params.get('iface_port'):
                    iface_dict = {'port': params['iface_port']}
                    for vm_i in vm_list:
                        libvirt.modify_vm_iface(vm_i.name, 'update_iface', iface_dict)
                        logging.debug(virsh.dumpxml(vm_i.name).stdout_text)
                if live_update:
                    for vm_i in vm_list:
                        vm_i.start()

                # Test Update iface with new attrs
                new_iface_dict = {}
                if params.get('new_iface_port'):
                    new_iface_dict['port'] = params['new_iface_port']
                elif params.get('del_port') == 'yes':
                    new_iface_dict['del_port'] = True
                for vm_i in vm_list:
                    updated_iface = libvirt.modify_vm_iface(vm_i.name, 'get_xml', new_iface_dict)
                    result = virsh.update_device(vm_i.name, updated_iface, debug=True)
                    libvirt.check_exit_status(result)

            if case == 'attach_iface':
                new_ifaces = {}
                for vm_i in vm_list:
                    # Create iface xml to be attached
                    new_iface = interface.Interface('network')
                    new_iface.xml = libvirt.modify_vm_iface(
                        vm_i.name, 'get_xml',
                        {'port': params.get('new_iface_port')}
                    )
                    new_ifaces[vm_i.name] = new_iface

                    # Remove current ifaces on vm
                    vmxml_i = vm_xml.VMXML.new_from_inactive_dumpxml(vm_i.name)
                    vmxml_i.remove_all_device_by_type('interface')
                    vmxml_i.sync()
                    logging.debug(virsh.dumpxml(vm_i.name).stdout_text)

                    # Start vm for hotplug
                    vm_i.start()
                    session = vm_i.wait_for_serial_login()

                    # Hotplug iface
                    virsh.attach_device(vm_i.name, new_iface.xml, debug=True, ignore_status=False)

                    # Wait a few seconds for interface to be fully attached
                    time.sleep(5)
                    ip_l_before = session.cmd_output('ip l')
                    logging.debug(ip_l_before)
                    session.close()

            if case == 'set_network':
                create_bridge(bridge_name, iface_name)
                bridge_created = True
                net_dict = {
                    'net_forward': "{'mode': 'bridge'}",
                    'net_bridge': "{'name': '%s'}" % bridge_name,
                    'net_port': "{'isolated': '%s'}" % params.get(
                        'net_isolated', 'yes')}
                prepare_network(test_net, **net_dict)

                # Modify iface to connect to newly added network
                updated_iface_dict = {'type': 'network',
                                      'source': "{'network': '%s'}" % test_net}
                for vm_i in vm_list:
                    libvirt.modify_vm_iface(vm_i.name, 'update_iface',
                                            updated_iface_dict)
                    logging.debug(virsh.domiflist(vm_i.name).stdout_text)

        # Check ping result from vm session to host, outside, the other vm
        if check_ping:
            for vm_i in vm_list:
                if vm_i.is_dead():
                    vm_i.start()
            host_ip = utils_net.get_host_ip_address()
            ping_expect = {
                host_ip: expect_ping_host,
                out_ip: expect_ping_out,
            }

            # A map of vm session and vm's ip addr
            session_n_ip = {}
            for vm_i in vm_list:
                mac = vm_i.get_mac_address()
                sess = vm_i.wait_for_serial_login()
                vm_ip = utils_net.get_guest_ip_addr(sess, mac)
                session_n_ip[sess] = vm_ip
                logging.debug('Vm %s ip: %s', vm_i.name, vm_ip)

            # Check ping result from each vm's session
            for i in (0, 1):
                sess = list(session_n_ip.keys())[i]
                another_sess = list(session_n_ip.keys())[1 - i]
                ping_expect[session_n_ip[another_sess]] = expect_ping_vm
                if not ping_func(sess, **ping_expect):
                    test.fail('Ping check failed')
                # Remove the other session's ip from ping result, then the
                # next round of ping check will not do a ping check to the vm itself
                ping_expect.pop(session_n_ip[another_sess])

        # Some test steps after ping check
        if feature == 'port_isolated':
            if case == 'attach_iface':
                # Test detach of iface
                for vm_name_i in new_ifaces:
                    virsh.detach_device(
                        vm_name_i,
                        new_ifaces[vm_name_i].xml,
                        wait_for_event=True,
                        debug=True, ignore_status=False
                    )

                # Check whether iface successfully detached by checking 'ip l' output
                for vm_i in vm_list:
                    session = vm_i.wait_for_serial_login()
                    ip_l_after = session.cmd_output('ip l')
                    session.close()
                    if len(ip_l_before.splitlines()) == len(ip_l_after.splitlines()):
                        test.fail('Output of "ip l" is not changed afte detach, '
                                  'interface not successfully detached')
Ejemplo n.º 19
0
def run(test, params, env):
    """
    Test interface with unprivileged user
    """

    def create_bridge(br_name, iface_name):
        """
        Create bridge attached to physical interface
        """
        # Make sure the bridge not exist
        if libvirt.check_iface(br_name, "exists", "--all"):
            test.cancel("The bridge %s already exist" % br_name)

        # Create bridge
        utils_package.package_install('tmux')
        cmd = 'tmux -c "ip link add name {0} type bridge; ip link set {1} up;' \
              ' ip link set {1} master {0}; ip link set {0} up; pkill dhclient; ' \
              'sleep 6; dhclient {0}; ifconfig {1} 0"'.format(br_name, iface_name)
        process.run(cmd, shell=True, verbose=True)

    def check_ping(dest_ip, ping_count, timeout, src_ip=None, session=None,
                   expect_success=True):
        """
        Check if ping result meets expectation
        """
        status, output = utils_net.ping(dest=dest_ip, count=ping_count,
                                        interface=src_ip, timeout=timeout,
                                        session=session, force_ipv4=True)
        success = True if status == 0 else False

        if success != expect_success:
            test.fail('Ping result not met expectation, '
                      'actual result is {}'.format(success))

    if not libvirt_version.version_compare(5, 6, 0):
        test.cancel('Libvirt version is too low for this test.')

    vm_name = params.get('main_vm')
    rand_id = '_' + utils_misc.generate_random_string(3)

    upu_vm_name = 'upu_vm' + rand_id
    user_vm_name = params.get('user_vm_name', 'non_root_vm')
    bridge_name = params.get('bridge_name', 'test_br0') + rand_id
    device_type = params.get('device_type', '')
    iface_name = utils_net.get_net_if(state="UP")[0]
    tap_name = params.get('tap_name', 'mytap0') + rand_id
    macvtap_name = params.get('macvtap_name', 'mymacvtap0') + rand_id
    remote_ip = params.get('remote_ip')
    up_user = params.get('up_user', 'test_upu') + rand_id
    case = params.get('case', '')

    # Create unprivileged user
    logging.info('Create unprivileged user %s', up_user)
    process.run('useradd %s' % up_user, shell=True, verbose=True)
    root_vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

    upu_args = {
        'unprivileged_user': up_user,
        'ignore_status': False,
        'debug': True,
    }

    try:
        # Create vm as unprivileged user
        logging.info('Create vm as unprivileged user')
        upu_vmxml = root_vmxml.copy()

        # Prepare vm for unprivileged user
        xml_devices = upu_vmxml.devices
        disks = xml_devices.by_device_tag("disk")
        for disk in disks:
            ori_path = disk.source['attrs'].get('file')
            if not ori_path:
                continue

            file_name = ori_path.split('/')[-1]
            new_disk_path = '/home/{}/{}'.format(up_user, file_name)
            logging.debug('New disk path:{}'.format(new_disk_path))

            # Copy disk image file and chown to make sure that
            # unprivileged user has access
            shutil.copyfile(ori_path, new_disk_path)
            shutil.chown(new_disk_path, up_user, up_user)

            # Modify xml to set new path of disk
            disk_index = xml_devices.index(disk)
            source = xml_devices[disk_index].source
            new_attrs = source.attrs
            new_attrs['file'] = new_disk_path
            source.attrs = new_attrs
            xml_devices[disk_index].source = source
            logging.debug(xml_devices[disk_index].source)

        upu_vmxml.devices = xml_devices

        new_xml_path = '/home/{}/upu.xml'.format(up_user)
        shutil.copyfile(upu_vmxml.xml, new_xml_path)

        # Define vm for unprivileged user
        virsh.define(new_xml_path, **upu_args)
        virsh.domrename(vm_name, upu_vm_name, **upu_args)
        logging.debug(virsh.dumpxml(upu_vm_name, **upu_args))
        upu_vmxml = vm_xml.VMXML()
        upu_vmxml.xml = virsh.dumpxml(upu_vm_name, **upu_args).stdout_text

        if case == 'precreated':
            if device_type == 'tap':
                # Create bridge
                create_bridge(bridge_name, iface_name)

                # Create tap device
                tap_cmd = 'ip tuntap add mode tap user {user} group {user} ' \
                          'name {tap};ip link set {tap} up;ip link set {tap} ' \
                          'master {br}'.format(tap=tap_name, user=up_user,
                                               br=bridge_name)

                # Execute command as root
                process.run(tap_cmd, shell=True, verbose=True)

            if device_type == 'macvtap':
                # Create macvtap device
                mac_addr = utils_net.generate_mac_address_simple()
                macvtap_cmd = 'ip link add link {iface} name {macvtap} address' \
                              ' {mac} type macvtap mode bridge;' \
                              'ip link set {macvtap} up'.format(
                               iface=iface_name,
                               macvtap=macvtap_name,
                               mac=mac_addr)
                process.run(macvtap_cmd, shell=True, verbose=True)
                cmd_get_tap = 'ip link show {} | head -1 | cut -d: -f1'.format(macvtap_name)
                tap_index = process.run(cmd_get_tap, shell=True, verbose=True).stdout_text.strip()
                device_path = '/dev/tap{}'.format(tap_index)
                logging.debug('device_path: {}'.format(device_path))
                # Change owner and group for device
                process.run('chown {user} {path};chgrp {user} {path}'.format(
                    user=up_user, path=device_path),
                    shell=True, verbose=True)
                # Check if device owner is changed to unprivileged user
                process.run('ls -l %s' % device_path, shell=True, verbose=True)

            # Modify interface
            all_devices = upu_vmxml.devices
            iface_list = all_devices.by_device_tag('interface')
            if not iface_list:
                test.error('No iface to modify')
            iface = iface_list[0]

            # Remove other interfaces
            for ifc in iface_list[1:]:
                all_devices.remove(ifc)

            if device_type == 'tap':
                dev_name = tap_name
            elif device_type == 'macvtap':
                dev_name = macvtap_name
            else:
                test.error('Invalid device type: {}'.format(device_type))

            if_index = all_devices.index(iface)
            iface = all_devices[if_index]
            iface.type_name = 'ethernet'
            iface.target = {
                'dev': dev_name,
                'managed': 'no'
            }

            if device_type == 'macvtap':
                iface.mac_address = mac_addr
            logging.debug(iface)

            upu_vmxml.devices = all_devices
            logging.debug(upu_vmxml)

            # Define updated xml
            shutil.copyfile(upu_vmxml.xml, new_xml_path)
            upu_vmxml.xml = new_xml_path
            virsh.define(new_xml_path, **upu_args)

            # Switch to unprivileged user and modify vm's interface
            # Start vm as unprivileged user and test network
            virsh.start(upu_vm_name, debug=True, ignore_status=False,
                        unprivileged_user=up_user)
            cmd = ("su - %s -c 'virsh console %s'"
                   % (up_user, upu_vm_name))
            session = aexpect.ShellSession(cmd)
            session.sendline()
            remote.handle_prompts(session, params.get("username"),
                                  params.get("password"), r"[\#\$]\s*$", 60)
            logging.debug(session.cmd_output('ifconfig'))
            check_ping(remote_ip, 5, 10, session=session)
            session.close()

    finally:
        if 'upu_virsh' in locals():
            virsh.destroy(upu_vm_name, unprivileged_user=up_user)
            virsh.undefine(upu_vm_name, unprivileged_user=up_user)
        if case == 'precreated':
            try:
                if device_type == 'tap':
                    process.run('ip tuntap del mode tap {}'.format(tap_name), shell=True, verbose=True)
                elif device_type == 'macvtap':
                    process.run('ip l del {}'.format(macvtap_name), shell=True, verbose=True)
            except Exception:
                pass
            finally:
                cmd = 'tmux -c "ip link set {1} nomaster;  ip link delete {0};' \
                      'pkill dhclient; sleep 6; dhclient {1}"'.format(bridge_name, iface_name)
                process.run(cmd, shell=True, verbose=True, ignore_status=True)
        process.run('pkill -u {0};userdel -f -r {0}'.format(up_user), shell=True, verbose=True, ignore_status=True)
def run(test, params, env):
    """
    Test command: virsh net-define/net-undefine.

    1) Collect parameters&environment info before test
    2) Prepare options for command
    3) Execute command for test
    4) Check state of defined network
    5) Recover environment
    6) Check result
    """
    uri = libvirt_vm.normalize_connect_uri(params.get("connect_uri",
                                                      "default"))
    net_name = params.get("net_define_undefine_net_name", "default")
    net_uuid = params.get("net_define_undefine_net_uuid", "")
    options_ref = params.get("net_define_undefine_options_ref", "default")
    trans_ref = params.get("net_define_undefine_trans_ref", "trans")
    extra_args = params.get("net_define_undefine_extra", "")
    remove_existing = params.get("net_define_undefine_remove_existing", "yes")
    status_error = "yes" == params.get("status_error", "no")
    check_states = "yes" == params.get("check_states", "no")
    net_persistent = "yes" == params.get("net_persistent")
    net_active = "yes" == params.get("net_active")
    expect_msg = params.get("net_define_undefine_err_msg")

    # define multi ip/dhcp sections in network
    multi_ip = "yes" == params.get("multi_ip", "no")
    netmask = params.get("netmask")
    prefix_v6 = params.get("prefix_v6")
    single_v6_range = "yes" == params.get("single_v6_range", "no")
    # Get 2nd ipv4 dhcp range
    dhcp_ranges_start = params.get("dhcp_ranges_start", None)
    dhcp_ranges_end = params.get("dhcp_ranges_end", None)

    # Get 2 groups of ipv6 ip address and dhcp section
    address_v6_1 = params.get("address_v6_1")
    dhcp_ranges_v6_start_1 = params.get("dhcp_ranges_v6_start_1", None)
    dhcp_ranges_v6_end_1 = params.get("dhcp_ranges_v6_end_1", None)

    address_v6_2 = params.get("address_v6_2")
    dhcp_ranges_v6_start_2 = params.get("dhcp_ranges_v6_start_2", None)
    dhcp_ranges_v6_end_2 = params.get("dhcp_ranges_v6_end_2", None)

    # Edit net xml forward/ip part then define/start to check invalid setting
    edit_xml = "yes" == params.get("edit_xml", "no")
    address_v4 = params.get("address_v4")
    nat_port_start = params.get("nat_port_start")
    nat_port_end = params.get("nat_port_end")
    test_port = "yes" == params.get("test_port", "no")
    loop = int(params.get("loop", 1))

    # Get params about creating a bridge
    bridge = params.get('bridge', None)
    create_bridge = "yes" == params.get('create_bridge', 'no')
    ovs_bridge = "yes" == params.get('ovs_bridge', 'no')
    iface_name = utils_net.get_net_if(state="UP")[0]

    # Get params about creating a network
    create_netxml = "yes" == params.get("create_netxml", "no")
    domain = params.get('domain', None)
    forward = params.get("forward", None)
    net_dns_txt = params.get("net_dns_txt", None)
    net_bandwidth_inbound = params.get("net_bandwidth_inbound", None)
    net_bandwidth_outbound = params.get("net_bandwidth_outbound", None)
    mac = params.get("mac")

    # Edit the created network xml to get the xml to be tested
    del_mac = "yes" == params.get('del_mac', 'no')
    del_ip = "yes" == params.get('del_ip', 'no')
    add_dev = "yes" == params.get('add_dev', 'no')
    virtualport = 'yes' == params.get("virtualport", "no")
    virtualport_type = params.get("virtualport_type")

    virsh_dargs = {'uri': uri, 'debug': False, 'ignore_status': True}
    virsh_instance = virsh.VirshPersistent(**virsh_dargs)
    # libvirt acl polkit related params
    if not libvirt_version.version_compare(1, 1, 1):
        if params.get('setup_libvirt_polkit') == 'yes':
            test.cancel("API acl test not supported in current"
                        " libvirt version.")

    virsh_uri = params.get("virsh_uri")
    if virsh_uri and not utils_split_daemons.is_modular_daemon():
        virsh_uri = "qemu:///system"
    unprivileged_user = params.get('unprivileged_user')
    if unprivileged_user:
        if unprivileged_user.count('EXAMPLE'):
            unprivileged_user = '******'

    # Prepare environment and record current net_state_dict
    backup = network_xml.NetworkXML.new_all_networks_dict(virsh_instance)
    backup_state = virsh_instance.net_state_dict()
    logging.debug("Backed up network(s): %s", backup_state)

    # Make some XML to use for testing, for now we just copy 'default'
    test_xml = xml_utils.TempXMLFile()  # temporary file
    try:
        # LibvirtXMLBase.__str__ returns XML content
        test_xml.write(str(backup['default']))
        test_xml.flush()
    except (KeyError, AttributeError):
        test.cancel("Test requires default network to exist")

    testnet_xml = get_network_xml_instance(virsh_dargs,
                                           test_xml,
                                           net_name,
                                           net_uuid,
                                           bridge=None)
    logging.debug("Get network xml as testnet_xml: %s" % testnet_xml)

    if remove_existing:
        for netxml in list(backup.values()):
            netxml.orbital_nuclear_strike()

    # Test both define and undefine, So collect info
    # both of them for result check.
    # When something wrong with network, set it to 1
    fail_flag = 0
    result_info = []

    if options_ref == "correct_arg":
        define_options = testnet_xml.xml
        undefine_options = net_name
    elif options_ref == "no_option":
        define_options = ""
        undefine_options = ""
    elif options_ref == "not_exist_option":
        define_options = "/not/exist/file"
        undefine_options = "NOT_EXIST_NETWORK"

    define_extra = undefine_extra = extra_args
    if trans_ref != "define":
        define_extra = ""

    if params.get('setup_libvirt_polkit') == 'yes':
        virsh_dargs = {
            'uri': virsh_uri,
            'unprivileged_user': unprivileged_user,
            'debug': False,
            'ignore_status': True
        }
        cmd = "chmod 666 %s" % testnet_xml.xml
        process.run(cmd, shell=True)

    if params.get('net_define_undefine_readonly', 'no') == 'yes':
        virsh_dargs = {
            'uri': uri,
            'debug': False,
            'ignore_status': True,
            'readonly': True
        }
    try:
        if edit_xml:
            ipxml_v4 = network_xml.IPXML()
            ipxml_v4.address = address_v4
            ipxml_v4.netmask = netmask
            range_4 = network_xml.RangeXML()
            range_4.attrs = {
                "start": dhcp_ranges_start,
                "end": dhcp_ranges_end
            }
            ipxml_v4.dhcp_ranges = range_4
            testnet_xml.del_ip()
            testnet_xml.set_ip(ipxml_v4)
            if test_port:
                nat_port = {"start": nat_port_start, "end": nat_port_end}
                testnet_xml.nat_port = nat_port
            testnet_xml.debug_xml()
        if multi_ip:
            # Enabling IPv6 forwarding with RA routes without accept_ra set to 2
            # is likely to cause routes loss
            sysctl_cmd = 'sysctl net.ipv6.conf.all.accept_ra'
            original_accept_ra = process.run(sysctl_cmd + ' -n').stdout_text
            if original_accept_ra != '2':
                process.system(sysctl_cmd + '=2')
            # add another ipv4 address and dhcp range
            set_ip_section(testnet_xml,
                           address_v4,
                           ipv6=False,
                           netmask=netmask,
                           dhcp_ranges_start=dhcp_ranges_start,
                           dhcp_ranges_end=dhcp_ranges_end)
            # add ipv6 address and dhcp range
            set_ip_section(testnet_xml,
                           address_v6_1,
                           ipv6=True,
                           prefix_v6=prefix_v6,
                           dhcp_ranges_start=dhcp_ranges_v6_start_1,
                           dhcp_ranges_end=dhcp_ranges_v6_end_1)
            # 2nd ipv6 address and dhcp range
            set_ip_section(testnet_xml,
                           address_v6_2,
                           ipv6=True,
                           prefix_v6=prefix_v6,
                           dhcp_ranges_start=dhcp_ranges_v6_start_2,
                           dhcp_ranges_end=dhcp_ranges_v6_end_2)
        if create_netxml:
            net_dict = {
                'del_nat_attrs': True,
                'del_ip': del_ip,
                'dns_txt': net_dns_txt,
                'domain': domain,
                'bridge': bridge,
                'forward': forward,
                'interface_dev': iface_name,
                'virtualport': virtualport,
                'virtualport_type': virtualport_type,
                'mac': mac,
                'net_bandwidth_inbound': net_bandwidth_inbound,
                'net_bandwidth_outbound': net_bandwidth_outbound
            }
            logging.debug("net_dict is %s" % net_dict)
            testnet_xml = libvirt_network.modify_network_xml(
                net_dict, testnet_xml)
        testnet_xml.debug_xml()
        if create_bridge:
            if ovs_bridge:
                utils_net.create_ovs_bridge(bridge, ignore_status=False)
            else:
                utils_net.create_linux_bridge_tmux(bridge,
                                                   iface_name,
                                                   ignore_status=False)
        # Run test case
        while loop:
            try:
                define_result = virsh.net_define(define_options, define_extra,
                                                 **virsh_dargs)
                logging.debug(define_result)
                define_status = define_result.exit_status

                # Check network states after define
                if check_states and not define_status:
                    net_state = virsh_instance.net_state_dict()
                    if (net_state[net_name]['active']
                            or net_state[net_name]['autostart']
                            or not net_state[net_name]['persistent']):
                        fail_flag = 1
                        result_info.append("Found wrong network states for "
                                           "defined network: %s" %
                                           str(net_state))

                if define_status == 1 and status_error and expect_msg:
                    logging.debug("check result is %s, expect_msg is %s" %
                                  (define_result, expect_msg))
                    libvirt.check_result(define_result, expect_msg.split(';'))

                # If defining network succeed, then trying to start it.
                if define_status == 0:
                    start_result = virsh.net_start(net_name,
                                                   extra="",
                                                   **virsh_dargs)
                    logging.debug(start_result)
                    start_status = start_result.exit_status

                if trans_ref == "trans":
                    if define_status:
                        fail_flag = 1
                        result_info.append(
                            "Define network with right command failed.")
                    else:
                        if start_status:
                            fail_flag = 1
                            result_info.append(
                                "Found wrong network states for "
                                "defined network: %s" % str(net_state))

                # Check network states after start
                if check_states and not status_error:
                    net_state = virsh_instance.net_state_dict()
                    if (not net_state[net_name]['active']
                            or net_state[net_name]['autostart']
                            or not net_state[net_name]['persistent']):
                        fail_flag = 1
                        result_info.append("Found wrong network states for "
                                           "started network: %s" %
                                           str(net_state))
                    # Try to set autostart
                    virsh.net_autostart(net_name, **virsh_dargs)
                    net_state = virsh_instance.net_state_dict()
                    if not net_state[net_name]['autostart']:
                        fail_flag = 1
                        result_info.append(
                            "Failed to set autostart for network %s" %
                            net_name)
                    # Restart libvirtd and check state
                    # Close down persistent virsh session before libvirtd restart
                    if hasattr(virsh_instance, 'close_session'):
                        virsh_instance.close_session()
                    libvirtd = utils_libvirtd.Libvirtd()
                    libvirtd.restart()
                    # Need to redefine virsh_instance after libvirtd restart
                    virsh_instance = virsh.VirshPersistent(**virsh_dargs)
                    net_state = virsh_instance.net_state_dict()
                    if (not net_state[net_name]['active']
                            or not net_state[net_name]['autostart']):
                        fail_flag = 1
                        result_info.append(
                            "Found wrong network state after restarting"
                            " libvirtd: %s" % str(net_state))
                    logging.debug("undefine network:")
                    # prepare the network status
                    if not net_persistent:
                        virsh.net_undefine(net_name, ignore_status=False)
                    if not net_active:
                        virsh.net_destroy(net_name, ignore_status=False)
                    undefine_status = virsh.net_undefine(
                        undefine_options, undefine_extra,
                        **virsh_dargs).exit_status

                    net_state = virsh_instance.net_state_dict()
                    if net_persistent:
                        if undefine_status:
                            fail_flag = 1
                            result_info.append(
                                "undefine should succeed but failed")
                        if net_active:
                            if (not net_state[net_name]['active']
                                    or net_state[net_name]['autostart']
                                    or net_state[net_name]['persistent']):
                                fail_flag = 1
                                result_info.append(
                                    "Found wrong network states for "
                                    "undefined network: %s" % str(net_state))
                        else:
                            if net_name in net_state:
                                fail_flag = 1
                                result_info.append(
                                    "Transient network should not exists "
                                    "after undefine : %s" % str(net_state))
                    else:
                        if not undefine_status:
                            fail_flag = 1
                            result_info.append(
                                "undefine transient network should fail "
                                "but succeed: %s" % str(net_state))
                # Stop network for undefine test anyway
                destroy_result = virsh.net_destroy(net_name,
                                                   extra="",
                                                   **virsh_dargs)
                logging.debug(destroy_result)

                # Undefine network
                if not check_states:
                    undefine_result = virsh.net_undefine(
                        undefine_options, undefine_extra, **virsh_dargs)
                    if trans_ref != "define":
                        logging.debug(undefine_result)
                    undefine_status = undefine_result.exit_status
            except Exception:
                logging.debug(
                    "The define and undefine operation in loop %s failed. ",
                    loop)
            finally:
                loop = loop - 1

    finally:
        # Recover environment
        leftovers = network_xml.NetworkXML.new_all_networks_dict(
            virsh_instance)
        for netxml in list(leftovers.values()):
            netxml.orbital_nuclear_strike()

        # Recover from backup
        for netxml in list(backup.values()):
            netxml.sync(backup_state[netxml.name])

        # Close down persistent virsh session (including for all netxml copies)
        if hasattr(virsh_instance, 'close_session'):
            virsh_instance.close_session()

        # Done with file, cleanup
        del test_xml
        del testnet_xml
        if create_bridge:
            if ovs_bridge:
                utils_net.delete_ovs_bridge(bridge, ignore_status=False)
            else:
                utils_net.delete_linux_bridge_tmux(bridge,
                                                   iface_name,
                                                   ignore_status=False)
    # Check status_error
    # If fail_flag is set, it must be transaction test.
    if fail_flag:
        test.fail("Define network for transaction test "
                  "failed:%s" % result_info)

    # The logic to check result:
    # status_error&only undefine:it is negative undefine test only
    # status_error&(no undefine):it is negative define test only
    # (not status_error)&(only undefine):it is positive transaction test.
    # (not status_error)&(no undefine):it is positive define test only
    if status_error:
        if trans_ref == "undefine":
            if undefine_status == 0:
                test.fail("Run successfully with wrong command.")
        else:
            if define_status == 0:
                if start_status == 0:
                    test.fail("Define an unexpected network, "
                              "and start it successfully.")
                else:
                    test.fail("Define an unexpected network, "
                              "but start it failed.")
    else:
        if trans_ref == "undefine":
            if undefine_status:
                test.fail("Define network for transaction "
                          "successfully, but undefine failed.")
        else:
            if define_status != 0:
                test.fail("Run failed with right command")
            else:
                if start_status != 0:
                    test.fail("Network is defined as expected, "
                              "but start it failed.")
Ejemplo n.º 21
0
def run(test, params, env):
    """
    Test bridge support from network

    1) create a linux bridge and connect a physical interface to it
    2) define nwfilter with "vdsm-no-mac-spoofing"
    3) redefine the vm with the new create bridge and filter
    4) check if guest can get public ip after vm start
    5) check if guest and host can ping each other
    6) check if guest and host can ping outside
    7) start another vm connected to the same bridge
    8) check if the 2 guests can ping each other
    """
    def create_bridge(br_name, iface_name):
        """
        Create a linux bridge by virsh cmd:
        1. Stop NetworkManager and Start network service
        2. virsh iface-bridge <iface> <name> [--no-stp]

        :param br_name: bridge name
        :param iface_name: physical interface name
        :return: bridge created or raise exception
        """
        # Make sure the bridge not exist
        if libvirt.check_iface(br_name, "exists", "--all"):
            test.cancel("The bridge %s already exist" % br_name)

        # Create bridge
        utils_package.package_install('tmux')
        cmd = 'tmux -c "ip link add name {0} type bridge; ip link set {1} up;' \
              ' ip link set {1} master {0}; ip link set {0} up;' \
              ' pkill dhclient; sleep 6; dhclient {0}; ifconfig {1} 0"'.format(br_name, iface_name)
        process.run(cmd, shell=True, verbose=True)

    def create_bridge_network(br_name, net_name):
        """
        Define and start the bridge type network
        """
        # check if network with the same name already exists
        output_all = virsh.net_list("--all").stdout.strip()
        if re.search(net_name, output_all):
            test.cancel("Network with the same name already exists!")
        test_xml = network_xml.NetworkXML(network_name="%s" % net_name)
        test_xml.forward = {"mode": "bridge"}
        test_xml.bridge = {"name": br_name}
        test_xml.create()

    def define_nwfilter(filter_name):
        """
        Define nwfilter vdsm-no-mac-spoofing with content like:
        <filter name='vdsm-no-mac-spoofing' chain='root'>
            <filterref filter='no-mac-spoofing'/>
            <filterref filter='no-arp-mac-spoofing'/>
        </filter>

        :param filter_name: the name of nwfilter
        :return: filter created or raise exception
        """
        filter_uuid = params.get("filter_uuid",
                                 "11111111-b071-6127-b4ec-111111111111")
        filter_params = {
            "filter_name": "vdsm-no-mac-spoofing",
            "filter_chain": "root",
            "filter_uuid": filter_uuid,
            "filterref_name_1": "no-mac-spoofing",
            "filterref_name_2": "no-arp-mac-spoofing"
        }
        filter_xml = libvirt.create_nwfilter_xml(filter_params).xml
        # Run command
        result = virsh.nwfilter_define(filter_xml,
                                       ignore_status=True,
                                       debug=True)
        if result.exit_status:
            test.fail("Failed to define nwfilter with %s" % filter_xml)

    def ping(src_ip, dest_ip, ping_count, timeout, session=None):
        """
        Wrap of ping

        :param src_ip: source address
        :param dest_ip: destination address
        :param ping_count: count of icmp packet
        :param timeout: timeout for the ping command
        :param session: local execution or session to execute the ping command
        :return: ping succeed or raise exception
        """
        status, output = utils_net.ping(dest=dest_ip,
                                        count=ping_count,
                                        interface=src_ip,
                                        timeout=timeout,
                                        session=session,
                                        force_ipv4=True)
        if status:
            test.fail("Fail to ping %s from %s" % (dest_ip, src_ip))

    def check_net_functions(guest_ip, ping_count, ping_timeout, guest_session,
                            host_ip, remote_url, endpoint_ip):
        # make sure host network works well
        # host ping remote url
        ping(host_ip, remote_url, ping_count, ping_timeout)
        # host ping guest
        ping(host_ip, guest_ip, ping_count, ping_timeout)
        # guest ping host
        ping(guest_ip,
             host_ip,
             ping_count,
             ping_timeout,
             session=guest_session)
        # guest ping remote url
        ping(guest_ip,
             remote_url,
             ping_count,
             ping_timeout,
             session=guest_session)
        # guest ping endpoint
        ping(guest_ip,
             endpoint_ip,
             ping_count,
             ping_timeout,
             session=guest_session)

    # Get test params
    bridge_name = params.get("bridge_name", "test_br0")
    filter_name = params.get("filter_name", "vdsm-no-mac-spoofing")
    ping_count = params.get("ping_count", "5")
    ping_timeout = float(params.get("ping_timeout", "10"))
    iface_name = utils_net.get_net_if(state="UP")[0]
    bridge_script = NETWORK_SCRIPT + bridge_name
    iface_script = NETWORK_SCRIPT + iface_name
    iface_script_bk = os.path.join(data_dir.get_tmp_dir(),
                                   "iface-%s.bk" % iface_name)
    attach_interface = "yes" == params.get("attach_interface", "no")
    iface_model = params.get("iface_model", "virtio")
    iface_source = eval(params.get("iface_source", "{'bridge':'test_br0'}"))
    iface_type = params.get("iface_type", None)
    iface_target = params.get("iface_target", "br_target")
    iface_alias = params.get("iface_alias", None)
    hotplug = "yes" == params.get("hotplug", "no")
    iface_driver = params.get("iface_driver", None)
    start_vm2 = "yes" == params.get("start_vm2", "no")
    create_network = "yes" == params.get("create_network", "no")
    update_device = "yes" == params.get("update_with_diff_type", "no")

    vms = params.get("vms").split()
    if len(vms) <= 1:
        test.cancel("Need two VMs to test")
    else:
        vm1_name = vms[0]
        vm2_name = vms[1]

    vm1 = env.get_vm(vm1_name)
    vm2 = env.get_vm(vm2_name)

    # Back up the interface script
    process.run("cp %s %s" % (iface_script, iface_script_bk),
                shell=True,
                verbose=True)
    # Back up vm xml
    vm1_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm1_name)
    vm2_xml_bak = vm_xml.VMXML.new_from_dumpxml(vm2_name)

    # Stop NetworkManager service
    NM_service = service.Factory.create_service("NetworkManager")
    NM_status = NM_service.status()
    if not NM_status:
        NM_service.start()
    mac = utils_net.generate_mac_address_simple()

    try:
        create_bridge(bridge_name, iface_name)
        define_nwfilter(filter_name)
        if hotplug:
            err_msgs = ("No more available PCI slots",
                        "No more available PCI addresses")
            # delete the original interface on the vm before hot-plug
            if vm1.is_alive():
                vm1.destroy()
            vmxml = vm_xml.VMXML.new_from_dumpxml(vm1_name)
            iface_xml = vmxml.get_devices('interface')[0]
            logging.debug("Delete the original interface")
            vmxml.del_device(iface_xml)
            vmxml.sync()
            vm1.start()
            # do hot-plug
            if attach_interface:
                logging.info("Try to hot-plug interface")
                options = (
                    "%s %s --model %s --mac %s" %
                    (iface_type, iface_source['bridge'], iface_model, mac))
                ret = virsh.attach_interface(vm1_name,
                                             options,
                                             ignore_status=True)
            else:
                logging.info("Try to hot-plug device")
                if create_network:
                    create_bridge_network(bridge_name, iface_source["network"])
                target = str({'dev': iface_target})
                iface_alias = str({'name': iface_alias})
                vm_iface_source = str(iface_source)
                iface_params = {
                    "type": iface_type,
                    "source": vm_iface_source,
                    "filter": filter_name,
                    "mac": mac,
                    'alias': iface_alias,
                    'target': target,
                    'model': iface_model,
                    'driver': iface_driver
                }
                attach_xml = interface.Interface(iface_params['type'])
                attach_xml.xml = libvirt.modify_vm_iface(
                    vm1_name, 'get_xml', iface_params)
                ret = virsh.attach_device(vm1_name,
                                          attach_xml.xml,
                                          ignore_status=True,
                                          debug=True)
            if ret.exit_status:
                if any([msg in ret.stderr for msg in err_msgs]):
                    test.error("No more pci slots, can't attach more devices")
                else:
                    test.fail("Failed to attach-interface: %s" %
                              ret.stderr.strip())
            else:
                logging.debug("Hot-plug interface or device pass")
                if update_device:
                    # As the interface type will change to actual type "bridge" in live xml, we need to ensure
                    # the update with original "network" type will not fail.
                    # Try to delete the nwfilter with original type in iface_params
                    update_xml = interface.Interface(iface_type)
                    iface_params_update = {
                        "del_filter": "yes",
                        "type": "network",
                        "source": vm_iface_source
                    }
                    update_xml.xml = libvirt.modify_vm_iface(
                        vm1_name, 'get_xml', iface_params_update)
                    ret = virsh.update_device(vm1_name,
                                              update_xml.xml,
                                              ignore_status=True,
                                              debug=True)
                    libvirt.check_exit_status(ret)

        else:
            vm_iface_source = str(iface_source)
            vm1_iface_params = {
                "type": "bridge",
                "source": vm_iface_source,
                "filter": filter_name,
                "mac": mac,
                'driver': iface_driver,
                "iface_model": iface_model
            }
            libvirt.modify_vm_iface(vm1_name, "update_iface", vm1_iface_params)

            if vm1.is_alive():
                vm1.destroy()

            vm1.start()
        # apply ip address as it may not be initialized
        session1 = session2 = None
        session1 = vm1.wait_for_serial_login()
        utils_net.restart_guest_network(session1)
        output = session1.cmd_output("ifconfig || ip a")
        logging.debug("guest1 ip info %s" % output)

        # Check guest's network function
        host_ip = utils_net.get_ip_address_by_interface(bridge_name)
        remote_url = params.get("remote_ip", "www.google.com")

        try:
            vm1_ip = utils_net.get_guest_ip_addr(session1, mac)
        except Exception as errs:
            test.fail("vm1 can't get IP with the new create bridge: %s" % errs)
        if hotplug:
            # reboot vm1 then check network function to ensure the interface still there and works fine
            logging.info("reboot the vm")
            virsh.reboot(vm1)
            if session1 is None:
                session1 = vm1.wait_for_serial_login()
            ping(vm1_ip,
                 remote_url,
                 ping_count,
                 ping_timeout,
                 session=session1)
            # restart libvirtd service then check the interface still works fine
            libvirtd = utils_libvirtd.Libvirtd()
            libvirtd.restart()
            vm1.cleanup_serial_console()
            vm1.create_serial_console()
            session1 = vm1.wait_for_serial_login()
            ping(vm1_ip,
                 remote_url,
                 ping_count,
                 ping_timeout,
                 session=session1)
            logging.info(
                "after reboot and restart libvirtd, the network works fine")
            if iface_driver:
                try:
                    driver_dict = eval(iface_driver)
                    if session1 is None:
                        session1 = vm1.wait_for_serial_login()
                    guest_iface_info = session1.cmd_output("ip l").strip()
                    guest_iface_name = re.findall(
                        r"^\d+: (\S+?)[@:].*state UP.*$", guest_iface_info,
                        re.MULTILINE)[0]
                    comb_size = driver_dict.get('queues')
                    rx_size = driver_dict.get('rx_queue_size')
                    session1.cmd_status("ethtool -L %s combined %s" %
                                        (guest_iface_name, comb_size))
                    ret, outp = session1.cmd_status_output("ethtool -l %s" %
                                                           guest_iface_name)
                    logging.debug("ethtool cmd output:%s" % outp)
                    if not ret:
                        pre_comb = re.search(
                            "Pre-set maximums:[\s\S]*?Combined:.*?(\d+)",
                            outp).group(1)
                        cur_comb = re.search(
                            "Current hardware settings:[\s\S]*?Combined:.*?(\d+)",
                            outp).group(1)
                        if int(pre_comb) != int(comb_size) or int(
                                cur_comb) != int(comb_size):
                            test.fail(
                                "Fail to check the combined size: setting: %s,"
                                "Pre-set: %s, Current-set: %s" %
                                (comb_size, pre_comb, cur_comb))
                        else:
                            logging.info(
                                "Getting correct Pre-set and Current set value"
                            )
                    else:
                        test.error("ethtool list fail: %s" % outp)
                    # as tx_queue size is only supported for vhost-user interface, only check rx_queue size
                    ret1, outp1 = session1.cmd_status_output("ethtool -g %s" %
                                                             guest_iface_name)
                    logging.debug("guest queue size setting is %s" % outp1)
                    if not ret1:
                        pre_set = re.search(r"Pre-set maximums:\s*RX:\s*(\d+)",
                                            outp1).group(1)
                        cur_set = re.search(
                            r"Current hardware settings:\s*RX:\s*(\d+)",
                            outp1).group(1)
                        if int(pre_set) != int(rx_size) or int(cur_set) != int(
                                rx_size):
                            test.fail("Fail to check the rx_queue_size!")
                except Exception as errs:
                    test.fail("fail to get driver info")
            # hot-unplug interface/device
            if attach_interface:
                ret = virsh.detach_interface(vm1_name,
                                             "bridge",
                                             ignore_status=True)
            else:
                ret = virsh.detach_device(vm1_name,
                                          attach_xml.xml,
                                          ignore_status=True,
                                          debug=True)
            if ret.exit_status:
                test.fail("Hot-unplug interface/device fail")
            else:
                logging.info("hot-unplug interface/device succeed")

        else:
            if start_vm2:
                # Start vm2 connect to the same bridge
                mac2 = utils_net.generate_mac_address_simple()
                vm2_iface_params = {
                    "type": "bridge",
                    "source": vm_iface_source,
                    "filter": filter_name,
                    "mac": mac2
                }
                libvirt.modify_vm_iface(vm2_name, "update_iface",
                                        vm2_iface_params)
                if vm2.is_alive():
                    vm2.destroy()
                vm2.start()

                # Check if vm1 and vm2 can ping each other
                try:
                    utils_net.update_mac_ip_address(vm2, timeout=120)
                    vm2_ip = vm2.get_address()
                except Exception as errs:
                    test.fail(
                        "vm2 can't get IP with the new create bridge: %s" %
                        errs)
                session2 = vm2.wait_for_login()
                # make sure guest has got ip address
                utils_net.restart_guest_network(session2)
                output2 = session2.cmd_output("ifconfig || ip a")
                logging.debug("guest ip info %s" % output2)
                # check 2 guests' network functions
                check_net_functions(vm1_ip, ping_count, ping_timeout, session1,
                                    host_ip, remote_url, vm2_ip)
                check_net_functions(vm2_ip, ping_count, ping_timeout, session2,
                                    host_ip, remote_url, vm1_ip)

    finally:
        logging.debug("Start to restore")
        vm1_xml_bak.sync()
        vm2_xml_bak.sync()
        virsh.nwfilter_undefine(filter_name, ignore_status=True)
        if libvirt.check_iface(bridge_name, "exists", "--all"):
            virsh.iface_unbridge(bridge_name, timeout=60, debug=True)
        if os.path.exists(iface_script_bk):
            process.run("mv %s %s" % (iface_script_bk, iface_script),
                        shell=True,
                        verbose=True)
        if os.path.exists(bridge_script):
            process.run("rm -rf %s" % bridge_script, shell=True, verbose=True)
        cmd = 'tmux -c "ip link set {1} nomaster;  ip link delete {0};' \
              'pkill dhclient; sleep 6; dhclient {1}"'.format(bridge_name, iface_name)
        process.run(cmd, shell=True, verbose=True)
        # reload network configuration
        NM_service.restart()
        # recover NetworkManager
        if NM_status is True:
            NM_service.start()
        if 'network' in iface_source and iface_source[
                "network"] in virsh.net_state_dict():
            virsh.net_destroy(iface_source["network"], ignore_status=False)
Ejemplo n.º 22
0
def run(test, params, env):
    """
    Test interafce xml options.

    1.Prepare test environment,destroy or suspend a VM.
    2.Edit xml and start the domain.
    3.Perform test operation.
    4.Recover test environment.
    5.Confirm the test result.
    """
    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)

    def prepare_pxe_boot():
        """
        Prepare tftp server and pxe boot files
        """
        pkg_list = ["syslinux", "tftp-server",
                    "tftp", "ipxe-roms-qemu", "wget"]
        # Try to install required packages
        if not utils_package.package_install(pkg_list):
            test.error("Failed ot install required packages")
        boot_initrd = params.get("boot_initrd", "EXAMPLE_INITRD")
        boot_vmlinuz = params.get("boot_vmlinuz", "EXAMPLE_VMLINUZ")
        if boot_initrd.count("EXAMPLE") or boot_vmlinuz.count("EXAMPLE"):
            test.cancel("Please provide initrd/vmlinuz URL")
        # Download pxe boot images
        process.system("wget %s -O %s/initrd.img" % (boot_initrd, tftp_root))
        process.system("wget %s -O %s/vmlinuz" % (boot_vmlinuz, tftp_root))
        process.system("cp -f /usr/share/syslinux/pxelinux.0 {0};"
                       " mkdir -m 777 -p {0}/pxelinux.cfg".format(tftp_root), shell=True)
        pxe_file = "%s/pxelinux.cfg/default" % tftp_root
        boot_txt = """
DISPLAY boot.txt
DEFAULT rhel
LABEL rhel
        kernel vmlinuz
        append initrd=initrd.img
PROMPT 1
TIMEOUT 3"""
        with open(pxe_file, 'w') as p_file:
            p_file.write(boot_txt)

    def modify_iface_xml():
        """
        Modify interface xml options
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        if pxe_boot:
            # Config boot console for pxe boot
            osxml = vm_xml.VMOSXML()
            osxml.type = vmxml.os.type
            osxml.arch = vmxml.os.arch
            osxml.machine = vmxml.os.machine
            osxml.loader = "/usr/share/seabios/bios.bin"
            osxml.bios_useserial = "yes"
            osxml.bios_reboot_timeout = "-1"
            osxml.boots = ['network']
            del vmxml.os
            vmxml.os = osxml

        xml_devices = vmxml.devices
        iface_index = xml_devices.index(
            xml_devices.by_device_tag("interface")[0])
        iface = xml_devices[iface_index]
        iface_bandwidth = {}
        iface_inbound = ast.literal_eval(iface_bandwidth_inbound)
        iface_outbound = ast.literal_eval(iface_bandwidth_outbound)
        if iface_inbound:
            iface_bandwidth["inbound"] = iface_inbound
        if iface_outbound:
            iface_bandwidth["outbound"] = iface_outbound
        if iface_bandwidth:
            bandwidth = iface.new_bandwidth(**iface_bandwidth)
            iface.bandwidth = bandwidth

        iface_type = params.get("iface_type", "network")
        iface.type_name = iface_type
        source = ast.literal_eval(iface_source)
        if not source:
            source = {"network": "default"}
        net_ifs = utils_net.get_net_if(state="UP")
        # Check source device is valid or not,
        # if it's not in host interface list, try to set
        # source device to first active interface of host
        if (iface.type_name == "direct" and
            'dev' in source and
                source['dev'] not in net_ifs):
            logging.warn("Source device %s is not a interface"
                         " of host, reset to %s",
                         source['dev'], net_ifs[0])
            source['dev'] = net_ifs[0]
        del iface.source
        iface.source = source
        iface_model = params.get("iface_model", "virtio")
        iface.model = iface_model
        logging.debug("New interface xml file: %s", iface)
        vmxml.devices = xml_devices
        vmxml.xmltreefile.write()
        vmxml.sync()

    def run_dnsmasq_default_test(key, value=None, exists=True, name="default"):
        """
        Test dnsmasq configuration.

        :param key: key in conf file to check
        :param value: value in conf file to check
        :param exists: check the key:value exist or not
        :param name: The name of conf file
        """
        conf_file = "/var/lib/libvirt/dnsmasq/%s.conf" % name
        if not os.path.exists(conf_file):
            test.cancel("Can't find %s.conf file" % name)

        configs = ""
        with open(conf_file, 'r') as f:
            configs = f.read()
        logging.debug("configs in file %s: %s", conf_file, configs)
        if value:
            config = "%s=%s" % (key, value)
        else:
            config = key

        if not configs.count(config):
            if exists:
                test.fail("Can't find %s=%s in configuration file" % (key, value))
        else:
            if not exists:
                test.fail("Found %s=%s in configuration file" % (key, value))

    def run_dnsmasq_addnhosts_test(hostip, hostnames):
        """
        Test host ip and names configuration
        """
        conf_file = "/var/lib/libvirt/dnsmasq/default.addnhosts"
        hosts_re = ".*".join(hostnames)
        configs = ""
        with open(conf_file, 'r') as f:
            configs = f.read()
        logging.debug("configs in file %s: %s", conf_file, configs)
        if not re.search(r"%s.*%s" % (hostip, hosts_re), configs, re.M):
            test.fail("Can't find '%s' in configuration file" % hostip)

    def run_dnsmasq_host_test(iface_mac, guest_ip, guest_name):
        """
        Test host name and ip configuration for dnsmasq
        """
        conf_file = "/var/lib/libvirt/dnsmasq/default.hostsfile"
        config = "%s,%s,%s" % (iface_mac, guest_ip, guest_name)
        configs = ""
        with open(conf_file, 'r') as f:
            configs = f.read()
        logging.debug("configs in file %s: %s", conf_file, configs)
        if not configs.count(config):
            test.fail("Can't find host configuration in file %s" % conf_file)

    def check_class_rules(ifname, rule_id, bandwidth):
        """
        Check bandwidth settings via 'tc class' output
        """
        cmd = "tc class show dev %s" % ifname
        class_output = to_text(process.system_output(cmd))
        logging.debug("Bandwidth class output: %s", class_output)
        class_pattern = (r"class htb %s.*rate (\d+)(K?M?)bit ceil"
                         " (\d+)(K?M?)bit burst (\d+)(K?M?)b.*" % rule_id)
        se = re.search(class_pattern, class_output, re.M)
        if not se:
            test.fail("Can't find outbound setting for htb %s" % rule_id)
        logging.debug("bandwidth from tc output:%s" % str(se.groups()))
        rate = None
        if "floor" in bandwidth:
            rate = int(bandwidth["floor"]) * 8
        elif "average" in bandwidth:
            rate = int(bandwidth["average"]) * 8
        if rate:
            if se.group(2) == 'M':
                rate_check = int(se.group(1)) * 1000
            else:
                rate_check = int(se.group(1))
            assert rate_check == rate
        if "peak" in bandwidth:
            if se.group(4) == 'M':
                ceil_check = int(se.group(3)) * 1000
            else:
                ceil_check = int(se.group(3))
            assert ceil_check == int(bandwidth["peak"]) * 8
        if "burst" in bandwidth:
            if se.group(6) == 'M':
                tc_burst = int(se.group(5)) * 1024
            else:
                tc_burst = int(se.group(5))
            assert tc_burst == int(bandwidth["burst"])

    def check_filter_rules(ifname, bandwidth):
        """
        Check bandwidth settings via 'tc filter' output
        """
        cmd = "tc -d filter show dev %s parent ffff:" % ifname
        filter_output = to_text(process.system_output(cmd))
        logging.debug("Bandwidth filter output: %s", filter_output)
        if not filter_output.count("filter protocol all pref"):
            test.fail("Can't find 'protocol all' settings in filter rules")
        filter_pattern = ".*police.*rate (\d+)(K?M?)bit burst (\d+)(K?M?)b.*"
        se = re.search(r"%s" % filter_pattern, filter_output, re.M)
        if not se:
            test.fail("Can't find any filter policy")
        logging.debug("bandwidth from tc output:%s" % str(se.groups()))
        logging.debug("bandwidth from setting:%s" % str(bandwidth))
        if "average" in bandwidth:
            if se.group(2) == 'M':
                tc_average = int(se.group(1)) * 1000
            else:
                tc_average = int(se.group(1))
            assert tc_average == int(bandwidth["average"]) * 8
        if "burst" in bandwidth:
            if se.group(4) == 'M':
                tc_burst = int(se.group(3)) * 1024
            else:
                tc_burst = int(se.group(3))
            assert tc_burst == int(bandwidth["burst"])

    def check_host_routes():
        """
        Check network routes on host
        """
        for rt in routes:
            try:
                route = ast.literal_eval(rt)
                addr = "%s/%s" % (route["address"], route["prefix"])
                cmd = "ip route list %s" % addr
                if "family" in route and route["family"] == "ipv6":
                    cmd = "ip -6 route list %s" % addr
                output = to_text(process.system_output(cmd))
                match_obj = re.search(r"via (\S+).*metric (\d+)", output)
                if match_obj:
                    via_addr = match_obj.group(1)
                    metric = match_obj.group(2)
                    logging.debug("via address %s for %s, matric is %s"
                                  % (via_addr, addr, metric))
                    assert via_addr == route["gateway"]
                    if "metric" in route:
                        assert metric == route["metric"]
            except KeyError:
                pass

    def run_bandwidth_test(check_net=False, check_iface=False):
        """
        Test bandwidth option for network or interface by tc command.
        """
        iface_inbound = ast.literal_eval(iface_bandwidth_inbound)
        iface_outbound = ast.literal_eval(iface_bandwidth_outbound)
        net_inbound = ast.literal_eval(net_bandwidth_inbound)
        net_outbound = ast.literal_eval(net_bandwidth_outbound)
        net_bridge_name = ast.literal_eval(net_bridge)["name"]
        iface_name = libvirt.get_ifname_host(vm_name, iface_mac)

        try:
            if check_net and net_inbound:
                # Check qdisc rules
                cmd = "tc -d qdisc show dev %s" % net_bridge_name
                qdisc_output = to_text(process.system_output(cmd))
                logging.debug("Bandwidth qdisc output: %s", qdisc_output)
                if not qdisc_output.count("qdisc ingress ffff:"):
                    test.fail("Can't find ingress setting")
                check_class_rules(net_bridge_name, "1:1",
                                  {"average": net_inbound["average"],
                                   "peak": net_inbound["peak"]})
                check_class_rules(net_bridge_name, "1:2", net_inbound)

            # Check filter rules on bridge interface
            if check_net and net_outbound:
                check_filter_rules(net_bridge_name, net_outbound)

            # Check class rules on interface inbound settings
            if check_iface and iface_inbound:
                check_class_rules(iface_name, "1:1",
                                  {'average': iface_inbound['average'],
                                   'peak': iface_inbound['peak'],
                                   'burst': iface_inbound['burst']})
                if "floor" in iface_inbound:
                    if not libvirt_version.version_compare(1, 0, 1):
                        test.cancel("Not supported Qos options 'floor'")

                    check_class_rules(net_bridge_name, "1:3",
                                      {'floor': iface_inbound["floor"]})

            # Check filter rules on interface outbound settings
            if check_iface and iface_outbound:
                check_filter_rules(iface_name, iface_outbound)
        except AssertionError:
            stacktrace.log_exc_info(sys.exc_info())
            test.fail("Failed to check network bandwidth")

    def check_name_ip(session):
        """
        Check dns resolving on guest
        """
        # Check if bind-utils is installed
        if not utils_package.package_install(['bind-utils'], session):
            test.error("Failed to install bind-utils on guest")
        # Run host command to check if hostname can be resolved
        if not guest_ipv4 and not guest_ipv6:
            test.fail("No ip address found from parameters")
        guest_ip = guest_ipv4 if guest_ipv4 else guest_ipv6
        cmd = "host %s | grep %s" % (guest_name, guest_ip)
        if session.cmd_status(cmd):
            test.fail("Can't resolve name %s on guest" % guest_name)

    def check_ipt_rules(check_ipv4=True, check_ipv6=False):
        """
        Check iptables for network/interface
        """
        br_name = ast.literal_eval(net_bridge)["name"]
        net_forward = ast.literal_eval(params.get("net_forward", "{}"))
        net_ipv4 = params.get("net_ipv4")
        net_ipv6 = params.get("net_ipv6")
        ipt_rules = ("INPUT -i %s -p udp -m udp --dport 53 -j ACCEPT" % br_name,
                     "INPUT -i %s -p tcp -m tcp --dport 53 -j ACCEPT" % br_name,
                     "INPUT -i %s -p udp -m udp --dport 67 -j ACCEPT" % br_name,
                     "INPUT -i %s -p tcp -m tcp --dport 67 -j ACCEPT" % br_name,
                     "FORWARD -i {0} -o {0} -j ACCEPT".format(br_name),
                     "FORWARD -o %s -j REJECT --reject-with icmp" % br_name,
                     "FORWARD -i %s -j REJECT --reject-with icmp" % br_name,
                     "OUTPUT -o %s -p udp -m udp --dport 68 -j ACCEPT" % br_name)
        net_dev_in = ""
        net_dev_out = ""
        if "dev" in net_forward:
            net_dev_in = " -i %s" % net_forward["dev"]
            net_dev_out = " -o %s" % net_forward["dev"]
        if check_ipv4:
            ipv4_rules = list(ipt_rules)
            ctr_rule = ""
            nat_rules = []
            if "mode" in net_forward and net_forward["mode"] == "nat":
                nat_port = ast.literal_eval(params.get("nat_port"))
                p_start = nat_port["start"]
                p_end = nat_port["end"]
                ctr_rule = " -m .* RELATED,ESTABLISHED"
                nat_rules = [("POSTROUTING -s {0} ! -d {0} -p tcp -j MASQUERADE"
                              " --to-ports {1}-{2}".format(net_ipv4, p_start, p_end)),
                             ("POSTROUTING -s {0} ! -d {0} -p udp -j MASQUERADE"
                              " --to-ports {1}-{2}".format(net_ipv4, p_start, p_end)),
                             ("POSTROUTING -s {0} ! -d {0} -p udp"
                              " -j MASQUERADE".format(net_ipv4))]
            if nat_rules:
                ipv4_rules.extend(nat_rules)
            if (net_ipv4 and "mode" in net_forward and
                    net_forward["mode"] in ["nat", "route"]):
                rules = [("FORWARD -d %s%s -o %s%s -j ACCEPT"
                          % (net_ipv4, net_dev_in, br_name, ctr_rule)),
                         ("FORWARD -s %s -i %s%s -j ACCEPT"
                          % (net_ipv4, br_name, net_dev_out))]
                ipv4_rules.extend(rules)

            output = to_text(process.system_output('iptables-save'))
            logging.debug("iptables: %s", output)
            if "mode" in net_forward and net_forward["mode"] == "open":
                if re.search(r"%s|%s" % (net_ipv4, br_name), output, re.M):
                    test.fail("Find iptable rule for open mode")
                utils_libvirtd.libvirtd_restart()
                output_again = to_text(process.system_output('iptables-save'))
                if re.search(r"%s|%s" % (net_ipv4, br_name), output_again, re.M):
                    test.fail("Find iptable rule for open mode after restart "
                              "libvirtd")
                else:
                    logging.info("Can't find iptable rule for open mode as expected")
            else:
                for ipt in ipv4_rules:
                    if not re.search(r"%s" % ipt, output, re.M):
                        test.fail("Can't find iptable rule:\n%s" % ipt)
            return ipv4_rules
        if check_ipv6:
            ipv6_rules = list(ipt_rules)
            if (net_ipv6 and "mode" in net_forward and
                    net_forward["mode"] in ["nat", "route"]):
                rules = [("FORWARD -d %s%s -o %s -j ACCEPT"
                          % (net_ipv6, net_dev_in, br_name)),
                         ("FORWARD -s %s -i %s%s -j ACCEPT"
                          % (net_ipv6, br_name, net_dev_out))]
                ipv6_rules.extend(rules)
            output = to_text(process.system_output("ip6tables-save"))
            logging.debug("iptables: %s", output)
            for ipt in ipv6_rules:
                if not output.count(ipt):
                    test.fail("Can't find ipbtable rule:\n%s" % ipt)
            return ipv6_rules

    def run_ip_test(session, ip_ver):
        """
        Check iptables on host and ipv6 address on guest
        """
        if ip_ver == "ipv6":
            # Clean up iptables rules for guest to get ipv6 address
            session.cmd_status("ip6tables -F")

        # It may take some time to get the ip address
        def get_ip_func():
            return utils_net.get_guest_ip_addr(session, iface_mac,
                                               ip_version=ip_ver)
        utils_misc.wait_for(get_ip_func, 5)
        if not get_ip_func():
            utils_net.restart_guest_network(session, iface_mac,
                                            ip_version=ip_ver)
            utils_misc.wait_for(get_ip_func, 5)
        vm_ip = get_ip_func()
        logging.debug("Guest has ip: %s", vm_ip)
        if not vm_ip:
            test.fail("Can't find ip address on guest")
        ip_gateway = net_ip_address
        if ip_ver == "ipv6":
            ip_gateway = net_ipv6_address
            # Cleanup ip6talbes on host for ping6 test
            process.system("ip6tables -F")
        if ip_gateway and not routes:
            ping_s, _ = ping(dest=ip_gateway, count=5,
                             timeout=10, session=session)
            if ping_s:
                test.fail("Failed to ping gateway address: %s" % ip_gateway)

    def run_guest_libvirt(session):
        """
        Check guest libvirt network
        """
        # Try to install required packages
        if not utils_package.package_install(['libvirt'], session):
            test.error("Failed ot install libvirt package on guest")
        # Try to load tun module first
        session.cmd("lsmod | grep tun || modprobe  tun")
        # Check network state on guest
        cmd = ("service libvirtd restart; virsh net-info default"
               " | grep 'Active:.*yes'")
        if session.cmd_status(cmd):
            test.fail("'default' network isn't in active state")
        # Try to destroy&start default network on guest
        for opt in ['net-destroy', 'net-start']:
            cmd = "virsh %s default" % opt
            status, output = session.cmd_status_output(cmd)
            logging.debug("Run %s on guest exit %s, output %s"
                          % (cmd, status, output))
            if status:
                test.fail(output)
        if not utils_package.package_remove("libvirt*", session):
            test.error("Failed to remove libvirt packages on guest")

    start_error = "yes" == params.get("start_error", "no")
    define_error = "yes" == params.get("define_error", "no")
    restart_error = "yes" == params.get("restart_error", "no")

    # network specific attributes.
    net_name = params.get("net_name", "default")
    net_bridge = params.get("net_bridge", "{'name':'virbr0'}")
    net_domain = params.get("net_domain")
    net_ip_address = params.get("net_ip_address")
    net_ipv6_address = params.get("net_ipv6_address")
    net_dns_forward = params.get("net_dns_forward")
    net_dns_txt = params.get("net_dns_txt")
    net_dns_srv = params.get("net_dns_srv")
    net_dns_hostip = params.get("net_dns_hostip")
    net_dns_hostnames = params.get("net_dns_hostnames", "").split()
    dhcp_start_ipv4 = params.get("dhcp_start_ipv4")
    dhcp_end_ipv4 = params.get("dhcp_end_ipv4")
    dhcp_start_ipv6 = params.get("dhcp_start_ipv6")
    dhcp_end_ipv6 = params.get("dhcp_end_ipv6")
    guest_name = params.get("guest_name")
    guest_ipv4 = params.get("guest_ipv4")
    guest_ipv6 = params.get("guest_ipv6")
    tftp_root = params.get("tftp_root")
    pxe_boot = "yes" == params.get("pxe_boot", "no")
    routes = params.get("routes", "").split()
    net_bandwidth_inbound = params.get("net_bandwidth_inbound", "{}")
    net_bandwidth_outbound = params.get("net_bandwidth_outbound", "{}")
    iface_bandwidth_inbound = params.get("iface_bandwidth_inbound", "{}")
    iface_bandwidth_outbound = params.get("iface_bandwidth_outbound", "{}")
    iface_num = params.get("iface_num", "1")
    iface_source = params.get("iface_source", "{}")
    multiple_guests = params.get("multiple_guests")
    create_network = "yes" == params.get("create_network", "no")
    attach_iface = "yes" == params.get("attach_iface", "no")
    serial_login = "******" == params.get("serial_login", "no")
    change_iface_option = "yes" == params.get("change_iface_option", "no")
    test_bridge = "yes" == params.get("test_bridge", "no")
    test_dnsmasq = "yes" == params.get("test_dnsmasq", "no")
    test_dhcp_range = "yes" == params.get("test_dhcp_range", "no")
    test_dns_host = "yes" == params.get("test_dns_host", "no")
    test_qos_bandwidth = "yes" == params.get("test_qos_bandwidth", "no")
    test_pg_bandwidth = "yes" == params.get("test_portgroup_bandwidth", "no")
    test_qos_remove = "yes" == params.get("test_qos_remove", "no")
    test_ipv4_address = "yes" == params.get("test_ipv4_address", "no")
    test_ipv6_address = "yes" == params.get("test_ipv6_address", "no")
    test_guest_libvirt = "yes" == params.get("test_guest_libvirt", "no")
    net_no_bridge = "yes" == params.get("no_bridge", "no")
    net_no_mac = "yes" == params.get("no_mac", "no")
    net_no_ip = "yes" == params.get("no_ip", "no")
    net_with_dev = "yes" == params.get("with_dev", "no")
    username = params.get("username")
    password = params.get("password")
    ipt_rules = []

    # Destroy VM first
    if vm.is_alive():
        vm.destroy(gracefully=False)

    # Back up xml file.
    netxml_backup = NetworkXML.new_from_net_dumpxml("default")
    iface_mac = vm_xml.VMXML.get_first_mac_by_name(vm_name)
    params["guest_mac"] = iface_mac
    vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    vms_list = []
    if "floor" in ast.literal_eval(iface_bandwidth_inbound):
        if not libvirt_version.version_compare(1, 0, 1):
            test.cancel("Not supported Qos options 'floor'")

    # Enabling IPv6 forwarding with RA routes without accept_ra set to 2
    # is likely to cause routes loss
    sysctl_cmd = 'sysctl net.ipv6.conf.all.accept_ra'
    original_accept_ra = to_text(process.system_output(sysctl_cmd + ' -n'))
    if test_ipv6_address and original_accept_ra != '2':
        process.system(sysctl_cmd + '=2')

    # Build the xml and run test.
    try:
        if test_dnsmasq:
            # Check the settings before modifying network xml
            if net_dns_forward == "no":
                run_dnsmasq_default_test("domain-needed", exists=False)
                run_dnsmasq_default_test("local", "//", exists=False)
            if net_domain:
                run_dnsmasq_default_test("domain", net_domain, exists=False)
                run_dnsmasq_default_test("expand-hosts", exists=False)

        # Prepare pxe boot directory
        if pxe_boot:
            prepare_pxe_boot()
        # Edit the network xml or create a new one.
        if create_network:
            net_ifs = utils_net.get_net_if(state="UP")
            # Check forward device is valid or not,
            # if it's not in host interface list, try to set
            # forward device to first active interface of host
            forward = ast.literal_eval(params.get("net_forward",
                                                  "{}"))
            if ('mode' in forward and forward['mode'] in
                ['passthrough', 'private', 'bridge', 'macvtap'] and
                'dev' in forward and
                    forward['dev'] not in net_ifs):
                logging.warn("Forward device %s is not a interface"
                             " of host, reset to %s",
                             forward['dev'], net_ifs[0])
                forward['dev'] = net_ifs[0]
                params["net_forward"] = str(forward)
            forward_iface = params.get("forward_iface")
            if forward_iface:
                interface = [x for x in forward_iface.split()]
                # The guest will use first interface of the list,
                # check if it's valid or not, if it's not in host
                # interface list, try to set forward interface to
                # first active interface of host.
                if interface[0] not in net_ifs:
                    logging.warn("Forward interface %s is not a "
                                 " interface of host, reset to %s",
                                 interface[0], net_ifs[0])
                    interface[0] = net_ifs[0]
                    params["forward_iface"] = " ".join(interface)

            netxml = libvirt.create_net_xml(net_name, params)
            if "mode" in forward and forward["mode"] == "open":
                netxml.mac = utils_net.generate_mac_address_simple()
                try:
                    if net_no_bridge:
                        netxml.del_bridge()
                    if net_no_ip:
                        netxml.del_ip()
                        netxml.del_ip()
                    if net_no_mac:
                        netxml.del_mac()
                except xcepts.LibvirtXMLNotFoundError:
                    pass
                if net_with_dev:
                    net_forward = netxml.forward
                    net_forward.update({"dev": net_ifs[0]})
                    netxml.forward = net_forward
            logging.info("netxml before define is %s", netxml)
            try:
                netxml.sync()
            except xcepts.LibvirtXMLError as details:
                logging.info(str(details))
                if define_error:
                    return
                else:
                    test.fail("Failed to define network")

        # Check open mode network xml
        if "mode" in forward and forward["mode"] == "open":
            netxml_new = NetworkXML.new_from_net_dumpxml(net_name)
            logging.info("netxml after define is %s", netxml_new)
            try:
                if net_no_bridge:
                    net_bridge = str(netxml_new.bridge)
                if net_no_mac:
                    netxml_new.mac
            except xcepts.LibvirtXMLNotFoundError as details:
                test.fail("Failed to check %s xml: %s" % (net_name, details))
            logging.info("mac/bridge still exist even if removed before define")

        # Edit the interface xml.
        if change_iface_option:
            modify_iface_xml()
        # Attach interface if needed
        if attach_iface:
            iface_type = params.get("iface_type", "network")
            iface_model = params.get("iface_model", "virtio")
            for i in range(int(iface_num)):
                logging.info("Try to attach interface loop %s" % i)
                options = ("%s %s --model %s --config" %
                           (iface_type, net_name, iface_model))
                ret = virsh.attach_interface(vm_name, options,
                                             ignore_status=True)
                if ret.exit_status:
                    logging.error("Command output %s" %
                                  ret.stdout.strip())
                    test.fail("Failed to attach-interface")

        if multiple_guests:
            # Clone more vms for testing
            for i in range(int(multiple_guests)):
                guest_name = "%s_%s" % (vm_name, i)
                timeout = params.get("clone_timeout", 360)
                utils_libguestfs.virt_clone_cmd(vm_name, guest_name,
                                                True, timeout=timeout)
                vms_list.append(vm.clone(guest_name))

        if test_bridge:
            bridge = ast.literal_eval(net_bridge)
            br_if = utils_net.Interface(bridge['name'])
            if not br_if.is_up():
                test.fail("Bridge interface isn't up")
        if test_dnsmasq:
            # Check dnsmasq process
            dnsmasq_cmd = to_text(process.system_output("ps -aux|grep dnsmasq", shell=True))
            logging.debug(dnsmasq_cmd)
            if not re.search("dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/%s.conf"
                             % net_name, dnsmasq_cmd):
                test.fail("Can not find dnsmasq process or the process is not correct")

            # Check the settings in dnsmasq config file
            if net_dns_forward == "no":
                run_dnsmasq_default_test("domain-needed")
                run_dnsmasq_default_test("local", "//")
            if net_domain:
                run_dnsmasq_default_test("domain", net_domain)
                run_dnsmasq_default_test("expand-hosts")
            if net_bridge:
                bridge = ast.literal_eval(net_bridge)
                run_dnsmasq_default_test("interface", bridge['name'], name=net_name)
                if 'stp' in bridge and bridge['stp'] == 'on':
                    if 'delay' in bridge and bridge['delay'] != '0':
                        br_delay = float(bridge['delay'])
                        cmd = ("brctl showstp %s | grep 'bridge forward delay'"
                               % bridge['name'])
                        out = to_text(process.system_output(
                            cmd, shell=True, ignore_status=False))
                        logging.debug("brctl showstp output: %s", out)
                        pattern = (r"\s*forward delay\s+(\d+.\d+)\s+bridge"
                                   " forward delay\s+(\d+.\d+)")
                        match_obj = re.search(pattern, out, re.M)
                        if not match_obj or len(match_obj.groups()) != 2:
                            test.fail("Can't see forward delay messages from command")
                        elif (float(match_obj.groups()[0]) != br_delay or
                              float(match_obj.groups()[1]) != br_delay):
                            test.fail("Foward delay setting can't take effect")
            if dhcp_start_ipv4 and dhcp_end_ipv4:
                run_dnsmasq_default_test("dhcp-range", "%s,%s"
                                         % (dhcp_start_ipv4, dhcp_end_ipv4),
                                         name=net_name)
            if dhcp_start_ipv6 and dhcp_end_ipv6:
                run_dnsmasq_default_test("dhcp-range", "%s,%s,64"
                                         % (dhcp_start_ipv6, dhcp_end_ipv6),
                                         name=net_name)
            if guest_name and guest_ipv4:
                run_dnsmasq_host_test(iface_mac, guest_ipv4, guest_name)

            # check the left part in dnsmasq conf
            run_dnsmasq_default_test("strict-order", name=net_name)
            run_dnsmasq_default_test("pid-file",
                                     "/var/run/libvirt/network/%s.pid" % net_name,
                                     name=net_name)
            run_dnsmasq_default_test("except-interface", "lo", name=net_name)
            run_dnsmasq_default_test("bind-dynamic", name=net_name)
            run_dnsmasq_default_test("dhcp-no-override", name=net_name)
            if dhcp_start_ipv6 and dhcp_start_ipv4:
                run_dnsmasq_default_test("dhcp-lease-max", "493", name=net_name)
            else:
                range_num = int(params.get("dhcp_range", "252"))
                run_dnsmasq_default_test("dhcp-lease-max", str(range_num+1), name=net_name)
            run_dnsmasq_default_test("dhcp-hostsfile",
                                     "/var/lib/libvirt/dnsmasq/%s.hostsfile" % net_name,
                                     name=net_name)
            run_dnsmasq_default_test("addn-hosts",
                                     "/var/lib/libvirt/dnsmasq/%s.addnhosts" % net_name,
                                     name=net_name)
            if dhcp_start_ipv6:
                run_dnsmasq_default_test("enable-ra", name=net_name)

        if test_dns_host:
            if net_dns_txt:
                dns_txt = ast.literal_eval(net_dns_txt)
                run_dnsmasq_default_test("txt-record", "%s,%s" %
                                         (dns_txt["name"],
                                          dns_txt["value"]))
            if net_dns_srv:
                dns_srv = ast.literal_eval(net_dns_srv)
                run_dnsmasq_default_test("srv-host", "_%s._%s.%s,%s,%s,%s,%s" %
                                         (dns_srv["service"], dns_srv["protocol"],
                                          dns_srv["domain"], dns_srv["target"],
                                          dns_srv["port"], dns_srv["priority"],
                                          dns_srv["weight"]))
            if net_dns_hostip and net_dns_hostnames:
                run_dnsmasq_addnhosts_test(net_dns_hostip, net_dns_hostnames)

        # Run bandwidth test for network
        if test_qos_bandwidth:
            run_bandwidth_test(check_net=True)
        # Check routes if needed
        if routes:
            check_host_routes()

        try:
            # Start the VM.
            vm.start()
            if start_error:
                test.fail("VM started unexpectedly")
            if pxe_boot:
                # Just check network boot messages here
                vm.serial_console.read_until_output_matches(
                    ["Loading vmlinuz", "Loading initrd.img"],
                    utils_misc.strip_console_codes)
                output = vm.serial_console.get_stripped_output()
                logging.debug("Boot messages: %s", output)

            else:
                if serial_login:
                    session = vm.wait_for_serial_login(username=username,
                                                       password=password)
                else:
                    session = vm.wait_for_login()

                if test_dhcp_range:
                    dhcp_range = int(params.get("dhcp_range", "252"))
                    utils_net.restart_guest_network(session, iface_mac)
                    vm_ip = utils_net.get_guest_ip_addr(session, iface_mac)
                    logging.debug("Guest has ip: %s", vm_ip)
                    if not vm_ip and dhcp_range:
                        test.fail("Guest has invalid ip address")
                    elif vm_ip and not dhcp_range:
                        test.fail("Guest has ip address: %s" % vm_ip)
                    dhcp_range = dhcp_range - 1
                    for vms in vms_list:
                        # Start other VMs.
                        vms.start()
                        sess = vms.wait_for_serial_login()
                        vms_mac = vms.get_virsh_mac_address()
                        # restart guest network to get ip addr
                        utils_net.restart_guest_network(sess, vms_mac)
                        vms_ip = utils_net.get_guest_ip_addr(sess,
                                                             vms_mac)
                        if not vms_ip and dhcp_range:
                            test.fail("Guest has invalid ip address")
                        elif vms_ip and not dhcp_range:
                            # Get IP address on guest should return Null
                            # if it exceeds the dhcp range
                            test.fail("Guest has ip address: %s" % vms_ip)
                        dhcp_range = dhcp_range - 1
                        if vms_ip:
                            ping_s, _ = ping(dest=vm_ip, count=5,
                                             timeout=10, session=sess)
                            if ping_s:
                                test.fail("Failed to ping, src: %s, "
                                          "dst: %s" % (vms_ip, vm_ip))
                        sess.close()

                # Check dnsmasq settings if take affect in guest
                if guest_ipv4:
                    check_name_ip(session)

                # Run bandwidth test for interface
                if test_qos_bandwidth:
                    run_bandwidth_test(check_iface=True)
                # Run bandwidth test for portgroup
                if test_pg_bandwidth:
                    pg_bandwidth_inbound = params.get(
                        "portgroup_bandwidth_inbound", "").split()
                    pg_bandwidth_outbound = params.get(
                        "portgroup_bandwidth_outbound", "").split()
                    pg_name = params.get("portgroup_name", "").split()
                    pg_default = params.get("portgroup_default", "").split()
                    iface_inbound = ast.literal_eval(iface_bandwidth_inbound)
                    iface_outbound = ast.literal_eval(iface_bandwidth_outbound)
                    iface_name = libvirt.get_ifname_host(vm_name, iface_mac)
                    if_source = ast.literal_eval(iface_source)
                    if "portgroup" in if_source:
                        pg = if_source["portgroup"]
                    else:
                        pg = "default"
                    for (name, df, bw_ib, bw_ob) in zip(pg_name, pg_default,
                                                        pg_bandwidth_inbound,
                                                        pg_bandwidth_outbound):
                        if pg == name:
                            inbound = ast.literal_eval(bw_ib)
                            outbound = ast.literal_eval(bw_ob)
                        elif pg == "default" and df == "yes":
                            inbound = ast.literal_eval(bw_ib)
                            outbound = ast.literal_eval(bw_ob)
                        else:
                            continue
                        # Interface bandwidth settings will
                        # overwriting portgroup settings
                        if iface_inbound:
                            inbound = iface_inbound
                        if iface_outbound:
                            outbound = iface_outbound
                        check_class_rules(iface_name, "1:1", inbound)
                        check_filter_rules(iface_name, outbound)
                if test_qos_remove:
                    # Remove the bandwidth settings in network xml
                    logging.debug("Removing network bandwidth settings...")
                    netxml_backup.sync()
                    vm.destroy(gracefully=False)
                    # Should fail to start vm
                    vm.start()
                    if restart_error:
                        test.fail("VM started unexpectedly")
                if test_ipv6_address:
                    ipt_rules = check_ipt_rules(check_ipv6=True)
                    if not ("mode" in forward and forward["mode"] == "open"):
                        run_ip_test(session, "ipv6")
                if test_ipv4_address:
                    ipt_rules = check_ipt_rules(check_ipv4=True)
                    if not ("mode" in forward and forward["mode"] == "open"):
                        run_ip_test(session, "ipv4")
                if test_guest_libvirt:
                    run_guest_libvirt(session)

                session.close()
        except virt_vm.VMStartError as details:
            logging.info(str(details))
            if not (start_error or restart_error):
                test.fail('VM failed to start:\n%s' % details)

        # Destroy created network and check iptable rules
        if net_name != "default":
            virsh.net_destroy(net_name)
        if ipt_rules:
            output_des = to_text(process.system_output('iptables-save'))
            for ipt in ipt_rules:
                if re.search(r"%s" % ipt, output_des, re.M):
                    test.fail("Find iptable rule %s after net destroyed" % ipt)
    finally:
        # Recover VM.
        if vm.is_alive():
            vm.destroy(gracefully=False)
        for vms in vms_list:
            virsh.remove_domain(vms.name, "--remove-all-storage")
        logging.info("Restoring network...")
        if net_name == "default":
            netxml_backup.sync()
        else:
            # Destroy and undefine new created network
            virsh.net_destroy(net_name)
            virsh.net_undefine(net_name)
        vmxml_backup.sync()

        if test_ipv6_address and original_accept_ra != '2':
            process.system(sysctl_cmd + "=%s" % original_accept_ra)
Ejemplo n.º 23
0
def run(test, params, env):

    global flag_list, flag_list_abs, update_sec, without_sec
    global check_sec, check_without_sec, newxml

    # Basic network params
    net_name = params.get("net_update_net_name", "updatenet")
    net_section = params.get("network_section")
    update_command = params.get("update_command", "add-last")
    options = params.get("cmd_options", "")
    net_state = params.get("net_state")
    use_in_guest = params.get("use_in_guest")
    iface_type = params.get("iface_type", "network")
    ip_version = params.get("ip_version", "ipv4")
    new_start_ip = params.get("start_ip")
    new_end_ip = params.get("end_ip")
    parent_index = params.get("parent_index")
    status_error = params.get("status_error", "no")

    # dhcp host test
    new_dhcp_host_ip = params.get("new_dhcp_host_ip")
    new_dhcp_host_id = params.get("new_dhcp_host_id")
    new_dhcp_host_name = params.get("new_dhcp_host_name")
    new_dhcp_host_mac = params.get("new_dhcp_host_mac")

    # ipv4 range/host test
    ipv4_range_start = params.get("ori_ipv4_range_start")
    ipv4_range_end = params.get("ori_ipv4_range_end")
    ipv4_host_mac = params.get("ori_ipv4_host_mac")
    ipv4_host_ip = params.get("ori_ipv4_host_ip")
    ipv4_host_name = params.get("ori_ipv4_host_name")

    # ipv6 range/host test
    ipv6_range_start = params.get("ori_ipv6_range_start")
    ipv6_range_end = params.get("ori_ipv6_range_end")
    ipv6_host_id = params.get("ori_ipv6_host_id")
    ipv6_host_name = params.get("ori_ipv6_host_name")
    ipv6_host_ip = params.get("ori_ipv6_host_ip")

    # dns test
    dns_name = params.get("ori_dns_name")
    dns_value = params.get("ori_dns_value")
    new_dns_name = params.get("new_dns_name")
    new_dns_value = params.get("new_dns_value")

    # srv test
    srv_service = params.get("ori_srv_service")
    srv_protocol = params.get("ori_srv_protocol")
    srv_domain = params.get("ori_srv_domain")
    srv_target = params.get("ori_srv_target")
    srv_port = params.get("ori_srv_port")
    srv_priority = params.get("ori_srv_priority")
    srv_weight = params.get("ori_srv_weight")
    new_srv_service = params.get("new_srv_service")
    new_srv_protocol = params.get("new_srv_protocol")
    new_srv_domain = params.get("new_srv_domain")
    new_srv_target = params.get("new_srv_target")
    new_srv_port = params.get("new_srv_port")
    new_srv_priority = params.get("new_srv_priority")
    new_srv_weight = params.get("new_srv_weight")

    # dns host test
    dns_hostip = params.get("ori_dns_hostip")
    dns_hostname = params.get("ori_dns_hostname")
    dns_hostname2 = params.get("ori_dns_hostname2")

    # setting for without part
    without_ip_dhcp = params.get("without_ip_dhcp", "no")
    without_dns = params.get("without_dns", "no")
    without_dns_host = params.get("without_dns_host", "no")
    without_dns_txt = params.get("without_dns_txt", "no")
    without_dns_srv = params.get("without_dns_srv", "no")

    # setting for update/check/without section
    update_sec = params.get("update_sec")
    check_sec = params.get("check_sec")
    without_sec = params.get("without_sec")
    check_without_sec = params.get("check_without_sec")

    # forward test
    forward_mode = params.get("forward_mode")
    forward_iface = params.get("forward_iface", "eth2")

    # other params
    error_type = params.get("error_type", "")
    vm_name = params.get("main_vm")
    loop_time = int(params.get("loop_time", 1))
    check_config_round = params.get("check_config_round", -1)
    ipv4_host_id = ipv6_host_mac = ""
    dns_enable = params.get("dns_enable", "yes")
    guest_iface_num = int(params.get("guest_iface_num", 1))
    newxml = ""

    def get_hostfile():
        """
        Get the content of hostfile
        """
        logging.info("Checking network hostfile...")
        hostfile = "/var/lib/libvirt/dnsmasq/%s.hostsfile" % net_name
        with open(hostfile) as hostfile_d:
            hostfile = hostfile_d.readlines()
        return hostfile

    def find_config(check_file, need_find):
        """
        Find configure in check_file

        :param check_file: The file that will check
        :param need_find: If need to find the item in check_file, Boolean
        """
        def _find_config(check_func):
            def __find_config(*args, **kwargs):
                logging.info("Checking content of %s", check_file)
                ret = False
                item = None
                with open(check_file) as checkfile_d:
                    while True:
                        check_line = checkfile_d.readline()
                        if not check_line:
                            break
                        (ret, item) = check_func(check_line, *args, **kwargs)
                        if ret:
                            break
                if not ret:
                    if need_find:
                        test.fail("Fail to find %s in %s" % (item, check_file))
                    else:
                        logging.info("Can not find %s in %s as expected" % (item, check_file))
            return __find_config
        return _find_config

    conf_file = "/var/lib/libvirt/dnsmasq/%s.conf" % net_name

    @find_config(conf_file, True)
    def check_item(check_line, item):
        """
        Check if the item in config file
        """
        if item in check_line:
            logging.info("Find %s in %s", item, conf_file)
            return (True, item)
        else:
            return (False, item)

    host_file = "/var/lib/libvirt/dnsmasq/%s.addnhosts" % net_name

    @find_config(host_file, True)
    def check_host(check_line, item):
        """
        Check if the item in host_file
        """
        if re.search(item, check_line):
            logging.info("Find %s in %s", item, host_file)
            return (True, item)
        else:
            return (False, item)

    @find_config(conf_file, False)
    def check_item_absent(check_line, item):
        """
        Check if the item not in config file
        """
        if item in check_line:
            test.fail("Find %s in %s" % (item, conf_file))
        else:
            return (False, item)

    @find_config(host_file, False)
    def check_host_absent(check_line, item):
        """
        Check if the item not in host_file
        """
        if re.search(item, check_line):
            test.fail("Find %s in %s" % (item, host_file))
        else:
            return (False, item)

    def section_update(ori_pre, new_pre):
        """
        Deal with update section and without section in func

        :param ori_pre: prefix of original section parameter name
        :param new_pre: prefix of new section parameter name
        """
        global flag_list, flag_list_abs, update_sec, without_sec
        global check_sec, check_without_sec, newxml

        if update_sec:
            for sec in update_sec.split(","):
                newxml = newxml.replace(names[ori_pre+sec],
                                        names[new_pre+sec])
            if update_command != "delete":
                check_sec = update_sec
        if without_sec:
            for sec_no in without_sec.split(","):
                newxml = re.sub(sec_no+"=\".*?\"", "", newxml)
            if update_command == "modify":
                check_without_sec = without_sec
        if check_sec:
            for c_sec in check_sec.split(","):
                flag_list.append(names[new_pre+c_sec])
        if check_without_sec:
            for c_sec_no in check_without_sec.split(","):
                flag_list_abs.append(names[ori_pre+c_sec_no])

    dns_host_xml = """
<host ip='%s'>
 <hostname>%s</hostname>
 <hostname>%s</hostname>
</host>
""" % (dns_hostip, dns_hostname, dns_hostname2)

    virtual_net = """
<network>
  <name>%s</name>
  <forward mode='nat'/>
  <bridge name='%s' stp='on' delay='0' />
  <mac address='52:54:00:03:78:6c'/>
  <dns enable='%s'>
      <txt name='%s' value='%s'/>
      <srv service='%s' protocol='%s' domain='%s' target='%s' port='%s' priority='%s' weight='%s'/>
      %s
  </dns>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='%s' end='%s' />
      <host mac='%s' ip='%s' name='%s' />
    </dhcp>
  </ip>
  <ip family='ipv6' address='2001:db8:ca2:2::1' prefix='64'>
    <dhcp>
      <range start='%s' end='%s'/>
      <host id='%s' name='%s' ip='%s'/>
    </dhcp>
  </ip>
  <route family='ipv6' address='2001:db8:ca2:2::' prefix='64' gateway='2001:db8:ca2:2::4'/>
  <ip address='192.168.101.1' netmask='255.255.255.0'/>
  <ip family='ipv6' address='2001:db8:ca2:3::1' prefix='64' />
</network>
""" % (net_name, net_name, dns_enable, dns_name, dns_value, srv_service, srv_protocol,
       srv_domain, srv_target, srv_port, srv_priority, srv_weight, dns_host_xml,
       ipv4_range_start, ipv4_range_end, ipv4_host_mac, ipv4_host_ip, ipv4_host_name,
       ipv6_range_start, ipv6_range_end, ipv6_host_id, ipv6_host_name, ipv6_host_ip)

    port_group = """
<portgroup name='engineering' default='no'>
  <virtualport type='802.1Qbh'>
    <parameters profileid='test'/>
  </virtualport>
  <bandwidth>
    <inbound average='1000' peak='5000' burst='5120'/>
    <outbound average='1000' peak='5000' burst='5120'/>
  </bandwidth>
</portgroup>
"""

    if use_in_guest == "yes":
        vm = env.get_vm(vm_name)
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        vmxml_backup = vmxml.copy()

    backup_files = []
    try:
        for loop in range(loop_time):
            if loop_time > 1:
                logging.info("Round %s:", loop+1)
                update_command = params.get("update_command").split(",")[loop]
                if net_section == "ip-dhcp-host":
                    new_dhcp_host_ip = params.get("new_dhcp_host_ip").split(",")[loop]
                    new_dhcp_host_name = params.get("new_dhcp_host_name").split(",")[loop]
                    new_dhcp_host_mac = params.get("new_dhcp_host_mac").split(",")[loop]
                    status_error = params.get("status_error").split(",")[loop]
                elif net_section == "dns-txt":
                    net_state = params.get("net_state").split(",")[loop]

            # Get a tmp_dir.
            tmp_dir = data_dir.get_tmp_dir()

            # Write new xml into a tempfile
            tmp_file = tempfile.NamedTemporaryFile(prefix=("new_xml_"),
                                                   dir=tmp_dir)
            xmlfile = tmp_file.name
            tmp_file.close()

            # Generate testxml
            test_xml = network_xml.NetworkXML(network_name=net_name)
            test_xml.xml = virtual_net

            names = locals()

            if net_section == "portgroup":
                portgroup_xml = network_xml.PortgroupXML()
                portgroup_xml.xml = port_group
                test_xml.portgroup = portgroup_xml
            elif net_section == "forward-interface":
                if forward_mode == "bridge":
                    forward_iface = utils_net.get_net_if(state="UP")[0]
                test_xml.forward = {'mode': forward_mode}
                test_xml.forward_interface = [{'dev': forward_iface}]
                del test_xml.bridge
                del test_xml.mac
                for ip_num in range(4):
                    del test_xml.ip
                del test_xml.routes
                del test_xml.dns

            section_index = 0
            if ip_version == "ipv6":
                section_index = 1
            element = "/%s" % net_section.replace('-', '/')
            try:
                section_xml = test_xml.get_section_string(xpath=element, index=section_index)
            except xcepts.LibvirtXMLNotFoundError:
                newxml = section_xml = test_xml.get_section_string(xpath="/ip/dhcp/range")

            newxml = section_xml
            logging.debug("section xml is %s", newxml)

            flag_list = []
            flag_list_abs = []

            if (update_command == "delete" and
                    error_type not in ["host-mismatch", "range-mismatch"] and
                    not without_sec and not update_sec):
                logging.info("The delete xml is %s", newxml)
            else:
                if net_section == "bridge":
                    new_bridge_name = net_name + "_new"
                    flag_list.append(new_bridge_name)
                    newxml = section_xml.replace(net_name, new_bridge_name)
                    logging.info("The new bridge xml is %s", newxml)
                elif net_section == "forward":
                    new_mode = "route"
                    flag_list.append(new_mode)
                    newxml = section_xml.replace("nat", new_mode)
                    logging.info("The new forward xml is %s", newxml)
                elif net_section == "ip":
                    new_netmask = "255.255.0.0"
                    flag_list.append(new_netmask)
                    newxml = section_xml.replace("255.255.255.0", new_netmask)
                elif net_section == "ip-dhcp-range":
                    newxml = section_xml.replace(names[ip_version+"_range_start"], new_start_ip)
                    newxml = newxml.replace(names[ip_version+"_range_end"], new_end_ip)
                    for location in ["end", "start"]:
                        if names["new_"+location+"_ip"] == "":
                            newxml = newxml.replace(location+"=\"\"", "")
                        else:
                            flag_list.append(names["new_"+location+"_ip"])
                elif net_section == "portgroup":
                    new_inbound_average = "2000"
                    flag_list.append(new_inbound_average)
                    newxml = section_xml.replace("1000", new_inbound_average)
                    newxml = newxml.replace("default=\"no\"", "default=\"yes\"")
                    flag_list.append("default=('|\")yes")
                    if update_command in ['add-first', 'add-last', 'add']:
                        newxml = newxml.replace("engineering", "sales")
                        flag_list.append("sales")
                elif net_section == "forward-interface":
                    new_forward_iface = params.get("new_forward_iface")
                    if error_type != "interface-duplicate":
                        find_iface = 0
                        if not new_forward_iface and forward_mode == "bridge":
                            new_iface_list = utils_net.get_net_if(qdisc="(mq|pfifo_fast)",
                                                                  state="(UP|DOWN)",
                                                                  optional="MULTICAST,UP")
                            logging.info("new_iface_list is %s", new_iface_list)
                            for iface in new_iface_list:
                                if iface[0] != forward_iface:
                                    new_forward_iface = iface[0]
                                    find_iface = 1
                                    break
                            if not find_iface:
                                test.cancel("Can not find another physical interface to attach")
                    else:
                        new_forward_iface = forward_iface
                    flag_list.append(new_forward_iface)
                    newxml = section_xml.replace(forward_iface, new_forward_iface)
                elif net_section == "ip-dhcp-host":
                    if (update_sec is None and
                            update_command not in ['modify', 'delete']):
                        if ip_version == "ipv4":
                            update_sec = "ip,mac,name"
                        elif ip_version == "ipv6":
                            update_sec = "ip,id,name"
                    section_update(ip_version+"_host_", "new_dhcp_host_")
                elif net_section == "dns-txt":
                    section_update("dns_", "new_dns_")
                elif net_section == "dns-srv":
                    section_update("srv_", "new_srv_")
                elif net_section == "dns-host":
                    if without_sec == "hostname":
                        newxml = re.sub("<hostname>.*</hostname>\n", "", newxml)
                    flag_list.append("ip=.*?"+dns_hostip)
                    flag_list.append(dns_hostname)
                    flag_list.append(dns_hostname2)
                # for negative test may have net_section do not match issues
                elif status_error == "no":
                    test.fail("Unknown network section")
                logging.info("The new xml of %s is %s", net_section, newxml)

            with open(xmlfile, 'w') as xmlfile_d:
                xmlfile_d.write(newxml)

            if without_ip_dhcp == "yes":
                test_xml.del_element(element="/ip/dhcp")
                test_xml.del_element(element="/ip/dhcp")

            if without_dns == "yes":
                test_xml.del_element(element='/dns')
            if without_dns_host == "yes":
                test_xml.del_element(element='/dns/host')
            if without_dns_txt == "yes":
                test_xml.del_element(element='/dns/txt')
            if without_dns_srv == "yes":
                test_xml.del_element(element='/dns/srv')
            # Only do net define/start in first loop

            if (net_section == "ip-dhcp-range" and use_in_guest == "yes" and
                    without_ip_dhcp == "no"):
                test_xml.del_element(element="/ip/dhcp", index=section_index)

            if loop == 0:
                try:
                    # Define and start network
                    test_xml.debug_xml()
                    test_xml.define()
                    ori_net_xml = virsh.net_dumpxml(net_name).stdout.strip()
                    if "ipv6" in ori_net_xml:
                        host_ifaces = utils_net.get_net_if(state="UP")
                        backup_files.append(
                            remote.RemoteFile(address='127.0.0.1',
                                              client='scp',
                                              username=params.get('username'),
                                              password=params.get('password'),
                                              port='22',
                                              remote_path='/proc/sys/net/ipv6/'
                                                          'conf/all/accept_ra'))
                        process.run("echo 2 > /proc/sys/net/ipv6/conf/all/accept_ra",
                                    shell=True)
                        for host_iface in host_ifaces:
                            backup_files.append(
                                remote.RemoteFile(address='127.0.0.1',
                                                  client='scp',
                                                  username=params.get('username'),
                                                  password=params.get('password'),
                                                  port='22',
                                                  remote_path='/proc/sys/net/ipv6/'
                                                              'conf/%s/accept_ra'
                                                              % host_iface))
                            process.run("echo 2 > /proc/sys/net/ipv6/conf/%s/accept_ra"
                                        % host_iface, shell=True)
                            process.run("cat /proc/sys/net/ipv6/conf/%s/accept_ra"
                                        % host_iface)
                    if net_state == "active" or net_state == "transient":
                        test_xml.start()
                    if net_state == "transient":
                        test_xml.del_defined()
                    list_result = virsh.net_list("--all --name").stdout.strip()
                    if net_name not in list_result:
                        test.fail("Can not find %s in net-list" % net_name)
                except xcepts.LibvirtXMLError as detail:
                    test.error("Failed to define a test network.\n"
                               "Detail: %s." % detail)
            else:
                # setting net status for following loops
                if net_state == "active":
                    test_xml.set_active(True)
                elif net_state == "inactive":
                    test_xml.set_active(False)

            # get hostfile before update
            if without_ip_dhcp == "yes" and net_state == "active":
                hostfile_before = get_hostfile()
                if hostfile_before != []:
                    test.fail("hostfile is not empty before update: %s"
                              % hostfile_before)
                logging.info("hostfile is empty before update")

            # Get dnsmasq pid before update
            check_dnsmasq = ((update_command == "add" or update_command == "delete") and
                             net_section == "ip-dhcp-range" and status_error == "no" and
                             net_state == "active" and options != "--config")
            if check_dnsmasq:
                cmd = "ps aux|grep dnsmasq|grep -v grep|grep %s|awk '{print $2}'" % net_name
                pid_list_bef = results_stdout_52lts(process.run(cmd, shell=True)).strip().split('\n')

            if parent_index:
                options += " --parent-index %s" % parent_index

            # Check config before update
            if net_state == "active":
                dns_txt = dns_srv = dns_host_str = None
                try:
                    dns_txt = test_xml.get_section_string(xpath="/dns/txt")
                    dns_srv = test_xml.get_section_string(xpath="/dns/srv")
                    dns_host_str = test_xml.get_section_string(xpath="/dns/host")
                except xcepts.LibvirtXMLNotFoundError:
                    pass

                txt_record = "txt-record=%s,%s" % (dns_name, dns_value)
                srv_host = "srv-host=_%s._%s.%s,%s,%s,%s,%s" % (srv_service, srv_protocol,
                                                                srv_domain, srv_target, srv_port,
                                                                srv_priority, srv_weight)
                hostline = "%s.*%s.*%s" % (dns_hostip, dns_hostname, dns_hostname2)
                if dns_txt:
                    check_item(txt_record)
                if dns_srv:
                    check_item(srv_host)
                if dns_host_str:
                    check_host(hostline)

            # Do net-update operation
            cmd_result = virsh.net_update(net_name,
                                          update_command,
                                          net_section,
                                          xmlfile, options, debug=True)

            if cmd_result.exit_status:
                err = cmd_result.stderr.strip()
                if re.search("not supported", err):
                    test.cancel("Skip the test: %s" % err)
                elif status_error == "yes":
                    # index-mismatch error info and judgement
                    index_err1 = "the address family of a host entry IP must match the" + \
                                 " address family of the dhcp element's parent"
                    index_err2 = "XML error: Invalid to specify MAC address.* in network" + \
                                 ".* IPv6 static host definition"
                    index_err3 = "mismatch of address family in range.* for network"
                    mismatch_expect = (error_type == "index-mismatch" and
                                       (re.search(index_err1, err) or
                                        re.search(index_err2, err) or
                                        re.search(index_err3, err)))
                    err_dic = {}
                    # multi-host error info
                    err_dic["multi-hosts"] = "dhcp is supported only for a single.*" + \
                                             " address on each network"
                    # range-mismatch error info
                    err_dic["range-mismatch"] = "couldn't locate a matching dhcp " + \
                                                "range entry in network "
                    # host-mismatch error info
                    err_dic["host-mismatch"] = "couldn't locate a matching dhcp " + \
                                               "host entry in network "
                    # dns-mismatch error info
                    err_dic["dns-mismatch"] = "couldn't locate a matching DNS TXT " + \
                                              "record in network "
                    # range-duplicate error info
                    err_dic["range-duplicate"] = "there is an existing dhcp range" + \
                                                 " entry in network.* that matches"
                    # host-duplicate error info
                    err_dic["host-duplicate"] = "there is an existing dhcp host" + \
                                                " entry in network.* that matches"
                    # out_of_range error info
                    err_dic["out-of-range"] = "range.* is not entirely within network"
                    # no end for range error
                    err_dic["range-no-end"] = "Missing 'end' attribute in dhcp " + \
                                              "range for network"
                    # no match item for host modify err
                    err_dic["no-match-item"] = "couldn't locate an existing dhcp" + \
                                               " host entry with.* in network"
                    # no host name and mac for modify err
                    err_dic["host-no-name-mac"] = "Static host definition in IPv4 network" + \
                                                  ".* must have mac or name attribute"
                    # no host ip for modify err
                    err_dic["host-no-ip"] = "Missing IP address in static host " + \
                                            "definition for network"
                    # wrong command name
                    err_dic["wrong-command-name"] = "unrecognized command name"
                    # wrong section name
                    err_dic["wrong-section-name"] = "unrecognized section name"
                    # delete with only id
                    err_dic["only-id"] = "At least one of name, mac, or ip attribute must be" + \
                                         " specified for static host definition in network"
                    # options exclusive
                    err_dic["opt-exclusive"] = "Options --current and.* are mutually exclusive"
                    # range_reverse error info
                    if ip_version == "ipv4":
                        err_dic["range-reverse"] = "range.* is reversed"
                    elif ip_version == "ipv6":
                        err_dic["range-reverse"] = "range.*start larger than end"
                    # --live with inactive net
                    err_dic["invalid-state"] = "network is not running"
                    err_dic["transient"] = "cannot change persistent config of a transient network"
                    err_dic["dns-disable"] = "Extra data in disabled network"
                    err_dic["interface-duplicate"] = "there is an existing interface entry " + \
                                                     "in network.* that matches"

                    if (error_type in list(err_dic.keys()) and
                            re.search(err_dic[error_type], err) or mismatch_expect):
                        logging.info("Get expect error: %s", err)
                    else:
                        test.fail("Do not get expect err msg: %s, %s"
                                  % (error_type, err_dic))
                else:
                    test.fail("Failed to execute net-update command")
            elif status_error == "yes":
                test.fail("Expect fail, but succeed")

            # Get dnsmasq pid after update
            if check_dnsmasq:
                pid_list_aft = results_stdout_52lts(process.run(cmd, shell=True)).strip().split('\n')
                for pid in pid_list_aft:
                    if pid in pid_list_bef:
                        test.fail("dnsmasq do not updated")

            # Check the actual xml
            cmd_result = virsh.net_dumpxml(net_name)
            actual_net_xml = cmd_result.stdout.strip()
            new_xml_obj = network_xml.NetworkXML.new_from_net_dumpxml(net_name)
            logging.info("After net-update, the actual net xml is %s",
                         actual_net_xml)

            if "ip-dhcp" in net_section:
                if ip_version == "ipv6":
                    new_xml_obj.del_element(element="/ip", index=0)
                if ip_version == "ipv4":
                    new_xml_obj.del_element(element="/ip", index=1)

            config_not_work = ("--config" in options and net_state == "active" and
                               "--live" not in options)
            if config_not_work:
                if update_command != "delete":
                    flag_list_abs = flag_list
                    flag_list = []
                else:
                    flag_list = flag_list_abs
                    flag_list_abs = []

            logging.info("The check list is %s, absent list is %s", flag_list, flag_list_abs)

            if (update_command == "delete" and status_error == "no" and
                    not config_not_work and loop_time == 1):
                try:
                    section_str = new_xml_obj.get_section_string(xpath=element)
                except xcepts.LibvirtXMLNotFoundError:
                    section_str = None
                    logging.info("Can not find section %s in xml after delete", element)
                if section_str is not None:
                    test.fail("The actual net xml is not expected,"
                              "element still exists")
            elif ("duplicate" not in error_type and error_type != "range-mismatch" and
                    error_type != "host-mismatch"):
                # check xml should exists
                for flag_string in flag_list:
                    logging.info("checking %s should in xml in positive test,"
                                 "and absent in negative test", flag_string)
                    if not re.search(flag_string, actual_net_xml):
                        if ((status_error == "no" and update_command != "delete") or
                                (update_command == "delete" and status_error == "yes")):
                            test.fail("The actual net xml failed to update,"
                                      "or expect delete fail but xml missing"
                                      ":%s" % flag_string)
                    else:
                        if ((status_error == "yes" and update_command != "delete") or
                                (status_error == "no" and update_command == "delete" and
                                 not config_not_work)):
                            test.fail("Expect test fail, but find xml %s"
                                      " actual, or expect delete succeed,"
                                      "but fail in fact" % flag_string)
                # check xml should not exists
                for flag_string_abs in flag_list_abs:
                    logging.info("checking %s should NOT in xml in positive test,"
                                 "and exist in negative test", flag_string_abs)
                    if re.search(flag_string_abs, actual_net_xml):
                        if status_error == "no":
                            test.fail("Expect absent in net xml, but exists"
                                      "in fact: %s" % flag_string_abs)
                    else:
                        if status_error == "yes":
                            test.fail("Should exists in net xml, but it "
                                      "disappeared: %s" % flag_string_abs)

                # Check if add-last, add-fist works well
                if (status_error == "no" and not config_not_work and
                        update_command in ["add-last", "add", "add-first"]):
                    if update_command == "add-first":
                        find_index = 0
                    else:
                        find_index = -1
                    section_str_aft = new_xml_obj.get_section_string(xpath=element,
                                                                     index=find_index)
                    logging.info("xpath is %s, find_index is %s, section_str_aft is %s", element, find_index, section_str_aft)
                    for flag_string in flag_list:
                        logging.info("flag_string is %s", flag_string)
                        if not re.search(flag_string, section_str_aft):
                            test.fail("Can not find %s in %s" %
                                      (flag_string, section_str_aft))
                    logging.info("%s %s in right place", update_command, section_str_aft)

            # Check the positive test result
            if status_error == "no":
                # Check the network conf file
                # live update
                if ("--live" in options or "--config" not in options) and net_state == "active":
                    if net_section == "ip-dhcp-range" and update_command == "add-first":
                        ip_range = "%s,%s" % (new_start_ip, new_end_ip)
                        if ip_version == "ipv6":
                            ip_range = ip_range + ",64"
                        check_item(ip_range)
                    if "dns" in net_section:
                        if update_command == "delete" and loop == 0:
                            if net_section == "dns-srv":
                                check_item_absent(srv_host)
                            if net_section == "dns-txt":
                                check_item_absent(txt_record)
                            if net_section == "dns-host":
                                check_host_absent(dns_host_str)
                        elif "add" in update_command:
                            if net_section == "dns-srv":
                                for sec in update_sec.split(","):
                                    srv_host = srv_host.replace(names["srv_"+sec],
                                                                names["new_srv_"+sec])
                                check_item(srv_host)
                            if net_section == "dns-txt":
                                for sec in update_sec.split(","):
                                    txt_record = txt_record.replace(names["dns_"+sec],
                                                                    names["new_dns_"+sec])
                                check_item(txt_record)
                            if net_section == "dns-host":
                                check_host(hostline)

                    # Check the hostfile
                    if (net_section == "ip-dhcp-host" and update_command != "modify" and
                            update_command != "delete"):
                        dic_hostfile = {}
                        for sec in ["ip", "mac", "name", "id"]:
                            if update_sec is not None and sec in update_sec.split(","):
                                dic_hostfile[sec] = names["new_dhcp_host_"+sec]+","
                            else:
                                dic_hostfile[sec] = names[ip_version+"_host_"+sec]+","

                            if sec == "ip" and ip_version == "ipv6":
                                dic_hostfile[sec] = "[" + dic_hostfile[sec].strip(",") + "]"

                            if without_sec is not None and sec in without_sec.split(","):
                                dic_hostfile[sec] = ""

                        if ip_version == "ipv4":
                            host_info = (dic_hostfile["mac"] + dic_hostfile["ip"] +
                                         dic_hostfile["name"])
                            if dic_hostfile["mac"] == "":
                                host_info = dic_hostfile["name"] + dic_hostfile["ip"]
                        if ip_version == "ipv6":
                            host_info = ("id:" + dic_hostfile["id"] + dic_hostfile["name"] +
                                         dic_hostfile["ip"])

                        hostfile = get_hostfile()
                        host_info_patten = host_info.strip(",") + "\n"
                        if host_info_patten in hostfile:
                            logging.info("host info %s is in hostfile %s", host_info, hostfile)
                        else:
                            test.fail("Can not find %s in host file: %s"
                                      % (host_info, hostfile))

                # Check the net in guest
                if use_in_guest == "yes" and loop == 0:
                    # Detach all interfaces of vm first
                    iface_index = 0
                    mac_list = vm_xml.VMXML.get_iface_dev(vm_name)
                    for mac in mac_list:
                        iface_dict = vm_xml.VMXML.get_iface_by_mac(vm_name, mac)
                        virsh.detach_interface(vm_name,
                                               "--type %s --mac %s --config"
                                               % (iface_dict.get('type'), mac))
                        vm.free_mac_address(iface_index)
                        iface_index += 1

                    # attach new interface to guest
                    for j in range(guest_iface_num):
                        if net_section == "ip-dhcp-host" and new_dhcp_host_mac:
                            mac = new_dhcp_host_mac
                        else:
                            mac = utils_net.generate_mac_address_simple()
                        ret = virsh.attach_interface(vm_name,
                                                     "--type %s --source %s --mac %s --config"
                                                     % (iface_type, net_name, mac))
                        if ret.exit_status:
                            test.fail("Fail to attach new interface to guest: %s" %
                                      ret.stderr.strip())

                    # The sleep here is to make sure the update make effect
                    time.sleep(2)

                    # Start guest and check ip/mac/hostname...
                    vm.start()
                    logging.debug("vm xml is %s", vm.get_xml())
                    session = vm.wait_for_serial_login()
                    if "ip-dhcp" in net_section:
                        dhclient_cmd = "(if pgrep dhclient;" \
                                       "then pkill dhclient; sleep 3; fi) " \
                                       "&& dhclient -%s" % ip_version[-1]
                        session.cmd(dhclient_cmd)
                        iface_ip = utils_net.get_guest_ip_addr(session, mac,
                                                               ip_version=ip_version,
                                                               timeout=10)
                    if net_section == "ip-dhcp-range":
                        if new_start_ip <= iface_ip <= new_end_ip:
                            logging.info("getting ip %s is in range [%s ~ %s]",
                                         iface_ip, new_start_ip, new_end_ip)
                        else:
                            test.fail("getting ip %s not in range [%s ~ %s]" %
                                      (iface_ip, new_start_ip, new_end_ip))
                    if net_section == "ip-dhcp-host":
                        if iface_ip == new_dhcp_host_ip:
                            logging.info("getting ip is same with set: %s", iface_ip)
                        else:
                            test.fail("getting ip %s is not same with setting %s"
                                      % (iface_ip, new_dhcp_host_ip))
                        hostname = session.cmd_output("hostname").strip('\n')
                        if hostname == new_dhcp_host_name.split('.')[0]:
                            logging.info("getting hostname same with setting: %s", hostname)
                        else:
                            test.fail("getting hostname %s is not same with "
                                      "setting: %s" % (hostname, new_dhcp_host_name))

                    session.close()

                # Check network connection for macvtap
                if (use_in_guest == "yes" and net_section == "forward-interface" and
                        forward_mode == "bridge"):
                    xml_obj_use = network_xml.NetworkXML.new_from_net_dumpxml(net_name)
                    net_conn = int(xml_obj_use.connection)
                    iface_conn = xml_obj_use.get_interface_connection()
                    conn_count = 0
                    for k in iface_conn:
                        conn_count = conn_count + int(k)
                    logging.info("net_conn=%s, conn_count=%s, guest_iface_num=%s"
                                 % (net_conn, conn_count, guest_iface_num))
                    if (net_conn != conn_count or
                            (loop == 1 and guest_iface_num != net_conn)):
                        test.fail("Can not get expected connection num: "
                                  "net_conn = %s, iface_conn = %s"
                                  % (net_conn, conn_count))

                #Check --config option after net destroyed
                if (int(check_config_round) == loop or
                        (loop_time == 1 and "--current" in options and net_state == "active")):
                    test_xml.set_active(False)
                    logging.info("Checking xml after net destroyed")
                    cmd_result = virsh.net_dumpxml(net_name)
                    inactive_xml = cmd_result.stdout.strip()
                    logging.info("inactive_xml is %s", inactive_xml)
                    #Check the inactive xml
                    for check_str in flag_list:
                        if update_command != "delete":
                            if "--config" in options:
                                if not re.search(check_str, inactive_xml):
                                    test.fail("Can not find xml after net destroyed")
                            if "--current" in options:
                                if re.search(check_str, inactive_xml):
                                    test.fail("XML still exists after net destroyed")
                        else:
                            if "--config" in options:
                                if re.search(check_str, inactive_xml):
                                    test.fail("XML still exists after net destroyed")
                            if "--current" in options:
                                if not re.search(check_str, inactive_xml):
                                    test.fail("Can not find xml after net destroyed")

                    logging.info("Check for net inactive PASS")

    finally:
        if test_xml.get_active():
            test_xml.del_active()
        if test_xml.get_defined():
            test_xml.del_defined()

        if os.path.exists(xmlfile):
            os.remove(xmlfile)

        if use_in_guest == "yes":
            vm = env.get_vm(vm_name)
            if vm.is_alive():
                vm.destroy(gracefully=False)
            vmxml_backup.sync()
        for config_file in backup_files:
            config_file._reset_file()
Ejemplo n.º 24
0
def run(test, params, env):
    """
    Test 802.1Q vlan of NIC among guests and host.

    1) Configure vlan interface over host bridge interface.
    2) Create two VMs over vlan interface.
    3) Load 8021q module in guest.
    4) Configure ip address of guest with 192.168.*.*
    5) Test by ping between guest and host, should fail.
    6) Test by ping beween guests, should pass.
    7) Setup vlan in guests and using hard-coded ip address 192.168.*.*
    8) Test by ping between guest and host, should pass.
    9) Test by ping among guests, should pass.
    10) Test by netperf between guests and host.
    11) Test by netperf between guests.
    12) Delete vlan interface in host.

    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
    """

    def add_vlan(interface, v_id, session=None):
        """
        Create a vlan-device on interface.
        :params interface: Interface.
        :params v_id: Vlan id.
        :params session: VM session or none.
        """
        vlan_if = '%s.%s' % (interface, v_id)
        add_cmd = "ip link add link %s name %s type " % (interface, vlan_if)
        add_cmd += "vlan id %s" % v_id
        error_context.context("Create vlan interface '%s' on %s" % (vlan_if,
                                                                    interface),
                              logging.info)
        if session:
            session.cmd(add_cmd)
        else:
            process.system(add_cmd)
        return vlan_if

    def set_ip_vlan(vlan_if, vlan_ip, session=None):
        """
        Set ip address of vlan interface.
        :params vlan_if: Vlan interface.
        :params vlan_ip: Vlan internal ip.
        :params session: VM session or none.
        """
        error_context.context("Assign IP '%s' to vlan interface '%s'" %
                              (vlan_ip, vlan_if), logging.info)
        if session:
            session.cmd("ifconfig %s 0.0.0.0" % vlan_if)
            session.cmd("ifconfig %s down" % vlan_if)
            session.cmd("ifconfig %s %s up" % (vlan_if, vlan_ip))
        else:
            process.system("ifconfig %s %s up" % (vlan_if, vlan_ip))

    def set_mac_vlan(vlan_if, mac_str, session):
        """
        Give a new mac address for vlan interface in guest.
        :params: vlan_if: Vlan interface.
        :params: mac_str: New mac address for vlan.
        :params: session: VM session.
        """
        mac_cmd = "ip link set %s add %s up" % (vlan_if, mac_str)
        error_context.context("Give a new mac address '%s' for vlan interface "
                              "'%s'" % (mac_str, vlan_if), logging.info)
        session.cmd(mac_cmd)

    def set_arp_ignore(session):
        """
        Enable arp_ignore for all ipv4 device in guest
        """
        error_context.context("Enable arp_ignore for all ipv4 device in guest",
                              logging.info)
        ignore_cmd = "echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore"
        session.cmd(ignore_cmd)

    def ping_vlan(vm, dest, vlan_if, session):
        """
        Test ping between vlans, from guest to host/guest.
        :params vm: VM object
        :params dest: Dest ip to ping.
        :params vlan_if: Vlan interface.
        :params session: VM session.
        """
        error_context.context("Test ping from '%s' to '%s' on guest '%s'" %
                              (vlan_if, dest, vm.name))
        status, output = utils_test.ping(dest=dest, count=10,
                                         interface=vlan_if,
                                         session=session,
                                         timeout=30)
        if status:
            raise NetPingError(vlan_if, dest, output)

    def netperf_vlan(client='main_vm', server='localhost',
                     sub_type='netperf_stress'):
        """
        Test netperf stress among guests and host.
        :params client: Netperf client.
        :params server: Netperf server.
        :params sub_type: Sub_type to run.
        """
        params["netperf_client"] = client
        params["netperf_server"] = server
        error_context.context("Run netperf stress test among guests and host, "
                              "server: %s, client: %s" % (server, client),
                              logging.info)
        utils_test.run_virt_sub_test(test, params, env, sub_type)

    vms = []
    sessions = []
    ifname = []
    vm_ip = []
    vm_vlan_ip = []
    vm_vlan_if = []
    sub_type = params["sub_type"]
    host_br = params.get("host_br", "switch")
    host_vlan_id = params.get("host_vlan_id", "10")
    host_vlan_ip = params.get("host_vlan_ip", "192.168.10.10")
    subnet = params.get("subnet", "192.168")
    mac_str = params.get("mac_str").split(',')
    os_type = params.get("os_type", "linux")

    linux_modules.load_module("8021q")

    host_vlan_if = "%s.%s" % (host_br, host_vlan_id)
    if host_vlan_if not in utils_net.get_net_if():
        host_vlan_if = add_vlan(interface=host_br, v_id=host_vlan_id)
        if host_vlan_if in utils_net.get_net_if():
            set_ip_vlan(vlan_if=host_vlan_if, vlan_ip=host_vlan_ip)
            rm_host_vlan_cmd = params["rm_host_vlan_cmd"] % host_vlan_if
            funcatexit.register(env, params["type"], _system,
                                rm_host_vlan_cmd)
        else:
            test.cancel("Fail to set up vlan over bridge interface in host!")

    if params.get("start_vm", "yes") == "no":
        vm_main = env.get_vm(params["main_vm"])
        vm_main.create(params=params)
        vm2 = env.get_vm("vm2")
        vm2.create(params=params)
        vms.append(vm_main)
        vms.append(vm2)
    else:
        vms.append(env.get_vm([params["main_vm"]]))
        vms.append(env.get_vm('vm2'))

    for vm_ in vms:
        vm_.verify_alive()

    for vm_index, vm in enumerate(vms):
        error_context.context("Prepare test env on %s" % vm.name)
        session = vm.wait_for_serial_login()
        if not session:
            err_msg = "Could not log into guest %s" % vm.name
            test.error(err_msg)

        if os_type == "linux":
            interface = utils_net.get_linux_ifname(session,
                                                   vm.get_mac_address())

            error_context.context("Load 8021q module in guest %s" % vm.name,
                                  logging.info)
            session.cmd_output_safe("modprobe 8021q")

            error_context.context("Setup vlan environment in guest %s" % vm.name,
                                  logging.info)
            inter_ip = "%s.%s.%d" % (subnet, host_vlan_id, vm_index + 1)
            set_ip_vlan(interface, inter_ip, session=session)
            set_arp_ignore(session)
            error_context.context("Test ping from guest '%s' to host with "
                                  "interface '%s'" %
                                  (vm.name, interface), logging.info)
            try:
                ping_vlan(vm, dest=host_vlan_ip, vlan_if=interface,
                          session=session)
            except NetPingError:
                logging.info("Guest ping fail to host as expected with "
                             "interface '%s'" % interface)
            else:
                test.fail("Guest ping to host should fail with interface"
                          " '%s'" % interface)
            ifname.append(interface)
            vm_ip.append(inter_ip)
            sessions.append(session)

    # Ping succeed between guests
    error_context.context("Test ping between guests with interface %s"
                          % ifname[0], logging.info)
    ping_vlan(vms[0], dest=vm_ip[1], vlan_if=ifname[0], session=sessions[0])

    # set vlan tag for guest
    for vm_index, vm in enumerate(vms):
        session = sessions[vm_index]
        error_context.context("Add vlan interface on guest '%s'" % vm.name)
        session.cmd("ifconfig %s 0.0.0.0" % ifname[vm_index])
        vlan_if = add_vlan(interface=ifname[vm_index], v_id=host_vlan_id,
                           session=session)
        vm_vlan_if.append(vlan_if)
        set_mac_vlan(vlan_if, mac_str[vm_index], session=session)
        vlan_ip = "%s.%s.%d" % (subnet, host_vlan_id, vm_index + 11)
        set_ip_vlan(vlan_if, vlan_ip, session=session)
        vm_vlan_ip.append(vlan_ip)

        error_context.context("Test ping from interface '%s' on guest "
                              "'%s' to host." %
                              (vm_vlan_if[vm_index], vm.name), logging.info)
        ping_vlan(vm, dest=host_vlan_ip, vlan_if=vm_vlan_if[vm_index],
                  session=session)
        netperf_vlan(client=vm.name, server="localhost")

    error_context.context("Test ping and netperf between guests with "
                          "interface '%s'" %
                          vm_vlan_if[vm_index], logging.info)
    ping_vlan(vms[0], dest=vm_vlan_ip[1], vlan_if=vm_vlan_if[0],
              session=sessions[0])
    netperf_vlan(client=params["main_vm"], server='vm2')

    exithandlers = "exithandlers__%s" % sub_type
    sub_exit_timeout = int(params.get("sub_exit_timeout", 10))
    start_time = time.time()
    end_time = start_time + float(sub_exit_timeout)

    while time.time() < end_time:
        logging.debug("%s (%f secs)", sub_type + " is running",
                      (time.time() - start_time))
        if env.data.get(exithandlers):
            break
        time.sleep(1)

    for sess in sessions:
        if sess:
            sess.close()
Ejemplo n.º 25
0
    def modify_iface_xml(sync=True):
        """
        Modify interface xml options

        :param sync: whether or not sync vmxml after the iface xml modified,
                    default to be True
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        if pxe_boot:
            # Config boot console for pxe boot
            osxml = vm_xml.VMOSXML()
            osxml.type = vmxml.os.type
            osxml.arch = vmxml.os.arch
            osxml.machine = vmxml.os.machine
            osxml.loader = "/usr/share/seabios/bios.bin"
            osxml.bios_useserial = "yes"
            if utils_misc.compare_qemu_version(4, 0, 0, False):
                osxml.bios_reboot_timeout = "-1"
            osxml.boots = ['network']
            del vmxml.os
            vmxml.os = osxml

        xml_devices = vmxml.devices
        iface_index = xml_devices.index(
            xml_devices.by_device_tag("interface")[0])
        iface = xml_devices[iface_index]
        if not sync:
            params.setdefault('original_iface', vmxml.devices[iface_index])
        iface_bandwidth = {}
        iface_inbound = ast.literal_eval(iface_bandwidth_inbound)
        iface_outbound = ast.literal_eval(iface_bandwidth_outbound)
        if iface_inbound:
            iface_bandwidth["inbound"] = iface_inbound
        if iface_outbound:
            iface_bandwidth["outbound"] = iface_outbound
        if iface_bandwidth:
            bandwidth = iface.new_bandwidth(**iface_bandwidth)
            iface.bandwidth = bandwidth

        iface_type = params.get("iface_type", "network")
        iface.type_name = iface_type
        source = ast.literal_eval(iface_source)
        if not source:
            source = {"network": "default"}
        net_ifs = utils_net.get_net_if(state="UP")
        # Check source device is valid or not,
        # if it's not in host interface list, try to set
        # source device to first active interface of host
        if (iface.type_name == "direct" and
                'dev' in source and
                source['dev'] not in net_ifs):
            logging.warning("Source device %s is not a interface of host, reset to %s",
                            source['dev'], net_ifs[0])
            source['dev'] = net_ifs[0]
        del iface.source
        iface.source = source
        if iface_model:
            iface.model = get_iface_model(iface_model, host_arch)
        if iface_rom:
            iface.rom = eval(iface_rom)
        if iface_boot:
            vmxml.remove_all_boots()
            iface.boot = iface_boot
        logging.debug("New interface xml file: %s", iface)
        if sync:
            vmxml.devices = xml_devices
            vmxml.xmltreefile.write()
            vmxml.sync()
        else:
            return iface
Ejemplo n.º 26
0
def run(test, params, env):

    global flag_list, flag_list_abs, update_sec, without_sec
    global check_sec, check_without_sec, newxml

    # Basic network params
    net_name = params.get("net_update_net_name", "updatenet")
    net_section = params.get("network_section")
    update_command = params.get("update_command", "add-last")
    options = params.get("cmd_options", "")
    net_state = params.get("net_state")
    use_in_guest = params.get("use_in_guest")
    iface_type = params.get("iface_type", "network")
    ip_version = params.get("ip_version", "ipv4")
    new_start_ip = params.get("start_ip")
    new_end_ip = params.get("end_ip")
    parent_index = params.get("parent_index")
    status_error = params.get("status_error", "no")

    # dhcp host test
    new_dhcp_host_ip = params.get("new_dhcp_host_ip")
    new_dhcp_host_id = params.get("new_dhcp_host_id")
    new_dhcp_host_name = params.get("new_dhcp_host_name")
    new_dhcp_host_mac = params.get("new_dhcp_host_mac")

    # ipv4 range/host test
    ipv4_range_start = params.get("ori_ipv4_range_start")
    ipv4_range_end = params.get("ori_ipv4_range_end")
    ipv4_host_mac = params.get("ori_ipv4_host_mac")
    ipv4_host_ip = params.get("ori_ipv4_host_ip")
    ipv4_host_name = params.get("ori_ipv4_host_name")

    # ipv6 range/host test
    ipv6_range_start = params.get("ori_ipv6_range_start")
    ipv6_range_end = params.get("ori_ipv6_range_end")
    ipv6_host_id = params.get("ori_ipv6_host_id")
    ipv6_host_name = params.get("ori_ipv6_host_name")
    ipv6_host_ip = params.get("ori_ipv6_host_ip")

    # dns test
    dns_name = params.get("ori_dns_name")
    dns_value = params.get("ori_dns_value")
    new_dns_name = params.get("new_dns_name")
    new_dns_value = params.get("new_dns_value")

    # srv test
    srv_service = params.get("ori_srv_service")
    srv_protocol = params.get("ori_srv_protocol")
    srv_domain = params.get("ori_srv_domain")
    srv_target = params.get("ori_srv_target")
    srv_port = params.get("ori_srv_port")
    srv_priority = params.get("ori_srv_priority")
    srv_weight = params.get("ori_srv_weight")
    new_srv_service = params.get("new_srv_service")
    new_srv_protocol = params.get("new_srv_protocol")
    new_srv_domain = params.get("new_srv_domain")
    new_srv_target = params.get("new_srv_target")
    new_srv_port = params.get("new_srv_port")
    new_srv_priority = params.get("new_srv_priority")
    new_srv_weight = params.get("new_srv_weight")

    # dns host test
    dns_hostip = params.get("ori_dns_hostip")
    dns_hostname = params.get("ori_dns_hostname")
    dns_hostname2 = params.get("ori_dns_hostname2")

    # setting for without part
    without_ip_dhcp = params.get("without_ip_dhcp", "no")
    without_dns = params.get("without_dns", "no")
    without_dns_host = params.get("without_dns_host", "no")
    without_dns_txt = params.get("without_dns_txt", "no")
    without_dns_srv = params.get("without_dns_srv", "no")
    without_dns_forwarder = params.get("without_dns_forwarder", "no")

    # setting for update/check/without section
    update_sec = params.get("update_sec")
    check_sec = params.get("check_sec")
    without_sec = params.get("without_sec")
    check_without_sec = params.get("check_without_sec")

    # forward test
    forward_mode = params.get("forward_mode")
    forward_iface = params.get("forward_iface", "eth2")

    # other params
    error_type = params.get("error_type", "")
    vm_name = params.get("main_vm")
    loop_time = int(params.get("loop_time", 1))
    check_config_round = params.get("check_config_round", -1)
    ipv4_host_id = ipv6_host_mac = ""
    dns_enable = params.get("dns_enable", "yes")
    guest_iface_num = int(params.get("guest_iface_num", 1))
    newxml = ""

    def get_hostfile():
        """
        Get the content of hostfile
        """
        logging.info("Checking network hostfile...")
        hostfile = "/var/lib/libvirt/dnsmasq/%s.hostsfile" % net_name
        with open(hostfile) as hostfile_d:
            hostfile = hostfile_d.readlines()
        return hostfile

    def find_config(check_file, need_find):
        """
        Find configure in check_file

        :param check_file: The file that will check
        :param need_find: If need to find the item in check_file, Boolean
        """
        def _find_config(check_func):
            def __find_config(*args, **kwargs):
                logging.info("Checking content of %s", check_file)
                ret = False
                item = None
                with open(check_file) as checkfile_d:
                    while True:
                        check_line = checkfile_d.readline()
                        if not check_line:
                            break
                        (ret, item) = check_func(check_line, *args, **kwargs)
                        if ret:
                            break
                if not ret:
                    if need_find:
                        test.fail("Fail to find %s in %s" % (item, check_file))
                    else:
                        logging.info("Can not find %s in %s as expected" %
                                     (item, check_file))

            return __find_config

        return _find_config

    conf_file = "/var/lib/libvirt/dnsmasq/%s.conf" % net_name

    @find_config(conf_file, True)
    def check_item(check_line, item):
        """
        Check if the item in config file
        """
        if item in check_line:
            logging.info("Find %s in %s", item, conf_file)
            return (True, item)
        else:
            return (False, item)

    host_file = "/var/lib/libvirt/dnsmasq/%s.addnhosts" % net_name

    @find_config(host_file, True)
    def check_host(check_line, item):
        """
        Check if the item in host_file
        """
        if re.search(item, check_line):
            logging.info("Find %s in %s", item, host_file)
            return (True, item)
        else:
            return (False, item)

    @find_config(conf_file, False)
    def check_item_absent(check_line, item):
        """
        Check if the item not in config file
        """
        if item in check_line:
            test.fail("Find %s in %s" % (item, conf_file))
        else:
            return (False, item)

    @find_config(host_file, False)
    def check_host_absent(check_line, item):
        """
        Check if the item not in host_file
        """
        if re.search(item, check_line):
            test.fail("Find %s in %s" % (item, host_file))
        else:
            return (False, item)

    def section_update(ori_pre, new_pre):
        """
        Deal with update section and without section in func

        :param ori_pre: prefix of original section parameter name
        :param new_pre: prefix of new section parameter name
        """
        global flag_list, flag_list_abs, update_sec, without_sec
        global check_sec, check_without_sec, newxml

        if update_sec:
            for sec in update_sec.split(","):
                newxml = newxml.replace(names[ori_pre + sec],
                                        names[new_pre + sec])
            if update_command != "delete":
                check_sec = update_sec
        if without_sec:
            for sec_no in without_sec.split(","):
                newxml = re.sub(sec_no + "=\".*?\"", "", newxml)
            if update_command == "modify":
                check_without_sec = without_sec
        if check_sec:
            for c_sec in check_sec.split(","):
                flag_list.append(names[new_pre + c_sec])
        if check_without_sec:
            for c_sec_no in check_without_sec.split(","):
                flag_list_abs.append(names[ori_pre + c_sec_no])

    dns_host_xml = """
<host ip='%s'>
 <hostname>%s</hostname>
 <hostname>%s</hostname>
</host>
""" % (dns_hostip, dns_hostname, dns_hostname2)

    virtual_net = """
<network>
  <name>%s</name>
  <forward mode='nat'/>
  <bridge name='%s' stp='on' delay='0' />
  <mac address='52:54:00:03:78:6c'/>
  <domain name="example.com" localOnly="no"/>
  <mtu size="9000"/>
  <dns enable='%s'>
     <forwarder domain='example.com' addr="8.8.4.4"/>
      <txt name='%s' value='%s'/>
      <srv service='%s' protocol='%s' domain='%s' target='%s' port='%s' priority='%s' weight='%s'/>
      %s
  </dns>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='%s' end='%s' />
      <host mac='%s' ip='%s' name='%s' />
    </dhcp>
  </ip>
  <ip family='ipv6' address='2001:db8:ca2:2::1' prefix='64'>
    <dhcp>
      <range start='%s' end='%s'/>
      <host id='%s' name='%s' ip='%s'/>
    </dhcp>
  </ip>
  <route family='ipv6' address='2001:db8:ca2:2::' prefix='64' gateway='2001:db8:ca2:2::4'/>
  <ip address='192.168.101.1' netmask='255.255.255.0'/>
  <ip family='ipv6' address='2001:db8:ca2:3::1' prefix='64' />
</network>
""" % (net_name, net_name, dns_enable, dns_name, dns_value, srv_service,
       srv_protocol, srv_domain, srv_target, srv_port, srv_priority,
       srv_weight, dns_host_xml, ipv4_range_start, ipv4_range_end,
       ipv4_host_mac, ipv4_host_ip, ipv4_host_name, ipv6_range_start,
       ipv6_range_end, ipv6_host_id, ipv6_host_name, ipv6_host_ip)

    port_group = """
<portgroup name='engineering' default='no'>
  <virtualport type='802.1Qbh'>
    <parameters profileid='test'/>
  </virtualport>
  <bandwidth>
    <inbound average='1000' peak='5000' burst='5120'/>
    <outbound average='1000' peak='5000' burst='5120'/>
  </bandwidth>
</portgroup>
"""

    if use_in_guest == "yes":
        vm = env.get_vm(vm_name)
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        vmxml_backup = vmxml.copy()

    backup_files = []
    try:
        for loop in range(loop_time):
            if loop_time > 1:
                logging.info("Round %s:", loop + 1)
                update_command = params.get("update_command").split(",")[loop]
                if net_section == "ip-dhcp-host":
                    new_dhcp_host_ip = params.get("new_dhcp_host_ip").split(
                        ",")[loop]
                    new_dhcp_host_name = params.get(
                        "new_dhcp_host_name").split(",")[loop]
                    new_dhcp_host_mac = params.get("new_dhcp_host_mac").split(
                        ",")[loop]
                    status_error = params.get("status_error").split(",")[loop]
                elif net_section == "dns-txt":
                    net_state = params.get("net_state").split(",")[loop]

            # Get a tmp_dir.
            tmp_dir = data_dir.get_tmp_dir()

            # Write new xml into a tempfile
            tmp_file = tempfile.NamedTemporaryFile(prefix=("new_xml_"),
                                                   dir=tmp_dir)
            xmlfile = tmp_file.name
            tmp_file.close()

            # Generate testxml
            test_xml = network_xml.NetworkXML(network_name=net_name)
            test_xml.xml = virtual_net

            names = locals()

            if net_section == "portgroup":
                portgroup_xml = network_xml.PortgroupXML()
                portgroup_xml.xml = port_group
                test_xml.portgroup = portgroup_xml
            elif net_section == "forward-interface":
                if forward_mode == "bridge":
                    forward_iface = utils_net.get_net_if(state="UP")[0]
                test_xml.forward = {'mode': forward_mode}
                test_xml.forward_interface = [{'dev': forward_iface}]
                del test_xml.bridge
                del test_xml.mac
                for ip_num in range(4):
                    del test_xml.ip
                del test_xml.routes
                del test_xml.dns
                del test_xml.mtu
                del test_xml.domain_name

            section_index = 0
            if ip_version == "ipv6":
                section_index = 1
            element = "/%s" % net_section.replace('-', '/')
            try:
                section_xml = test_xml.get_section_string(xpath=element,
                                                          index=section_index)
            except xcepts.LibvirtXMLNotFoundError:
                newxml = section_xml = test_xml.get_section_string(
                    xpath="/ip/dhcp/range")

            newxml = section_xml
            logging.debug("section xml is %s", newxml)

            flag_list = []
            flag_list_abs = []

            if (update_command == "delete"
                    and error_type not in ["host-mismatch", "range-mismatch"]
                    and not without_sec and not update_sec):
                logging.info("The delete xml is %s", newxml)
            else:
                if net_section == "bridge":
                    new_bridge_name = net_name + "_new"
                    flag_list.append(new_bridge_name)
                    newxml = section_xml.replace(net_name, new_bridge_name)
                    logging.info("The new bridge xml is %s", newxml)
                elif net_section == "forward":
                    new_mode = "route"
                    flag_list.append(new_mode)
                    newxml = section_xml.replace("nat", new_mode)
                    logging.info("The new forward xml is %s", newxml)
                elif net_section == "ip":
                    new_netmask = "255.255.0.0"
                    flag_list.append(new_netmask)
                    newxml = section_xml.replace("255.255.255.0", new_netmask)
                elif net_section == "ip-dhcp-range":
                    newxml = section_xml.replace(
                        names[ip_version + "_range_start"], new_start_ip)
                    newxml = newxml.replace(names[ip_version + "_range_end"],
                                            new_end_ip)
                    for location in ["end", "start"]:
                        if names["new_" + location + "_ip"] == "":
                            newxml = newxml.replace(location + "=\"\"", "")
                        else:
                            flag_list.append(names["new_" + location + "_ip"])
                elif net_section == "portgroup":
                    new_inbound_average = "2000"
                    flag_list.append(new_inbound_average)
                    newxml = section_xml.replace("1000", new_inbound_average)
                    newxml = newxml.replace("default=\"no\"",
                                            "default=\"yes\"")
                    flag_list.append("default=('|\")yes")
                    if update_command in ['add-first', 'add-last', 'add']:
                        newxml = newxml.replace("engineering", "sales")
                        flag_list.append("sales")
                elif net_section == "forward-interface":
                    new_forward_iface = params.get("new_forward_iface")
                    if error_type != "interface-duplicate":
                        find_iface = 0
                        if not new_forward_iface and forward_mode == "bridge":
                            new_iface_list = utils_net.get_net_if(
                                qdisc="(mq|pfifo_fast)",
                                state="(UP|DOWN)",
                                optional="MULTICAST,UP")
                            logging.info("new_iface_list is %s",
                                         new_iface_list)
                            for iface in new_iface_list:
                                if iface[0] != forward_iface:
                                    new_forward_iface = iface[0]
                                    find_iface = 1
                                    break
                            if not find_iface:
                                test.cancel(
                                    "Can not find another physical interface to attach"
                                )
                    else:
                        new_forward_iface = forward_iface
                    flag_list.append(new_forward_iface)
                    newxml = section_xml.replace(forward_iface,
                                                 new_forward_iface)
                elif net_section == "ip-dhcp-host":
                    if (update_sec is None
                            and update_command not in ['modify', 'delete']):
                        if ip_version == "ipv4":
                            update_sec = "ip,mac,name"
                        elif ip_version == "ipv6":
                            update_sec = "ip,id,name"
                    section_update(ip_version + "_host_", "new_dhcp_host_")
                elif net_section == "dns-txt":
                    section_update("dns_", "new_dns_")
                elif net_section == "dns-srv":
                    section_update("srv_", "new_srv_")
                elif net_section == "dns-host":
                    if without_sec == "hostname":
                        newxml = re.sub("<hostname>.*</hostname>\n", "",
                                        newxml)
                    if status_error == 'no':
                        flag_list.append("ip=.*?" + dns_hostip)
                        flag_list.append(dns_hostname)
                        flag_list.append(dns_hostname2)
                # for negative test may have net_section do not match issues
                elif status_error == "no":
                    test.fail("Unknown network section")
                logging.info("The new xml of %s is %s", net_section, newxml)

            with open(xmlfile, 'w') as xmlfile_d:
                xmlfile_d.write(newxml)

            if without_ip_dhcp == "yes":
                test_xml.del_element(element="/ip/dhcp")
                test_xml.del_element(element="/ip/dhcp")

            if without_dns == "yes":
                test_xml.del_element(element='/dns')
            if without_dns_host == "yes":
                test_xml.del_element(element='/dns/host')
            if without_dns_txt == "yes":
                test_xml.del_element(element='/dns/txt')
            if without_dns_srv == "yes":
                test_xml.del_element(element='/dns/srv')
            if without_dns_forwarder == "yes":
                test_xml.del_element(element='/dns/forwarder')
            # Only do net define/start in first loop

            if (net_section == "ip-dhcp-range" and use_in_guest == "yes"
                    and without_ip_dhcp == "no"):
                test_xml.del_element(element="/ip/dhcp", index=section_index)

            if loop == 0:
                try:
                    # Define and start network
                    test_xml.debug_xml()
                    test_xml.define()
                    ori_net_xml = virsh.net_dumpxml(net_name).stdout.strip()
                    if "ipv6" in ori_net_xml:
                        host_ifaces = utils_net.get_net_if(state="UP")
                        backup_files.append(
                            remote.RemoteFile(address='127.0.0.1',
                                              client='scp',
                                              username=params.get('username'),
                                              password=params.get('password'),
                                              port='22',
                                              remote_path='/proc/sys/net/ipv6/'
                                              'conf/all/accept_ra'))
                        process.run(
                            "echo 2 > /proc/sys/net/ipv6/conf/all/accept_ra",
                            shell=True)
                        for host_iface in host_ifaces:
                            backup_files.append(
                                remote.RemoteFile(
                                    address='127.0.0.1',
                                    client='scp',
                                    username=params.get('username'),
                                    password=params.get('password'),
                                    port='22',
                                    remote_path='/proc/sys/net/ipv6/'
                                    'conf/%s/accept_ra' % host_iface))
                            process.run(
                                "echo 2 > /proc/sys/net/ipv6/conf/%s/accept_ra"
                                % host_iface,
                                shell=True)
                            process.run(
                                "cat /proc/sys/net/ipv6/conf/%s/accept_ra" %
                                host_iface)
                    if net_state == "active" or net_state == "transient":
                        test_xml.start()
                    if net_state == "transient":
                        test_xml.del_defined()
                    list_result = virsh.net_list("--all --name").stdout.strip()
                    if net_name not in list_result:
                        test.fail("Can not find %s in net-list" % net_name)
                except xcepts.LibvirtXMLError as detail:
                    test.error("Failed to define a test network.\n"
                               "Detail: %s." % detail)
            else:
                # setting net status for following loops
                if net_state == "active":
                    test_xml.set_active(True)
                elif net_state == "inactive":
                    test_xml.set_active(False)

            # get hostfile before update
            if without_ip_dhcp == "yes" and net_state == "active":
                hostfile_before = get_hostfile()
                if hostfile_before != []:
                    test.fail("hostfile is not empty before update: %s" %
                              hostfile_before)
                logging.info("hostfile is empty before update")

            # Get dnsmasq pid before update
            check_dnsmasq = ((update_command == "add"
                              or update_command == "delete")
                             and net_section == "ip-dhcp-range"
                             and status_error == "no" and net_state == "active"
                             and options != "--config")
            if check_dnsmasq:
                cmd = "ps aux|grep dnsmasq|grep -v grep|grep %s|awk '{print $2}'" % net_name
                pid_list_bef = results_stdout_52lts(
                    process.run(cmd, shell=True)).strip().split('\n')

            if parent_index:
                options += " --parent-index %s" % parent_index

            # Check config before update
            if net_state == "active":
                dns_txt = dns_srv = dns_host_str = None
                try:
                    dns_txt = test_xml.get_section_string(xpath="/dns/txt")
                    dns_srv = test_xml.get_section_string(xpath="/dns/srv")
                    dns_host_str = test_xml.get_section_string(
                        xpath="/dns/host")
                except xcepts.LibvirtXMLNotFoundError:
                    pass

                txt_record = "txt-record=%s,%s" % (dns_name, dns_value)
                srv_host = "srv-host=_%s._%s.%s,%s,%s,%s,%s" % (
                    srv_service, srv_protocol, srv_domain, srv_target,
                    srv_port, srv_priority, srv_weight)
                hostline = "%s.*%s.*%s" % (dns_hostip, dns_hostname,
                                           dns_hostname2)
                if dns_txt:
                    check_item(txt_record)
                if dns_srv:
                    check_item(srv_host)
                if dns_host_str:
                    check_host(hostline)

            # Do net-update operation
            cmd_result = virsh.net_update(net_name,
                                          update_command,
                                          net_section,
                                          xmlfile,
                                          options,
                                          debug=True)

            if cmd_result.exit_status:
                err = cmd_result.stderr.strip()
                if status_error == "yes":
                    # index-mismatch error info and judgement
                    index_err1 = "the address family of a host entry IP must match the" + \
                                 " address family of the dhcp element's parent"
                    index_err2 = "XML error: Invalid to specify MAC address.* in network" + \
                                 ".* IPv6 static host definition"
                    index_err3 = "mismatch of address family in range.* for network"
                    mismatch_expect = (error_type == "index-mismatch"
                                       and (re.search(index_err1, err)
                                            or re.search(index_err2, err)
                                            or re.search(index_err3, err)))
                    err_dic = {}
                    # multi-host error info
                    err_dic["multi-hosts"] = "dhcp is supported only for a single.*" + \
                                             " address on each network"
                    # range-mismatch error info
                    err_dic["range-mismatch"] = "couldn't locate a matching dhcp " + \
                                                "range entry in network "
                    # host-mismatch error info
                    err_dic["host-mismatch"] = "couldn't locate a matching dhcp " + \
                                               "host entry in network "
                    # dns-mismatch error info
                    err_dic["dns-mismatch"] = "couldn't locate a matching DNS TXT " + \
                                              "record in network "
                    # range-duplicate error info
                    err_dic["range-duplicate"] = "there is an existing dhcp range" + \
                                                 " entry in network.* that matches"
                    # host-duplicate error info
                    err_dic["host-duplicate"] = "there is an existing dhcp host" + \
                                                " entry in network.* that matches"
                    # out_of_range error info
                    err_dic[
                        "out-of-range"] = "range.* is not entirely within network"
                    # no end for range error
                    err_dic["range-no-end"] = "Missing 'end' attribute in dhcp " + \
                                              "range for network"
                    # no match item for host modify err
                    err_dic["no-match-item"] = "couldn't locate an existing dhcp" + \
                                               " host entry with.* in network"
                    # no host name and mac for modify err
                    err_dic["host-no-name-mac"] = "Static host definition in IPv4 network" + \
                                                  ".* must have mac or name attribute"
                    # no host ip for modify err
                    err_dic["host-no-ip"] = "Missing IP address in static host " + \
                                            "definition for network"
                    # wrong command name
                    err_dic["wrong-command-name"] = "unrecognized command name"
                    # wrong section name
                    err_dic["wrong-section-name"] = "unrecognized section name"
                    # delete with only id
                    err_dic["only-id"] = "At least one of name, mac, or ip attribute must be" + \
                                         " specified for static host definition in network"
                    # options exclusive
                    err_dic[
                        "opt-exclusive"] = "Options --current and.* are mutually exclusive"
                    # range_reverse error info
                    if ip_version == "ipv4":
                        err_dic["range-reverse"] = "range.* is reversed"
                    elif ip_version == "ipv6":
                        err_dic[
                            "range-reverse"] = "range.*start larger than end"
                    # --live with inactive net
                    err_dic["invalid-state"] = "network is not running"
                    err_dic[
                        "transient"] = "cannot change persistent config of a transient network"
                    err_dic["dns-disable"] = "Extra data in disabled network"
                    err_dic[
                        "modify"] = "cannot be modified, only added or deleted"
                    err_dic["not-support"] = "can't update.*section of network"
                    err_dic["unrecognized"] = "unrecognized section name"
                    err_dic["interface-duplicate"] = "there is an existing interface entry " + \
                                                     "in network.* that matches"

                    if (error_type in list(err_dic.keys())
                            and re.search(err_dic[error_type], err)
                            or mismatch_expect):
                        logging.debug("Get expect error: %s", err)
                    else:
                        test.fail("Do not get expect err msg: %s, %s" %
                                  (error_type, err_dic))
                else:
                    test.fail("Failed to execute net-update command")
            elif status_error == "yes":
                test.fail("Expect fail, but succeed")

            # Get dnsmasq pid after update
            if check_dnsmasq:
                pid_list_aft = results_stdout_52lts(
                    process.run(cmd, shell=True)).strip().split('\n')
                for pid in pid_list_aft:
                    if pid in pid_list_bef:
                        test.fail("dnsmasq do not updated")

            # Check the actual xml
            cmd_result = virsh.net_dumpxml(net_name)
            actual_net_xml = cmd_result.stdout.strip()
            new_xml_obj = network_xml.NetworkXML.new_from_net_dumpxml(net_name)
            logging.info("After net-update, the actual net xml is %s",
                         actual_net_xml)

            if "ip-dhcp" in net_section:
                if ip_version == "ipv6":
                    new_xml_obj.del_element(element="/ip", index=0)
                if ip_version == "ipv4":
                    new_xml_obj.del_element(element="/ip", index=1)

            config_not_work = ("--config" in options and net_state == "active"
                               and "--live" not in options)
            if config_not_work:
                if update_command != "delete":
                    flag_list_abs = flag_list
                    flag_list = []
                else:
                    flag_list = flag_list_abs
                    flag_list_abs = []

            logging.info("The check list is %s, absent list is %s", flag_list,
                         flag_list_abs)

            if (update_command == "delete" and status_error == "no"
                    and not config_not_work and loop_time == 1):
                try:
                    section_str = new_xml_obj.get_section_string(xpath=element)
                except xcepts.LibvirtXMLNotFoundError:
                    section_str = None
                    logging.info("Can not find section %s in xml after delete",
                                 element)
                if section_str is not None:
                    test.fail("The actual net xml is not expected,"
                              "element still exists")
            elif ("duplicate" not in error_type
                  and error_type != "range-mismatch"
                  and error_type != "host-mismatch"
                  and error_type != "not-support"):
                # check xml should exists
                for flag_string in flag_list:
                    logging.info(
                        "checking %s should in xml in positive test,"
                        "and absent in negative test", flag_string)
                    if not re.search(flag_string, actual_net_xml):
                        if ((status_error == "no"
                             and update_command != "delete")
                                or (update_command == "delete"
                                    and status_error == "yes")):
                            test.fail("The actual net xml failed to update,"
                                      "or expect delete fail but xml missing"
                                      ":%s" % flag_string)
                    else:
                        if ((status_error == "yes"
                             and update_command != "delete")
                                or (status_error == "no"
                                    and update_command == "delete"
                                    and not config_not_work)):
                            test.fail("Expect test fail, but find xml %s"
                                      " actual, or expect delete succeed,"
                                      "but fail in fact" % flag_string)
                # check xml should not exists
                for flag_string_abs in flag_list_abs:
                    logging.info(
                        "checking %s should NOT in xml in positive test,"
                        "and exist in negative test", flag_string_abs)
                    if re.search(flag_string_abs, actual_net_xml):
                        if status_error == "no":
                            test.fail("Expect absent in net xml, but exists"
                                      "in fact: %s" % flag_string_abs)
                    else:
                        if status_error == "yes":
                            test.fail("Should exists in net xml, but it "
                                      "disappeared: %s" % flag_string_abs)

                # Check if add-last, add-fist works well
                if (status_error == "no" and not config_not_work and
                        update_command in ["add-last", "add", "add-first"]):
                    if update_command == "add-first":
                        find_index = 0
                    else:
                        find_index = -1
                    section_str_aft = new_xml_obj.get_section_string(
                        xpath=element, index=find_index)
                    logging.info(
                        "xpath is %s, find_index is %s, section_str_aft is %s",
                        element, find_index, section_str_aft)
                    for flag_string in flag_list:
                        logging.info("flag_string is %s", flag_string)
                        if not re.search(flag_string, section_str_aft):
                            test.fail("Can not find %s in %s" %
                                      (flag_string, section_str_aft))
                    logging.info("%s %s in right place", update_command,
                                 section_str_aft)

            # Check the positive test result
            if status_error == "no":
                # Check the network conf file
                # live update
                if ("--live" in options or "--config"
                        not in options) and net_state == "active":
                    if net_section == "ip-dhcp-range" and update_command == "add-first":
                        ip_range = "%s,%s" % (new_start_ip, new_end_ip)
                        if ip_version == "ipv6":
                            ip_range = ip_range + ",64"
                        check_item(ip_range)
                    if "dns" in net_section:
                        if update_command == "delete" and loop == 0:
                            if net_section == "dns-srv":
                                check_item_absent(srv_host)
                            if net_section == "dns-txt":
                                check_item_absent(txt_record)
                            if net_section == "dns-host":
                                check_host_absent(dns_host_str)
                        elif "add" in update_command:
                            if net_section == "dns-srv":
                                for sec in update_sec.split(","):
                                    srv_host = srv_host.replace(
                                        names["srv_" + sec],
                                        names["new_srv_" + sec])
                                check_item(srv_host)
                            if net_section == "dns-txt":
                                for sec in update_sec.split(","):
                                    txt_record = txt_record.replace(
                                        names["dns_" + sec],
                                        names["new_dns_" + sec])
                                check_item(txt_record)
                            if net_section == "dns-host":
                                check_host(hostline)

                    # Check the hostfile
                    if (net_section == "ip-dhcp-host"
                            and update_command != "modify"
                            and update_command != "delete"):
                        dic_hostfile = {}
                        for sec in ["ip", "mac", "name", "id"]:
                            if update_sec is not None and sec in update_sec.split(
                                    ","):
                                dic_hostfile[sec] = names["new_dhcp_host_" +
                                                          sec] + ","
                            else:
                                dic_hostfile[sec] = names[ip_version +
                                                          "_host_" + sec] + ","

                            if sec == "ip" and ip_version == "ipv6":
                                dic_hostfile[sec] = "[" + dic_hostfile[
                                    sec].strip(",") + "]"

                            if without_sec is not None and sec in without_sec.split(
                                    ","):
                                dic_hostfile[sec] = ""

                        if ip_version == "ipv4":
                            host_info = (dic_hostfile["mac"] +
                                         dic_hostfile["ip"] +
                                         dic_hostfile["name"])
                            if dic_hostfile["mac"] == "":
                                host_info = dic_hostfile[
                                    "name"] + dic_hostfile["ip"]
                        if ip_version == "ipv6":
                            host_info = ("id:" + dic_hostfile["id"] +
                                         dic_hostfile["name"] +
                                         dic_hostfile["ip"])

                        hostfile = get_hostfile()
                        host_info_patten = host_info.strip(",") + "\n"
                        if host_info_patten in hostfile:
                            logging.info("host info %s is in hostfile %s",
                                         host_info, hostfile)
                        else:
                            test.fail("Can not find %s in host file: %s" %
                                      (host_info, hostfile))

                # Check the net in guest
                if use_in_guest == "yes" and loop == 0:
                    # Detach all interfaces of vm first
                    iface_index = 0
                    mac_list = vm_xml.VMXML.get_iface_dev(vm_name)
                    for mac in mac_list:
                        iface_dict = vm_xml.VMXML.get_iface_by_mac(
                            vm_name, mac)
                        virsh.detach_interface(
                            vm_name, "--type %s --mac %s --config" %
                            (iface_dict.get('type'), mac))
                        vm.free_mac_address(iface_index)
                        iface_index += 1

                    # attach new interface to guest
                    for j in range(guest_iface_num):
                        if net_section == "ip-dhcp-host" and new_dhcp_host_mac:
                            mac = new_dhcp_host_mac
                        else:
                            mac = utils_net.generate_mac_address_simple()
                        ret = virsh.attach_interface(
                            vm_name,
                            "--type %s --source %s --mac %s --config" %
                            (iface_type, net_name, mac))
                        if ret.exit_status:
                            test.fail(
                                "Fail to attach new interface to guest: %s" %
                                ret.stderr.strip())

                    # The sleep here is to make sure the update make effect
                    time.sleep(2)

                    # Start guest and check ip/mac/hostname...
                    vm.start()
                    logging.debug("vm xml is %s", vm.get_xml())
                    session = vm.wait_for_serial_login()
                    if "ip-dhcp" in net_section:
                        dhclient_cmd = "(if pgrep dhclient;" \
                                       "then pkill dhclient; sleep 3; fi) " \
                                       "&& dhclient -%s" % ip_version[-1]
                        session.cmd(dhclient_cmd)
                        iface_ip = utils_net.get_guest_ip_addr(
                            session, mac, ip_version=ip_version, timeout=10)
                    if net_section == "ip-dhcp-range":
                        if new_start_ip <= iface_ip <= new_end_ip:
                            logging.info("getting ip %s is in range [%s ~ %s]",
                                         iface_ip, new_start_ip, new_end_ip)
                        else:
                            test.fail("getting ip %s not in range [%s ~ %s]" %
                                      (iface_ip, new_start_ip, new_end_ip))
                    if net_section == "ip-dhcp-host":
                        if iface_ip == new_dhcp_host_ip:
                            logging.info("getting ip is same with set: %s",
                                         iface_ip)
                        else:
                            test.fail(
                                "getting ip %s is not same with setting %s" %
                                (iface_ip, new_dhcp_host_ip))
                        hostname = session.cmd_output("hostname").strip('\n')
                        if hostname == new_dhcp_host_name.split('.')[0]:
                            logging.info(
                                "getting hostname same with setting: %s",
                                hostname)
                        else:
                            test.fail("getting hostname %s is not same with "
                                      "setting: %s" %
                                      (hostname, new_dhcp_host_name))

                    session.close()

                # Check network connection for macvtap
                if (use_in_guest == "yes"
                        and net_section == "forward-interface"
                        and forward_mode == "bridge"):
                    xml_obj_use = network_xml.NetworkXML.new_from_net_dumpxml(
                        net_name)
                    net_conn = int(xml_obj_use.connection)
                    iface_conn = xml_obj_use.get_interface_connection()
                    conn_count = 0
                    for k in iface_conn:
                        conn_count = conn_count + int(k)
                    logging.info(
                        "net_conn=%s, conn_count=%s, guest_iface_num=%s" %
                        (net_conn, conn_count, guest_iface_num))
                    if (net_conn != conn_count
                            or (loop == 1 and guest_iface_num != net_conn)):
                        test.fail("Can not get expected connection num: "
                                  "net_conn = %s, iface_conn = %s" %
                                  (net_conn, conn_count))

                #Check --config option after net destroyed
                if (int(check_config_round) == loop
                        or (loop_time == 1 and "--current" in options
                            and net_state == "active")):
                    test_xml.set_active(False)
                    logging.info("Checking xml after net destroyed")
                    cmd_result = virsh.net_dumpxml(net_name)
                    inactive_xml = cmd_result.stdout.strip()
                    logging.info("inactive_xml is %s", inactive_xml)
                    #Check the inactive xml
                    for check_str in flag_list:
                        if update_command != "delete":
                            if "--config" in options:
                                if not re.search(check_str, inactive_xml):
                                    test.fail(
                                        "Can not find xml after net destroyed")
                            if "--current" in options:
                                if re.search(check_str, inactive_xml):
                                    test.fail(
                                        "XML still exists after net destroyed")
                        else:
                            if "--config" in options:
                                if re.search(check_str, inactive_xml):
                                    test.fail(
                                        "XML still exists after net destroyed")
                            if "--current" in options:
                                if not re.search(check_str, inactive_xml):
                                    test.fail(
                                        "Can not find xml after net destroyed")

                    logging.info("Check for net inactive PASS")

    finally:
        if test_xml.get_active():
            test_xml.del_active()
        if test_xml.get_defined():
            test_xml.del_defined()

        if os.path.exists(xmlfile):
            os.remove(xmlfile)

        if use_in_guest == "yes":
            vm = env.get_vm(vm_name)
            if vm.is_alive():
                vm.destroy(gracefully=False)
            vmxml_backup.sync()
        for config_file in backup_files:
            config_file._reset_file()
Ejemplo n.º 27
0
    def modify_iface_xml(update, status_error=False):
        """
        Modify interface xml options
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        xml_devices = vmxml.devices
        iface_index = xml_devices.index(
            xml_devices.by_device_tag("interface")[0])
        iface = xml_devices[iface_index]
        if iface_model:
            iface.model = iface_model
        else:
            del iface.model
        if iface_type:
            iface.type_name = iface_type
        del iface.source
        source = ast.literal_eval(iface_source)
        if source:
            net_ifs = utils_net.get_net_if(state="UP")
            # Check source device is valid or not,
            # if it's not in host interface list, try to set
            # source device to first active interface of host
            if (iface.type_name == "direct" and
                    source.has_key('dev') and
                    source['dev'] not in net_ifs):
                logging.warn("Source device %s is not a interface"
                             " of host, reset to %s",
                             source['dev'], net_ifs[0])
                source['dev'] = net_ifs[0]
            iface.source = source
        backend = ast.literal_eval(iface_backend)
        if backend:
            iface.backend = backend
        driver_dict = {}
        driver_host = {}
        driver_guest = {}
        if iface_driver:
            driver_dict = ast.literal_eval(iface_driver)
        if iface_driver_host:
            driver_host = ast.literal_eval(iface_driver_host)
        if iface_driver_guest:
            driver_guest = ast.literal_eval(iface_driver_guest)
        iface.driver = iface.new_driver(driver_attr=driver_dict,
                                        driver_host=driver_host,
                                        driver_guest=driver_guest)
        if iface.address:
            del iface.address

        logging.debug("New interface xml file: %s", iface)
        if unprivileged_user:
            # Create disk image for unprivileged user
            disk_index = xml_devices.index(
                xml_devices.by_device_tag("disk")[0])
            disk_xml = xml_devices[disk_index]
            logging.debug("source: %s", disk_xml.source)
            disk_source = disk_xml.source.attrs["file"]
            cmd = ("cp -fZ {0} {1} && chown {2}:{2} {1}"
                   "".format(disk_source, dst_disk, unprivileged_user))
            utils.run(cmd)
            disk_xml.source = disk_xml.new_disk_source(
                attrs={"file": dst_disk})
            vmxml.devices = xml_devices
            # Remove all channels to avoid of permission problem
            channels = vmxml.get_devices(device_type="channel")
            for channel in channels:
                vmxml.del_device(channel)

            vmxml.xmltreefile.write()
            logging.debug("New VM xml: %s", vmxml)
            utils.run("chmod a+rw %s" % vmxml.xml)
            virsh.define(vmxml.xml, **virsh_dargs)
        # Try to modify interface xml by update-device or edit xml
        elif update:
            iface.xmltreefile.write()
            ret = virsh.update_device(vm_name, iface.xml,
                                      ignore_status=True)
            libvirt.check_exit_status(ret, status_error)
        else:
            vmxml.devices = xml_devices
            vmxml.xmltreefile.write()
            vmxml.sync()
Ejemplo n.º 28
0
def run(test, params, env):
    """
    Test interface devices update
    """
    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)
    new_network_name = params.get("net_name")
    expect_error = "yes" == params.get("status_error", "no")
    expect_err_msg = params.get("expect_err_msg")

    iface_driver = params.get("iface_driver")
    iface_model = params.get("iface_model")
    iface_mtu = params.get("iface_mtu")
    iface_rom = params.get("iface_rom")
    iface_filter = params.get("iface_filter")

    new_iface_driver = params.get("new_iface_driver")
    new_iface_driver_host = params.get("new_iface_driver_host")
    new_iface_driver_guest = params.get("new_iface_driver_guest")
    new_iface_model = params.get("new_iface_model")
    new_iface_rom = params.get("new_iface_rom")
    new_iface_inbound = params.get("new_iface_inbound")
    new_iface_outbound = params.get("new_iface_outbound")
    new_iface_link = params.get("new_iface_link")
    new_iface_source = params.get("new_iface_source")
    new_iface_target = params.get("new_iface_target")
    new_iface_addr = params.get("new_iface_addr")
    new_iface_filter = params.get("new_iface_filter")
    new_iface_mtu = params.get("new_iface_mtu")
    new_iface_type = params.get("new_iface_type")
    create_new_net = "yes" == params.get("create_new_net")
    new_iface_alias = params.get("new_iface_alias")
    cold_update = "yes" == params.get("cold_update", "no")
    del_addr = "yes" == params.get("del_address")
    del_rom = "yes" == params.get("del_rom")
    del_filter = "yes" == params.get("del_filter")

    # Backup the vm xml for recover at last
    vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

    try:
        # According to the different os find different file for rom
        if (iface_rom and "file" in eval(iface_rom)
                and "%s" in eval(iface_rom)['file']):
            if os.path.exists(eval(iface_rom)['file'] % "pxe"):
                iface_rom = iface_rom % "pxe"
            elif os.path.exists(eval(iface_rom)['file'] % "efi"):
                iface_rom = iface_rom % "efi"
            else:
                logging.error("Can not find suitable rom file")
        iface_dict_bef = {}
        iface_dict_aft = {}
        names = locals()
        # Collect need update items in 2 dicts for both start vm before and after
        update_list_bef = ["driver", "model", "mtu", "rom", "filter"]
        for update_item_bef in update_list_bef:
            if names['iface_' + update_item_bef]:
                iface_dict_bef.update(
                    {update_item_bef: names['iface_' + update_item_bef]})

        update_list_aft = [
            "driver", "driver_host", "driver_guest", "model", "rom", "inbound",
            "outbound", "link", "source", "target", "addr", "filter", "mtu",
            "type", "alias"
        ]
        for update_item_aft in update_list_aft:
            if names["new_iface_" + update_item_aft]:
                iface_dict_aft.update(
                    {update_item_aft: names["new_iface_" + update_item_aft]})
        logging.info("iface_dict_bef is %s, iface_dict_aft is %s",
                     iface_dict_bef, iface_dict_aft)

        del_list = ["del_addr", "del_rom", "del_filter"]
        for del_item in del_list:
            if names[del_item]:
                iface_dict_aft.update({del_item: "True"})

        # Update vm interface with items in iface_dict_bef and start it
        if iface_dict_bef:
            libvirt.modify_vm_iface(vm_name, "update_iface", iface_dict_bef)
        logging.info("vm xml is %s", vm.get_xml())

        if not cold_update:
            vm.start()

        if iface_mtu:
            # Do check for mtu size after start vm
            target_dev = libvirt.get_interface_details(vm_name)[0]['interface']
            cmd = "ip link show %s | grep 'mtu %s'" % (target_dev,
                                                       eval(iface_mtu)['size'])

            def check_mtu():
                """
                Check the mtu setting take effect for interface
                """
                ret = process.run(cmd, ignore_status=True, shell=True)
                if ret.exit_status:
                    test.fail("Can not find mtu setting in cmd result")

            check_mtu()
            utils_libvirtd.libvirtd_restart()
            check_mtu()

        # Create new network if need
        if create_new_net:
            new_net_xml = libvirt.create_net_xml(new_network_name, params)
            new_net_xml.sync()

        # Do update for iface_driver
        new_iface_xml = libvirt.modify_vm_iface(vm_name, "get_xml",
                                                iface_dict_aft)
        ret = virsh.update_device(vm_name,
                                  new_iface_xml,
                                  ignore_status=True,
                                  debug=True)
        libvirt.check_exit_status(ret, expect_error)
        if expect_error:
            real_err_msg = ret.stderr.strip()
            if not re.search(expect_err_msg, real_err_msg, re.IGNORECASE):
                test.fail("The real error msg:'%s' does not match expect one:"
                          '%s' % (real_err_msg, expect_err_msg))
            else:
                logging.info("Get expect result: %s", real_err_msg)
        else:
            if new_iface_inbound:
                iface_bandwidth = {}
                iface_bandwidth = vm_xml.VMXML.get_iftune_params(vm_name)
                for bound_para in ["inbound", "outbound"]:
                    for tune_para in ["average", "peak", "burst"]:
                        get_value = iface_bandwidth.get(bound_para).get(
                            tune_para)
                        expect_value = eval(names["new_iface_" +
                                                  bound_para]).get(tune_para)
                        logging.info("Get value for %s:%s is %s, expect is %s",
                                     bound_para, tune_para, get_value,
                                     expect_value)
                        if get_value != expect_value:
                            test.fail("Get value is not equal to expect")
            vmxml_aft = vm_xml.VMXML.new_from_dumpxml(vm_name)
            iface_aft = list(vmxml_aft.get_iface_all().values())[0]
            if new_iface_link:
                iface_link_value = iface_aft.find('link').get('state')
                if iface_link_value == new_iface_link:
                    logging.info("Find link state is %s in xml",
                                 new_iface_link)

                    # Checking the statue in guest
                    mac_addr = iface_aft.find('mac').get('address')
                    state_map = "%s.*\n.*%s" % (iface_link_value.upper(),
                                                mac_addr)
                    session = vm.wait_for_serial_login()
                    logging.info("ip link output:%s",
                                 session.cmd_output("ip link"))
                    if_name = utils_net.get_net_if(runner=session.cmd_output,
                                                   state=state_map)[0]
                    session.close()
                    if if_name:
                        logging.info("Find iface state %s for %s",
                                     iface_link_value, mac_addr)
                    else:
                        test.fail(
                            "Can not find iface with mac %s and state %s" %
                            (mac_addr, iface_link_value))
                else:
                    test.fail(
                        "Check fail to get link state, expect %s, but get %s" %
                        (iface_link_value, new_iface_link))
            if create_new_net and new_iface_source:
                iface_source_value = iface_aft.find('source').get('network')
                if iface_source_value == eval(new_iface_source)['network']:
                    logging.info("Get %s in xml as set", iface_source_value)
                else:
                    test.fail("Get source %s is not equal to set %s" %
                              (iface_source_value, new_iface_source))
            if new_iface_filter:
                iface_filter_value = iface_aft.find('filterref').get('filter')
                if iface_filter_value == new_iface_filter:
                    logging.info("Get %s in xml as set", iface_filter_value)
                else:
                    test.fail("Get filter %s is not equal to set %s" %
                              (iface_filter_value, new_iface_filter))
            if del_filter:
                iface_filter_value = iface_aft.find('filterref')
                if iface_filter_value:
                    logging.debug("After delete, the filter still exists: %s",
                                  iface_filter_value)
            if new_iface_alias:
                iface_alias_value = iface_aft.find('alias').get('name')
                if iface_alias_value == eval(new_iface_alias)['name']:
                    logging.info("Get %s in xml as set", iface_alias_value)
                else:
                    test.fail("Get alias %s is not equal to set %s" %
                              (iface_alias_value, new_iface_alias))
    finally:
        vmxml_backup.sync()
        if create_new_net:
            new_net_xml.undefine()
Ejemplo n.º 29
0
    def modify_iface_xml(update, status_error=False):
        """
        Modify interface xml options
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        xml_devices = vmxml.devices
        iface_index = xml_devices.index(
            xml_devices.by_device_tag("interface")[0])
        iface = xml_devices[iface_index]
        if iface_model:
            iface.model = iface_model
        else:
            del iface.model
        if iface_type:
            iface.type_name = iface_type
        del iface.source
        source = ast.literal_eval(iface_source)
        if source:
            net_ifs = utils_net.get_net_if(state="UP")
            # Check source device is valid or not,
            # if it's not in host interface list, try to set
            # source device to first active interface of host
            if (iface.type_name == "direct" and source.has_key('dev')
                    and source['dev'] not in net_ifs):
                logging.warn(
                    "Source device %s is not a interface"
                    " of host, reset to %s", source['dev'], net_ifs[0])
                source['dev'] = net_ifs[0]
            iface.source = source
        backend = ast.literal_eval(iface_backend)
        if backend:
            iface.backend = backend
        driver_dict = {}
        driver_host = {}
        driver_guest = {}
        if iface_driver:
            driver_dict = ast.literal_eval(iface_driver)
        if iface_driver_host:
            driver_host = ast.literal_eval(iface_driver_host)
        if iface_driver_guest:
            driver_guest = ast.literal_eval(iface_driver_guest)
        iface.driver = iface.new_driver(driver_attr=driver_dict,
                                        driver_host=driver_host,
                                        driver_guest=driver_guest)
        if iface.address:
            del iface.address

        logging.debug("New interface xml file: %s", iface)
        if unprivileged_user:
            # Create disk image for unprivileged user
            disk_index = xml_devices.index(
                xml_devices.by_device_tag("disk")[0])
            disk_xml = xml_devices[disk_index]
            logging.debug("source: %s", disk_xml.source)
            disk_source = disk_xml.source.attrs["file"]
            cmd = ("cp -fZ {0} {1} && chown {2}:{2} {1}"
                   "".format(disk_source, dst_disk, unprivileged_user))
            utils.run(cmd)
            disk_xml.source = disk_xml.new_disk_source(
                attrs={"file": dst_disk})
            vmxml.devices = xml_devices
            # Remove all channels to avoid of permission problem
            channels = vmxml.get_devices(device_type="channel")
            for channel in channels:
                vmxml.del_device(channel)

            vmxml.xmltreefile.write()
            logging.debug("New VM xml: %s", vmxml)
            utils.run("chmod a+rw %s" % vmxml.xml)
            virsh.define(vmxml.xml, **virsh_dargs)
        # Try to modify interface xml by update-device or edit xml
        elif update:
            iface.xmltreefile.write()
            ret = virsh.update_device(vm_name, iface.xml, ignore_status=True)
            libvirt.check_exit_status(ret, status_error)
        else:
            vmxml.devices = xml_devices
            vmxml.xmltreefile.write()
            vmxml.sync()
Ejemplo n.º 30
0
def run(test, params, env):
    """
    This test is for macvtap nic

    1. Check and backup environment
    2. Configure guest, add new nic and set a static ip address
    3. According to nic mode, start test
    4. Recover environment
    """
    vm_names = params.get("vms").split()
    remote_ip = params.get("remote_ip", "ENTER.YOUR.REMOTE.IP")
    iface_mode = params.get("mode", "vepa")
    eth_card_no = params.get("eth_card_no", "ENTER.YOUR.DEV.NAME")
    vm1_ip = params.get("vm1_ip", "ENTER.YOUR.GUEST1.IP")
    vm2_ip = params.get("vm2_ip", "ENTER.YOUR.GUEST2.IP")
    eth_config_file = params.get("eth_config_file",
                                 "ENTER.YOUR.CONFIG.FILE.PATH")
    persistent_net_file = params.get("persistent_net_file",
                                     "ENTER.YOUR.RULE.FILE.PATH")

    param_keys = [
        "remote_ip", "vm1_ip", "vm2_ip", "eth_card_no", "eth_config_file",
        "persistent_net_file"
    ]
    param_values = [
        remote_ip, vm1_ip, vm2_ip, eth_card_no, eth_config_file,
        persistent_net_file
    ]
    for key, value in zip(param_keys, param_values):
        if value.count("ENTER.YOUR"):
            test.cancel("Parameter '%s'(%s) is not configured." % (key, value))

    vm1 = env.get_vm(vm_names[0])
    vm2 = None
    if len(vm_names) > 1:
        vm2 = env.get_vm(vm_names[1])

    if eth_card_no not in utils_net.get_net_if():
        test.cancel("Device %s do not exists." % eth_card_no)
    try:
        iface_cls = utils_net.Interface(eth_card_no)
        origin_status = iface_cls.is_up()
        if not origin_status:
            iface_cls.up()
    except process.CmdError as detail:
        test.cancel(str(detail))
    br_cls = utils_net.Bridge()
    if eth_card_no in br_cls.list_iface():
        test.cancel("%s has been used!" % eth_card_no)
    vmxml1 = vm_xml.VMXML.new_from_inactive_dumpxml(vm_names[0])
    if vm2:
        vmxml2 = vm_xml.VMXML.new_from_inactive_dumpxml(vm_names[1])

    def guest_config(vm, ip_addr):
        """
        Add a new nic to guest and set a static ip address

        :param vm: Configured guest
        :param ip_addr: Set ip address
        """
        # Attach an interface device
        # Use attach-device, not attach-interface, because attach-interface
        # doesn't support 'direct'
        interface_class = vm_xml.VMXML.get_device_class('interface')
        interface = interface_class(type_name="direct")
        interface.source = dict(dev=str(eth_card_no), mode=str(iface_mode))
        interface.model = "virtio"
        interface.xmltreefile.write()
        if vm.is_alive():
            vm.destroy(gracefully=False)
        virsh.attach_device(vm.name, interface.xml, flagstr="--config")
        os.remove(interface.xml)
        vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name)
        new_nic = vmxml.get_devices(device_type="interface")[-1]

        # Modify new interface's IP
        vm.start()
        session = vm.wait_for_login()
        eth_name = utils_net.get_linux_ifname(session, new_nic.mac_address)
        eth_config_detail_list = [
            'DEVICE=%s' % eth_name,
            'HWADDR=%s' % new_nic.mac_address, 'ONBOOT=yes',
            'BOOTPROTO=static',
            'IPADDR=%s' % ip_addr
        ]
        remote_file = remote.RemoteFile(vm.get_address(), 'scp', 'root',
                                        params.get('password'), 22,
                                        eth_config_file)
        remote_file.truncate()
        remote_file.add(eth_config_detail_list, linesep='\n')
        try:
            # Attached interface maybe already active
            session.cmd("ifdown %s" % eth_name)
        except aexpect.ShellCmdError:
            test.fail("ifdown %s failed." % eth_name)

        try:
            session.cmd("ifup %s" % eth_name)
        except aexpect.ShellCmdError:
            test.fail("ifup %s failed." % eth_name)
        return session

    def guest_clean(vm, vmxml):
        """
        Recover guest configuration

        :param: Recovered guest
        """
        if vm.is_dead():
            vm.start()
        session = vm.wait_for_login()
        session.cmd("rm -f %s" % eth_config_file)
        session.cmd("sync")
        try:
            # Delete the last 3 lines
            session.cmd('sed -i "$[$(cat %s | wc -l) - 2],$"d %s' %
                        (persistent_net_file, persistent_net_file))
            session.cmd("sync")
        except aexpect.ShellCmdError:
            # This file may not exists
            pass
        vm.destroy()
        vmxml.sync()

    def vepa_test(session):
        """
        vepa mode test.
        Check guest can ping remote host
        """
        ping_s, _ = ping(remote_ip, count=1, timeout=5, session=session)
        if ping_s:
            test.fail("%s ping %s failed." % (vm1.name, remote_ip))

    def private_test(session):
        """
        private mode test.
        Check guest cannot ping other guest, but can pin remote host
        """
        ping_s, _ = ping(remote_ip, count=1, timeout=5, session=session)
        if ping_s:
            test.fail("%s ping %s failed." % (vm1.name, remote_ip))
        ping_s, _ = ping(vm2_ip, count=1, timeout=5, session=session)
        if not ping_s:
            test.fail("%s ping %s succeed, but expect failed." %
                      (vm1.name, vm2.name))
        try:
            iface_cls.down()
        except process.CmdError as detail:
            test.cancel(str(detail))
        ping_s, _ = ping(vm2_ip, count=1, timeout=5, session=session)
        if not ping_s:
            test.fail("%s ping %s succeed, but expect failed." %
                      (vm1.name, remote_ip))

    def passthrough_test(session):
        """
        passthrough mode test.
        Check guest can ping remote host.
        When guest is running, local host cannot ping remote host,
        When guest is poweroff, local host can ping remote host,
        """
        ping_s, _ = ping(remote_ip, count=1, timeout=5, session=session)
        if ping_s:
            test.fail("%s ping %s failed." % (vm1.name, remote_ip))
        ping_s, _ = ping(remote_ip, count=1, timeout=5)
        if not ping_s:
            test.fail("host ping %s succeed, but expect fail." % remote_ip)
        vm1.destroy(gracefully=False)
        ping_s, _ = ping(remote_ip, count=1, timeout=5)
        if ping_s:
            test.fail("host ping %s failed." % remote_ip)

    def bridge_test(session):
        """
        bridge mode test.
        Check guest can ping remote host
        guest can ping other guest when macvtap nic is up
        guest cannot ping remote host when macvtap nic is up
        """
        ping_s, _ = ping(remote_ip, count=1, timeout=5, session=session)
        if ping_s:
            test.fail("%s ping %s failed." % (vm1.name, remote_ip))
        ping_s, _ = ping(vm2_ip, count=1, timeout=5, session=session)
        if ping_s:
            test.fail("%s ping %s failed." % (vm1.name, vm2.name))
        try:
            iface_cls.down()
        except process.CmdError as detail:
            test.cancel(str(detail))
        ping_s, _ = ping(remote_ip, count=1, timeout=5, session=session)
        if not ping_s:
            test.fail("%s ping %s success, but expected fail." %
                      (vm1.name, remote_ip))

    # Test start
    try:
        try:
            session = guest_config(vm1, vm1_ip)
        except remote.LoginTimeoutError as fail:
            test.fail(str(fail))
        if vm2:
            try:
                guest_config(vm2, vm2_ip)
            except remote.LoginTimeoutError as fail:
                test.fail(str(fail))

        # Four mode test
        if iface_mode == "vepa":
            vepa_test(session)
        elif iface_mode == "bridge":
            bridge_test(session)
        elif iface_mode == "private":
            private_test(session)
        elif iface_mode == "passthrough":
            passthrough_test(session)
    finally:
        if iface_cls.is_up():
            if not origin_status:
                iface_cls.down()
        else:
            if origin_status:
                iface_cls.up()
        guest_clean(vm1, vmxml1)
        if vm2:
            guest_clean(vm2, vmxml2)