def run(test, params, env): """ Run Pktgen test between host/guest 1) Boot the main vm, or just grab it if it's already booted. 2) Configure pktgen on guest or host 3) Run pktgen test, finish when timeout :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def _pin_vm_threads(node): """ pin guest vcpu and vhost threads to cpus of a numa node repectively :param node: which numa node to pin """ if node: if not isinstance(node, utils_misc.NumaNode): node = utils_misc.NumaNode(int(node)) utils_test.qemu.pin_vm_threads(vm, node) timeout = float(params.get("pktgen_test_timeout", "240")) error_context.context("Init the VM, and try to login", logging.info) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session_serial = vm.wait_for_serial_login(restart_network=True) session = vm.wait_for_login() # print numa information on host and pinning vhost and vcpus to cpus process.system_output("numactl --hardware") process.system_output("numactl --show") _pin_vm_threads(params.get("numa_node")) # get parameter from dictionary category = params.get("category") pkt_size = params.get("pkt_size") run_threads = params.get("pktgen_threads") burst = params.get("burst") record_list = params.get("record_list") pktgen_script = params.get('pktgen_script') kvm_ver_chk_cmd = params.get("kvm_ver_chk_cmd") guest_ver_cmd = params["guest_ver_cmd"] # get qemu, guest kernel and kvm version info and write them into result result_path = utils_misc.get_path(test.resultsdir, "pktgen_perf.RHS") result_file = open(result_path, "w") kvm_ver = process.system_output(kvm_ver_chk_cmd, shell=True).decode() host_ver = os.uname()[2] guest_ver = session.cmd_output(guest_ver_cmd, timeout) result_file.write("### kvm-userspace-ver : %s\n" % kvm_ver) result_file.write("### kvm_version : %s\n" % host_ver) result_file.write("### guest-kernel-ver :%s\n" % guest_ver) # get record_list record_line = "" for record in record_list.split(): record_line += "%s|" % format_result(record) def install_package(ver, session=None): """ check module pktgen, install kernel-modules-internal package """ output_cmd = _system_output kernel_ver = "kernel-modules-internal-%s" % ver cmd_download = "cd /tmp && brew download-build %s --rpm" % kernel_ver cmd_install = "cd /tmp && rpm -ivh %s.rpm --force --nodeps" % kernel_ver output_cmd(cmd_download).decode() cmd_clean = "rm -rf /tmp/%s.rpm" % kernel_ver if session: output_cmd = session.cmd_output local_path = "/tmp/%s.rpm" % kernel_ver remote_path = "/tmp/" vm.copy_files_to(local_path, remote_path) output_cmd(cmd_install) output_cmd(cmd_clean) def is_version_lt_rhel7(uname_str): ver = re.findall('el(\\d)', uname_str) if ver: return int(ver[0]) > 7 return False if is_version_lt_rhel7(process.getoutput('uname -r')): install_package(host_ver) if is_version_lt_rhel7(session.cmd('uname -r')): install_package(guest_ver.strip(), session=session) # get result tested by each scenario for pkt_cate in category.split(): result_file.write("Category:%s\n" % pkt_cate) result_file.write("%s\n" % record_line.rstrip("|")) # copy pktgen_test script to test server local_path = os.path.join(data_dir.get_shared_dir(), "scripts/pktgen_perf") remote_path = "/tmp/" if pkt_cate == "tx": vm.copy_files_to(local_path, remote_path) elif pkt_cate == "rx": process.run("cp -r %s %s" % (local_path, remote_path)) pktgen_script = params.get('pktgen_script') for pktgen_script in pktgen_script.split(): for size in pkt_size.split(): for threads in run_threads.split(): for burst in burst.split(): if pkt_cate == "tx": error_context.context( "test guest tx pps" " performance", logging.info) guest_mac = vm.get_mac_address(0) pktgen_interface = utils_net.get_linux_ifname( session, guest_mac) dsc_dev = utils_net.Interface(vm.get_ifname(0)) dsc = dsc_dev.get_mac() runner = session.cmd pktgen_ip = vm.wait_for_get_address(0, timeout=5) elif pkt_cate == "rx": error_context.context( "test guest rx pps" " performance", logging.info) host_bridge = params.get("netdst", "switch") host_nic = utils_net.Interface(host_bridge) pktgen_ip = host_nic.get_ip() if pktgen_script == "pktgen_perf": dsc = vm.wait_for_get_address(0, timeout=5) else: dsc = vm.get_mac_address(0) pktgen_interface = vm.get_ifname(0) runner = _system_output pkt_cate_r = run_test(session_serial, runner, pktgen_script, pkt_cate, pktgen_ip, pktgen_interface, dsc, threads, size, burst, timeout) line = "%s|" % format_result(pktgen_script) line += "%s|" % format_result(size) line += "%s|" % format_result(threads) line += "%s|" % format_result(burst) line += "%s" % format_result(pkt_cate_r) result_file.write(("%s\n" % line)) error_context.context( "Verify Host and guest kernel no error\ and call trace", logging.info) vm.verify_kernel_crash() utils_misc.verify_dmesg() result_file.close() session_serial.close() session.close()
def run(test, params, env): """ Run netperf on server and client side, we need run this case on two machines. if dsthost is not set will start netperf server on local host. Netperf stress test will keep running, until stress timeout or env["netperf_run"] is False 1) Start one vm guest os as server. 2) Start a reference machine (dsthost) as client. 3) Run netperf stress test. 4) Finish test until timeout or env["netperf_run"] is False. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ login_timeout = float(params.get("login_timeout", 360)) dsthost = params.get("dsthost", "localhost") vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) session.cmd("service iptables stop; iptables -F", ignore_all_errors=True) if dsthost in params.get("vms", "vm1 vm2"): server_vm = env.get_vm(dsthost) server_vm.verify_alive() server_vm.wait_for_login(timeout=login_timeout) dsthost_ip = server_vm.get_address() elif re.match(r"((\d){1,3}\.){3}(\d){1,3}", dsthost): dsthost_ip = dsthost else: server_interface = params.get("netdst", "switch") host_nic = utils_net.Interface(server_interface) dsthost_ip = host_nic.get_ip() download_link = params.get("netperf_download_link") md5sum = params.get("pkg_md5sum") server_download_link = params.get("server_download_link", download_link) server_md5sum = params.get("server_md5sum", md5sum) server_path = params.get("server_path", "/var/tmp") client_path = params.get("client_path", "/var/tmp") guest_usrname = params.get("username", "") guest_passwd = params.get("password", "") host_passwd = params.get("hostpasswd") client = params.get("shell_client") port = params.get("shell_port") #main vm run as server when vm_as_server is 'yes'. if params.get("vm_as_server", "yes") == "yes": netserver_ip = vm.get_address() netperf_client_ip = dsthost_ip else: netserver_ip = dsthost_ip netperf_client_ip = vm.get_address() netperf_client = utils_netperf.NetperfClient(netperf_client_ip, client_path, md5sum, download_link, password=host_passwd) netperf_server = utils_netperf.NetperfServer(netserver_ip, server_path, server_md5sum, server_download_link, client, port, username=guest_usrname, password=guest_passwd) # Get range of message size. try: netperf_server.start() # Run netperf with message size defined in range. stress_timeout = float(params.get("netperf_test_timeout", 1200)) netperf_test_duration = float(params.get("netperf_test_duration", 60)) netperf_para_sess = params.get("netperf_para_sessions", "1") test_protocol = params.get("test_protocol", "TCP_STREAM") netperf_cmd_prefix = params.get("netperf_cmd_prefix", "") test_option = "-t %s -l %s" % (test_protocol, netperf_test_duration) start_time = time.time() stop_time = start_time + stress_timeout netperf_client.bg_start(netserver_ip, test_option, netperf_para_sess, netperf_cmd_prefix) if utils_misc.wait_for(netperf_client.is_test_running, 10, 0, 1, "Wait netperf test start"): logging.debug("Netperf test start successfully.") #here when set a run flag, when other case call this case as a #subprocess backgroundly, can set this run flag to False to stop #the stress test. env["netperf_run"] = True else: raise error.TestNAError("Can not start netperf test") while (env["netperf_run"] and time.time() < stop_time): run_left_time = stop_time - time.time() if netperf_client.is_test_running(): if not utils_misc.wait_for(lambda: not netperf_client.is_test_running(), run_left_time, 0, 5, "Wait netperf test finish"): logging.debug("Stress test timeout, finish it") break netperf_client.bg_start(vm.get_address(), test_option, netperf_para_sess) finally: netperf_server.stop() netperf_server.env_cleanup(True) netperf_client.env_cleanup(True) env["netperf_run"] = False if session: session.close()
def run(test, params, env): """ While the guest is using the interface, delete it. 1) Boot a guest with network card. 2) Ping host from guest, should return successfully. 3) In host, disable the interface which the guest uses. 4) Ping host would fail. 5) Enable the interface again, ping would work. 6) Remove the interface from host, qemu would not crash, the guest would not crash too. 7) Shutdown guest, and repeat step1 to step2. Guest would recover. """ secs_after_iplink_action = 3 login_timeout = int(params.get("login_timeout", 360)) # Step 1: Boot a guest vm = env.get_vm(params.get("main_vm")) vm.verify_alive() error.context("Login to guest", logging.info) vm.wait_for_login(timeout=login_timeout) # Step 2, ping should work guest_ip = vm.get_address() error.context("Get the guest ip %s" % guest_ip, logging.info) error.context("Ping test from host to guest, should work", logging.info) status, output = utils_test.ping(guest_ip, 30, timeout=20) if status != 0: raise error.TestFail("Ping failed, status: %s, output: %s" % (status, output)) host_ifname_name = vm.get_ifname() error.context("Get interface name: %s. " % host_ifname_name, logging.info) host_ifname = utils_net.Interface(host_ifname_name) # Step 3,4, disable interface and ping should fail error.context("Set interface %s down." % host_ifname_name, logging.info) host_ifname.down() time.sleep(secs_after_iplink_action) error.context( "After disable the ifname, " "Ping test from host to guest, should fail.", logging.info) status, output = utils_test.ping(guest_ip, 30, timeout=20) if status == 0: raise error.TestFail("Ping should fail, " "status: %s, output: %s" % (status, output)) # Step 5, enable interface, ping should work error.context("Set interface %s up." % host_ifname_name, logging.info) host_ifname.up() time.sleep(secs_after_iplink_action) error.context( "After enable the ifname, " "Ping test from host to guest, should work", logging.info) status, output = utils_test.ping(guest_ip, 30, timeout=20) if status != 0: raise error.TestFail("Ping should work, " "status: %s, output: %s" % (status, output)) # Step 6, delete the interface, qemu should not crash, # ping should fail error.context("Delete the interface %s." % host_ifname_name, logging.info) host_ifname.dellink() time.sleep(secs_after_iplink_action) error.context( "After delete the ifname, " "VM and qemu should not crash, ping should fail", logging.info) vm.verify_alive() status, output = utils_test.ping(guest_ip, 30, timeout=20) if status == 0: raise error.TestFail("Ping should fail, " "status: %s, output: %s" % (status, output)) # Step 7, shutdown guest, and restart a guest error.context("Shutdown the VM.", logging.info) session = vm.wait_for_serial_login() shutdown_cmd = params.get("shutdown_command", "shutdown") logging.debug("Shutdown guest with command %s" % shutdown_cmd) session.sendline(shutdown_cmd) error.context("Waiting VM to go down", logging.info) if not utils_misc.wait_for(vm.is_dead, 360, 0, 1): raise error.TestFail("Guest refuses to go down") env_process.preprocess_vm(test, params, env, params.get("main_vm")) # Repeat step 1: Boot a guest vm = env.get_vm(params.get("main_vm")) vm.verify_alive() error.context("Login to guest", logging.info) vm.wait_for_login(timeout=login_timeout) guest_ip = vm.get_address() error.context("Get the guest ip %s" % guest_ip, logging.info) # Repeat step 2, ping should work error.context("Ping test from host to guest, should work", logging.info) status, output = utils_test.ping(guest_ip, 30, timeout=20) if status != 0: raise error.TestFail("Ping failed, status: %s, output: %s" % (status, output))
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)
def run(test, params, env): """ Test basic QinQ - 10 * 4096 with bridge backend 1) Create a private bridge 2) Boot a VM over private bridge 3) Create interfaces in guest with qinq.sh 4) Set IP on guest L1 interface and bring this interface on 5) Create 802.1ad interface on host with the private bridge 6) Start tcpdump on host 7) Do ping test 8) Check tcpdump result with vlan tag and ethertype 9) Set IP on guest L2 interface and bring this interface on 10) Create 802.1q interface on host with the 802.1ad interface 11) Start tcpdump on host 12) Do ping test 13) Check tcpdump result with vlan tag and ethertype 14) SCP file transfer between host and guest :param test: KVM test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def copy_qinq_file(vm, guest_qinq_dir): """ Copy qinq file from host to guest :param vm: guest vm :param guest_qinq_dir: qing script dir in guest """ error_context.context("Copy qinq script to guest", logging.info) host_qinq_dir = os.path.join(data_dir.get_deps_dir(), params.get("copy_qinq_script")) vm.copy_files_to(host_qinq_dir, guest_qinq_dir) def check_tcpdump_result(session, iface_name, ethertype, ethertype2=None, vlan_tag=None, vlan_tag2=None, enable_logging=False): """ Check tcpdump result. :param session: guest session :param iface_name: the tcpdump file of the interface :param ethertype: ethertype value need to be matched :param ethertype2: ethertype value 2 needed to be matched if not None :param vlan_tag: vlan tag value needed to be matched if not None :param vlan_tag2: vlan tag value 2 needed to be matched if not None :param enable_logging: whether to dump tcpdump results during test """ get_tcpdump_log_cmd = params["get_tcpdump_log_cmd"] % iface_name tcpdump_content = session.cmd_output(get_tcpdump_log_cmd, timeout=300).strip() lines = tcpdump_content.splitlines() sum = 0 for i in range(len(lines)): if enable_logging: logging.info("line %s: %s", i, lines[i]) if not ethertype2: if "ICMP echo re" in lines[i] and \ ethertype in lines[i-1]: sum += 1 if vlan_tag and vlan_tag not in lines[i - 1]: if "too much work for irq" in lines[i - 1]: continue else: test.fail( "in %s tcpdump log, there should be vlan " "tag %s" % (iface_name, vlan_tag)) elif not vlan_tag: if "vlan" in lines[i - 1]: test.fail("in %s tcpdump log, there should not be " "vlan tag" % iface_name) else: if "ICMP echo re" in lines[i] and \ ethertype in lines[i-1] and \ ethertype2 in lines[i-1]: sum += 1 if vlan_tag not in lines[i-1] or \ vlan_tag2 not in lines[i-1]: if "too much work for irq" in lines[i - 1]: continue else: test.fail( "in %s tcpdump log, there should be vlan " "tag %s" % (iface_name, vlan_tag)) if sum == 0: test.fail("in %s tcpdump log, ethertype is not %s" % (iface_name, ethertype)) def compare_host_guest_md5sum(): """ Compare md5 value of file on host and guest :param name: file name """ logging.info("Comparing md5sum on guest and host") host_result = crypto.hash_file(host_path, algorithm="md5") try: output = session.cmd_output("md5sum %s" % guest_path, 120).split()[0] guest_result = re.findall(r"\w+", output)[0] except IndexError: logging.error("Could not get file md5sum in guest") return False logging.debug("md5sum: guest(%s), host(%s)", guest_result, host_result) return guest_result == host_result if params["netdst"] not in utils_net.Bridge().list_br(): test.cancel("Only support Linux bridge") login_timeout = int(params.get("login_timeout", "600")) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=login_timeout) guest_qinq_dir = params["guest_qinq_dir"] copy_qinq_file(vm, guest_qinq_dir) session.close() vm.destroy(gracefully=True) brname = params.get("private_bridge", "tmpbr") host_bridges = utils_net.Bridge() if brname in host_bridges.list_br(): utils_net.Interface(brname).down() host_bridges.del_bridge(brname) set_ip_cmd = params["set_ip_cmd"] logging.debug("Create private bridge %s", brname) host_bridges.add_bridge(brname) host_bridge_iface = utils_net.Interface(brname) logging.debug("Bring up %s", brname) process.system(set_ip_cmd % ("192.168.1.1", brname)) host_bridge_iface.up() try: login_timeout = int(params.get("login_timeout", "600")) params['netdst'] = brname params["start_vm"] = "yes" params["image_snapshot"] = "yes" env_process.preprocess_vm(test, params, env, params["main_vm"]) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_serial_login(timeout=login_timeout) stop_NM_cmd = params.get("stop_NM_cmd") session.cmd(stop_NM_cmd, ignore_all_errors=True) mac = vm.get_mac_address() nic_name = utils_net.get_linux_ifname(session, mac) # Set first_nic IP in guest ip = params["ip_vm"] session.cmd_output(set_ip_cmd % (ip, nic_name)) # Create vlans via script qinq.sh output = session.cmd_output("sh %sqinq.sh %s" % (guest_qinq_dir, nic_name), timeout=300) logging.info("%s", output) # Set interface v1v10 IP in guest L1tag_iface = params["L1tag_iface"] L1tag_iface_ip = params["L1tag_iface_ip"] session.cmd_output(set_ip_cmd % (L1tag_iface_ip, L1tag_iface)) session.cmd("ip link set %s up" % L1tag_iface) output = session.cmd_output("ip addr show %s" % L1tag_iface, timeout=120) logging.info(output) # Start tcpdump on L1tag interface and first_nic in guest error_context.context("Start tcpdump in %s" % params["main_vm"], logging.info) L1tag_tcpdump_log = params.get("tcpdump_log") % L1tag_iface L1tag_tcpdump_cmd = params.get("tcpdump_cmd") % (L1tag_iface, L1tag_tcpdump_log) first_nic_tcpdump_log = params.get("tcpdump_log") % nic_name first_nic_tcpdump_cmd = params.get("tcpdump_cmd") % ( nic_name, first_nic_tcpdump_log) session.sendline(L1tag_tcpdump_cmd) time.sleep(2) session.sendline(first_nic_tcpdump_cmd) time.sleep(5) # Create 802.1ad vlan via bridge in host error_context.context("Create 802.1ad vlan via bridge %s" % brname, logging.info) advlan_ifname = params["advlan_name"] add_advlan_cmd = params["add_advlan_cmd"] process.system_output(add_advlan_cmd) advlan_iface = utils_net.Interface(advlan_ifname) advlan_iface.set_mac(params["advlan_mac"]) process.system(set_ip_cmd % (params["advlan_ip"], advlan_ifname)) advlan_iface.up() output = process.getoutput("ip addr show %s" % advlan_ifname) logging.info(output) # Ping guest from host via 802.1ad vlan interface error_context.context( "Start ping test from host to %s via %s" % (L1tag_iface_ip, advlan_ifname), logging.info) ping_count = int(params.get("ping_count")) status, output = utils_net.ping(L1tag_iface_ip, ping_count, interface=advlan_ifname, timeout=float(ping_count) * 1.5) if status != 0: test.fail("Ping returns non-zero value %s" % output) package_lost = utils_test.get_loss_ratio(output) if package_lost != 0: test.fail("%s packeage lost when ping guest ip %s " % (package_lost, L1tag_iface_ip)) # Stop tcpdump and check result session.cmd_output_safe("pkill tcpdump") check_tcpdump_result(session, L1tag_iface, "ethertype IPv4 (0x0800)") check_tcpdump_result(session, nic_name, "ethertype 802.1Q-QinQ (0x88a8)", vlan_tag="vlan 10,") # Set IP on L2 tag on the guest interface with vid 20 L2tag_iface = params["L2tag_iface"] L2tag_iface_ip = params["L2tag_iface_ip"] session.cmd_output(set_ip_cmd % (L2tag_iface_ip, L2tag_iface)) session.cmd("ip link set %s up" % L2tag_iface) output = session.cmd_output("ip addr show %s" % L2tag_iface, timeout=120) logging.info(output) # Start tcpdump on L1tag and L2tag interfaces and first_nic in guest error_context.context("Start tcpdump in %s" % params["main_vm"], logging.info) L2tag_tcpdump_log = params.get("tcpdump_log") % L2tag_iface L2tag_tcpdump_cmd = params.get("tcpdump_cmd") % (L2tag_iface, L2tag_tcpdump_log) session.sendline(L1tag_tcpdump_cmd) time.sleep(2) session.sendline(L2tag_tcpdump_cmd) time.sleep(2) session.sendline(first_nic_tcpdump_cmd) time.sleep(5) # Create 802.1q vlan via 802.1ad vlan in host error_context.context( "Create 802.1q vlan via 802.1ad vlan %s" % advlan_ifname, logging.info) qvlan_ifname = params["qvlan_name"] add_qvlan_cmd = params["add_qvlan_cmd"] process.system_output(add_qvlan_cmd) qvlan_iface = utils_net.Interface(qvlan_ifname) process.system(set_ip_cmd % (params["qvlan_ip"], qvlan_ifname)) qvlan_iface.up() output = process.getoutput("ip addr show %s" % qvlan_ifname) logging.info(output) # Ping guest from host via 802.1q vlan interface error_context.context( "Start ping test from host to %s via %s" % (L2tag_iface_ip, qvlan_ifname), logging.info) status, output = utils_net.ping(L2tag_iface_ip, ping_count, interface=qvlan_ifname, timeout=float(ping_count) * 1.5) if status != 0: test.fail("Ping returns non-zero value %s" % output) package_lost = utils_test.get_loss_ratio(output) if package_lost >= 5: test.fail("%s packeage lost when ping guest ip %s " % (package_lost, L2tag_iface_ip)) # Stop tcpdump and check result session.cmd_output_safe("pkill tcpdump") check_tcpdump_result(session, L1tag_iface, "ethertype 802.1Q (0x8100)", vlan_tag="vlan 20,") check_tcpdump_result(session, L2tag_iface, "ethertype IPv4 (0x0800)") check_tcpdump_result(session, nic_name, ethertype="ethertype 802.1Q-QinQ (0x88a8)", ethertype2="ethertype 802.1Q", vlan_tag="vlan 10,", vlan_tag2="vlan 20,") # scp file to guest with L2 vlan tag file_size = int(params.get("file_size", "4096")) host_path = os.path.join(test.tmpdir, "transferred_file") guest_path = params.get("guest_path", "/var/tmp/transferred_file") transfer_timeout = int(params.get("transfer_timeout", 1000)) cmd = "dd if=/dev/zero of=%s bs=1M count=%d" % (host_path, file_size) error_context.context("Creating %dMB file on host" % file_size, logging.info) process.run(cmd) error_context.context( "Transferring file host -> guest, " "timeout: %ss" % transfer_timeout, logging.info) shell_port = int(params.get("shell_port", 22)) password = params["password"] username = params["username"] remote.scp_to_remote(L2tag_iface_ip, shell_port, username, password, host_path, guest_path) if not compare_host_guest_md5sum(): test.fail("md5sum mismatch on guest and host") finally: session.cmd("rm -rf %s" % guest_path) session.close() vm.destroy(gracefully=True) host_bridge_iface.down() host_bridges.del_bridge(brname)
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)
def run(test, params, env): """ Run netperf on server and client side, we need run this case on two machines. If dsthost is not set will start netperf server on local host and log a error message.: 1) Start one vm guest os as client or server (windows guest must using as server). 2) Start a reference machine (dsthost) as server/client. 3) Setup netperf on guest and reference machine (dsthost). 4) Start netperf server on the server host. 5) Run netperf client command in guest several time with different message size. 6) Compare UDP performance to make sure it is acceptable. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ login_timeout = float(params.get("login_timeout", 360)) dsthost = params.get("dsthost", "localhost") vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) main_vm_ip = vm.get_address() session.cmd("iptables -F", ignore_all_errors=True) error.context("Test env prepare", logging.info) netperf_link = params.get("netperf_link") if netperf_link: netperf_link = os.path.join(data_dir.get_deps_dir("netperf"), netperf_link) md5sum = params.get("pkg_md5sum") netperf_server_link = params.get("netperf_server_link_win") if netperf_server_link: netperf_server_link = os.path.join(data_dir.get_deps_dir("netperf"), netperf_server_link) netperf_client_link = params.get("netperf_client_link_win") if netperf_client_link: netperf_client_link = os.path.join(data_dir.get_deps_dir("netperf"), netperf_client_link) server_md5sum = params.get("server_md5sum") client_md5sum = params.get("client_md5sum") os_type = params.get("os_type") server_path = params.get("server_path", "/var/tmp/") client_path = params.get("client_path", "/var/tmp/") server_path_win = params.get("server_path_win", "c:\\") client_path_win = params.get("client_path_win", "c:\\") guest_username = params.get("username", "") guest_password = params.get("password", "") host_password = params.get("hostpassword") client = params.get("shell_client") port = params.get("shell_port") if dsthost in params.get("vms", "vm1 vm2"): server_vm = env.get_vm(dsthost) server_vm.verify_alive() s_session = server_vm.wait_for_login(timeout=login_timeout) s_session.cmd("iptables -F", ignore_all_errors=True) netserver_ip = server_vm.get_address() s_session.close() s_client = client s_port = port s_username = guest_username s_password = guest_password if os_type == "windows": s_link = netperf_server_link s_path = server_path_win s_md5sum = server_md5sum else: s_link = netperf_link s_path = server_path s_md5sum = md5sum else: if re.match(r"((\d){1,3}\.){3}(\d){1,3}", dsthost): netserver_ip = dsthost else: server_interface = params.get("netdst", "switch") host_nic = utils_net.Interface(server_interface) netserver_ip = host_nic.get_ip() s_client = params.get("shell_client_%s" % dsthost, "ssh") s_port = params.get("shell_port_%s" % dsthost, "22") s_username = params.get("username_%s" % dsthost, "root") s_password = params.get("password_%s" % dsthost, "redhat") s_link = netperf_link s_path = server_path s_md5sum = md5sum if os_type == "windows": c_path = client_path_win c_md5sum = client_md5sum c_link = netperf_client_link else: c_path = client_path c_md5sum = md5sum c_link = netperf_link netperf_client = utils_netperf.NetperfClient(main_vm_ip, c_path, c_md5sum, c_link, client, port, username=guest_username, password=guest_password) netperf_server = utils_netperf.NetperfServer(netserver_ip, s_path, s_md5sum, s_link, s_client, s_port, username=s_username, password=s_password) # Get range of message size. message_size = params.get("message_size_range", "580 590 1").split() start_size = int(message_size[0]) end_size = int(message_size[1]) step = int(message_size[2]) m_size = start_size throughput = [] try: error.context("Start netperf_server", logging.info) netperf_server.start() # Run netperf with message size defined in range. msg = "Detail result of netperf test with different packet size.\n" while(m_size <= end_size): test_protocol = params.get("test_protocol", "UDP_STREAM") test_option = "-t %s -- -m %s" % (test_protocol, m_size) txt = "Run netperf client with protocol: '%s', packet size: '%s'" error.context(txt % (test_protocol, m_size), logging.info) output = netperf_client.start(netserver_ip, test_option) re_str = "[0-9\.]+\s+[0-9\.]+\s+[0-9\.]+\s+[0-9\.]+\s+[0-9\.]+" re_str += "\s+[0-9\.]+" try: line_tokens = re.findall(re_str, output)[0].split() except IndexError: txt = "Fail to get Throughput for %s." % m_size txt += " netprf client output: %s" % output raise error.TestError(txt) if not line_tokens: raise error.TestError("Output format is not expected") throughput.append(float(line_tokens[5])) msg += output m_size += step finally: netperf_server.stop() file(os.path.join(test.debugdir, "udp_results"), "w").write(msg) failratio = float(params.get("failratio", 0.3)) error.context("Compare UDP performance.", logging.info) for i in range(len(throughput) - 1): if abs(throughput[i] - throughput[i + 1]) > throughput[i] * failratio: txt = "The gap between adjacent throughput is greater than" txt += "%f." % failratio txt += "Please refer to log file for details:\n %s" % msg raise error.TestFail(txt) logging.info("The UDP performance as measured via netperf is ok.") logging.info("Throughput of netperf command: %s" % throughput) logging.debug("Output of netperf command:\n %s" % msg) error.context("Kill netperf server on server (dsthost).") try: if session: session.close() except Exception: pass
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_misc.yum_install(pkg_list): raise error.TestNAError("Failed ot install " "required packages") boot_initrd = params.get("boot_initrd") boot_vmlinuz = params.get("boot_vmlinuz") # Download pxe boot images utils.run("wget %s -O %s/initrd.img" % (boot_initrd, tftp_root)) utils.run("wget %s -O %s/vmlinuz" % (boot_vmlinuz, tftp_root)) utils.run("cp -f /usr/share/syslinux/pxelinux.0 {0};" " mkdir -m 777 -p {0}/pxelinux.cfg".format(tftp_root)) 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 = eval(iface_bandwidth_inbound) iface_outbound = 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_source = params.get("iface_source") if iface_source: source = eval(iface_source) if source: iface.source = source 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" 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: raise error.TestFail("Can't find %s=%s in configuration" " file" % (key, value)) else: if not exists: raise error.TestFail("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): raise error.TestFail("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): raise error.TestFail("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 = utils.run(cmd).stdout 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: raise error.TestFail("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 = utils.run(cmd).stdout logging.debug("Bandwidth filter output: %s", filter_output) if not filter_output.count("filter protocol all pref"): raise error.TestFail("Can't find 'protocol all' settings" " in filter rules") filter_pattern = ".*police.*rate (\d+)Kbit burst (\d+)Kb.*" se = re.search(r"%s" % filter_pattern, filter_output, re.M) if not se: raise error.TestFail("Can't find any filter policy") logging.debug("bandwidth from tc output:%s" % str(se.groups())) if bandwidth.has_key("average"): assert int(se.group(1)) == int(bandwidth["average"]) * 8 if bandwidth.has_key("burst"): assert int(se.group(2)) == int(bandwidth["burst"]) def run_bandwidth_test(check_net=False, check_iface=False): """ Test bandwidth option for network or interface by tc command. """ iface_inbound = eval(iface_bandwidth_inbound) iface_outbound = eval(iface_bandwidth_outbound) net_inbound = eval(net_bandwidth_inbound) net_outbound = eval(net_bandwidth_outbound) net_bridge_name = 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 = utils.run(cmd).stdout logging.debug("Bandwidth qdisc output: %s", qdisc_output) if not qdisc_output.count("qdisc ingress ffff:"): raise error.TestFail("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"): 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: utils.log_last_traceback() raise error.TestFail("Failed to check network bandwidth") def check_name_ip(session): """ Check dns resolving on guest """ # Check if bind-utils is installed if not utils_misc.yum_install(['bind-utils'], session): raise error.TestNAError("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: raise error.TestFail("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): raise error.TestFail("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 = eval(net_bridge)["name"] net_forward = 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 = eval(params.get("nat_port")) p_start = nat_port["start"] p_end = nat_port["end"] ctr_rule = " -m conntrack --ctstate RELATED,ESTABLISHED" nat_rules = ["POSTROUTING -s %s -d 224.0.0.0/24 -j RETURN" % net_ipv4, "POSTROUTING -s %s -d 255.255.255.255/32 -j RETURN" % net_ipv4, ("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 = utils.run("iptables-save").stdout.strip() logging.debug("iptables: %s", output) for ipt in ipv4_rules: if not output.count(ipt): raise error.TestFail("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 = utils.run("ip6tables-save").stdout.strip() logging.debug("iptables: %s", output) for ipt in ipv6_rules: if not output.count(ipt): raise error.TestFail("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") utils_net.restart_guest_network(session, iface_mac, ip_version=ip_ver) # 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, 10) vm_ip = get_ip_func() logging.debug("Guest has ip: %s", vm_ip) if not vm_ip: raise error.TestFail("Can't find ip address on guest") ping_cmd = "ping -c 5" ip_gateway = net_ip_address if ip_ver == "ipv6": ping_cmd = "ping6 -c 5" ip_gateway = net_ipv6_address if ip_gateway: if utils.system("%s %s" % (ping_cmd, ip_gateway), ignore_status=True): raise error.TestFail("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_misc.yum_install(['libvirt'], session): raise error.TestNAError("Failed ot install libvirt" " package on guest") result = True # Check network state on guest cmd = ("service libvirtd restart; virsh net-info default" " | grep 'Active:.*no'") if session.cmd_status(cmd): result = False logging.error("Default network isn't in inactive state") # Try to start default network on guest, check error messages if result: cmd = "virsh net-start default" status, output = session.cmd_status_output(cmd) logging.debug("Run command on guest exit %s, output %s" % (status, output)) if not status or not output.count("already in use"): result = False logging.error("Failed to see network messges on guest") if session.cmd_status("rpm -e libvirt"): logging.error("Failed to remove libvirt packages on guest") if not result: raise error.TestFail("Check libvirt network on guest failed") start_error = "yes" == params.get("start_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") 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", "{}") multiple_guests = params.get("multiple_guests") create_network = "yes" == params.get("create_network", "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_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") if serial_login: # Set serial console for serial login if vm.is_dead(): vm.start() session = vm.wait_for_login() # Set console option vm.set_kernel_console("ttyS0", "115200") # Shutdown here for sync fs vm.shutdown() else: 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 = [] # 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: libvirt.create_net_xml(net_name, params) # Edit the interface xml. if change_iface_option: modify_iface_xml() if multiple_guests: # Clone more vms for testing for i in range(int(multiple_guests)): guest_name = "%s_%s" % (vm_name, i) utils_libguestfs.virt_clone_cmd(vm_name, guest_name, True) vms_list.append(vm.clone(guest_name)) if test_bridge: bridge = eval(net_bridge) br_if = utils_net.Interface(bridge['name']) if not br_if.is_up(): raise error.TestFail("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 = 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 = utils.run(cmd, ignore_status=False).stdout.strip() 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: raise error.TestFail("Can't see forward delay" " messages from command") elif (float(match_obj.groups()[0]) != br_delay or float(match_obj.groups()[1]) != br_delay): raise error.TestFail("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 = eval(net_dns_txt) run_dnsmasq_default_test("txt-record", "%s,%s" % (dns_txt["name"], dns_txt["value"])) if net_dns_srv: dns_srv = 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) try: # Start the VM. vm.start() if start_error: raise error.TestFail("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() else: session = vm.wait_for_login() if test_dhcp_range: # First vm should have a valid ip address 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: raise error.TestFail("Guest has invalid ip address") # Other vms cloudn't get the ip address 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 vms_ip: # Get IP address on guest should return Null raise error.TestFail("Guest has ip address: %s" % vms_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) 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: raise error.TestFail("VM started unexpectedly") if test_ipv4_address: check_ipt_rules(check_ipv4=True) run_ip_test(session, "ipv4") if test_ipv6_address: check_ipt_rules(check_ipv6=True) run_ip_test(session, "ipv6") if test_guest_libvirt: run_guest_libvirt(session) session.close() except virt_vm.VMStartError, details: logging.info(str(details)) if start_error or restart_error: pass else: raise error.TestFail('VM Failed to start for some reason!') 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()
def run(test, params, env): """ Test interfaces attached from network """ def test_at_dt(): """ Test attach-detach interfaces """ if not pf_status: logging.info("Set pf state to down.") pf_iface_obj = utils_net.Interface(pf_name) pf_iface_obj.down() logging.info("Define network - %s.", params.get("net_name")) create_network(params) logging.debug("Remove VM's interface devices.") libvirt_vmxml.remove_vm_devices_by_type(vm, 'interface') vm.start() vm_session = vm.wait_for_serial_login(timeout=240) logging.info("Hotplug an interface to VM.") iface_dict = { "model": "virtio", "source": { 'network': params.get("net_name") } } iface = create_iface(iface_dict) res = virsh.attach_device(vm_name, iface.xml, debug=True) libvirt.check_exit_status(res, status_error) if not pf_status: logging.info("Set pf state to up then check again.") pf_iface_obj.up() virsh.attach_device(vm_name, iface.xml, debug=True, ignore_status=False) libvirt_vmxml.check_guest_xml(vm.name, params["net_name"]) sriov_base.check_vm_network_accessed(vm_session) def test_connection(): """ Test network connections 1. Create a network 2. Attach the interfaces and check network connections 3. Check the network connections after detaching ifaces, restarting libvirtd and destroying the VM """ vf_no = int(params.get("vf_no", "4")) net_name = params.get("net_name") iface_type = params.get("iface_type") logging.info("Define network - %s.", net_name) create_network(params) libvirt_vmxml.remove_vm_devices_by_type(vm, 'interface') libvirt_pcicontr.reset_pci_num(vm_name) vm.start() vm.wait_for_serial_login(timeout=240) logging.info("Attach 4 interfaces to the guest.") opts = ' '.join( ["network", net_name, params.get('attach_extra_opts', "")]) for i in range(vf_no): virsh.attach_interface(vm_name, option=opts, debug=True, ignore_status=False) libvirt_network.check_network_connection(net_name, i + 1) logging.info("Try to attach one more interface.") res = virsh.attach_interface(vm_name, option=opts, debug=True) libvirt.check_exit_status(res, True) logging.info("Detach an interface.") vm_ifaces = [ iface for iface in vm_xml.VMXML.new_from_dumpxml( vm_name).devices.by_device_tag("interface") ] mac_addr = vm_ifaces[0].get_mac_address() opts = ' '.join([iface_type, "--mac %s" % mac_addr]) virsh.detach_interface(vm_name, option=opts, debug=True, ignore_status=False) libvirt_network.check_network_connection(net_name, vf_no - 1) logging.info( "Restart libvirtd service and check the network connection.") utils_libvirtd.Libvirtd().restart() libvirt_network.check_network_connection(net_name, vf_no - 1) logging.info("Destroy the VM and check the network connection.") vm.destroy(gracefully=False) libvirt_network.check_network_connection(net_name, 0) test_case = params.get("test_case", "") run_test = eval("test_%s" % test_case) status_error = "yes" == params.get("status_error", "no") vm_name = params.get("main_vm", "avocado-vt-vm1") vm = env.get_vm(vm_name) pf_pci = utils_sriov.get_pf_pci() if not pf_pci: test.cancel("NO available pf found.") sriov_base.setup_vf(pf_pci, params) vf_pci = utils_sriov.get_vf_pci_id(pf_pci) params['vf_iface'] = utils_sriov.get_iface_name(vf_pci) pf_status = "active" == params.get("pf_status", "active") pf_name = utils_sriov.get_pf_info_by_pci(pf_pci).get('iface') params['pf_name'] = pf_name vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) orig_config_xml = vmxml.copy() try: run_test() finally: logging.info("Recover test enviroment.") if not pf_status: pf_iface_obj = utils_net.Interface(pf_name) pf_iface_obj.up() sriov_base.recover_vf(pf_pci, params) if vm.is_alive(): vm.destroy(gracefully=False) orig_config_xml.sync() libvirt_network.create_or_del_network( {"net_name": params.get("net_name")}, True)
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(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" 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.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 if iface_model: iface.model = iface_model 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 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, expect_none=False): """ Check bandwidth settings via 'tc filter' output :param ifname: name of iface to be checked :param bandwidth: bandwidth to be match with :param expect_none: whether or not expect nothing in output, default to be False :return: if expect nothing from the output, return True if the output is empty, else return False """ 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 expect_none: return not filter_output.strip() 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 "ubuntu" in vm.get_distro().lower(): pkg = "bind9" else: pkg = "bind-utils" if not utils_package.package_install(pkg, 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") 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 libvirt_version.version_compare(5, 1, 0): input_chain = "LIBVIRT_INP" output_chain = "LIBVIRT_OUT" postrouting_chain = "LIBVIRT_PRT" forward_filter = "LIBVIRT_FWX" forward_in = "LIBVIRT_FWI" forward_out = "LIBVIRT_FWO" else: input_chain = "INPUT" output_chain = "OUTPUT" postrouting_chain = "POSTROUTING" forward_filter = "FORWARD" forward_in = "FORWARD" forward_out = "FORWARD" ipt_rules = ( "%s -i %s -p udp -m udp --dport 53 -j ACCEPT" % (input_chain, br_name), "%s -i %s -p tcp -m tcp --dport 53 -j ACCEPT" % (input_chain, br_name), "{0} -i {1} -o {1} -j ACCEPT".format(forward_filter, br_name), "%s -o %s -j REJECT --reject-with icmp" % (forward_in, br_name), "%s -i %s -j REJECT --reject-with icmp" % (forward_out, br_name)) if check_ipv4: ipv4_rules = list(ipt_rules) ipv4_rules.extend( ["%s -i %s -p udp -m udp --dport 67 -j ACCEPT" % (input_chain, br_name), "%s -i %s -p tcp -m tcp --dport 67 -j ACCEPT" % (input_chain, br_name), "%s -o %s -p udp -m udp --dport 68 -j ACCEPT" % (output_chain, br_name), "%s -o %s -p udp -m udp --dport 68 " "-j CHECKSUM --checksum-fill" % (postrouting_chain, br_name)]) 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 = [("{0} -s {1} ! -d {1} -p tcp -j MASQUERADE" " --to-ports {2}-{3}".format(postrouting_chain, net_ipv4, p_start, p_end)), ("{0} -s {1} ! -d {1} -p udp -j MASQUERADE" " --to-ports {2}-{3}".format(postrouting_chain, net_ipv4, p_start, p_end)), ("{0} -s {1} ! -d {1}" " -j MASQUERADE".format(postrouting_chain, 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 = [("%s -d %s%s -o %s%s -j ACCEPT" % (forward_in, net_ipv4, net_dev_in, br_name, ctr_rule)), ("%s -s %s -i %s%s -j ACCEPT" % (forward_out, 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) ipt6_rules.extend([ ("INPUT -i %s -p udp -m udp --dport 547 -j ACCEPT" % br_name)]) if (net_ipv6 and "mode" in net_forward and net_forward["mode"] in ["nat", "route"]): rules = [("%s -d %s%s -o %s -j ACCEPT" % (forward_in, net_ipv6, net_dev_in, br_name)), ("%s -s %s -i %s%s -j ACCEPT" % (forward_out, net_ipv6, br_name, net_dev_out))] ipv6_rules.extend(rules) output = to_text(process.system_output("ip6tables-save")) logging.debug("ip6tables: %s", output) if "mode" in net_forward and net_forward["mode"] == "open": if re.search(r"%s|%s" % (net_ipv6, br_name), output, re.M): test.fail("Find ip6table rule for open mode") utils_libvirtd.libvirtd_restart() output_again = to_text(process.system_output('ip6tables-save')) if re.search(r"%s|%s" % (net_ipv6, br_name), output_again, re.M): test.fail("Find ip6table rule for open mode after restart " "libvirtd") else: for ipt in ipv6_rules: if not re.search(r"%s" % ipt, output, re.M): test.fail("Can't find ip6table 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 "ubuntu" in vm.get_distro().lower(): pkg = "libvirt-bin" else: pkg = "libvirt" if not utils_package.package_install(pkg, session): test.error("Failed to 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", "{}") iface_rom = params.get("iface_rom") iface_boot = params.get("iface_boot") iface_model = params.get("iface_model") 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") update_device = 'yes' == params.get('update_device', 'no') remove_bandwidth = 'yes' == params.get('remove_bandwidth', 'no') loop = int(params.get('loop', 0)) username = params.get("username") password = params.get("password") forward = ast.literal_eval(params.get("net_forward", "{}")) boot_failure = "yes" == params.get("boot_failure", "no") ipt_rules = [] ipt6_rules = [] # Destroy VM first if vm.is_alive() and not update_device: 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 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: try: if update_device: updated_iface = modify_iface_xml(sync=False) virsh.update_device(vm_name, updated_iface.xml, ignore_status=False, debug=True) else: modify_iface_xml() except xcepts.LibvirtXMLError as details: logging.info(str(details)) if define_error: if not str(details).count("Failed to define"): test.fail("VM sync failed msg not expected") return else: test.fail("Failed to sync VM") # Attach interface if needed if attach_iface: iface_type = params.get("iface_type", "network") 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': # network xml forward delay value in seconds, while on # host, check by ip command, the value is in second*100 br_delay = int(bridge['delay'])*100 logging.debug("Expect forward_delay is %s ms" % br_delay) cmd = ("ip -d link sh %s | grep 'bridge forward_delay'" % bridge['name']) out = to_text(process.system_output( cmd, shell=True, ignore_status=False)) logging.debug("bridge statistics output: %s", out) pattern = (r"\s*bridge forward_delay\s+(\d+)") match_obj = re.search(pattern, out, re.M) if not match_obj: test.fail("Can't see forward delay messages from command") elif int(match_obj.group(1)) != br_delay: test.fail("Foward delay setting can't take effect") else: logging.debug("Foward delay set successfully!") 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 and not update_device: run_bandwidth_test(check_net=True) # If to remove bandwidth from iface, # update iface xml to the original one if remove_bandwidth: ori_iface = params['original_iface'] logging.debug(ori_iface) virsh.update_device(vm_name, ori_iface.xml, ignore_status=False, debug=True) # Check routes if needed if routes: check_host_routes() try: # Start the VM. if not update_device: vm.start() if start_error: test.fail("VM started unexpectedly") if pxe_boot: # Just check network boot messages here try: 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) except ExpectTimeoutError as details: if boot_failure: logging.info("Fail to boot from pxe as expected") else: test.fail("Fail to boot from pxe") 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: ipt6_rules = check_ipt_rules(check_ipv4=False, 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) if ipt6_rules: output_des = to_text(process.system_output('ip6tables-save')) for ipt in ipt6_rules: if re.search(r"%s" % ipt, output_des, re.M): test.fail("Find ip6table rule %s after net destroyed" % ipt) if remove_bandwidth: iface_name = libvirt.get_ifname_host(vm_name, iface_mac) cur_xml = virsh.dumpxml(vm_name).stdout_text logging.debug(cur_xml) if 'bandwidth' in cur_xml: test.fail('bandwidth still in xml') if not check_filter_rules(iface_name, 0, expect_none=True): test.fail('There should be nothing in output') if update_device and loop: loop -= 1 if loop: # Rerun this procedure again with updated params # Reset params of the corresponding loop loop_prefix = 'loop' + str(loop) + '_' for k in {k: v for k, v in params.items() if k.startswith(loop_prefix)}: params[k.lstrip(loop_prefix)] = params[k] params['loop'] = str(loop) run(test, params, env) 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)
def run(test, params, env): """ Test port mirror with linux bridge backend. 1) Create a private bridge 2) Set private bridge promisc mode and up 3) Boot 3 VMs over private bridge 4) Mirror all traffic on bridge to tap device connected to VM1 5) Start tcpdump in VM1 to dump icmp packets from VM2 to VM3 6) Ping VM3 from VM2 7) Stop Ping in VM2 8) Stop tcpdump and check results :param test: KVM test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def mirror_bridge_to_tap(tap_name): """ Mirror all packages on bridge to tap device connected to vm vNIC :param tap_name: name of tap connected to vm """ tc_qdisc_add_ingress = params.get("tc_qdisc_add_ingress") tc_filter_show_dev = params.get("tc_filter_show_dev") tc_filter_replace_dev = params.get("tc_filter_replace_dev") % tap_name tc_qdisc_replace = params.get("tc_qdisc_replace") process.system_output(tc_qdisc_add_ingress) process.system_output(tc_filter_show_dev) process.system_output(tc_filter_replace_dev) process.system_output(tc_qdisc_replace) tc_qdisc_show_dev = params.get("tc_qdisc_show_dev") output = process.system_output(tc_qdisc_show_dev).decode() port = re.findall("qdisc prio (.*):", output)[0] tc_filter_show_dev_port = params.get("tc_filter_show_dev_port") % port tc_filter_replace_dev_port = params.get( "tc_filter_replace_dev_port") % (port, tap_name) process.system_output(tc_filter_show_dev_port) process.system_output(tc_filter_replace_dev_port) def check_tcpdump(output, src_ip, des_ip, ping_count): """ Check tcpdump result. :parm output: string of tcpdump output. :parm src_ip: ip to ping :parm des_ip: ip to receive ping :parm ping_count: total ping packets number :return: bool type result. """ rex_request = r".*IP %s > %s.*ICMP echo request.*" % (src_ip, des_ip) rex_reply = r".*IP %s > %s.*ICMP echo reply.*" % (des_ip, src_ip) request_num = 0 reply_num = 0 for idx, _ in enumerate(output.splitlines()): if re.match(rex_request, _): request_num += 1 elif re.match(rex_reply, _): reply_num += 1 if request_num != ping_count or reply_num != ping_count: logging.debug( "Unexpected request or reply number. " "current request number is: %d, " "current reply number is: %d, " "expected request and reply number is: %d. ", request_num, reply_num, ping_count) return False return True netdst = params.get("netdst", "switch") br_backend = utils_net.find_bridge_manager(netdst) if not isinstance(br_backend, utils_net.Bridge): test.cancel("Host does not use Linux Bridge") brname = params.get("private_bridge", "tmpbr") net_mask = params.get("net_mask", "24") login_timeout = int(params.get("login_timeout", "600")) stop_NM_cmd = params.get("stop_NM_cmd") stop_firewall_cmd = params.get("stop_firewall_cmd") tcpdump_cmd = params.get("tcpdump_cmd") tcpdump_log = params.get("tcpdump_log") get_tcpdump_log_cmd = params.get("get_tcpdump_log_cmd") ping_count = int(params.get("ping_count")) error_context.context("Create a private bridge", logging.info) br_backend.add_bridge(brname) br_iface = utils_net.Interface(brname) br_iface.up() br_iface.promisc_on() params['netdst'] = brname params["start_vm"] = "yes" vm_names = params.get("vms").split() vms_info = {} try: for vm_name in vm_names: env_process.preprocess_vm(test, params, env, vm_name) vm = env.get_vm(vm_name) vm.verify_alive() ip = params["ip_%s" % vm_name] mac = vm.get_mac_address() serial_session = vm.wait_for_serial_login(timeout=login_timeout) serial_session.cmd_output_safe(stop_NM_cmd) serial_session.cmd_output_safe(stop_firewall_cmd) nic_name = utils_net.get_linux_ifname(serial_session, mac) ifname = vm.get_ifname() ifset_cmd = "ip addr add %s/%s dev %s" % (ip, net_mask, nic_name) ifup_cmd = "ip link set dev %s up" % nic_name serial_session.cmd_output_safe(ifset_cmd) serial_session.cmd_output_safe(ifup_cmd) vms_info[vm_name] = [vm, ifname, ip, serial_session, nic_name] vm_mirror = vm_names[0] vm_src = vm_names[1] vm_des = vm_names[2] error_context.context( "Mirror all packets on bridge to tap device conncted to %s" % vm_mirror) tap_ifname = vms_info[vm_mirror][0].virtnet[0].ifname mirror_bridge_to_tap(tap_ifname) error_context.context("Start tcpdump in %s" % vm_mirror, logging.info) tcpdump_cmd = tcpdump_cmd % (vms_info[vm_des][2], tcpdump_log) logging.info("tcpdump command: %s", tcpdump_cmd) vms_info[vm_mirror][3].sendline(tcpdump_cmd) time.sleep(5) error_context.context("Start ping from %s to %s" % (vm_src, vm_des), logging.info) ping_cmd = params.get("ping_cmd") % vms_info[vm_des][2] vms_info[vm_src][3].cmd(ping_cmd, timeout=150) error_context.context("Check tcpdump results", logging.info) time.sleep(5) vms_info[vm_mirror][3].cmd_output_safe("pkill tcpdump") tcpdump_content = vms_info[vm_mirror][3].cmd_output( get_tcpdump_log_cmd).strip() if not check_tcpdump(tcpdump_content, vms_info[vm_src][2], vms_info[vm_des][2], ping_count): test.fail("tcpdump results are not expected, mirror fail.") finally: for vm in vms_info: vms_info[vm][0].destroy(gracefully=False) br_iface.down() br_backend.del_bridge(brname)
def run_pktgen(test, params, env): """ Run Pktgen test between host/guest 1) Boot the main vm, or just grab it if it's already booted. 2) Configure pktgen server(only linux) 3) Run pktgen test, finish when timeout or env["pktgen_run"] != True :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ login_timeout = float(params.get("login_timeout", 360)) error.context("Init the VM, and try to login", logging.info) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login() error.context("Pktgen server environment prepare", logging.info) #pktgen server only support linux, since pktgen is a linux kernel module pktgen_server = params.get("pktgen_server", "localhost") params_server = params.object_params("pktgen_server") s_shell_client = params_server.get("shell_client", "ssh") s_shell_port = params_server.get("shell_port", "22") s_username = params_server.get("username", "root") s_passwd = params_server.get("password", "123456") s_shell_prompt = params_server.get("shell_prompt") server_session = "" #pktgen server is autotest virtual guest(only linux) if pktgen_server in params.get("vms", "vm1 vm2"): vm_pktgen = env.get_vm(pktgen_server) vm_pktgen.verify_alive() server_session = vm_pktgen.wait_for_login(timeout=login_timeout) runner = server_session.cmd_output_safe pktgen_ip = vm_pktgen.get_address() pktgen_mac = vm_pktgen.get_mac_address() server_interface = utils_net.get_linux_ifname(server_session, pktgen_mac) #pktgen server is a external host assigned elif re.match(r"((\d){1,3}\.){3}(\d){1,3}", pktgen_server): pktgen_ip = pktgen_server server_session = remote.wait_for_login(s_shell_client, pktgen_ip, s_shell_port, s_username, s_passwd, s_shell_prompt) runner = server_session.cmd_output_safe server_interface = params.get("server_interface") if not server_interface: raise error.TestNAError("Must config server interface before test") else: #using host as a pktgen server server_interface = params.get("netdst", "switch") host_nic = utils_net.Interface(server_interface) pktgen_ip = host_nic.get_ip() pktgen_mac = host_nic.get_mac() runner = utils.system #copy pktgen_test scipt to the test server. local_path = os.path.join(data_dir.get_root_dir(), "shared/scripts/pktgen.sh") remote_path = "/tmp/pktgen.sh" remote.scp_to_remote(pktgen_ip, s_shell_port, s_username, s_passwd, local_path, remote_path) error.context("Run pktgen test") run_threads = params.get("pktgen_threads", 1) pktgen_stress_timeout = float(params.get("pktgen_test_timeout", 600)) exec_cmd = "%s %s %s %s %s" % (remote_path, vm.get_address(), vm.get_mac_address(), server_interface, run_threads) try: env["pktgen_run"] = True try: #Set a run flag in env, when other case call this case as a sub #backgroud process, can set run flag to False to stop this case. start_time = time.time() stop_time = start_time + pktgen_stress_timeout while (env["pktgen_run"] and time.time < stop_time): runner(exec_cmd, timeout=pktgen_stress_timeout) #using ping to kill the pktgen stress except aexpect.ShellTimeoutError: session.cmd("ping pktgen_ip") finally: env["pktgen_run"] = False if server_session: server_session.close() if session: session.close()
def run(test, params, env): """ Run Pktgen test between host/guest 1) Boot the main vm, or just grab it if it's already booted. 2) Configure pktgen on guest or host 3) Run pktgen test, finish when timeout :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def _pin_vm_threads(node): """ pin guest vcpu and vhost threads to cpus of a numa node repectively :param node: which numa node to pin """ if node: if not isinstance(node, utils_misc.NumaNode): node = utils_misc.NumaNode(int(node)) utils_test.qemu.pin_vm_threads(vm, node) timeout = float(params.get("pktgen_test_timeout", "240")) run_threads = params.get("pktgen_threads", 1) record_list = params.get("record_list") error_context.context("Init the VM, and try to login", logging.info) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session_serial = vm.wait_for_serial_login(restart_network=True) session = vm.wait_for_login() # print numa information on host and pinning vhost and vcpus to cpus process.system_output("numactl --hardware") process.system_output("numactl --show") _pin_vm_threads(params.get("numa_node")) # get parameter from dictionary category = params.get("category") pkt_size = params.get("pkt_size") kvm_ver_chk_cmd = params.get("kvm_ver_chk_cmd") guest_ver_cmd = params["guest_ver_cmd"] # get qemu, guest kernel and kvm version info and write them into result result_path = utils_misc.get_path(test.resultsdir, "pktgen_perf.RHS") result_file = open(result_path, "w") kvm_ver = process.system_output(kvm_ver_chk_cmd, shell=True).decode() host_ver = os.uname()[2] guest_ver = session.cmd_output(guest_ver_cmd, timeout) result_file.write("### kvm-userspace-ver : %s\n" % kvm_ver) result_file.write("### kvm_version : %s\n" % host_ver) result_file.write("### guest-kernel-ver :%s\n" % guest_ver) # get record_list record_line = "" for record in record_list.split(): record_line += "%s|" % format_result(record) # get result tested by each scenario for pkt_cate in category.split(): result_file.write("Category:%s\n" % pkt_cate) result_file.write("%s\n" % record_line.rstrip("|")) # copy pktgen_test script to test server local_path = os.path.join(data_dir.get_shared_dir(), "scripts/pktgen_perf.sh") remote_path = "/tmp/pktgen_perf.sh" if pkt_cate == "tx": vm.copy_files_to(local_path, remote_path) elif pkt_cate == "rx": process.run("cp %s %s" % (local_path, remote_path)) for size in pkt_size.split(): if pkt_cate == "tx": error_context.context("test guest tx pps performance", logging.info) guest_mac = vm.get_mac_address(0) pktgen_interface = utils_net.get_linux_ifname( session, guest_mac) dsc_dev = utils_net.Interface(vm.get_ifname(0)) dsc = dsc_dev.get_mac() runner = session.cmd pktgen_ip = vm.wait_for_get_address(0, timeout=5) pkt_cate_r = run_test(session_serial, runner, remote_path, pktgen_ip, dsc, pktgen_interface, run_threads, size, timeout) elif pkt_cate == "rx": error_context.context("test guest rx pps performance", logging.info) host_bridge = params.get("netdst", "switch") host_nic = utils_net.Interface(host_bridge) pktgen_ip = host_nic.get_ip() dsc = vm.wait_for_get_address(0, timeout=5) pktgen_interface = vm.get_ifname(0) runner = _system_output pkt_cate_r = run_test(session_serial, runner, remote_path, pktgen_ip, dsc, pktgen_interface, run_threads, size, timeout) line = "%s|" % format_result(size) line += "%s" % format_result(pkt_cate_r) result_file.write(("%s\n" % line)) error_context.context( "Verify Host and guest kernel no error\ and call trace", logging.info) vm.verify_kernel_crash() utils_misc.verify_dmesg() result_file.close() session_serial.close() session.close()
def run(test, params, env): """ Test virsh interface related commands. (1) If using given exist interface for testing(eg. lo or ethX): 1.1 Dumpxml for the interface(with --inactive option) 1.2 Destroy the interface 1.3 Undefine the interface (2) Define an interface from XML file (3) List interfaces with '--inactive' optioin (4) Start the interface (5) List interfaces with no option (6) Dumpxml for the interface (7) Get interface MAC address by interface name (8) Get interface name by interface MAC address (9) Delete interface if not use the exist interface for testing 9.1 Destroy the interface 9.2 Undefine the interface Caveat, this test may affect the host network, so using the loopback(lo) device by default. You can specify the interface which you want, but be careful. """ iface_name = params.get("iface_name") iface_xml = params.get("iface_xml") ping_ip = params.get("ping_ip", "localhost") use_exist_iface = "yes" == params.get("use_exist_iface", "no") status_error = "yes" == params.get("status_error", "no") iface_script = NETWORK_SCRIPT + iface_name iface_script_bk = os.path.join(test.tmpdir, "iface-%s.bk" % iface_name) net_iface = utils_net.Interface(name=iface_name) iface_is_up = True list_option = "--all" if use_exist_iface: if not libvirt.check_iface(iface_name, "exists", "--all"): raise error.TestError("Interface '%s' not exists" % iface_name) iface_xml = os.path.join(test.tmpdir, "iface.xml.tmp") iface_is_up = net_iface.is_up() else: # Note, if not use the interface which already exists, iface_name must # be equal to the value specified in XML file if libvirt.check_iface(iface_name, "exists", "--all"): raise error.TestError("Interface '%s' already exists" % iface_name) if not iface_xml: raise error.TestError("XML file is needed.") # Stop NetworkManager as which may conflict with virsh iface commands try: NM = utils_misc.find_command("NetworkManager") except ValueError: logging.debug("No NetworkManager service.") NM = None NM_is_running = False if NM is not None: NM_service = service.Factory.create_service("NetworkManager") NM_is_running = NM_service.status() if NM_is_running: NM_service.stop() # run test cases try: if use_exist_iface: # back up the interface script utils.run("cp %s %s" % (iface_script, iface_script_bk)) # step 1.1 # dumpxml for interface xml = virsh.iface_dumpxml(iface_name, "--inactive", to_file=iface_xml, debug=True) # Step 1.2 # Destroy interface if iface_is_up: result = virsh.iface_destroy(iface_name, debug=True) libvirt.check_exit_status(result, status_error) # Step 1.3 # Undefine interface result = virsh.iface_undefine(iface_name, debug=True) libvirt.check_exit_status(result, status_error) if not status_error: if libvirt.check_iface(iface_name, "exists", list_option): raise error.TestFail("%s is still present." % iface_name) # Step 2 # Define interface result = virsh.iface_define(iface_xml, debug=True) libvirt.check_exit_status(result, status_error) # Step 3 # List inactive interfaces list_option = "--inactive" if not status_error: if not libvirt.check_iface(iface_name, "exists", list_option): raise error.TestFail("Fail to find %s." % iface_name) # Step 4 # Start interface result = virsh.iface_start(iface_name, debug=True) libvirt.check_exit_status(result, status_error) if not status_error: if not libvirt.check_iface(iface_name, "ping", ping_ip): raise error.TestFail("Ping %s fail." % ping_ip) # Step 5 # List active interfaces list_option = "" if not status_error: if not libvirt.check_iface(iface_name, "exists", list_option): raise error.TestFail( "Fail to find %s in active interface list." % iface_name) # Step 6 # Dumpxml for interface xml = virsh.iface_dumpxml(iface_name, "", to_file="", debug=True) logging.debug("Interface '%s' XML:\n%s", iface_name, xml) # Step 7 # Get interface MAC address by name result = virsh.iface_mac(iface_name, debug=True) libvirt.check_exit_status(result, status_error) if not status_error: if not libvirt.check_iface(iface_name, "mac", result.stdout.strip()): raise error.TestFail("Mac address check fail") # Step 8 # Get interface name by MAC address iface_mac = net_iface.get_mac() result = virsh.iface_name(iface_mac, debug=True) libvirt.check_exit_status(result, status_error) # Step 9 if not use_exist_iface: # Step 9.1 # Destroy interface result = virsh.iface_destroy(iface_name, debug=True) libvirt.check_exit_status(result, status_error) # Step 9.2 # Undefine interface result = virsh.iface_undefine(iface_name, debug=True) libvirt.check_exit_status(result, status_error) list_option = "--all" if not status_error: if libvirt.check_iface(iface_name, "exists", list_option): raise error.TestFail("%s is still present." % iface_name) finally: if use_exist_iface: if os.path.exists(iface_xml): os.remove(iface_xml) if not os.path.exists(iface_script): utils.run("mv %s %s" % (iface_script_bk, iface_script)) if iface_is_up: # Need reload script utils.run("ifup %s" % iface_name) else: net_iface.down() else: if libvirt.check_iface(iface_name, "exists", "--all"): # Remove the interface if os.path.exists(iface_script): os.remove(iface_script) utils_net.bring_down_ifname(iface_name) if NM_is_running: NM_service.start()
def run(test, params, env): """ Test virsh interface related commands. (1) If using given exist interface for testing(eg. lo or ethX): 1.1 Dumpxml for the interface(with --inactive option) 1.2 Destroy the interface 1.3 Undefine the interface (2) Define an interface from XML file (3) List interfaces with '--inactive' optioin (4) Start the interface (5) List interfaces with no option (6) Dumpxml for the interface (7) Get interface MAC address by interface name (8) Get interface name by interface MAC address (9) Delete interface if not use the exist interface for testing 9.1 Destroy the interface 9.2 Undefine the interface Caveat, this test may affect the host network, so using the loopback(lo) device by default. You can specify the interface which you want, but be careful. """ iface_name = params.get("iface_name", "ENTER.BRIDGE.NAME") iface_xml = params.get("iface_xml") iface_type = params.get("iface_type", "ethernet") iface_pro = params.get("iface_pro", "") iface_eth = params.get("iface_eth", "") iface_tag = params.get("iface_tag", "0") if iface_type == "vlan": iface_name = iface_eth + "." + iface_tag iface_eth_using = "yes" == params.get("iface_eth_using", "no") ping_ip = params.get("ping_ip", "localhost") use_exist_iface = "yes" == params.get("use_exist_iface", "no") status_error = "yes" == params.get("status_error", "no") net_restart = "yes" == params.get("iface_net_restart", "no") list_dumpxml_acl = "yes" == params.get("list_dumpxml_acl", "no") if ping_ip.count("ENTER"): test.cancel("Please input a valid ip address") if iface_name.count("ENTER"): test.cancel("Please input a existing bridge/ethernet name") uri = params.get("virsh_uri") unprivileged_user = params.get('unprivileged_user', "EXAMPLE") if unprivileged_user: if unprivileged_user.count('EXAMPLE'): unprivileged_user = '******' 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_dargs = {'debug': True} list_dumpxml_dargs = {'debug': True} if params.get('setup_libvirt_polkit') == 'yes': if not list_dumpxml_acl: virsh_dargs['uri'] = uri virsh_dargs['unprivileged_user'] = unprivileged_user else: list_dumpxml_dargs['uri'] = uri list_dumpxml_dargs['unprivileged_user'] = unprivileged_user list_dumpxml_dargs['ignore_status'] = False # acl api negative testing params write_save_status_error = "yes" == params.get("write_save_status_error", "no") start_status_error = "yes" == params.get("start_status_error", "no") stop_status_error = "yes" == params.get("stop_status_error", "no") delete_status_error = "yes" == params.get("delete_status_error", "no") vm_name = params.get("main_vm") vm = env.get_vm(vm_name) if vm: xml_bak = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) iface_script = NETWORK_SCRIPT + iface_name iface_script_bk = os.path.join(data_dir.get_tmp_dir(), "iface-%s.bk" % iface_name) net_bridge = utils_net.Bridge() if use_exist_iface: if iface_type == "bridge": if iface_name not in net_bridge.list_br(): test.error("Bridge '%s' not exists" % iface_name) ifaces = net_bridge.get_structure()[iface_name] if len(ifaces) < 1: # In this situation, dhcp maybe cannot get ip address # Unless you use static, we'd better skip such case test.cancel("Bridge '%s' has no interface" " bridged, perhaps cannot get" " ipaddress" % iface_name) net_iface = utils_net.Interface(name=iface_name) iface_is_up = True list_option = "--all" if use_exist_iface: if not libvirt.check_iface(iface_name, "exists", "--all"): test.error("Interface '%s' not exists" % iface_name) iface_xml = os.path.join(data_dir.get_tmp_dir(), "iface.xml.tmp") iface_is_up = net_iface.is_up() else: # Note, if not use the interface which already exists, iface_name must # be equal to the value specified in XML file if libvirt.check_iface(iface_name, "exists", "--all"): test.error("Interface '%s' already exists" % iface_name) if not iface_xml: test.error("XML file is needed.") iface_xml = os.path.join(data_dir.get_tmp_dir(), iface_xml) create_xml_file(iface_xml, params) # Stop NetworkManager as which may conflict with virsh iface commands try: NM = utils_path.find_command("NetworkManager") except utils_path.CmdNotFoundError: logging.debug("No NetworkManager service.") NM = None NM_is_running = False if NM is not None: NM_service = service.Factory.create_service("NetworkManager") NM_is_running = NM_service.status() if NM_is_running: NM_service.stop() # run test cases try: if use_exist_iface: # back up the interface script process.run("cp %s %s" % (iface_script, iface_script_bk), shell=True) # step 1.1 # dumpxml for interface if list_dumpxml_acl: virsh.iface_list(**list_dumpxml_dargs) xml = virsh.iface_dumpxml(iface_name, "--inactive", to_file=iface_xml, **list_dumpxml_dargs) # Step 1.2 # Destroy interface if iface_is_up: result = virsh.iface_destroy(iface_name, **virsh_dargs) if (params.get('setup_libvirt_polkit') == 'yes' and stop_status_error): # acl_test negative test libvirt.check_exit_status(result, stop_status_error) virsh.iface_destroy(iface_name, debug=True) else: libvirt.check_exit_status(result, status_error) # Step 1.3 # Undefine interface result = virsh.iface_undefine(iface_name, **virsh_dargs) if (params.get('setup_libvirt_polkit') == 'yes' and delete_status_error): # acl_test negative test libvirt.check_exit_status(result, delete_status_error) virsh.iface_undefine(iface_name, debug=True) else: libvirt.check_exit_status(result, status_error) if not status_error: if libvirt.check_iface(iface_name, "exists", list_option): test.fail("%s is still present." % iface_name) # Step 2 # Define interface result = virsh.iface_define(iface_xml, **virsh_dargs) if (params.get('setup_libvirt_polkit') == 'yes' and write_save_status_error): # acl_test negative test libvirt.check_exit_status(result, write_save_status_error) virsh.iface_define(iface_xml, debug=True) elif iface_type == "bond" and not ping_ip: libvirt.check_exit_status(result, True) return else: libvirt.check_exit_status(result, status_error) if net_restart: network = service.Factory.create_service("network") network.restart() # After network restart, (ethernet)interface will be started if (not net_restart and iface_type in ("bridge", "ethernet")) or\ (not use_exist_iface and iface_type in ("vlan", "bond")): # Step 3 # List inactive interfaces list_option = "--inactive" if not status_error: if not libvirt.check_iface(iface_name, "exists", list_option): test.fail("Fail to find %s." % iface_name) # Step 4 # Start interface result = virsh.iface_start(iface_name, **virsh_dargs) if (params.get('setup_libvirt_polkit') == 'yes' and start_status_error): # acl_test negative test libvirt.check_exit_status(result, start_status_error) virsh.iface_start(iface_name, debug=True) elif (not net_restart and not use_exist_iface and (iface_type == "ethernet" and iface_pro in ["", "dhcp"] or iface_type == "bridge" and iface_pro == "dhcp")): libvirt.check_exit_status(result, True) else: libvirt.check_exit_status(result, status_error) if not status_error: iface_ip = net_iface.get_ip() ping_ip = ping_ip if not iface_ip else iface_ip if ping_ip: if not libvirt.check_iface(iface_name, "ping", ping_ip): test.fail("Ping %s fail." % ping_ip) # Step 5 # List active interfaces if use_exist_iface or\ (iface_pro != "dhcp" and iface_type == "bridge") or\ (iface_eth_using and iface_type == "vlan"): list_option = "" if not status_error: if not libvirt.check_iface(iface_name, "exists", list_option): test.fail("Fail to find %s in active " "interface list" % iface_name) if vm: if vm.is_alive(): vm.destroy() iface_index = 0 iface_mac_list = vm_xml.VMXML.get_iface_dev(vm_name) # Before test, detach all interfaces in guest for mac in iface_mac_list: iface_info = vm_xml.VMXML.get_iface_by_mac(vm_name, mac) type = iface_info.get('type') virsh.detach_interface( vm_name, "--type %s --mac %s" " --config" % (type, mac)) # After detach interface, vm.virtnet also need update, the # easy way is free these mac addresses before start VM vm.free_mac_address(iface_index) iface_index += 1 virsh.attach_interface( vm_name, "--type %s --source %s" " --config" % (iface_type, iface_name)) vm.start() try: # Test if guest can be login vm.wait_for_login() except remote.LoginError: test.fail("Cannot login guest with %s" % iface_name) # Step 6 # Dumpxml for interface if list_dumpxml_acl: virsh.iface_list(**list_dumpxml_dargs) xml = virsh.iface_dumpxml(iface_name, "", to_file="", **list_dumpxml_dargs) logging.debug("Interface '%s' XML:\n%s", iface_name, xml) # Step 7 # Get interface MAC address by name result = virsh.iface_mac(iface_name, debug=True) libvirt.check_exit_status(result, status_error) if not status_error and result.stdout.strip(): if not libvirt.check_iface(iface_name, "mac", result.stdout.strip()): test.fail("Mac address check fail") # Step 8 # Get interface name by MAC address # Bridge's Mac equal to bridged interface's mac if iface_type not in ("bridge", "vlan") and result.stdout.strip(): iface_mac = net_iface.get_mac() result = virsh.iface_name(iface_mac, debug=True) libvirt.check_exit_status(result, status_error) # Step 9 if not use_exist_iface: # Step 9.0 # check if interface's state is active before destroy if libvirt.check_iface(iface_name, "state", "--all"): # Step 9.1 # Destroy interface result = virsh.iface_destroy(iface_name, **virsh_dargs) if (params.get('setup_libvirt_polkit') == 'yes' and stop_status_error): # acl_test negative test libvirt.check_exit_status(result, stop_status_error) virsh.iface_destroy(iface_name, debug=True) elif (not net_restart and iface_type == "ethernet" and iface_pro in ["", "dhcp"] or iface_type == "bridge" and iface_pro == "dhcp"): libvirt.check_exit_status(result, True) else: libvirt.check_exit_status(result, status_error) # Step 9.2 # Undefine interface result = virsh.iface_undefine(iface_name, **virsh_dargs) if (params.get('setup_libvirt_polkit') == 'yes' and delete_status_error): # acl_test negative test libvirt.check_exit_status(result, delete_status_error) virsh.iface_undefine(iface_name, debug=True) else: libvirt.check_exit_status(result, status_error) list_option = "--all" if not status_error: if libvirt.check_iface(iface_name, "exists", list_option): test.fail("%s is still present." % iface_name) finally: if os.path.exists(iface_xml): os.remove(iface_xml) if os.path.exists(iface_script): os.remove(iface_script) if use_exist_iface: if not os.path.exists(iface_script): process.run("mv %s %s" % (iface_script_bk, iface_script), shell=True) if iface_is_up and\ not libvirt.check_iface(iface_name, "exists", ""): # Need reload script process.run("ifup %s" % iface_name, shell=True) elif not iface_is_up and libvirt.check_iface( iface_name, "exists", ""): net_iface.down() if vm: xml_bak.sync() else: if libvirt.check_iface(iface_name, "exists", "--all"): # Remove the interface try: utils_net.bring_down_ifname(iface_name) except utils_net.TAPBringDownError: pass if iface_type == "bridge": if iface_name in net_bridge.list_br(): try: net_bridge.del_bridge(iface_name) except IOError: pass if NM_is_running: NM_service.start()
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). """ iface_name = params.get("iface_name") bridge_name = params.get("bridge_name") ping_ip = params.get("ping_ip", "") 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_script = NETWORK_SCRIPT + iface_name iface_script_bk = os.path.join(test.tmpdir, "iface-%s.bk" % iface_name) if not libvirt.check_iface(iface_name, "exists", "--all"): raise error.TestNAError("Interface '%s' not exists" % iface_name) net_iface = utils_net.Interface(name=iface_name) iface_is_up = net_iface.is_up() # Make sure the interface exists if not libvirt.check_iface(iface_name, "exists", "--all"): raise error.TestNAError("Interface '%s' not exists" % iface_name) # Make sure the bridge name not exists net_bridge = utils_net.Bridge() if bridge_name in net_bridge.list_br(): raise error.TestNAError("Bridge '%s' already exists" % bridge_name) # Stop NetworkManager service try: NM = utils_misc.find_command("NetworkManager") except ValueError: logging.debug("No NetworkManager service.") NM = None NM_is_running = False if NM is not None: NM_service = service.Factory.create_service("NetworkManager") NM_is_running = NM_service.status() if NM_is_running: NM_service.stop() # Back up the interface script utils.run("cp %s %s" % (iface_script, iface_script_bk)) def unbridge_check(): """ Check the result after do unbridge. """ list_option = "--all" if libvirt.check_iface(bridge_name, "exists", list_option): raise error.TestFail("%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): raise error.TestFail("%s is not present." % iface_name) if bridge_delay: bridge_option += " --delay %s" % delay_num # Run test try: if create_bridge: # Create bridge result = virsh.iface_bridge(iface_name, bridge_name, bridge_option) 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: br_ip = "" # 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): raise error.TestFail("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) libvirt.check_exit_status(result, unbridge_status_error) if not unbridge_status_error: unbridge_check() else: raise error.TestFail("%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: if libvirt.check_iface(bridge_name, "exists", "--all"): virsh.iface_unbridge(bridge_name) if not os.path.exists(iface_script): utils.run("mv %s %s" % (iface_script_bk, iface_script)) if iface_is_up: # Need reload script utils.run("ifup %s" % iface_name) else: net_iface.down() # Clear the new create bridge if it exists try: utils_net.bring_down_ifname(bridge_name) utils.run("brctl delbr %s" % bridge_name) except utils_net.TAPBringDownError: pass if NM_is_running: NM_service.start()
def run(test, params, env): """ Run Pktgen test between host/guest 1) Boot the main vm, or just grab it if it's already booted. 2) Configure pktgen server(only linux) 3) Run pktgen test, finish when timeout or env["pktgen_run"] != True :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ login_timeout = float(params.get("login_timeout", 360)) error_context.context("Init the VM, and try to login", logging.info) external_host = params.get("external_host") if not external_host: get_host_cmd = "ip route | awk '/default/ {print $3}'" external_host = process.system_output(get_host_cmd, shell=True).decode() vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=login_timeout) error_context.context("Pktgen server environment prepare", logging.info) # pktgen server only support linux, since pktgen is a linux kernel module pktgen_server = params.get("pktgen_server", "localhost") params_server = params.object_params("pktgen_server") s_shell_client = params_server.get("shell_client", "ssh") s_shell_port = params_server.get("shell_port", "22") s_username = params_server.get("username", "root") s_passwd = params_server.get("password", "123456") s_shell_prompt = params_server.get("shell_prompt") server_session = "" # pktgen server is autotest virtual guest(only linux) if pktgen_server in params.get("vms", "vm1 vm2"): vm_pktgen = env.get_vm(pktgen_server) vm_pktgen.verify_alive() server_session = vm_pktgen.wait_for_login(timeout=login_timeout) runner = server_session.cmd pktgen_ip = vm_pktgen.get_address() pktgen_mac = vm_pktgen.get_mac_address() server_interface = utils_net.get_linux_ifname(server_session, pktgen_mac) # pktgen server is a external host assigned elif re.match(r"((\d){1,3}\.){3}(\d){1,3}", pktgen_server): pktgen_ip = pktgen_server server_session = remote.wait_for_login(s_shell_client, pktgen_ip, s_shell_port, s_username, s_passwd, s_shell_prompt) runner = server_session.cmd server_interface = params.get("server_interface") if not server_interface: test.cancel("Must config server interface before test") else: # using host as a pktgen server server_interface = params.get("netdst", "switch") host_nic = utils_net.Interface(server_interface) pktgen_ip = host_nic.get_ip() pktgen_mac = host_nic.get_mac() runner = process.system # copy pktgen_test scipt to the test server. local_path = os.path.join(data_dir.get_root_dir(), "shared/scripts/pktgen.sh") remote_path = "/tmp/pktgen.sh" remote.scp_to_remote(pktgen_ip, s_shell_port, s_username, s_passwd, local_path, remote_path) error_context.context("Run pktgen test", logging.info) run_threads = params.get("pktgen_threads", 1) pktgen_stress_timeout = float(params.get("pktgen_test_timeout", 600)) exec_cmd = "%s %s %s %s %s" % (remote_path, vm.get_address(), vm.get_mac_address(), server_interface, run_threads) try: env["pktgen_run"] = True try: # Set a run flag in env, when other case call this case as a sub # backgroud process, can set run flag to False to stop this case. start_time = time.time() stop_time = start_time + pktgen_stress_timeout while (env["pktgen_run"] and time.time() < stop_time): runner(exec_cmd, timeout=pktgen_stress_timeout) # using ping to kill the pktgen stress except aexpect.ShellTimeoutError: session.cmd("ping %s" % pktgen_ip, ignore_all_errors=True) finally: env["pktgen_run"] = False error_context.context( "Verify Host and guest kernel no error " "and call trace", logging.info) vm.verify_kernel_crash() utils_misc.verify_dmesg() error_context.context("Ping external host after pktgen test", logging.info) session_ping = vm.wait_for_login(timeout=login_timeout) status, output = utils_test.ping(dest=external_host, session=session_ping, timeout=240, count=20) loss_ratio = utils_test.get_loss_ratio(output) if (loss_ratio > int(params.get("packet_lost_ratio", 5)) or loss_ratio == -1): logging.debug("Ping %s output: %s" % (external_host, output)) test.fail("Guest network connction unusable, " "packet lost ratio is '%d%%'" % loss_ratio) if server_session: server_session.close() if session: session.close() if session_ping: session_ping.close()
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()
def run(test, params, env): """ Qemu host nic bonding test: 1) Load bonding module with mode 802.3ad 2) Bring up bond interface 3) Add nics to bond interface 4) Add a new bridge and add bond interface to it 5) Get ip address for bridge 6) Boot up guest with the bridge 7) Checking guest netowrk via ping 8) Start file transfer between guest and host 9) Disable and enable physical interfaces during file transfer :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ bond_iface = params.get("bond_iface", "bond0") bond_br_name = params.get("bond_br_name", "br_bond0") timeout = int(params.get("login_timeout", 240)) remote_host = params.get("dsthost") ping_timeout = int(params.get("ping_timeout", 240)) bonding_timeout = int(params.get("bonding_timeout", 1)) bonding_mode = params.get("bonding_mode", "1") bonding_miimon = params.get("bonding_miimon", "100") params['netdst'] = bond_br_name host_bridges = utils_net.Bridge() error.context("Load bonding module with mode 802.3ad", logging.info) if not utils.system("lsmod|grep bonding", ignore_status=True): utils.system("modprobe -r bonding") utils.system( "modprobe bonding mode=%s miimon=%s" % (bonding_mode, bonding_miimon)) error.context("Bring up %s" % bond_iface, logging.info) host_ifaces = utils_net.get_host_iface() if bond_iface not in host_ifaces: raise error.TestError("Can not find bond0 in host") bond_iface = utils_net.Interface(bond_iface) bond_iface.up() bond_mac = bond_iface.get_mac() host_ph_iface_pre = params.get("host_ph_iface_prefix", "en") host_iface_bonding = int(params.get("host_iface_bonding", 2)) ph_ifaces = [_ for _ in host_ifaces if re.match(host_ph_iface_pre, _)] host_ph_ifaces = [_ for _ in ph_ifaces if utils_net.Interface(_).is_up()] ifaces_in_use = host_bridges.list_iface() host_ph_ifaces_un = list(set(host_ph_ifaces) - set(ifaces_in_use)) if (len(host_ph_ifaces_un) < 2 or len(host_ph_ifaces_un) < host_iface_bonding): raise error.TestNAError("Host need %s nics" " at least." % host_iface_bonding) error.context("Add nics to %s" % bond_iface.name, logging.info) host_ifaces_bonding = host_ph_ifaces_un[:host_iface_bonding] ifenslave_cmd = "ifenslave %s" % bond_iface.name op_ifaces = [] for host_iface_bonding in host_ifaces_bonding: op_ifaces.append(utils_net.Interface(host_iface_bonding)) ifenslave_cmd += " %s" % host_iface_bonding utils.system(ifenslave_cmd) error.context("Add a new bridge and add %s to it." % bond_iface.name, logging.info) if bond_br_name not in host_bridges.list_br(): host_bridges.add_bridge(bond_br_name) host_bridges.add_port(bond_br_name, bond_iface.name) error.context("Get ip address for bridge", logging.info) utils.system("dhclient -r; dhclient %s" % bond_br_name) error.context("Boot up guest with bridge %s" % bond_br_name, logging.info) params["start_vm"] = "yes" vm_name = params.get("main_vm") env_process.preprocess_vm(test, params, env, vm_name) vm = env.get_vm(vm_name) session = vm.wait_for_login(timeout=timeout) error.context("Checking guest netowrk via ping.", logging.info) ping_cmd = params.get("ping_cmd") ping_cmd = re.sub("REMOTE_HOST", remote_host, ping_cmd) session.cmd(ping_cmd, timeout=ping_timeout) error.context("Start file transfer", logging.info) f_transfer = utils.InterruptedThread(utils_test.run_virt_sub_test, args=(test, params, env,), kwargs={"sub_type": "file_transfer"}) f_transfer.start() utils_misc.wait_for(lambda: utils.system_output("pidof scp", ignore_status=True), 30) error.context("Disable and enable physical " "interfaces in %s" % bond_br_name, logging.info) while True: for op_iface in op_ifaces: logging.debug("Turn down %s" % op_iface.name) op_iface.down() time.sleep(bonding_timeout) logging.debug("Bring up %s" % op_iface.name) op_iface.up() time.sleep(bonding_timeout) if not f_transfer.is_alive(): break f_transfer.join()
def teardown_default(): """ Default cleanup """ pf_iface_obj = utils_net.Interface(pf_name) pf_iface_obj.up()
def run(test, params, env): """ QEMU 'open vswitch host vlan' test 1) Start a VM and setup netperf in it 2) Stop NetworkManager service in host 3) Create a new private ovs bridge, which has no physical nics inside 4) Create 4 ovs ports and add to 2 vlans 4) Boot 4 VMs on this bridge and add them to 2 vlans 5) Configure ip address of all systems make sure all IPs are in same subnet 6) Ping between two guests in same vlan 7) Ping between two guests in different vlan 8) Ping between two guests in another vlan 9) Netperf test between two guests in same vlan 10) Transfer file between two guests in same vlan (optional) :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ txt = "Setup netperf in guest." image_snapshot = params.get("image_snapshot", "yes") error_context.context(txt, logging.info) netperf_setup(test, params, env) params["image_snapshot"] = image_snapshot os_type = params.get("os_type", "linux") bridge_name = params.get("private_vlan_bridge", "ovs_private_br") login_timeout = int(params.get("login_timeout", 360)) match_error = params.get("destination_unreachable", "") txt = "Stop NetworkManager service in host." error_context.context(txt, logging.info) process.system(params["stop_network_manager"], timeout=120, ignore_status=True) txt = "Create a new private ovs bridge, which has" txt += " no physical nics inside." error_context.context(txt, logging.info) ovs_br_create_cmd = params["ovs_br_create_cmd"] ovs_br_remove_cmd = params["ovs_br_remove_cmd"] try: process.system(ovs_br_create_cmd, shell=True) except process.CmdError: test.fail("Fail to create ovs bridge %s" % bridge_name) try: params["start_vm"] = "yes" params["netdst"] = bridge_name vms = params.get("vms").split() sessions = [] ips = [] txt = "Start multi vms and add them to 2 vlans." error_context.context(txt, logging.info) for vm_name in vms: vm_params = params.object_params(vm_name) env_process.preprocess_vm(test, vm_params, env, vm_name) vm = env.get_vm(vm_name) ifname = vm.virtnet[0]["ifname"] guest_ip = vm.virtnet[0].ip vlan = vm_params["ovs_port_vlan"] create_port_cmd = "ovs-vsctl set Port %s tag=%s" % (ifname, vlan) try: output = process.system_output(create_port_cmd, timeout=120, ignore_status=False).decode() process.system_output("ovs-vsctl show") except process.CmdError: err = "Fail to create ovs port %s " % ifname err += "on bridge %s." % bridge_name err += " Command: %s, " % create_port_cmd err += "output: %s." % output test.fail(err) session_ctl = vm.wait_for_serial_login(timeout=login_timeout) if os_type == "linux": txt = "Stop NetworkManager service in guest %s." % vm_name session_ctl.cmd(params["stop_network_manager"], timeout=120) mac = vm.get_mac_address() txt = "Set guest %s mac %s IP to %s" % (vm_name, mac, guest_ip) error_context.context(txt, logging.info) utils_net.set_guest_ip_addr(session_ctl, mac, guest_ip, os_type=os_type) utils_net.Interface(ifname).down() utils_net.Interface(ifname).up() ips.append(guest_ip) sessions.append(session_ctl) txt = "Ping between two guests in same vlan. %s -> %s" % (vms[0], vms[1]) error_context.context(txt, logging.info) ping(test, os_type, match_error, ips[1], count=10, session=sessions[0], same_vlan=True) txt = "Ping between two guests in different " txt += "vlan. %s -> %s" % (vms[0], vms[2]) error_context.context(txt, logging.info) ping(test, os_type, match_error, ips[2], count=10, session=sessions[0], same_vlan=False) txt = "Ping between two guests in another " txt += "vlan. %s -> %s" % (vms[2], vms[3]) error_context.context(txt, logging.info) ping(test, os_type, match_error, ips[3], count=10, session=sessions[2], same_vlan=True) txt = "Netperf test between two guests in same vlan." txt += "%s -> %s" % (vms[0], vms[1]) error_context.context(txt, logging.info) txt = "Run netserver in VM %s" % vms[0] error_context.context(txt, logging.info) shutdown_firewall_cmd = params["shutdown_firewall"] sessions[0].cmd_status_output(shutdown_firewall_cmd, timeout=10) netserver_cmd = params.get("netserver_cmd") netperf_path = params.get("netperf_path") cmd = os.path.join(netperf_path, netserver_cmd) status, output = sessions[0].cmd_status_output(cmd, timeout=60) if status != 0: err = "Fail to start netserver in VM." err += " Command output %s" % output test.error(err) txt = "Run netperf client in VM %s" % vms[1] error_context.context(txt, logging.info) sessions[1].cmd_status_output(shutdown_firewall_cmd, timeout=10) test_duration = int(params.get("netperf_test_duration", 60)) test_protocol = params.get("test_protocol") netperf_cmd = params.get("netperf_cmd") netperf_cmd = os.path.join(netperf_path, netperf_cmd) cmd = netperf_cmd % (test_duration, ips[0]) if test_protocol: cmd += " -t %s" % test_protocol cmd_timeout = test_duration + 20 status, output = sessions[1].cmd_status_output(cmd, timeout=cmd_timeout) if status != 0: err = "Fail to run netperf test between %s and %s." % (vms[0], vms[1]) err += " Command output:\n%s" % output test.fail(err) if params.get("file_transfer_test", "yes") == "yes": filesize = int(params.get("filesize", 1024)) file_create_timeout = int(params.get("file_create_timeout", 720)) file_path = params.get("file_path", "/var/tmp/src_file") txt = "Create %s MB file %s in %s" % (filesize, file_path, vms[0]) error_context.context(txt, logging.info) create_file_in_guest(test, session=sessions[0], file_path=file_path, size=filesize, os_type=os_type, timeout=file_create_timeout) txt = "Transfer file %s between guests in same " % file_path txt += "vlan. %s -> %s" % (vms[0], vms[1]) error_context.context(txt, logging.info) password = params.get("password", "kvmautotest") username = params.get("username", "root") f_tmout = int(params.get("file_transfer_timeout", 1200)) shell_port = params.get("shell_port", "22") data_port = params.get("nc_file_transfer_port", "9000") log_file = "file_transfer_from_%s_to_%s.log" % (ips[0], ips[1]) if os_type == "linux": # TODO, windows will be supported later remote.nc_copy_between_remotes(ips[0], ips[1], shell_port, password, password, username, username, file_path, file_path, d_port=data_port, timeout=2, check_sum=True, s_session=sessions[0], d_session=sessions[1], file_transfer_timeout=f_tmout) finally: process.system(ovs_br_remove_cmd, ignore_status=False, shell=True)
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). """ iface_name = params.get("iface_name") 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_script = NETWORK_SCRIPT + iface_name iface_script_bk = os.path.join(data_dir.get_tmp_dir(), "iface-%s.bk" % iface_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) net_iface = utils_net.Interface(name=iface_name) iface_is_up = net_iface.is_up() iface_ip = net_iface.get_ip() # 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 try: NM = utils_path.find_command("NetworkManager") except utils_path.CmdNotFoundError: logging.debug("No NetworkManager service.") NM = None NM_is_running = False if NM is not None: NM_service = service.Factory.create_service("NetworkManager") NM_is_running = NM_service.status() if NM_is_running: NM_service.stop() 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 result = virsh.iface_bridge(iface_name, bridge_name, bridge_option) 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) 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) if os.path.exists(iface_script_bk): process.run("mv %s %s" % (iface_script_bk, iface_script), shell=True) if iface_is_up: # Need reload script process.run("ifdown %s" % iface_name, shell=True) process.run("ifup %s" % iface_name, shell=True) else: net_iface.down() # Clear the new create bridge if it exists try: utils_net.bring_down_ifname(bridge_name) process.run("brctl delbr %s" % bridge_name, shell=True) except utils_net.TAPBringDownError: pass if NM_is_running: NM_service.start()