1) attach-interface without vm name 2) detach-interface without vm name 3) attach-interface with vm id 4) detach-interface with vm id 5) attach-interface with hex vm id 6) detach-interface with hex vm id 7) attach-interface with invalid vm id 8) detach-interface with invalid vm id 9) attach-interface with correct vm name 10) detach-interface with correct vm name 11) attach-interface with vm name beginning with number 12) detach-interface with vm name beginning with number 13) attach-interface with vm name beginning with # 14) detach-interface with vm name beginning with # 15) attach-interface with vm name beginning with - 16) detach-interface with vm name beginning with - 17) attach-interface with vm suppend 18) detach-interface with vm suppend 19) attach-interface with libvirtd stop 20) detach-interface with libvirtd stop 21) attach-interface with vm uuid 22) detach-interface with vm uuid 23) attach-interface with invalid vm uuid 24) detach-interface with invalid vm uuid 25) attach-interface with vm shutdown 26) detach-interface with vm shutdown 27) attach-interface with invalid --type option 28) detach-interface with invalid --type option 29) attach-interface with invalid option xyz with mac address 30) detach-interface with invalid option xyz with mac address 31) attach-interface with invalid option --xyz with mac address 32) detach-interface with invalid option --xyz with mac address 33) detach-interface with invalid option xyz without mac address 34) attach-interface with invalid source option 35) attach-interface with vnet0(which already exists) --target option 36) attach-interface with invalid mac address 37) detach-interface with invalid mac address 38) attach-interface twice with the same mac address 39) detach-interface twice with the same mac address 40) attach-interface with invalid --script option 41) attach-interface 10 times 42) attach-interface on remote host 43) detach-interface on remote host 44) attach-interface with --persistent option when vm is running 45) detach-interface with --persistent option when vm is running 46) attach-interface with --persistent option when vm is shut off 47) detach-interface with --persistent option when vm is shut off
Signed-off-by: Tang Chen <tanc...@cn.fujitsu.com> --- .../libvirt/tests/virsh_attach_detach_interface.py | 493 ++++++++++++++++++++ 1 file changed, 493 insertions(+) create mode 100644 client/tests/libvirt/tests/virsh_attach_detach_interface.py diff --git a/client/tests/libvirt/tests/virsh_attach_detach_interface.py b/client/tests/libvirt/tests/virsh_attach_detach_interface.py new file mode 100644 index 0000000..2926fa4 --- /dev/null +++ b/client/tests/libvirt/tests/virsh_attach_detach_interface.py @@ -0,0 +1,493 @@ +import re, os, logging, shutil, codecs, time +from autotest.client.shared import utils, error +from autotest.client.virt import libvirt_vm, virt_remote +from xml.dom import minidom +from xml.dom.minidom import parse, parseString + + +def build_attach_options(type, source, target, mac, extra): + """ + Return the attach-interface commandline options. + """ + options = "" + if type: + options += " --type %s" % type + if source: + options += " --source %s" % source + if target: + options += " --target %s" % target + if mac: + options += " --mac %s" % mac + if extra: + options += " %s" % extra + return options + + +def build_detach_options(type, mac, extra): + """ + Return the detach-interface commandline options. + """ + options = "" + if type: + options += " --type %s" % type + if mac: + options += " --mac %s" % mac + if extra: + options += " %s" % extra + return options + + +def check_vm_xml_interface(vm_xml, device = "interface", type = "bridge", + source = "bridge", target = "vnet1", mac = ""): + """ + Check VM's xml file for certain device. + """ + + logging.debug("xml:\n%s" % vm_xml) + dom = parseString(vm_xml) + + devices = dom.getElementsByTagName("interface") + logging.debug("All devices: %s" % devices) + + if type == "bridge": + attribute_source = "bridge" + attribute_target = "dev" + attribute_mac = "address" + else: + logging.error("Unknown device type: %s" % type) + return False + + ret = False + for element in devices: + if element.getAttribute("type") == type: + nodelist = element.childNodes + for node in nodelist: + if node.nodeName == "source" and node.getAttribute(attribute_source) == source: + for node in nodelist: + if node.nodeName == "mac": + mac_lower = mac.lower() + mac_upper = mac.upper() + mac_address = node.getAttribute(attribute_mac) + if mac_address == mac_lower or mac_address == mac_upper: + if target == "": + return True + else: + for node in nodelist: + if node.nodeName == "target" and node.getAttribute(attribute_target) == target: + return True + dom.unlink + return False + + +def check_native_bridge(source, targets): + cmd = "brctl show %s" % source + cmd_result = utils.run(cmd, ignore_status=True) + logging.info("Output: %s", cmd_result.stdout.strip()) + logging.info("Error: %s", cmd_result.stderr.strip()) + logging.info("Status: %d", cmd_result.exit_status) + + if cmd_result.exit_status == 0: + i = 0 + while (i < len(targets)): + if not re.search(targets[i], cmd_result.stdout.strip()): + logging.info("Tap %s not found on host." % targets[i]) + return False + i = i + 1 + return True + else: + return False + + +def check_vm_nic(vm, os_type = "linux", mac = "", loop = 1): + logging.info("Checking VM nic...") + if vm.is_dead(): + logging.debug("%s is not alive, starting it (30 sec)...") + vm.start() + vm.verify_alive() + time.sleep(30) + try: + if os_type == "linux": + session = vm.wait_for_login(nic_index=0) + s, o = session.cmd_status_output("ifconfig -a") + logging.info("ifconfig in VM:\n%s" % o) + i = 0 + while (i < loop): + s, o = session.cmd_status_output("ifconfig -a | grep -i \"%s\"" % mac[i]) + logging.info("Virtio devices in VM:\n%s" % o) + i = i + 1 + if s != 0: + return False + session.close() + else: + #Fix me. + pass + return True + except Exception, detail: + logging.error("%s: %s" % (detail.__class__, detail)) + return False + + +def run_virsh_attach_detach_interface(test, params, env): + """ + Test virsh {at|de}tach-interface command. + """ + + # Get test command. + test_cmd = params.get("test_cmd", "attach-interface") + if test_cmd != "attach-interface" and test_cmd != "detach-interface": + raise error.TestError("Command %s is not support " + "in this test." % test_cmd) + + # Basic parameters. + vm_ref = params.get("vm_ref", "name") + at_options = params.get("at_options", "") + dt_options = params.get("dt_options", "") + back_uri = params.get("back_uri", "") + pre_vm_state = params.get("pre_vm_state", "running") + libvirtd_state = params.get("libvirtd_state", "on") + status_error = params.get("status_error", 'no') + no_attach = params.get("no_attach", 'no') + os_type = params.get("os_type", "linux") + dly = int(params.get("delay", 10)) + + # Interface specific attributes. + device = params.get("device", "interface") + device_type = params.get("device_type", "bridge") + device_source = params.get("device_source", "virbr0") + device_targets = params.get("device_targets", "vnet1").split(" ") + bus_type = params.get("bus_type", "virtio") + auto_nic_mac = params.get("auto_nic_mac", 'yes') + auto_target = params.get("auto_target", 'no') + test_times = int(params.get("test_times", "1")) + + mac_need_free = False + + try: + exception = False + + main_vm_name = params.get("main_vm") + new_vm_name = main_vm_name + vm = env.get_vm(params["main_vm"]) + + # Back up xml file. + vm_xml_file_bak = vm.backup_xml() + vm_xml_file = "/etc/libvirt/qemu/%s.xml" % vm.name + + vm.start() + vm.verify_alive() + time.sleep(dly) + vm_id = vm.get_id() + vm_uuid = vm.get_uuid() + + # Confirm how to reference a VM. + # For example: no name, wrong id or uuid, and so on. + if vm_ref == "name": + vm_ref = main_vm_name + elif vm_ref == "new_name": + vm_ref = params.get("new_vm_name") + # vm should be shutdown when we try to rename it. + vm.destroy() + vm.rename(vm_ref) + new_vm_name = vm.name + vm.start() + vm.verify_alive() + time.sleep(dly) + # And we should get id again, because vm has been + # shut down and started again. + vm_id = vm.get_id() + elif vm_ref == "id": + vm_ref = vm_id + elif vm_ref == "hex_id": + vm_ref = hex(int(vm_id)) + elif vm_ref == "invalid_id": + vm_ref = params.get("invalid_vm_id") + elif vm_ref == "invalid_vm_name": + vm_ref = params.get("invalid_vm_name") + elif vm_ref == "uuid": + vm_ref = vm_uuid + elif vm_ref == "invalid_vm_uuid": + vm_ref = params.get("invalid_vm_uuid") + else: + vm_ref = "" + + # Get nic number in VM, and the index should start from original_nic_num. + original_nic_num = len(params.objects("nics")) + i = 0 + check_in_vm = False + nic_macs = [] + if auto_nic_mac == "yes": + mac_need_free = True + while (i < test_times): + nic_dict = {'nic_model': 'virtio', 'nettype': 'bridge', 'netdst': 'virbr0'} + nic_dict = vm.add_nic(**dict(nic_dict)) + nic_macs.append(nic_dict.mac) + logging.debug("Generated mac address in loop %d: %s" % (i, nic_macs[i])) + i = i + 1 + check_in_vm = True + time.sleep(dly) + elif params.has_key("nic_macs"): + nic_macs = params.get("nic_macs").split(" ") + check_in_vm = True + else: + while (i < test_times): + nic_macs.append("") + i = i + 1 + + # Automatically generate target names. + if auto_target == "yes": + device_targets = [] + i = 0 + while (i < test_times): + target = "vnet%d" % (i + original_nic_num) + device_targets.append(target) + i = i + 1 + + # If we are testing detach-interface, we need to attach certain device first. + if test_cmd == "detach-interface" and no_attach != "yes": + if bus_type == "ide" and vm.is_alive(): + vm.destroy(gracefully=True) + i = 0 + while (i < test_times): + tmp_option = build_attach_options(device_type, + device_source, + device_targets[i], + nic_macs[i], + "--persistent") + s_attach = vm.attach_interface(tmp_option, True, True).exit_status + i = i + 1 + if s_attach != 0: + logging.error("Attaching device failed " + "before testing detach-disk.") + time.sleep(dly) + + # Turn VM into certain state. + if pre_vm_state == "paused": + logging.info("Suspending %s..." % vm.name) + if vm.is_alive(): + vm.pause() + elif pre_vm_state == "shut off": + logging.info("Shuting down %s..." % vm.name) + if vm.is_alive(): + vm.destroy(gracefully=True) + + time.sleep(dly) + # Get xml file before test. + vm_xml_before_cmd = vm.get_xml() + + # Turn libvirtd into certain state. + if libvirtd_state == "off": + libvirt_vm.libvirtd_stop() + + # Test. + vm.name = vm_ref # For error name testing. + if back_uri == "": + if params.has_key("invalid_nic_mac"): + invalid_nic_mac = params.get("invalid_nic_mac") + if test_cmd == "attach-interface": + tmp_option = build_attach_options(device_type, + device_source, + device_targets[0], + invalid_nic_mac, + at_options) + status = vm.attach_interface(tmp_option, True, True).exit_status + else: + tmp_option = build_detach_options(device_type, + invalid_nic_mac, + dt_options) + status = vm.detach_interface(tmp_option, True, True).exit_status + + else: + i = 0 + while (i < test_times): + if test_cmd == "attach-interface": + tmp_option = build_attach_options(device_type, + device_source, + device_targets[i], + nic_macs[i], + at_options) + status = vm.attach_interface(tmp_option, True, True).exit_status + logging.info("TOM: %d" % status) + else: + tmp_option = build_detach_options(device_type, + nic_macs[i], + dt_options) + status = vm.detach_interface(tmp_option, True, True).exit_status + + i = i+1 + time.sleep(dly) + else: + remote_ip = params.get("remote_ip") + remote_user = params.get("remote_user", "root") + remote_pwd = params.get("remote_pwd", "rootxen") + remote_prompt = params.get("remote_prompt", "#") + session = virt_remote.remote_login("ssh", remote_ip, + "22", remote_user, + remote_pwd, + remote_prompt) + + if test_cmd == "attach-interface": + tmp_option = build_attach_options(device_type, + device_source, + device_targets[0], + nic_macs[0], + at_options) + else: + tmp_option = build_detach_options(device_type, + nic_macs[0], + dt_options) + cmd_interface = "virsh -c %s %s --domain %s %s" \ + % (back_uri, test_cmd, vm_ref, tmp_option) + logging.info("TOM: %s" % cmd_interface) + status, output = session.cmd_status_output(cmd = cmd_interface, internal_timeout = 30) + logging.info("Output: %s" % output) + + # Recover vm.name in VM object. + if vm_ref != main_vm_name: + vm.name = new_vm_name + + time.sleep(dly) + + # Recover libvirtd state. + if libvirtd_state == "off": + libvirt_vm.libvirtd_start() + + time.sleep(dly) + # Get xml file after test. + vm_xml_after_cmd = vm.get_xml() + + # Recover VM state. + if pre_vm_state == "paused": + vm.resume() + elif pre_vm_state == "shut off": + vm.start() + + # Check on native for tap device. + check_native_after_cmd = True + check_native_after_cmd = check_native_bridge(device_source, device_targets) + + # Check in VM after command. + check_vm_after_cmd = True + if os_type == 'linux': + if check_in_vm: + check_vm_after_cmd = check_vm_nic(vm, os_type, nic_macs, test_times) + else: + if test_cmd == 'attach-interface': + check_vm_after_cmd = True + else: + check_vm_after_cmd = False + + # Destroy VM. + vm.destroy(gracefully=True) + + time.sleep(dly) + # Get xml file after VM is shut down. + vm_xml_after_shutdown = vm.get_xml() + + # Check xml file after command. + check_xml_after_cmd = True + i = 0 + if pre_vm_state != "shut off": + while (i < test_times): + tmp = check_vm_xml_interface(vm_xml_after_cmd, device, + device_type, device_source, + device_targets[i], nic_macs[i]) + if not tmp: + check_xml_after_cmd = False + break + i = i + 1 + else: + while (i < test_times): + tmp = check_vm_xml_interface(vm_xml_after_cmd, device, + device_type, device_source, + "", nic_macs[i]) + if not tmp: + check_xml_after_cmd = False + break + i = i + 1 + + # Check xml file after VM is shut down (with --persistent). + check_xml_after_shutdown = True + i = 0 + while (i < test_times): + # We should not check target after VM is shut down. + tmp = check_vm_xml_interface(vm_xml_after_shutdown, device, + device_type, device_source, + "", nic_macs[i]) + if not tmp: + check_xml_after_shutdown = False + break + i = i + 1 + + except Exception, detail: + # Whatever error occurs, we have to clean up all environment. + exception = True + logging.error("%s: %s" % (detail.__class__, detail)) + + # Free all generated mac addresses. + if mac_need_free: + i = 0 + while (i < test_times): + # Since the lenth of vm.virtnet will be decreased each time + # we delete a nic in it, we don't need to increase del_nic's + # parameter, otherwise it will lead to list out of range error. + vm.del_nic(original_nic_num) + i = i + 1 + + # Clean up. + # Redefine the main_vm. + vm.destroy(gracefully=True) + vm.undefine() + if os.path.exists(vm_xml_file): + logging.error("Undefine %s failed." % vm.name) + vm.define(vm_xml_file_bak) + if not os.path.exists(vm_xml_file): + logging.error("Define %s failed." % vm.name) + + # Remove + if os.path.exists(vm_xml_file_bak): + os.remove(vm_xml_file_bak) + + if exception: + raise error.TestError("Error occurred.") + + # Check results. + if status_error == 'yes': + if status == 0: + raise error.TestFail("virsh %s exit with unexpected " + "value." % test_cmd) + else: + if status != 0: + raise error.TestFail("virsh %s failed." % test_cmd) + if test_cmd == "attach-interface": + if not check_xml_after_cmd: + raise error.TestFail("Cannot see deivce in " + "xml file after attach.") + if not check_native_after_cmd: + raise error.TestFail("Cannot see tap device " + "in native after attach.") + if not check_vm_after_cmd: + raise error.TestFail("Cannot see deivce in " + "VM after attach.") + if at_options.count("persistent"): + if not check_xml_after_shutdown: + raise error.TestFail("Cannot see persistent attached " + "deivce in xml file after VM shutdown.") + else: + if check_xml_after_shutdown: + raise error.TestFail("See non-persistent attached " + "deivce in xml file after VM shutdown.") + elif test_cmd == "detach-interface": + if check_xml_after_cmd: + raise error.TestFail("See deivce in xml file after detach.") + if check_vm_after_cmd: + raise error.TestFail("See deivce in VM after detach.") + if dt_options.count("persistent"): + if check_xml_after_shutdown: + raise error.TestFail("See persistent detached device " + "in xml file after VM shutdown.") + else: + if not check_xml_after_shutdown: + raise error.TestFail("Cannot see non-persistent detached " + "device in xml file after VM shutdown.") + else: + raise error.TestError("Unknown command %s." % test_cmd) -- 1.7.10.2 _______________________________________________ Autotest mailing list Autotest@test.kernel.org http://test.kernel.org/cgi-bin/mailman/listinfo/autotest