Esempio n. 1
0
    def cleanup_ovs_ports(netdst, ports):
        """
        Clean up created ovs ports in this case

        :param netdst: netdst get from command line
        :param ports: existing ports need to be remain before this test
        """

        host_bridge = utils_net.find_bridge_manager(netdst)
        if utils_net.ovs_br_exists(netdst) is True:
            ports = set(host_bridge.list_ports(netdst)) - set(ports)
            for p in ports:
                utils_net.find_bridge_manager(netdst).del_port(netdst, p)
Esempio n. 2
0
    def cleanup_ovs_ports(netdst, ports):
        """
        Clean up created ovs ports in this case

        :param netdst: netdst get from command line
        :param ports: existing ports need to be remain before this test
        """

        host_bridge = utils_net.find_bridge_manager(netdst)
        if utils_net.ovs_br_exists(netdst) is True:
            ports = set(host_bridge.list_ports(netdst)) - set(ports)
            for p in ports:
                utils_net.find_bridge_manager(netdst).del_port(netdst, p)
Esempio n. 3
0
def run(test, params, env):
    """
    Test tap device deleted after vm quit with error

    1) Boot a with invaild params.
    1) Check qemu-kvm quit with error.
    2) Check vm tap device delete from ovs bridge.

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

    netdst = params.get("netdst")
    if not utils_net.ovs_br_exists(netdst):
        test.cancel("%s isn't an openvswith bridge" % netdst)

    host_bridge = utils_net.find_bridge_manager(netdst)
    deps_dir = data_dir.get_deps_dir("ovs")
    nic_script = utils_misc.get_path(deps_dir, params["nic_script"])
    nic_downscript = utils_misc.get_path(deps_dir, params["nic_downscript"])
    params["nic_script"] = nic_script
    params["nic_downscript"] = nic_downscript

    params["qemu_command_prefix"] = "export SHELL=/usr/bin/bash;"
    params["start_vm"] = "yes"
    params["nettype"] = "bridge"
    params["nic_model"] = "virtio-net-pci"

    ports = set(host_bridge.list_ports(netdst))
    try:
        env_process.preprocess_vm(test, params, env, params["main_vm"])
        env.get_vm(params["main_vm"])
    except virt_vm.VMCreateError:
        ports = set(host_bridge.list_ports(netdst)) - ports
        if ports:
            for p in ports:
                host_bridge.del_port(netdst, p)
            test.fail("%s not delete after qemu quit." % ports)
    else:
        test.fail("Qemu should quit with error")
Esempio n. 4
0
def run(test, params, env):
    """
    Enslave a port which is already a member of ovs into another

    1) Check current ovs bridge and list the ports in it
    2) Create a new ovs bridge
    3) Enslave one port which is a member of current ovs bridge
       into the new one
    4) Delete the new ovs bridge

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

    netdst = params["netdst"]
    if utils_net.ovs_br_exists(netdst) is not True:
        test.cancel("%s isn't an openvswith bridge" % netdst)

    new_br_name = params.get("new_ovs_bridge_name", "temp_ovs_bridge")
    host_bridge = utils_net.find_bridge_manager(netdst)
    if host_bridge.br_exist(new_br_name) is True:
        host_bridge.del_br(new_br_name)
    host_bridge.add_br(new_br_name)
    error_context.context("OVS bridge %s created." % new_br_name,
                          logging.info)

    try:
        ports = host_bridge.list_ports(netdst)
        host_bridge.add_port(new_br_name, ports[0])
    except process.CmdError as e:
        if "already exists on bridge" not in e.result.stderr_text:
            test.fail("Port %s should not be enslaved to another bridge."
                      " Output: %s" % (ports[0], e.result.stderr_text))
    else:
        test.fail("Add port cmd successfully excuted. However, port %s "
                  "should not be enslaved to another bridge." % ports[0])
    finally:
        host_bridge.del_br(new_br_name)
Esempio n. 5
0
def run(test, params, env):
    """
    Enslave a port which is already a member of ovs into another

    1) Check current ovs bridge and list the ports in it
    2) Create a new ovs bridge
    3) Enslave one port which is a member of current ovs bridge
       into the new one
    4) Delete the new ovs bridge

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

    netdst = params["netdst"]
    if utils_net.ovs_br_exists(netdst) is not True:
        test.cancel("%s isn't an openvswith bridge" % netdst)

    new_br_name = params.get("new_ovs_bridge_name", "temp_ovs_bridge")
    host_bridge = utils_net.find_bridge_manager(netdst)
    if host_bridge.br_exist(new_br_name) is True:
        host_bridge.del_br(new_br_name)
    host_bridge.add_br(new_br_name)
    error_context.context("OVS bridge %s created." % new_br_name, logging.info)

    try:
        ports = host_bridge.list_ports(netdst)
        host_bridge.add_port(new_br_name, ports[0])
    except process.CmdError as e:
        if "already exists on bridge" not in e.result.stderr_text:
            test.fail("Port %s should not be enslaved to another bridge."
                      " Output: %s" % (ports[0], e.result.stderr_text))
    else:
        test.fail("Add port cmd successfully excuted. However, port %s "
                  "should not be enslaved to another bridge." % ports[0])
    finally:
        host_bridge.del_br(new_br_name)
Esempio n. 6
0
def run(test, params, env):
    """
    Test openvswitch support for network.

    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 modify_iface_xml():
        """
        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]

        iface_type = params.get("iface_type")
        if iface_type:
            iface.type_name = iface_type
        source = eval(iface_source)
        if source:
            del iface.source
            iface.source = source
        iface_model = params.get("iface_model", "virtio")
        iface.model = iface_model
        iface_virtualport = params.get("iface_virtualport")
        if iface_virtualport:
            iface.virtualport_type = iface_virtualport
        logging.debug("New interface xml file: %s", iface)
        vmxml.devices = xml_devices
        vmxml.xmltreefile.write()
        vmxml.sync()

    def check_ovs_port(ifname, brname):
        """
        Check OVS port that created by libvirt
        """
        pg_name = params.get("porgroup_name", "").split()
        pg_vlan = params.get("portgroup_vlan", "").split()
        if_source = eval(iface_source)
        port_vlan = {}
        if if_source.has_key("portgroup"):
            pg = if_source["portgroup"]
            for (name, vlan) in zip(pg_name, pg_vlan):
                if pg == name:
                    port_vlan = eval(vlan)
        # Check bridge name by port name
        _, bridge = utils_net.find_current_bridge(ifname)
        assert bridge == brname
        # Get port info from ovs-vsctl output
        cmd = "ovs-vsctl list port %s" % ifname
        output = utils.run(cmd).stdout
        logging.debug("ovs port output: %s", output)
        for line in output.splitlines():
            if line.count("tag"):
                tag_info = line.rsplit(':')
                if (port_vlan.has_key("id") and tag_info[0] == "tag"):
                    assert port_vlan["id"] == tag_info[1]
            elif line.count("vlan_mode"):
                mode_info = line.rsplit(':')
                if (port_vlan.has_key("nativeMode")
                        and mode_info[0] == "vlan_mode"):
                    assert (port_vlan["nativeMode"] == "native-%s" %
                            mode_info[1])

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

    # network specific attributes.
    net_name = params.get("net_name", "default")
    net_bridge = params.get("net_bridge", "{'name':'virbr0'}")
    iface_source = params.get("iface_source", "{}")
    create_network = "yes" == params.get("create_network", "no")
    change_iface_option = "yes" == params.get("change_iface_option", "no")
    test_ovs_port = "yes" == params.get("test_ovs_port", "no")

    # Destroy the guest 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)

    bridge_name = eval(net_bridge)['name']
    # Build the xml and run test.
    try:
        # Edit the network xml or create a new one.
        if create_network:
            # Try to add ovs bridge first
            if not utils_net.ovs_br_exists(bridge_name):
                utils_net.add_ovs_bridge(bridge_name)
            netxml = libvirt.create_net_xml(net_name, params)
            netxml.sync()
        # Edit the interface xml.
        if change_iface_option:
            # Try to add bridge if needed
            source = eval(iface_source)
            if source:
                if source.has_key("bridge"):
                    if not utils_net.ovs_br_exists(source["bridge"]):
                        utils_net.add_ovs_bridge(source["bridge"])
            modify_iface_xml()

        try:
            # Start the VM.
            vm.start()
            if start_error:
                raise error.TestFail("VM started unexpectedly")

            iface_name = libvirt.get_ifname_host(vm_name, iface_mac)
            if test_ovs_port:
                check_ovs_port(iface_name, bridge_name)

        except virt_vm.VMStartError, details:
            logging.info(str(details))
            if start_error:
                pass
            else:
                raise error.TestFail('VM Failed to start for some reason!')

    finally:
        # Recover VM.
        if vm.is_alive():
            vm.destroy(gracefully=False)
        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)
        # Try to recovery ovs bridge
        if utils_net.ovs_br_exists(bridge_name):
            utils_net.del_ovs_bridge(bridge_name)
        vmxml_backup.sync()
Esempio n. 7
0
def run(test, params, env):
    """
    Test Step:
        1. Boot up two virtual machine
        2. Set openflow rules
        3. Run ping test, nc(tcp, udp) test, check whether openflow rules take
           effect.
    Params:
        :param test: QEMU test object
        :param params: Dictionary with the test parameters
        :param env: Dictionary with test environment.
    """
    def run_tcpdump_bg(vm, addresses, dump_protocol):
        """
        Run tcpdump in background, tcpdump will exit once catch a packet
        match the rules.
        """
        bg_session = vm.wait_for_login()
        if tcpdump_is_alive(bg_session):
            bg_session.cmd("killall -9 tcpdump")
        tcpdump_cmd = ("setsid tcpdump -iany -n -v %s and 'src %s and dst %s'"
                       " -c 1 >/dev/null 2>&1")
        bg_session.sendline(tcpdump_cmd % (dump_protocol, addresses[0],
                                           addresses[1]))
        if not utils_misc.wait_for(lambda: tcpdump_is_alive(bg_session),
                                   30, 0, 1, "Waiting tcpdump start..."):
            test.cancel("Error, can not run tcpdump")
        bg_session.close()

    def dump_catch_data(session, dump_log, catch_reg):
        """
        Search data from dump_log
        """
        dump_info = session.cmd_output("cat %s" % dump_log)
        if re.findall(catch_reg, dump_info, re.I):
            return True
        return False

    def tcpdump_is_alive(session):
        """
        Check whether tcpdump is alive
        """
        if session.cmd_status("pidof tcpdump"):
            return False
        return True

    def tcpdump_catch_packet_test(session, drop_flow=False):
        """
        Check whether tcpdump catch match rules packets, once catch a packet
        match rules tcpdump will exit.
        when drop_flow is 'True', tcpdump couldn't catch any packets.
        """
        packet_receive = not tcpdump_is_alive(session)
        if packet_receive == drop_flow:
            err_msg = "Error, flow %s" % (drop_flow and "was" or "wasn't")
            err_msg += " dropped, tcpdump "
            err_msg += "%s " % (packet_receive and "can" or "can not")
            err_msg += "receive the packets"
            test.error(err_msg)
        logging.info("Correct, flow %s dropped, tcpdump %s receive the packet"
                     % ((drop_flow and "was" or "was not"),
                         (packet_receive and "can" or "can not")))

    def arp_entry_clean(entry=None):
        """
        Clean arp catch in guest
        """
        if not entry:
            arp_clean_cmd = "arp -n | awk '/^[1-2]/{print \"arp -d \" $1}'|sh"
        else:
            arp_clean_cmd = "arp -d %s" % entry
        for session in sessions:
            session.cmd_output_safe(arp_clean_cmd)

    def check_arp_info(session, entry, vm, match_mac=None):
        arp_info = session.cmd_output("arp -n")
        arp_entries = [_ for _ in arp_info.splitlines() if re.match(entry, _)]

        match_string = match_mac or "incomplete"

        if not arp_entries:
            test.error("Can not find arp entry in %s: %s"
                       % (vm.name, arp_info))

        if not re.findall(match_string, arp_entries[0], re.I):
            test.fail("Can not find the mac address"
                      " %s of %s in arp"
                      " entry %s" % (match_mac, vm.name, arp_entries[0]))

    def ping_test(session, dst, drop_flow=False):
        """
        Ping test, check icmp
        """
        ping_status, ping_output = utils_test.ping(dest=dst, count=10,
                                                   timeout=20, session=session)
        # when drop_flow is true, ping should failed(return not zero)
        # drop_flow is false, ping should success
        packets_lost = 100
        if ping_status and not drop_flow:
            test.error("Ping should success when not drop_icmp")
        elif not ping_status:
            packets_lost = utils_test.get_loss_ratio(ping_output)
            if drop_flow and packets_lost != 100:
                test.error("When drop_icmp, ping shouldn't works")
            if not drop_flow and packets_lost == 100:
                test.error("When not drop_icmp, ping should works")

        info_msg = "Correct, icmp flow %s dropped, ping '%s', "
        info_msg += "packets lost rate is: '%s'"
        logging.info(info_msg % ((drop_flow and "was" or "was not"),
                                 (ping_status and "failed" or "success"),
                                 packets_lost))

    def run_ping_bg(vm, dst):
        """
        Run ping in background
        """
        ping_cmd = "ping %s" % dst
        session = vm.wait_for_login()
        logging.info("Ping %s in background" % dst)
        session.sendline(ping_cmd)
        return session

    def check_bg_ping(session):
        ping_pattern = r"\d+ bytes from \d+.\d+.\d+.\d+:"
        ping_pattern += r" icmp_seq=\d+ ttl=\d+ time=.*? ms"
        ping_failed_pattern = r"From .*? icmp_seq=\d+ Destination"
        ping_failed_pattern += r" Host Unreachable"
        try:
            out = session.read_until_output_matches([ping_pattern,
                                                     ping_failed_pattern])
            if re.search(ping_failed_pattern, out[1]):
                return False, out[1]
            else:
                return True, out[1]
        except Exception as msg:
            return False, msg

    def file_transfer(sessions, addresses, timeout):
        prepare_cmd = "dd if=/dev/zero of=/tmp/copy_file count=1024 bs=1M"
        md5_cmd = "md5sum /tmp/copy_file"
        port = params.get("shell_port")
        prompt = params.get("shell_prompt")
        username = params.get("username")
        password = params.get("password")
        sessions[0].cmd(prepare_cmd, timeout=timeout)
        ori_md5 = sessions[0].cmd_output(md5_cmd)
        scp_cmd = (r"scp -v -o UserKnownHostsFile=/dev/null "
                   r"-o StrictHostKeyChecking=no "
                   r"-o PreferredAuthentications=password -r "
                   r"-P %s /tmp/copy_file %s@\[%s\]:/tmp/copy_file" %
                   (port, username, addresses[1]))
        sessions[0].sendline(scp_cmd)
        remote.handle_prompts(sessions[0], username, password, prompt, 600)
        new_md5 = sessions[1].cmd_output(md5_cmd)
        for session in sessions:
            session.cmd("rm -f /tmp/copy_file")
        if new_md5 != ori_md5:
            test.fail("Md5 value changed after file transfer, "
                      "original is %s and the new file"
                      " is: %s" % (ori_md5, new_md5))

    def nc_connect_test(sessions, addresses, drop_flow=False, nc_port="8899",
                        udp_model=False):
        """
        Nc connect test, check tcp and udp
        """
        nc_log = "/tmp/nc_log"
        server_cmd = "nc -l %s"
        client_cmd = "echo client | nc %s %s"
        if udp_model:
            server_cmd += " -u -w 3"
            client_cmd += " -u -w 3"
        server_cmd += " > %s &"
        client_cmd += " &"
        try:
            sessions[1].cmd_output_safe(server_cmd % (nc_port, nc_log))
            sessions[0].cmd_output_safe(client_cmd % (addresses[1], nc_port))

            nc_protocol = udp_model and "UDP" or "TCP"
            nc_connect = False
            if utils_misc.wait_for(
                    lambda: dump_catch_data(sessions[1], nc_log, "client"),
                    10, 0, 2, text="Wait '%s' connect" % nc_protocol):
                nc_connect = True
            if nc_connect == drop_flow:
                err_msg = "Error, '%s' " % nc_protocol
                err_msg += "flow %s " % (drop_flow and "was" or "was not")
                err_msg += "dropped, nc connect should"
                err_msg += " '%s'" % (nc_connect and "failed" or "success")
                test.error(err_msg)

            logging.info("Correct, '%s' flow %s dropped, and nc connect %s" %
                         (nc_protocol, (drop_flow and "was" or "was not"),
                          (nc_connect and "success" or "failed")))
        finally:
            for session in sessions:
                session.cmd_output_safe("killall nc || killall ncat")
                session.cmd("%s %s" % (clean_cmd, nc_log),
                            ignore_all_errors=True)

    def acl_rules_check(acl_rules, flow_options):
        flow_options = re.sub("action=", "actions=", flow_options)
        if "arp" in flow_options:
            flow_options = re.sub("nw_src=", "arp_spa=", flow_options)
            flow_options = re.sub("nw_dst=", "arp_tpa=", flow_options)
        acl_options = re.split(",", flow_options)
        for line in acl_rules.splitlines():
            rule = [_.lower() for _ in re.split("[ ,]", line) if _]
            item_in_rule = 0

            for acl_item in acl_options:
                if acl_item.lower() in rule:
                    item_in_rule += 1

            if item_in_rule == len(acl_options):
                return True
        return False

    def remove_plus_items(open_flow_rules):
        plus_items = ["duration", "n_packets", "n_bytes", "idle_age", "hard_age"]
        for plus_item in plus_items:
            open_flow_rules = re.sub("%s=.*?," % plus_item, "",
                                     open_flow_rules)
        return open_flow_rules

    br_name = params.get("netdst", "ovs0")
    timeout = int(params.get("login_timeout", '360'))
    prepare_timeout = int(params.get("prepare_timeout", '360'))
    clean_cmd = params.get("clean_cmd", "rm -f")
    sessions = []
    addresses = []
    vms = []
    bg_ping_session = None

    if not utils_net.ovs_br_exists(br_name):
        test.cancel("%s isn't an openvswith bridge" % br_name)

    error_context.context("Init boot the vms")
    for vm_name in params.objects("vms"):
        vms.append(env.get_vm(vm_name))
    for vm in vms:
        vm.verify_alive()
        sessions.append(vm.wait_for_login(timeout=timeout))
        addresses.append(vm.get_address())

    # set openflow rules:
    f_protocol = params.get("flow", "arp")
    f_base_options = "%s,nw_src=%s,nw_dst=%s" % (f_protocol, addresses[0],
                                                 addresses[1])
    for session in sessions:
        session.cmd("systemctl stop firewalld || service firewalld stop",
                    ignore_all_errors=True)

    try:
        for drop_flow in [True, False]:
            if drop_flow:
                f_command = "add-flow"
                f_options = f_base_options + ",action=drop"
                drop_icmp = eval(params.get("drop_icmp", 'True'))
                drop_tcp = eval(params.get("drop_tcp", 'True'))
                drop_udp = eval(params.get("drop_udp", 'True'))
            else:
                f_command = "mod-flows"
                f_options = f_base_options + ",action=normal"
                drop_icmp = False
                drop_tcp = False
                drop_udp = False

            error_context.base_context("Test prepare")
            error_context.context("Do %s %s on %s"
                                  % (f_command, f_options, br_name))
            utils_net.openflow_manager(br_name, f_command, f_options)
            acl_rules = utils_net.openflow_manager(
                br_name, "dump-flows").stdout.decode()
            if not acl_rules_check(acl_rules, f_options):
                test.fail("Can not find the rules from"
                          " ovs-ofctl: %s" % acl_rules)

            error_context.context("Run tcpdump in guest %s" % vms[1].name,
                                  logging.info)
            run_tcpdump_bg(vms[1], addresses, f_protocol)

            if drop_flow or f_protocol is not "arp":
                error_context.context("Clean arp cache in both guest",
                                      logging.info)
                arp_entry_clean(addresses[1])

            error_context.base_context(
                "Exec '%s' flow '%s' test" %
                (f_protocol, drop_flow and "drop" or "normal"))
            if drop_flow:
                error_context.context("Ping test form %s to %s" %
                                      (vms[0].name, vms[1].name), logging.info)
                ping_test(sessions[0], addresses[1], drop_icmp)
                if params.get("run_file_transfer") == "yes":
                    error_context.context("Transfer file form %s to %s" %
                                          (vms[0].name, vms[1].name),
                                          logging.info)
                    file_transfer(sessions, addresses, prepare_timeout)
            else:
                error_context.context("Ping test form %s to %s in background" %
                                      (vms[0].name, vms[1].name), logging.info)
                bg_ping_session = run_ping_bg(vms[0], addresses[1])

            if f_protocol == 'arp' and drop_flow:
                error_context.context("Check arp inside %s" % vms[0].name,
                                      logging.info)
                check_arp_info(sessions[0], addresses[1], vms[0])
            elif f_protocol == 'arp' or params.get("check_arp") == "yes":
                time.sleep(2)
                error_context.context("Check arp inside guests.", logging.info)
                for index, address in enumerate(addresses):
                    sess_index = (index + 1) % 2
                    mac = vms[index].virtnet.get_mac_address(0)
                    check_arp_info(sessions[sess_index], address, vms[index],
                                   mac)

            error_context.context("Run nc connect test via tcp", logging.info)
            nc_connect_test(sessions, addresses, drop_tcp)

            error_context.context("Run nc connect test via udp", logging.info)
            nc_connect_test(sessions, addresses, drop_udp, udp_model=True)

            error_context.context("Check tcpdump data catch", logging.info)
            tcpdump_catch_packet_test(sessions[1], drop_flow)
    finally:
        openflow_rules_ori = utils_net.openflow_manager(
            br_name, "dump-flows").stdout.decode()
        openflow_rules_ori = remove_plus_items(openflow_rules_ori)
        utils_net.openflow_manager(br_name, "del-flows", f_protocol)
        openflow_rules = utils_net.openflow_manager(
            br_name, "dump-flows").stdout.decode()
        openflow_rules = remove_plus_items(openflow_rules)
        removed_rule = list(set(openflow_rules_ori.splitlines()) -
                            set(openflow_rules.splitlines()))

        if f_protocol == "tcp":
            error_context.context("Run nc connect test via tcp", logging.info)
            nc_connect_test(sessions, addresses)
        elif f_protocol == "udp":
            error_context.context("Run nc connect test via udp", logging.info)
            nc_connect_test(sessions, addresses, udp_model=True)

        for session in sessions:
            session.close()
        failed_msg = []
        if (not removed_rule or
                not acl_rules_check(removed_rule[0], f_options)):
            failed_msg.append("Failed to delete %s" % f_options)
        if bg_ping_session:
            bg_ping_ok = check_bg_ping(bg_ping_session)
            bg_ping_session.close()
            if not bg_ping_ok[0]:
                failed_msg.append("There is something wrong happen in "
                                  "background ping: %s" % bg_ping_ok[1])

        if failed_msg:
            test.fail(failed_msg)
Esempio n. 8
0
def run(test, params, env):
    """
    Since 3.3.0, Coalesce setting is supported.

    This case is to set coalesce and check for 4 network types and each guest interface type.

    Only network/bridge guest interface type take effect for setting interface coalesce.

    For each host network type, guest can use bridge/network interface type to set coalesce
    except macvtap network type.
    Execute 'ethtool -c ${interface}|grep "rx-frames"' and anylize the output to check
    whether coalesce setting take effect or not.

    For macvtap network type, guest can start but query coalesce will fail.

    1. For default host network

    network definition is below:
    <network>
       <name>default</name>
       <bridge name="virbr0"/>
       <forward/>
       <ip address="192.168.122.1" netmask="255.255.255.0">
          <dhcp>
             <range start="192.168.122.2" end="192.168.122.254"/>
          </dhcp>
       </ip>
    </network>

    This is default network.

    1) guest interface type 'bridge' and set coalesce:
    <interface type='bridge'>
      <mac address='52:54:00:a7:4d:f7'/>
      <source bridge='virbr0'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='64'/>
        </rx>
      </coalesce>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>

    2) guest interface type 'network' and set coalesce:
    <interface type='network'>
      <source network='default'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='32'/>
        </rx>
      </coalesce>
    </interface>

    2. For bridge host network
    This mode need true bridge in host network.
    'nmcli con add type bridge con-name br0 ifname br0'

    1) guest interface type 'bridge' and set coalesce:
    <interface type='bridge'>
      <mac address='52:54:00:8e:f3:6f'/>
      <source bridge='br0'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='64'/>
        </rx>
      </coalesce>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
    </interface>

    2) guest interface type 'network' and set coalesce:
    First, define one virtual network for bridge br0
    'virsh net-define net-br0.xml'
    'virsh net-dumpxml net-br0'
    <network>
       <name>net-br0</name>
       <forward mode='bridge'/>
       <bridge name='br0'/>
    </network>
    Secondly, use this network for guest
    <interface type='network'>
      <source network='net-br0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='32'/>
        </rx>
      </coalesce>
    </interface>

    3. For openvswitch bridge host network
    This mode need true openvswitch bridge in host network.
    'ovs-vsctl add-br ovsbr0'

    1) guest interface type 'bridge' and set coalesce:
    <interface type='bridge'>
      <mac address='52:54:00:8e:f3:6f'/>
      <source bridge='ovsbr0'/>
      <virtualport type='openvswitch'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='64'/>
        </rx>
      </coalesce>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
    </interface>

    2) guest interface type 'network' and set coalesce:
    First, define one virtual network for openvswitch bridge ovsbr0
    'virsh net-define net-ovsbr0.xml'
    'virsh net-dumpxml net-ovsbr0'
    <network>
       <name>net-ovs0</name>
       <forward mode='bridge'/>
       <bridge name='ovsbr0'/>
       <virtualport type='openvswitch'/>
    </network>

    Secondly, use this network for guest
    <interface type='network'>
      <source network='net-ovs0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='32'/>
        </rx>
      </coalesce>
    </interface>

    4. For macvtap bridge mode on host network
    For this mode, first, create one virtual network.
    Note, should set dev to one ture physical interface.
    'virsh net-define net-br-macvtap.xml'
    'virsh net-dumpxml net-br-macvtap'
    <network>
       <name>net-br-macvtap</name>
       <forward dev='eno1' mode='bridge'>
           <interface dev='eno1'/>
       </forward>
    </network>
    Set guest to use this macvtap network and set coalesc
    <interface type='network'>
      <mac address='52:54:00:6e:f4:f1'/>
      <source network='net-br-macvtap'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='32'/>
        </rx>
      </coalesce>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>

    Steps in this test:
    1. Prepare test environment,destroy or suspend a VM.
    2. Prepare network if necessary.
    3. Edit guest interface with definite network and set coalesce.
    4. Start guest and check whether coalesce setting take effect.
    5. Recover network and guest.
    """

    if not libvirt_version.version_compare(3, 3, 0):
        test.skip(
            "Coalesce setting is only supported by libvirt3.3.0 and above")

    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)

    def get_first_phy_iface():
        """
        Get first physical network interface from output of 'ls /sys/class/net'

        #ls /sys/class/net
         eno1  lo  virbr0  virbr0-nic

        :return: interface name
        """
        interface = ''
        lines = process.run('ls /sys/class/net').stdout_text.splitlines()
        interfaces = lines[0].split()
        for iface in interfaces:
            if iface != 'lo' and 'vir' not in iface:
                interface = iface
                break
        if interface == '':
            test.fail("There is no physical network interface")
        return interface

    def modify_iface_xml():
        """
        Modify interface xml options
        Two methods to modify domain interfae:
        1. modify guest xml, define it
        2. attach one interface for running guest

        :return: 0 for successful negative case
                 test.fail is fail for positive/negative case
                 None for successful positive case
        """
        if hotplug_iface:
            iface = Interface(iface_type)
        else:
            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_type == 'network':
            iface.type_name = iface_type
            source = {iface_type: net_name}
        elif iface_type == 'bridge' and bridge_name:
            iface.type_name = iface_type
            source = {iface_type: bridge_name}
        elif iface_type == 'direct':
            iface.type_name = iface_type
            source = {'dev': interface, 'mode': 'bridge'}

        if source:
            del iface.source
            iface.source = source
        iface_model = params.get("iface_model", "virtio")
        iface.model = iface_model
        iface.coalesce = {'max': coalesce_value}
        if network_type == "ovsbridge" and iface_type == "bridge":
            iface.virtualport_type = "openvswitch"

        if not hotplug_iface:
            vmxml.devices = xml_devices
            vmxml.xmltreefile.write()
            try:
                vmxml.sync()
            except xcepts.LibvirtXMLError as details:
                if status_error:
                    # Expect error for negetive test
                    return 0
                else:
                    test.fail("Define guest: FAIL")
        else:
            if not vm.is_alive():
                vm.start()
                # Wait guest boot completely
                time.sleep(2)
            try:
                ret = virsh.attach_device(vm_name,
                                          iface.xml,
                                          ignore_status=False,
                                          debug=True)
            except process.CmdError as error:
                if status_error:
                    # Expect error for negetive test
                    return 0
                else:
                    test.fail("Define guest: FAIL")

    start_error = "yes" == params.get("start_error", "no")
    status_error = "yes" == params.get("status_error", "no")

    # Get coalesce value.
    expect_coalesce = params.get("expect_coalesce", "")
    coalesce_value = params.get("coalesce", "15")
    if expect_coalesce == '':
        expect_coalesce = coalesce_value

    # Network specific attributes.
    network_type = params.get("network_type", "default")
    net_name = params.get("net_name", "default")
    net_bridge = params.get("net_bridge", "{'name':'virbr0'}")

    # Get guest interface type
    iface_type = params.get("iface_type", "network")

    # Whether attach interface
    hotplug_iface = "yes" == params.get("hotplug_iface", "no")
    error_info = params.get("error_info", "")

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

    # Back up xml file.
    netxml_backup = NetworkXML.new_from_net_dumpxml("default")
    vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

    # Build the xml and run test.
    try:
        interface = get_first_phy_iface()

        # Prepare network for specific network type.
        # Create bridge/ovsbridge for host bridge/ovsbridge network type
        if network_type == "default" and iface_type == "bridge":
            bridge_name = "virbr0"
        elif network_type == "bridge":
            bridge_name = eval(net_bridge)['name']
            bridge = utils_net.Bridge()
            # Try to add bridge if not exist
            if bridge_name not in bridge.list_br():
                bridge.add_bridge(bridge_name)
        elif network_type == 'ovsbridge':
            bridge_name = eval(net_bridge)['name']
            # Try to add ovs bridge if not exist
            if not utils_net.ovs_br_exists(bridge_name):
                utils_net.add_ovs_bridge(bridge_name)

        if iface_type == "network":
            # Define virtual network if not exist for 'network' type of guest interface
            network = NetworkXML()
            network.name = net_name
            # Prepare virtual network required parameters
            params['net_forward'] = "{'mode':'bridge'}"
            if network_type == "ovsbridge":
                params['net_virtualport'] = "openvswitch"
            if network_type == "macvtap":
                # For bridge type of macvtap network, one true physical interface shold be added
                # Check whether physical interface has been added into one bridge. if yes, skip macvtap test
                # If interface already added to a bridge, the output of the nmcli
                # command will include "connection.slave-type: bridge"
                out = process.run('nmcli dev show %s' % interface).stdout_text
                con_l = re.findall(r'GENERAL.CONNECTION:(.+?)\n', out)
                if not con_l:
                    test.cancel("no connection for the interface")
                else:
                    con = con_l[0].strip()
                if "bridge" not in process.run('nmcli con show "%s"' %
                                               con).stdout_text:
                    params['forward_iface'] = interface
                    params[
                        'net_forward'] = "{'mode':'bridge', 'dev': '%s'}" % interface
                else:
                    test.cancel(
                        "interface %s has been added into one brige, but macvtap"
                        "need also add this interface, so current network can't"
                        "suit macvtap testing" % interface)
            if not network.exists():
                netxml = libvirt.create_net_xml(net_name, params)
                netxml.define()
                netxml.start()
                virsh.net_dumpxml(network.name, debug=True)
        # Edit the interface xml.
        # For successful negative case, return 0 to specify PASS result directly
        ret = modify_iface_xml()
        if ret == 0:
            return 0
        try:
            # Get all interface
            link_before = set(
                process.run('ls /sys/class/net').stdout_text.splitlines())
            # Start the VM.
            vm.start()
            if start_error:
                raise test.fail("VM started unexpectedly")
            # Get guest virtual network interface
            link_after = set(
                process.run('ls /sys/class/net').stdout_text.splitlines())
            newinterface = (link_after - link_before).pop()
            out = process.run('ethtool -c %s' % newinterface,
                              ignore_status=True)
            if network_type == 'macvtap':
                # Currently, output coalesce for macvtap is not supported
                err_msg = "Cannot get device coalesce settings: Operation not supported"
                std_msg = "Coalesce parameters for %s:" % newinterface
                if err_msg not in out.stderr_text or std_msg not in out.stdout_text:
                    test.fail("coalesce setting on %s failed." % network_type)
            else:
                # Get coalesce value and check it is true
                if out.exit_status == 0:
                    for line in out.stdout_text.splitlines():
                        if 'rx-frames:' in line:
                            coalesce = line.split(':')[1].strip()
                            if expect_coalesce != coalesce:
                                test.fail("coalesce setting failed for %s" %
                                          network_type)
                            break
                else:
                    test.fail("coalesce setting on %s failed." % network_type)
        except virt_vm.VMStartError as details:
            logging.info(str(details))
            if not start_error:
                test.fail('VM failed to start:\n%s' % details)

    finally:
        # Recover VM.
        if vm.is_alive():
            vm.destroy(gracefully=False)
        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)
        # Try to recovery bridge
        if network_type == "bridge" and bridge_name:
            if bridge_name in bridge.list_br():
                bridge.del_bridge(bridge_name)
        elif network_type == "ovsbridge" and bridge_name:
            if utils_net.ovs_br_exists(bridge_name):
                utils_net.del_ovs_bridge(bridge_name)
        vmxml_backup.sync()
Esempio n. 9
0
def run(test, params, env):
    """
    Test openvswitch support for network.

    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 modify_iface_xml():
        """
        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]

        iface_type = params.get("iface_type")
        if iface_type:
            iface.type_name = iface_type
        source = eval(iface_source)
        if source:
            del iface.source
            iface.source = source
        iface_model = params.get("iface_model", "virtio")
        iface.model = iface_model
        iface_virtualport = params.get("iface_virtualport")
        if iface_virtualport:
            iface.virtualport_type = iface_virtualport
        logging.debug("New interface xml file: %s", iface)
        vmxml.devices = xml_devices
        vmxml.xmltreefile.write()
        vmxml.sync()

    def check_ovs_port(ifname, brname):
        """
        Check OVS port that created by libvirt
        """
        pg_name = params.get("porgroup_name", "").split()
        pg_vlan = params.get("portgroup_vlan", "").split()
        if_source = eval(iface_source)
        port_vlan = {}
        if if_source.has_key("portgroup"):
            pg = if_source["portgroup"]
            for (name, vlan) in zip(pg_name, pg_vlan):
                if pg == name:
                    port_vlan = eval(vlan)
        # Check bridge name by port name
        _, bridge = utils_net.find_current_bridge(ifname)
        assert bridge == brname
        # Get port info from ovs-vsctl output
        cmd = "ovs-vsctl list port %s" % ifname
        output = utils.run(cmd).stdout
        logging.debug("ovs port output: %s", output)
        for line in output.splitlines():
            if line.count("tag"):
                tag_info = line.rsplit(":")
                if port_vlan.has_key("id") and tag_info[0] == "tag":
                    assert port_vlan["id"] == tag_info[1]
            elif line.count("vlan_mode"):
                mode_info = line.rsplit(":")
                if port_vlan.has_key("nativeMode") and mode_info[0] == "vlan_mode":
                    assert port_vlan["nativeMode"] == "native-%s" % mode_info[1]

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

    # network specific attributes.
    net_name = params.get("net_name", "default")
    net_bridge = params.get("net_bridge", "{'name':'virbr0'}")
    iface_source = params.get("iface_source", "{}")
    create_network = "yes" == params.get("create_network", "no")
    change_iface_option = "yes" == params.get("change_iface_option", "no")
    test_ovs_port = "yes" == params.get("test_ovs_port", "no")

    # Destroy the guest 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)

    bridge_name = eval(net_bridge)["name"]
    # Build the xml and run test.
    try:
        # Edit the network xml or create a new one.
        if create_network:
            # Try to add ovs bridge first
            if not utils_net.ovs_br_exists(bridge_name):
                utils_net.add_ovs_bridge(bridge_name)
            netxml = libvirt.create_net_xml(net_name, params)
            netxml.sync()
        # Edit the interface xml.
        if change_iface_option:
            # Try to add bridge if needed
            source = eval(iface_source)
            if source:
                if source.has_key("bridge"):
                    if not utils_net.ovs_br_exists(source["bridge"]):
                        utils_net.add_ovs_bridge(source["bridge"])
            modify_iface_xml()

        try:
            # Start the VM.
            vm.start()
            if start_error:
                raise error.TestFail("VM started unexpectedly")

            iface_name = libvirt.get_ifname_host(vm_name, iface_mac)
            if test_ovs_port:
                check_ovs_port(iface_name, bridge_name)

        except virt_vm.VMStartError, details:
            logging.info(str(details))
            if start_error:
                pass
            else:
                raise error.TestFail("VM Failed to start for some reason!")

    finally:
        # Recover VM.
        if vm.is_alive():
            vm.destroy(gracefully=False)
        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)
        # Try to recovery ovs bridge
        if utils_net.ovs_br_exists(bridge_name):
            utils_net.del_ovs_bridge(bridge_name)
        vmxml_backup.sync()
Esempio n. 10
0
def run(test, params, env):
    """
    Expose host MTU to guest test

    1) Boot up guest with param 'host_mtu=4000' in nic part
    2) Disable NetworkManager in guest
    3) set mtu of guest tap (eg: tap0) and physical nic (eg: eno1) to
       4000 in host
    4) check the mtu in guest
    5) ping from guest to external host with packet size 3972

    :param test: kvm test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment
    """
    def cleanup_ovs_ports(netdst, ports):
        """
        Clean up created ovs ports in this case

        :param netdst: netdst get from command line
        :param ports: existing ports need to be remain before this test
        """

        host_bridge = utils_net.find_bridge_manager(netdst)
        if utils_net.ovs_br_exists(netdst) is True:
            ports = set(host_bridge.list_ports(netdst)) - set(ports)
            for p in ports:
                utils_net.find_bridge_manager(netdst).del_port(netdst, p)

    netdst = params.get("netdst", "switch")
    mtu_value = params.get_numeric("mtu_value")
    host_bridge = utils_net.find_bridge_manager(netdst)
    localhost = LocalHost()
    try:
        if netdst in utils_net.Bridge().list_br():
            host_hw_interface = utils_net.Bridge().list_iface(netdst)[0]
        else:
            host_hw_interface = host_bridge.list_ports(netdst)
            tmp_ports = re.findall(r"t[0-9]{1,}-[a-zA-Z0-9]{6}",
                                   ' '.join(host_hw_interface))
            if tmp_ports:
                for p in tmp_ports:
                    host_bridge.del_port(netdst, p)
                host_hw_interface = host_bridge.list_ports(netdst)
    except IndexError:
        host_hw_interface = netdst

    params["start_vm"] = "yes"
    env_process.preprocess_vm(test, params, env, params["main_vm"])

    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    vm_iface = vm.get_ifname()
    # Get host interface original mtu value before setting
    if netdst in utils_net.Bridge().list_br():
        host_hw_iface = NetworkInterface(host_hw_interface, localhost)
    elif utils_net.ovs_br_exists(netdst) is True:
        host_hw_iface = NetworkInterface(' '.join(host_hw_interface),
                                         localhost)
    host_mtu_origin = host_hw_iface.get_mtu()

    set_mtu_host(vm_iface, mtu_value)
    host_hw_iface.set_mtu(mtu_value)

    os_type = params.get("os_type", "linux")
    login_timeout = float(params.get("login_timeout", 360))
    session = vm.wait_for_login(timeout=login_timeout)

    host_ip = utils_net.get_ip_address_by_interface(params["netdst"])
    if os_type == "linux":
        session.cmd_output_safe(params["nm_stop_cmd"])
        guest_ifname = utils_net.get_linux_ifname(session,
                                                  vm.get_mac_address())
        output = session.cmd_output_safe(params["check_linux_mtu_cmd"] %
                                         guest_ifname)
        error_context.context(output, logging.info)
        match_string = "mtu %s" % params["mtu_value"]
        if match_string not in output:
            test.fail("host mtu %s not exposed to guest" % params["mtu_value"])
    elif os_type == "windows":
        connection_id = utils_net.get_windows_nic_attribute(
            session, "macaddress", vm.get_mac_address(), "netconnectionid")
        output = session.cmd_output_safe(params["check_win_mtu_cmd"] %
                                         connection_id)
        error_context.context(output, logging.info)
        lines = output.strip().splitlines()
        lines_len = len(lines)

        line_table = lines[0].split('  ')
        line_value = lines[2].split('  ')
        while '' in line_table:
            line_table.remove('')
        while '' in line_value:
            line_value.remove('')
        index = 0
        for name in line_table:
            if re.findall("MTU", name):
                break
            index += 1
        guest_mtu_value = line_value[index]
        logging.info("MTU is %s", guest_mtu_value)
        if not int(guest_mtu_value) == mtu_value:
            test.fail("Host mtu %s is not exposed to "
                      "guest!" % params["mtu_value"])

    logging.info("Ping from guest to host with packet size 3972")
    status, output = utils_test.ping(host_ip,
                                     10,
                                     packetsize=3972,
                                     timeout=30,
                                     session=session)
    ratio = utils_test.get_loss_ratio(output)
    if ratio != 0:
        test.fail("Loss ratio is %s", ratio)

    # Restore host mtu after finish testing
    set_mtu_host(vm_iface, host_mtu_origin)
    host_hw_iface.set_mtu(host_mtu_origin)

    if netdst not in utils_net.Bridge().list_br():
        cleanup_ovs_ports(netdst, host_hw_interface)
    session.close()
Esempio n. 11
0
def run(test, params, env):
    """
    Since 3.3.0, Coalesce setting is supported.

    This case is to set coalesce and check for 4 network types and each guest interface type.

    Only network/bridge guest interface type take effect for setting interface coalesce.

    For each host network type, guest can use bridge/network interface type to set coalesce
    except macvtap network type.
    Execute 'ethtool -c ${interface}|grep "rx-frames"' and anylize the output to check
    whether coalesce setting take effect or not.

    For macvtap network type, guest can start but query coalesce will fail.

    1. For default host network

    network definition is below:
    <network>
       <name>default</name>
       <bridge name="virbr0"/>
       <forward/>
       <ip address="192.168.122.1" netmask="255.255.255.0">
          <dhcp>
             <range start="192.168.122.2" end="192.168.122.254"/>
          </dhcp>
       </ip>
    </network>

    This is default network.

    1) guest interface type 'bridge' and set coalesce:
    <interface type='bridge'>
      <mac address='52:54:00:a7:4d:f7'/>
      <source bridge='virbr0'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='64'/>
        </rx>
      </coalesce>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>

    2) guest interface type 'network' and set coalesce:
    <interface type='network'>
      <source network='default'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='32'/>
        </rx>
      </coalesce>
    </interface>

    2. For bridge host network
    This mode need true bridge in host network.
    'nmcli con add type bridge con-name br0 ifname br0'

    1) guest interface type 'bridge' and set coalesce:
    <interface type='bridge'>
      <mac address='52:54:00:8e:f3:6f'/>
      <source bridge='br0'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='64'/>
        </rx>
      </coalesce>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
    </interface>

    2) guest interface type 'network' and set coalesce:
    First, define one virtual network for bridge br0
    'virsh net-define net-br0.xml'
    'virsh net-dumpxml net-br0'
    <network>
       <name>net-br0</name>
       <forward mode='bridge'/>
       <bridge name='br0'/>
    </network>
    Secondly, use this network for guest
    <interface type='network'>
      <source network='net-br0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='32'/>
        </rx>
      </coalesce>
    </interface>

    3. For openvswitch bridge host network
    This mode need true openvswitch bridge in host network.
    'ovs-vsctl add-br ovsbr0'

    1) guest interface type 'bridge' and set coalesce:
    <interface type='bridge'>
      <mac address='52:54:00:8e:f3:6f'/>
      <source bridge='ovsbr0'/>
      <virtualport type='openvswitch'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='64'/>
        </rx>
      </coalesce>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
    </interface>

    2) guest interface type 'network' and set coalesce:
    First, define one virtual network for openvswitch bridge ovsbr0
    'virsh net-define net-ovsbr0.xml'
    'virsh net-dumpxml net-ovsbr0'
    <network>
       <name>net-ovs0</name>
       <forward mode='bridge'/>
       <bridge name='ovsbr0'/>
       <virtualport type='openvswitch'/>
    </network>

    Secondly, use this network for guest
    <interface type='network'>
      <source network='net-ovs0'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='32'/>
        </rx>
      </coalesce>
    </interface>

    4. For macvtap bridge mode on host network
    For this mode, first, create one virtual network.
    Note, should set dev to one ture physical interface.
    'virsh net-define net-br-macvtap.xml'
    'virsh net-dumpxml net-br-macvtap'
    <network>
       <name>net-br-macvtap</name>
       <forward dev='eno1' mode='bridge'>
           <interface dev='eno1'/>
       </forward>
    </network>
    Set guest to use this macvtap network and set coalesc
    <interface type='network'>
      <mac address='52:54:00:6e:f4:f1'/>
      <source network='net-br-macvtap'/>
      <model type='virtio'/>
      <coalesce>
        <rx>
          <frames max='32'/>
        </rx>
      </coalesce>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>

    Steps in this test:
    1. Prepare test environment,destroy or suspend a VM.
    2. Prepare network if necessary.
    3. Edit guest interface with definite network and set coalesce.
    4. Start guest and check whether coalesce setting take effect.
    5. Recover network and guest.
    """

    if not libvirt_version.version_compare(3, 3, 0):
        test.skip("Coalesce setting is only supported by libvirt3.3.0 and above")

    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)

    def get_first_phy_iface():
        """
        Get first physical network interface from output of 'ls /sys/class/net'

        #ls /sys/class/net
         eno1  lo  virbr0  virbr0-nic

        :return: interface name
        """
        interface = ''
        lines = process.run('ls /sys/class/net').stdout_text.splitlines()
        interfaces = lines[0].split()
        for iface in interfaces:
            if iface != 'lo' and 'vir' not in iface:
                interface = iface
                break
        if interface == '':
            test.fail("There is no physical network interface")
        return interface

    def modify_iface_xml():
        """
        Modify interface xml options
        Two methods to modify domain interfae:
        1. modify guest xml, define it
        2. attach one interface for running guest

        :return: 0 for successful negative case
                 test.fail is fail for positive/negative case
                 None for successful positive case
        """
        if hotplug_iface:
            iface = Interface(iface_type)
        else:
            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_type == 'network':
            iface.type_name = iface_type
            source = {iface_type: net_name}
        elif iface_type == 'bridge' and bridge_name:
            iface.type_name = iface_type
            source = {iface_type: bridge_name}
        elif iface_type == 'direct':
            iface.type_name = iface_type
            source = {'dev': interface, 'mode': 'bridge'}

        if source:
            del iface.source
            iface.source = source
        iface_model = params.get("iface_model", "virtio")
        iface.model = iface_model
        iface.coalesce = {'max': coalesce_value}
        if network_type == "ovsbridge" and iface_type == "bridge":
            iface.virtualport_type = "openvswitch"

        if not hotplug_iface:
            vmxml.devices = xml_devices
            vmxml.xmltreefile.write()
            try:
                vmxml.sync()
            except xcepts.LibvirtXMLError as details:
                if status_error:
                    # Expect error for negetive test
                    return 0
                else:
                    test.fail("Define guest: FAIL")
        else:
            if not vm.is_alive():
                vm.start()
                # Wait guest boot completely
                time.sleep(2)
            try:
                ret = virsh.attach_device(vm_name, iface.xml,
                                          ignore_status=False,
                                          debug=True)
            except process.CmdError as error:
                if status_error:
                    # Expect error for negetive test
                    return 0
                else:
                    test.fail("Define guest: FAIL")

    start_error = "yes" == params.get("start_error", "no")
    status_error = "yes" == params.get("status_error", "no")

    # Get coalesce value.
    expect_coalesce = params.get("expect_coalesce", "")
    coalesce_value = params.get("coalesce", "15")
    if expect_coalesce == '':
        expect_coalesce = coalesce_value

    # Network specific attributes.
    network_type = params.get("network_type", "default")
    net_name = params.get("net_name", "default")
    net_bridge = params.get("net_bridge", "{'name':'virbr0'}")

    # Get guest interface type
    iface_type = params.get("iface_type", "network")

    # Whether attach interface
    hotplug_iface = "yes" == params.get("hotplug_iface", "no")
    error_info = params.get("error_info", "")

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

    # Back up xml file.
    netxml_backup = NetworkXML.new_from_net_dumpxml("default")
    vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

    # Build the xml and run test.
    try:
        interface = get_first_phy_iface()

        # Prepare network for specific network type.
        # Create bridge/ovsbridge for host bridge/ovsbridge network type
        if network_type == "default" and iface_type == "bridge":
            bridge_name = "virbr0"
        elif network_type == "bridge":
            bridge_name = eval(net_bridge)['name']
            bridge = utils_net.Bridge()
            # Try to add bridge if not exist
            if bridge_name not in bridge.list_br():
                bridge.add_bridge(bridge_name)
        elif network_type == 'ovsbridge':
            bridge_name = eval(net_bridge)['name']
            # Try to add ovs bridge if not exist
            if not utils_net.ovs_br_exists(bridge_name):
                utils_net.add_ovs_bridge(bridge_name)

        if iface_type == "network":
            # Define virtual network if not exist for 'network' type of guest interface
            network = NetworkXML()
            network.name = net_name
            # Prepare virtual network required parameters
            params['net_forward'] = "{'mode':'bridge'}"
            if network_type == "ovsbridge":
                params['net_virtualport'] = "openvswitch"
            if network_type == "macvtap":
                # For bridge type of macvtap network, one true physical interface shold be added
                # Check whether physical interface has been added into one bridge. if yes, skip macvtap test
                # If interface already added to a bridge, the output of the nmcli
                # command will include "connection.slave-type: bridge"
                out = process.run('nmcli dev show %s' % interface).stdout_text
                con_l = re.findall(r'GENERAL.CONNECTION:(.+?)\n', out)
                if not con_l:
                    test.cancel("no connection for the interface")
                else:
                    con = con_l[0].strip()
                if "bridge" not in process.run('nmcli con show "%s"' % con).stdout_text:
                    params['forward_iface'] = interface
                    params['net_forward'] = "{'mode':'bridge', 'dev': '%s'}" % interface
                else:
                    test.cancel("interface %s has been added into one brige, but macvtap"
                                "need also add this interface, so current network can't"
                                "suit macvtap testing" % interface)
            if not network.exists():
                netxml = libvirt.create_net_xml(net_name, params)
                netxml.define()
                netxml.start()
                virsh.net_dumpxml(network.name, debug=True)
        # Edit the interface xml.
        # For successful negative case, return 0 to specify PASS result directly
        ret = modify_iface_xml()
        if ret == 0:
            return 0
        try:
            # Get all interface
            link_before = set(process.run('ls /sys/class/net').stdout_text.splitlines())
            # Start the VM.
            vm.start()
            if start_error:
                raise test.fail("VM started unexpectedly")
            # Get guest virtual network interface
            link_after = set(process.run('ls /sys/class/net').stdout_text.splitlines())
            newinterface = (link_after - link_before).pop()
            out = process.run('ethtool -c %s' % newinterface, ignore_status=True)
            if network_type == 'macvtap':
                # Currently, output coalesce for macvtap is not supported
                err_msg = "Cannot get device coalesce settings: Operation not supported"
                std_msg = "Coalesce parameters for %s:" % newinterface
                if err_msg not in out.stderr_text or std_msg not in out.stdout_text:
                    test.fail("coalesce setting on %s failed." % network_type)
            else:
                # Get coalesce value and check it is true
                if out.exit_status == 0:
                    for line in out.stdout_text.splitlines():
                        if 'rx-frames:' in line:
                            coalesce = line.split(':')[1].strip()
                            if expect_coalesce != coalesce:
                                test.fail("coalesce setting failed for %s" % network_type)
                            break
                else:
                    test.fail("coalesce setting on %s failed." % network_type)
        except virt_vm.VMStartError as details:
            logging.info(str(details))
            if not start_error:
                test.fail('VM failed to start:\n%s' % details)

    finally:
        # Recover VM.
        if vm.is_alive():
            vm.destroy(gracefully=False)
        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)
        # Try to recovery bridge
        if network_type == "bridge" and bridge_name:
            if bridge_name in bridge.list_br():
                bridge.del_bridge(bridge_name)
        elif network_type == "ovsbridge" and bridge_name:
            if utils_net.ovs_br_exists(bridge_name):
                utils_net.del_ovs_bridge(bridge_name)
        vmxml_backup.sync()
Esempio n. 12
0
def run(test, params, env):
    """
    Expose host MTU to guest test

    1) Boot up guest with param 'host_mtu=4000' in nic part
    2) Disable NetworkManager in guest
    3) set mtu of guest tap (eg: tap0) and physical nic (eg: eno1) to
       4000 in host
    4) check the mtu in guest
    5) ping from guest to external host with packet size 3972

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

    def cleanup_ovs_ports(netdst, ports):
        """
        Clean up created ovs ports in this case

        :param netdst: netdst get from command line
        :param ports: existing ports need to be remain before this test
        """

        host_bridge = utils_net.find_bridge_manager(netdst)
        if utils_net.ovs_br_exists(netdst) is True:
            ports = set(host_bridge.list_ports(netdst)) - set(ports)
            for p in ports:
                utils_net.find_bridge_manager(netdst).del_port(netdst, p)

    netdst = params.get("netdst", "switch")
    host_bridge = utils_net.find_bridge_manager(netdst)
    if netdst in utils_net.Bridge().list_br():
        host_hw_interface = utils_net.Bridge().list_iface(netdst)[0]
    else:
        host_hw_interface = host_bridge.list_ports(netdst)
        tmp_ports = re.findall(r"t[0-9]{1,}-[a-zA-Z0-9]{6}",
                               ' '.join(host_hw_interface))
        if tmp_ports:
            for p in tmp_ports:
                host_bridge.del_port(netdst, p)
            host_hw_interface = host_bridge.list_ports(netdst)

    params["start_vm"] = "yes"
    env_process.preprocess_vm(test, params, env, params["main_vm"])

    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    vm_iface = vm.get_ifname()
    # Get host interface original mtu value before setting
    if netdst in utils_net.Bridge().list_br():
        host_hw_iface = utils_net.Interface(host_hw_interface)
    elif utils_net.ovs_br_exists(netdst) is True:
        host_hw_iface = utils_net.Interface(' '.join(host_hw_interface))
    host_mtu_origin = host_hw_iface.get_mtu()

    utils_net.Interface(vm_iface).set_mtu(int(params["mtu_value"]))
    host_hw_iface.set_mtu(int(params["mtu_value"]))

    os_type = params.get("os_type", "linux")
    login_timeout = float(params.get("login_timeout", 360))
    session = vm.wait_for_login(timeout=login_timeout)

    host_ip = utils_net.get_ip_address_by_interface(params["netdst"])
    if os_type == "linux":
        session.cmd_output_safe(params["nm_stop_cmd"])
        guest_ifname = utils_net.get_linux_ifname(session,
                                                  vm.get_mac_address())
        output = session.cmd_output_safe(
            params["check_linux_mtu_cmd"] % guest_ifname)
        error_context.context(output, logging.info)
        match_string = "mtu %s" % params["mtu_value"]
        if match_string not in output:
            test.fail("host mtu %s not exposed to guest" % params["mtu_value"])
    elif os_type == "windows":
        connection_id = utils_net.get_windows_nic_attribute(
            session, "macaddress", vm.get_mac_address(), "netconnectionid")
        output = session.cmd_output_safe(
            params["check_win_mtu_cmd"] % connection_id)
        error_context.context(output, logging.info)
        lines = output.strip().splitlines()
        lines_len = len(lines)

        line_table = lines[0].split('  ')
        line_value = lines[2].split('  ')
        while '' in line_table:
            line_table.remove('')
        while '' in line_value:
            line_value.remove('')
        index = 0
        for name in line_table:
            if re.findall("MTU", name):
                break
            index += 1
        mtu_value = line_value[index]
        logging.info("MTU is %s", mtu_value)
        if not int(mtu_value) == int(params["mtu_value"]):
            test.fail("Host mtu %s is not exposed to "
                      "guest!" % params["mtu_value"])

    logging.info("Ping from guest to host with packet size 3972")
    status, output = utils_test.ping(host_ip, 10, packetsize=3972,
                                     timeout=30, session=session)
    ratio = utils_test.get_loss_ratio(output)
    if ratio != 0:
        test.fail("Loss ratio is %s", ratio)

    # Restore host mtu after finish testing
    utils_net.Interface(vm_iface).set_mtu(host_mtu_origin)
    host_hw_iface.set_mtu(host_mtu_origin)

    if netdst not in utils_net.Bridge().list_br():
        cleanup_ovs_ports(netdst, host_hw_interface)
    session.close()
Esempio n. 13
0
def run(test, params, env):
    """
    Test openvswitch support for network.

    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)

    # install openvswitch on host.
    if distro.detect().name == 'Ubuntu':
        pkg = "openvswitch-switch"
    else:
        pkg = "openvswitch"

    ovs_service = service.Factory.create_service(pkg)

    if not shutil.which('ovs-vsctl') and not utils_package.package_install(
            pkg):
        test.cancel("Failed to install dependency package %s" " on host" % pkg)
    if not ovs_service.status():
        logging.debug("Restart %s service.." % pkg)
        ovs_service.restart()

    def check_ovs_port(ifname, brname):
        """
        Check OVS port that created by libvirt
        """
        pg_name = params.get("porgroup_name", "").split()
        pg_vlan = params.get("portgroup_vlan", "").split()
        if_source = eval(iface_source)
        port_vlan = {}
        if "portgroup" in if_source:
            pg = if_source["portgroup"]
            for (name, vlan) in zip(pg_name, pg_vlan):
                if pg == name:
                    port_vlan = eval(vlan)
        # Check bridge name by port name
        _, bridge = utils_net.find_current_bridge(ifname)
        assert bridge == brname
        # Get port info from ovs-vsctl output
        cmd = "ovs-vsctl list port %s" % ifname
        output = process.run(cmd, shell=True).stdout_text
        logging.debug("ovs port output: %s", output)
        for line in output.splitlines():
            if line.count("tag"):
                tag_info = line.rsplit(':')
                if ("id" in port_vlan and tag_info[0] == "tag"):
                    assert port_vlan["id"] == tag_info[1]
            elif line.count("vlan_mode"):
                mode_info = line.rsplit(':')
                if ("nativeMode" in port_vlan and mode_info[0] == "vlan_mode"):
                    assert (port_vlan["nativeMode"] == "native-%s" %
                            mode_info[1])

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

    # network specific attributes.
    net_name = params.get("net_name", "default")
    net_bridge = params.get("net_bridge", "{'name':'virbr0'}")
    iface_source = params.get("iface_source", "{}")
    create_network = "yes" == params.get("create_network", "no")
    change_iface_option = "yes" == params.get("change_iface_option", "no")
    test_ovs_port = "yes" == params.get("test_ovs_port", "no")
    iface_inbound = params.get("iface_bandwidth_inbound")
    iface_outbound = params.get("iface_bandwidth_outbound")
    test_qos = "yes" == params.get("test_qos", "no")
    hotplug = "yes" == params.get("hotplug", "no")
    iface_type = params.get("iface_type", "bridge")
    iface_model = params.get("iface_model", "virtio")
    iface_virtualport = params.get("iface_virtualport")
    live_add_qos = "yes" == params.get("live_add_qos", 'no')

    libvirt_version.is_libvirt_feature_supported(params)
    # Destroy the guest 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)

    bridge_name = eval(net_bridge)['name']
    # Build the xml and run test.
    try:
        # Edit the network xml or create a new one.
        if create_network:
            # Try to add ovs bridge first
            if not utils_net.ovs_br_exists(bridge_name):
                utils_net.add_ovs_bridge(bridge_name)
            netxml = libvirt.create_net_xml(net_name, params)
            netxml.sync()
        # Edit the interface xml.
        if change_iface_option:
            # Try to add bridge if needed
            source = eval(iface_source)
            if source:
                if "bridge" in source:
                    if not utils_net.ovs_br_exists(source["bridge"]):
                        utils_net.add_ovs_bridge(source["bridge"])
            iface_dict = {
                'type': iface_type,
                'model': iface_model,
                'source': iface_source,
                'virtualport_type': iface_virtualport,
                'inbound': iface_inbound,
                'outbound': iface_outbound
            }
            if live_add_qos:
                iface_dict.pop('inbound')
                iface_dict.pop('outbound')
            if not hotplug:
                libvirt.modify_vm_iface(vm_name, 'update_iface', iface_dict)
            else:
                iface_attach_xml = os.path.join(data_dir.get_data_dir(),
                                                "iface_attach.xml")
                shutil.copyfile(
                    libvirt.modify_vm_iface(vm_name, 'get_xml', iface_dict),
                    iface_attach_xml)
                libvirt_vmxml.remove_vm_devices_by_type(vm, 'interface')

        try:
            # Start the VM.
            vm.start()
            if start_error:
                test.fail("VM started unexpectedly")
            if hotplug:
                virsh.attach_device(vm_name,
                                    iface_attach_xml,
                                    debug=True,
                                    ignore_status=False)
            iface_name = libvirt.get_ifname_host(vm_name, iface_mac)
            if test_ovs_port:
                check_ovs_port(iface_name, bridge_name)
            if live_add_qos:
                inbound_opt = ",".join(re.findall(r'[0-9]+', iface_inbound))
                outbount_opt = ",".join(re.findall(r'[0-9]+', iface_outbound))
                virsh.domiftune(vm_name,
                                iface_name,
                                inbound=inbound_opt,
                                outbound=outbount_opt,
                                debug=True,
                                ignore_status=False)
            if test_qos:
                iface_mac = vm_xml.VMXML.get_first_mac_by_name(vm_name)
                tap_name = libvirt.get_ifname_host(vm_name, iface_mac)
                logging.info("Test inbound:")
                res1 = utils_net.check_class_rules(
                    tap_name, "1:1", ast.literal_eval(iface_inbound))
                logging.info("Test outbound:")
                res2 = utils_net.check_filter_rules(
                    tap_name, ast.literal_eval(iface_outbound))
                if not res1 or not res2:
                    test.fail("Qos test fail!")

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

    finally:
        # Recover VM.
        if vm.is_alive():
            vm.destroy(gracefully=False)
        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)
        # Try to recovery ovs bridge
        if utils_net.ovs_br_exists(bridge_name):
            utils_net.del_ovs_bridge(bridge_name)
        if "iface_attach_xml" in locals():
            os.remove(iface_attach_xml)
        vmxml_backup.sync()