示例#1
0
def run(test, params, env):

    net_name = params.get("net_update_net_name", "updatenet")
    net_section = params.get("network_section", "ip-dhcp-range")
    update_command = params.get("update_command", "add-last")
    add_portgroup = "yes" == params.get("add_portgroup", "no")
    options = params.get("cmd_options", "")
    net_state = params.get("net_state")

    virtual_net = """
<network>
  <name>%s</name>
  <forward mode='nat'/>
  <bridge name='%s' stp='on' delay='0' />
  <mac address='52:54:00:03:78:6c'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254' />
      <host mac='52:54:00:5a:a0:8b' ip='192.168.100.152' />
    </dhcp>
  </ip>
</network>
""" % (net_name, net_name)

    port_group = """
<portgroup name='engineering' default='no'>
  <virtualport type='802.1Qbh'>
    <parameters profileid='test'/>
  </virtualport>
  <bandwidth>
    <inbound average='1000' peak='5000' burst='5120'/>
    <outbound average='1000' peak='5000' burst='5120'/>
  </bandwidth>
</portgroup>
"""
    try:
        test_xml = network_xml.NetworkXML(network_name=net_name)
        test_xml.xml = virtual_net
        if net_section == "portgroup":
            portgroup_xml = network_xml.PortgroupXML()
            portgroup_xml.xml = port_group
            test_xml.portgroup = portgroup_xml
        elif net_section == "forward-interface":
            test_xml.forward = {'mode': 'passthrough'}
            test_xml.forward_interface = [{'dev': 'eth2'}]
            del test_xml.bridge
            del test_xml.mac
            del test_xml.ip
        test_xml.define()
        if net_state == "active":
            test_xml.start()
        test_xml.debug_xml()
        virsh.net_dumpxml(net_name)
    except xcepts.LibvirtXMLError, detail:
        raise error.TestError("Failed to define a test network.\n"
                              "Detail: %s." % detail)
示例#2
0
 def set_network(size, net='default'):
     """
     Set mtu size to a certain network
     """
     logging.info('Set mtu size of network "%s" to %s', net, size)
     default_xml = NetworkXML.new_from_net_dumpxml(net)
     default_xml.mtu = size
     default_xml.sync()
     logging.debug(virsh.net_dumpxml(net))
示例#3
0
 def get_info(self, name):
     infos = {}
     for line in virsh.net_info(name).stdout.strip().splitlines():
         if line.startswith('Name') or line.startswith('UUID'):
             key, value = line.split()
         else:
             key, value = line.split(':', 1)
         infos[key.lower()] = value.strip()
     infos['inactive xml'] = virsh.net_dumpxml(
         name, '--inactive').stdout.splitlines()
     return infos
示例#4
0
def network_validate(net_name, file=None, **virsh_dargs):
    """
    Test for schema network
    """
    if net_name is None:
        raise error.TestNAError("None network is specified.")

    # Confirm the network exists.
    output = virsh.net_list("--all").stdout.strip()
    if not re.search(net_name, output):
        raise error.TestNAError("Make sure the network exists!!")

    cmd_result = virsh.net_dumpxml(net_name, to_file=file)
    libvirt.check_exit_status(cmd_result)
示例#5
0
    def new_all_networks_dict(virsh_instance=virsh):
        """
        Return a dictionary of names to NetworkXML instances for all networks

        @param: virsh: virsh module or instance to use
        @return: Dictionary of network name to NetworkXML instance
        """
        result = {}
        # Values should all share virsh property
        new_netxml = NetworkXML(virsh_instance)
        networks = new_netxml.virsh.net_state_dict(only_names=True).keys()
        for net_name in networks:
            new_copy = new_netxml.copy()
            new_copy.xml = virsh.net_dumpxml(net_name).stdout.strip()
            result[net_name] = new_copy
        return result
示例#6
0
            if (not net_state[net_name]['active'] or
                    net_state[net_name]['autostart'] or
                    net_state[net_name]['persistent']):
                raise error.TestFail("Found wrong network states"
                                     " after restarting libvirtd: %s"
                                     % net_state)
        edit_net_xml()
        if test_create:
            # Network become persistent after editing
            net_state = virsh.net_state_dict()
            if (not net_state[net_name]['active'] or
                    net_state[net_name]['autostart'] or
                    not net_state[net_name]['persistent']):
                raise error.TestFail("Found wrong network states"
                                     " after editing: %s"
                                     % net_state)

        cmd_result = virsh.net_dumpxml(net_name, '--inactive', debug=True)
        if cmd_result.exit_status:
            raise error.TestFail("Failed to dump xml of virtual network %s" %
                                 net_name)

        # The xml should contain the match_string
        match_string = "100.253"
        xml = cmd_result.stdout.strip()
        if not re.search(match_string, xml):
            raise error.TestFail("The xml is not expected")

    finally:
        test_xml.orbital_nuclear_strike()
示例#7
0
def run(test, params, env):
    """
    Test command: virsh net-edit <network>

    1) Define a temp virtual network
    2) Execute virsh net-edit to modify it
    3) Dump its xml then check it
    """
    def edit_net_xml(edit_cmd, expect_error, **dargs):
        """
        Edit net xml with virsh net-edit

        :params edit_cmd: The edit cmd to execute
        :params expect_error: Boolean, expect success or not
        :params **dargs: The virsh edit's option
        """
        logging.debug("edit_cmd: %s", edit_cmd)
        readonly = dargs.get("readonly", False)
        session = aexpect.ShellSession("sudo -s")
        try:
            logging.info("Execute virsh net-edit %s", net_name)
            virsh_cmd = "virsh net-edit %s" % net_name
            if readonly:
                virsh_cmd = "virsh -r net-edit %s" % net_name
            logging.debug("virsh_cmd: %s", virsh_cmd)
            session.sendline(virsh_cmd)
            session.sendline(edit_cmd)
            session.send('\x1b')
            session.send('ZZ')
            remote.handle_prompts(session, None, None, r"[\#\$]\s*$")
            session.close()
        except (aexpect.ShellError, aexpect.ExpectError,
                remote.LoginTimeoutError) as details:
            log = session.get_output()
            session.close()
            if not expect_error:
                test.fail("Failed to do net-edit: %s\n%s" % (details, log))
            logging.debug("Expected error: %s" % log)
            if readonly and "read only" not in log:
                test.fail("Not expected error")

    # Gather test parameters
    net_name = params.get("net_edit_net_name", "editnet")
    test_create = "yes" == params.get("test_create", "no")

    virsh_dargs = {'debug': True, 'ignore_status': True}
    virsh_instance = virsh.VirshPersistent(**virsh_dargs)

    change_attribute = params.get("attribute", None)
    old_value = params.get("old_value", None)
    new_value = params.get("new_value", None)
    edit_type = params.get("edit_type", "modify")
    status_error = (params.get("status_error", "no") == "yes")
    readonly = (params.get("net_edit_readonly", "no") == "yes")

    # Get all network instance
    nets = network_xml.NetworkXML.new_all_networks_dict(virsh_instance)

    # First check if a bridge of this name already exists
    # Increment suffix integer from 1 then append it to net_name
    # till there is no name conflict.
    if net_name in nets:
        net_name_fmt = net_name + "%d"
        suffix_num = 1
        while ((net_name_fmt % suffix_num) in nets):
            suffix_num += 1

        net_name = net_name_fmt % suffix_num

    virtual_net = """
<network>
  <name>%s</name>
  <forward mode='nat'/>
  <bridge name='%s' stp='on' delay='0' />
  <mac address='52:54:00:03:78:6c'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254' />
    </dhcp>
  </ip>
</network>
""" % (net_name, net_name)

    try:
        test_xml = network_xml.NetworkXML(network_name=net_name)
        test_xml.xml = virtual_net
        if test_create:
            test_xml.create()
        else:
            test_xml.define()
    except xcepts.LibvirtXMLError as detail:
        test.cancel("Failed to define a test network.\n"
                    "Detail: %s." % detail)

    # Run test case
    try:
        libvirtd = utils_libvirtd.Libvirtd()
        if change_attribute == "uuid":
            # if the attribute need to change is uuid, the old uuid should get
            # from current network, and new uuid can generate by uuidgen
            new_value = process.run("uuidgen", shell=True).stdout[:-1]
            old_value = virsh.net_uuid(net_name).stdout.strip()
        if test_create:
            # Restart libvirtd and check state
            libvirtd.restart()
            net_state = virsh.net_state_dict()
            if (not net_state[net_name]['active']
                    or net_state[net_name]['autostart']
                    or net_state[net_name]['persistent']):
                test.fail("Found wrong network states"
                          " after restarting libvirtd: %s" % net_state)
        else:
            libvirtd.restart()
            net_state = virsh.net_state_dict()
            if (net_state[net_name]['active']
                    or net_state[net_name]['autostart']
                    or not net_state[net_name]['persistent']):
                test.fail("Found wrong network states: %s" % net_state)
            result = virsh.net_start(net_name)
            logging.debug("start the persistent network return: %s", result)

        if edit_type == "modify":
            edit_cmd = r":%%s/%s=\'%s\'/%s=\'%s\'" % (
                change_attribute, old_value, change_attribute, new_value)
            match_string = "%s=\'%s\'" % (change_attribute, new_value)

        if edit_type == "delete":
            match_string = "%s" % change_attribute
            # Pattern to be more accurate
            if old_value and change_attribute != 'uuid':
                match_string = "%s=\'%s\'" % (change_attribute, old_value)
            else:
                match_string = old_value
            edit_cmd = r":/%s/d" % match_string

        edit_net_xml(edit_cmd, status_error, readonly=readonly)

        net_state = virsh.net_state_dict()
        # transient Network become persistent after editing
        if not status_error and (not net_state[net_name]['active']
                                 or net_state[net_name]['autostart']
                                 or not net_state[net_name]['persistent']):
            test.fail("Found wrong network states"
                      " after editing: %s" % net_state)

        cmd_result = virsh.net_dumpxml(net_name, '--inactive', debug=True)
        if cmd_result.exit_status:
            test.fail("Failed to dump xml of virtual network %s" % net_name)

        # The inactive xml should contain the match string
        xml = cmd_result.stdout.strip()
        if edit_type == "modify":
            if not status_error and not re.search(match_string, xml):
                test.fail("The inactive xml should contain the change '%s'" %
                          match_string)
            if status_error and re.search(match_string, xml):
                test.fail("Expect to modify failure but run success")

        if edit_type == "delete":
            if not status_error and re.search(match_string, xml):
                test.fail("The inactive xml should delete the change '%s'" %
                          match_string)
            if status_error and not re.search(match_string, xml):
                test.fail("Expect to delete failure but run success")

        # The active xml should not contain the match string
        if net_state[net_name]['active']:
            if not status_error:
                cmd_result = virsh.net_dumpxml(net_name, debug=True)
                if cmd_result.exit_status:
                    test.fail(
                        "Failed to dump active xml of virtual network %s" %
                        net_name)
                xml = cmd_result.stdout.strip()
                if edit_type == "modify" and re.search(match_string, xml):
                    test.fail(
                        "The active xml should not contain the change '%s'" %
                        match_string)
                if edit_type == "delete" and not re.search(match_string, xml):
                    test.fail(
                        "The active xml should not delete the change '%s'" %
                        match_string)
    finally:
        test_xml.orbital_nuclear_strike()
示例#8
0
        cmd_result = virsh.net_update(net_name,
                                      update_command,
                                      net_section,
                                      xmlfile, debug=True)

        if cmd_result.exit_status:
            err = cmd_result.stderr.strip()
            if re.search("is not supported", err):
                raise error.TestNAError("Skip the test: %s" % err)
            else:
                raise error.TestFail("Failed to execute "
                                     "virsh net-update command")

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

        if update_command == "delete":
            new_xml_obj = network_xml.NetworkXML.new_from_net_dumpxml(net_name)
            try:
                section_str = new_xml_obj.get_section_string(xpath=element)
            except xcepts.LibvirtXMLNotFoundError:
                section_str = None
            if section_str is not None:
                raise error.TestFail("The actual net xml is not expected,"
                                     "element still exists")

        else:
示例#9
0
def run_virsh_net_list(test, params, env):
    """
    Test command: virsh net-list.

    The command returns list of networks.
    1.Get all parameters from configuration.
    2.Get current network's status(State, Autostart).
    3.Do some prepare works for testing.
    4.Perform virsh net-list operation.
    5.Recover network status.
    6.Confirm the result.
    """
    option = params.get("net_list_option", "")
    extra = params.get("net_list_extra", "")
    status_error = params.get("status_error", "no")
    net_name = params.get("net_list_name", "default")
    persistent = params.get("net_list_persistent", "yes")
    net_status = params.get("net_list_error", "active")
    tmp_xml = os.path.join(test.tmpdir, "tmp.xml")
    net_current_status = "active"
    autostart_status = "yes"
    if not virsh.net_state_dict()[net_name]['active']:
        net_current_status = "inactive"
    if not virsh.net_state_dict()[net_name]['autostart']:
        autostart_status = "no"

    # Create a transient network.
    try:
        if persistent == "no":
            virsh.net_dumpxml(net_name, to_file=tmp_xml, ignore_status=False)
            if net_current_status == "inactive":
                virsh.net_destroy(net_name, ignore_status=False)
            virsh.net_undefine(net_name, ignore_status=False)
            virsh.net_create(tmp_xml, ignore_status=False)
    except error.CmdError:
        raise error.TestFail("Transient network test failed!")

    # Prepare network's status for testing.
    if net_status == "active":
        try:
            if not virsh.net_state_dict()[net_name]['active']:
                virsh.net_start(net_name, ignore_status=False)
        except error.CmdError:
            raise error.TestFail("Active network test failed!")
    else:
        try:
            if virsh.net_state_dict()[net_name]['active']:
                virsh.net_destroy(net_name, ignore_status=False)
        except error.CmdError:
            raise error.TestFail("Inactive network test failed!")

    result = virsh.net_list(option, extra, ignore_status=True)
    status = result.exit_status
    output = result.stdout.strip()

    # Recover network
    try:
        if persistent == "no":
            virsh.net_destroy(net_name, ignore_status=False)
            virsh.net_define(tmp_xml, ignore_status=False)
            if net_current_status == "active":
                virsh.net_start(net_name, ignore_status=False)
            if autostart_status == "yes":
                virsh.net_autostart(net_name, ignore_status=False)
        else:
            if net_current_status == "active" and net_status == "inactive":
                virsh.net_start(net_name, ignore_status=False)
            elif net_current_status == "inactive" and net_status == "active":
                virsh.net_destroy(net_name, ignore_status=False)
    except error.CmdError:
        raise error.TestFail("Recover network failed!")

    # check result
    if status_error == "yes":
        if status == 0:
            raise error.TestFail("Run successfully with wrong command!")
    elif status_error == "no":
        if status != 0:
            raise error.TestFail("Run failed with right command")
        if option == "--inactive":
            if net_status == "active":
                if re.search(net_name, output):
                    raise error.TestFail("Found an active network with"
                                         " --inactive option")
            else:
                if persistent == "yes":
                    if not re.search(net_name, output):
                        raise error.TestFail("Found no inactive networks with"
                                             " --inactive option")
                else:
                    # If network is transient, after net-destroy it,
                    # it will disapear.
                    if re.search(net_name, output):
                        raise error.TestFail("Found transient inactive networks"
                                             " with --inactive option")
        elif option == "":
            if net_status == "active":
                if not re.search(net_name, output):
                    raise error.TestFail("Can't find active network with no"
                                         " option")
            else:
                if re.search(net_name, output):
                    raise error.TestFail("Found inactive network with"
                                         " no option")
        elif option == "--all":
            if net_status == "active":
                if not re.search(net_name, output):
                    raise error.TestFail("Can't find active network with"
                                         " --all option")
            else:
                if persistent == "yes":
                    if not re.search(net_name, output):
                        raise error.TestFail("Can't find inactive network with"
                                             " --all option")
                else:
                    # If network is transient, after net-destroy it,
                    # it will disapear.
                    if re.search(net_name, output):
                        raise error.TestFail("Found transient inactive network"
                                             " with --all option")
示例#10
0
def run(test, params, env):
    """
    Test command: virsh net-list.

    The command returns list of networks.
    1.Get all parameters from configuration.
    2.Get current network's status(State, Autostart).
    3.Do some prepare works for testing.
    4.Perform virsh net-list operation.
    5.Recover network status.
    6.Confirm the result.
    """
    option = params.get("net_list_option", "")
    extra = params.get("net_list_extra", "")
    status_error = params.get("status_error", "no")
    net_name = params.get("net_list_name", "default")
    persistent = params.get("net_list_persistent", "yes")
    net_status = params.get("net_list_error", "active")
    tmp_xml = os.path.join(test.tmpdir, "tmp.xml")
    net_current_status = "active"
    autostart_status = "yes"
    if not virsh.net_state_dict()[net_name]['active']:
        net_current_status = "inactive"
    if not virsh.net_state_dict()[net_name]['autostart']:
        autostart_status = "no"

    # acl polkit params
    uri = params.get("virsh_uri")
    unprivileged_user = params.get('unprivileged_user')
    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':
            raise error.TestNAError("API acl test not supported in current"
                                    " libvirt version.")

    # Create a transient network.
    try:
        if persistent == "no":
            virsh.net_dumpxml(net_name, to_file=tmp_xml, ignore_status=False)
            if net_current_status == "inactive":
                virsh.net_destroy(net_name, ignore_status=False)
            virsh.net_undefine(net_name, ignore_status=False)
            virsh.net_create(tmp_xml, ignore_status=False)
    except error.CmdError:
        raise error.TestFail("Transient network test failed!")

    # Prepare network's status for testing.
    if net_status == "active":
        try:
            if not virsh.net_state_dict()[net_name]['active']:
                virsh.net_start(net_name, ignore_status=False)
        except error.CmdError:
            raise error.TestFail("Active network test failed!")
    else:
        try:
            if virsh.net_state_dict()[net_name]['active']:
                virsh.net_destroy(net_name, ignore_status=False)
        except error.CmdError:
            raise error.TestFail("Inactive network test failed!")

    virsh_dargs = {'ignore_status': True}
    if params.get('setup_libvirt_polkit') == 'yes':
        virsh_dargs['unprivileged_user'] = unprivileged_user
        virsh_dargs['uri'] = uri
    result = virsh.net_list(option, extra, **virsh_dargs)
    status = result.exit_status
    output = result.stdout.strip()

    # Recover network
    try:
        if persistent == "no":
            virsh.net_destroy(net_name, ignore_status=False)
            virsh.net_define(tmp_xml, ignore_status=False)
            if net_current_status == "active":
                virsh.net_start(net_name, ignore_status=False)
            if autostart_status == "yes":
                virsh.net_autostart(net_name, ignore_status=False)
        else:
            if net_current_status == "active" and net_status == "inactive":
                virsh.net_start(net_name, ignore_status=False)
            elif net_current_status == "inactive" and net_status == "active":
                virsh.net_destroy(net_name, ignore_status=False)
    except error.CmdError:
        raise error.TestFail("Recover network failed!")

    # check result
    if status_error == "yes":
        if status == 0:
            raise error.TestFail("Run successfully with wrong command!")
    elif status_error == "no":
        if status != 0:
            raise error.TestFail("Run failed with right command")
        if option == "--inactive":
            if net_status == "active":
                if re.search(net_name, output):
                    raise error.TestFail("Found an active network with"
                                         " --inactive option")
            else:
                if persistent == "yes":
                    if not re.search(net_name, output):
                        raise error.TestFail("Found no inactive networks with"
                                             " --inactive option")
                else:
                    # If network is transient, after net-destroy it,
                    # it will disapear.
                    if re.search(net_name, output):
                        raise error.TestFail(
                            "Found transient inactive networks"
                            " with --inactive option")
        elif option == "":
            if net_status == "active":
                if not re.search(net_name, output):
                    raise error.TestFail("Can't find active network with no"
                                         " option")
            else:
                if re.search(net_name, output):
                    raise error.TestFail("Found inactive network with"
                                         " no option")
        elif option == "--all":
            if net_status == "active":
                if not re.search(net_name, output):
                    raise error.TestFail("Can't find active network with"
                                         " --all option")
            else:
                if persistent == "yes":
                    if not re.search(net_name, output):
                        raise error.TestFail("Can't find inactive network with"
                                             " --all option")
                else:
                    # If network is transient, after net-destroy it,
                    # it will disapear.
                    if re.search(net_name, output):
                        raise error.TestFail("Found transient inactive network"
                                             " with --all option")
示例#11
0
def run_virsh_net_dumpxml(test, params, env):
    """
    Test command: virsh net-dumpxml.

    This command can output the network information as an XML dump to stdout.
    1.Get all parameters from config file.
    2.If test case's network status is inactive, destroy it.
    3.Perform virsh net-dumpxml operation.
    4.Recover test environment(network status).
    5.Confirm the test result.
    """
    status_error = params.get("status_error", "no")
    net_ref = params.get("net_dumpxml_net_ref")
    net_name = params.get("net_dumpxml_network", "default")
    net_status = params.get("net_dumpxml_network_status", "active")
    xml_flie = params.get("net_dumpxml_xml_file", "default.xml")
    extra = params.get("net_dumpxml_extra", "")
    network_xml = os.path.join(test.tmpdir, xml_flie)

    # Run test case
    if net_ref == "uuid":
        net_ref = virsh.net_uuid(net_name).stdout.strip()
    elif net_ref == "name":
        net_ref = net_name

    net_status_current = "active"
    if not virsh.net_state_dict()[net_name]['active']:
        net_status_current = "inactive"

    if not virsh.net_state_dict()[net_name]['persistent']:
        raise error.TestError("Network is transient!")
    try:
        if net_status == "inactive" and net_status_current == "active":
            status_destroy = virsh.net_destroy(net_name,
                                               ignore_status=True).exit_status
            if status_destroy != 0:
                raise error.TestError("Network destroied failed!")

        result = virsh.net_dumpxml(net_ref,
                                   extra,
                                   network_xml,
                                   ignore_status=True)
        status = result.exit_status
        err = result.stderr.strip()
        xml_validate_cmd = "virt-xml-validate %s network" % network_xml
        valid_s = utils.run(xml_validate_cmd, ignore_status=True).exit_status

        # Check option valid or not.
        if extra.find("--") != -1:
            options = extra.split("--")
            for option in options:
                if option.strip() == "":
                    continue
                if not virsh.has_command_help_match("net-dumpxml",
                                                    option.strip()):
                    status_error = "yes"
                    break
    finally:
        # Recover network
        if net_status == "inactive" and net_status_current == "active":
            status_start = virsh.net_start(net_name,
                                           ignore_status=True).exit_status
            if status_start != 0:
                raise error.TestError("Network started failed!")

    # Check status_error
    if status_error == "yes":
        if status == 0:
            raise error.TestFail("Run successfully with wrong command!")
        if err == "":
            raise error.TestFail("The wrong command has no error outputed!")
    elif status_error == "no":
        if status != 0:
            raise error.TestFail("Run failed with right command!")
        if valid_s != 0:
            raise error.TestFail("Command output is invalid!")
    else:
        raise error.TestError("The status_error must be 'yes' or 'no'!")
示例#12
0
def run(test, params, env):
    """
    Test command: virsh net-list.

    The command returns list of networks.
    1.Get all parameters from configuration.
    2.Get current network's status(State, Autostart).
    3.Do some prepare works for testing.
    4.Perform virsh net-list operation.
    5.Recover network status.
    6.Confirm the result.
    """
    option = params.get("net_list_option", "")
    extra = params.get("net_list_extra", "")
    status_error = params.get("status_error", "no")
    net_name = params.get("net_list_name", "default")
    persistent = params.get("net_list_persistent", "yes")
    net_status = params.get("net_list_error", "active")
    tmp_xml = os.path.join(test.tmpdir, "tmp.xml")
    net_current_status = "active"
    autostart_status = "yes"
    if not virsh.net_state_dict()[net_name]['active']:
        net_current_status = "inactive"
    if not virsh.net_state_dict()[net_name]['autostart']:
        autostart_status = "no"

    # acl polkit params
    uri = params.get("virsh_uri")
    unprivileged_user = params.get('unprivileged_user')
    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':
            raise error.TestNAError("API acl test not supported in current"
                                    " libvirt version.")

    # Create a transient network.
    try:
        if persistent == "no":
            virsh.net_dumpxml(net_name, to_file=tmp_xml, ignore_status=False)
            if net_current_status == "inactive":
                virsh.net_destroy(net_name, ignore_status=False)
            virsh.net_undefine(net_name, ignore_status=False)
            virsh.net_create(tmp_xml, ignore_status=False)
    except error.CmdError:
        raise error.TestFail("Transient network test failed!")

    # Prepare network's status for testing.
    if net_status == "active":
        try:
            if not virsh.net_state_dict()[net_name]['active']:
                virsh.net_start(net_name, ignore_status=False)
        except error.CmdError:
            raise error.TestFail("Active network test failed!")
    else:
        try:
            if virsh.net_state_dict()[net_name]['active']:
                virsh.net_destroy(net_name, ignore_status=False)
        except error.CmdError:
            raise error.TestFail("Inactive network test failed!")

    virsh_dargs = {'ignore_status': True}
    if params.get('setup_libvirt_polkit') == 'yes':
        virsh_dargs['unprivileged_user'] = unprivileged_user
        virsh_dargs['uri'] = uri
    result = virsh.net_list(option, extra, **virsh_dargs)
    status = result.exit_status
    output = result.stdout.strip()

    # Recover network
    try:
        if persistent == "no":
            virsh.net_destroy(net_name, ignore_status=False)
            virsh.net_define(tmp_xml, ignore_status=False)
            if net_current_status == "active":
                virsh.net_start(net_name, ignore_status=False)
            if autostart_status == "yes":
                virsh.net_autostart(net_name, ignore_status=False)
        else:
            if net_current_status == "active" and net_status == "inactive":
                virsh.net_start(net_name, ignore_status=False)
            elif net_current_status == "inactive" and net_status == "active":
                virsh.net_destroy(net_name, ignore_status=False)
    except error.CmdError:
        raise error.TestFail("Recover network failed!")

    # check result
    if status_error == "yes":
        if status == 0:
            raise error.TestFail("Run successfully with wrong command!")
    elif status_error == "no":
        if status != 0:
            raise error.TestFail("Run failed with right command")
        if option == "--inactive":
            if net_status == "active":
                if re.search(net_name, output):
                    raise error.TestFail("Found an active network with"
                                         " --inactive option")
            else:
                if persistent == "yes":
                    if not re.search(net_name, output):
                        raise error.TestFail("Found no inactive networks with"
                                             " --inactive option")
                else:
                    # If network is transient, after net-destroy it,
                    # it will disapear.
                    if re.search(net_name, output):
                        raise error.TestFail("Found transient inactive networks"
                                             " with --inactive option")
        elif option == "":
            if net_status == "active":
                if not re.search(net_name, output):
                    raise error.TestFail("Can't find active network with no"
                                         " option")
            else:
                if re.search(net_name, output):
                    raise error.TestFail("Found inactive network with"
                                         " no option")
        elif option == "--all":
            if net_status == "active":
                if not re.search(net_name, output):
                    raise error.TestFail("Can't find active network with"
                                         " --all option")
            else:
                if persistent == "yes":
                    if not re.search(net_name, output):
                        raise error.TestFail("Can't find inactive network with"
                                             " --all option")
                else:
                    # If network is transient, after net-destroy it,
                    # it will disapear.
                    if re.search(net_name, output):
                        raise error.TestFail("Found transient inactive network"
                                             " with --all option")
示例#13
0
    </dhcp>
  </ip>
</network>
""" % (net_name, net_name)

    try:
        test_xml = network_xml.NetworkXML(network_name=net_name)
        test_xml.xml = virtual_net
        test_xml.define()
    except xcepts.LibvirtXMLError, detail:
        raise error.TestNAError("Failed to define a test network.\n"
                                "Detail: %s." % detail)

    # Run test case
    try:
        edit_net_xml()

        cmd_result = virsh.net_dumpxml(net_name, debug=True)
        if cmd_result.exit_status:
            raise error.TestFail("Failed to dump xml of virtual network %s" %
                                 net_name)

        # The xml should contain the match_string
        match_string = "100.253"
        xml = cmd_result.stdout.strip()
        if not re.search(match_string, xml):
            raise error.TestFail("The xml is not expected")

    finally:
        test_xml.undefine()
示例#14
0
def run(test, params, env):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            names = locals()

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

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

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

            flag_list = []
            flag_list_abs = []

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    session.close()

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

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

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

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

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

        if use_in_guest == "yes":
            vm = env.get_vm(vm_name)
            if vm.is_alive():
                vm.destroy(gracefully=False)
            vmxml_backup.sync()
        for config_file in backup_files:
            config_file._reset_file()
示例#15
0
def run(test, params, env):
    """
    Test mtu feature from virtual network
    """
    vm_name = params.get('main_vm')
    vm = env.get_vm(vm_name)
    mtu_type = params.get('mtu_type')
    mtu_size = params.get('mtu_size', '')
    net = params.get('net', DEFAULT_NET)
    net_type = params.get('net_type', '')
    with_iface = 'yes' == params.get('with_iface', 'no')
    with_net = 'yes' == params.get('with_net', 'no')
    status_error = 'yes' == params.get('status_error', 'no')
    check = params.get('check', '')
    error_msg = params.get('error_msg', '')
    bridge_name = 'br_mtu' + utils_misc.generate_random_string(3)
    add_pkg = params.get('add_pkg', '')
    model = params.get('model', 'virtio')

    def set_network(size, net='default'):
        """
        Set mtu size to a certain network
        """
        logging.info('Set mtu size of network "%s" to %s', net, size)
        default_xml = NetworkXML.new_from_net_dumpxml(net)
        default_xml.mtu = size
        default_xml.sync()
        logging.debug(virsh.net_dumpxml(net))

    def set_interface(mtu_size='', source_network='default',
                      iface_type='network', iface_model='virtio'):
        """
        Set mtu size to a certain interface
        """
        interface_type = 'bridge' if iface_type in ('bridge', 'openvswitch') else iface_type
        iface_dict = {
            'type': interface_type,
            'source': "{'%s': '%s'}" % (interface_type, source_network),
            'model': iface_model
        }

        if iface_type == 'openvswitch':
            iface_dict.update({'virtualport_type': 'openvswitch'})

        if mtu_size:
            iface_dict.update({'mtu': "{'size': %s}" % mtu_size})

        libvirt.modify_vm_iface(vm_name, 'update_iface', iface_dict)
        logging.debug(virsh.dumpxml(vm_name).stdout)

    def get_default_if():
        """
        Get default interface that is using by vm
        """
        ifaces = utils_net.get_sorted_net_if()
        logging.debug('Interfaces on host: %s', ifaces)
        for iface in ifaces[0]:
            if 'Link detected: yes' in process.run('ethtool %s' % iface).stdout_text:
                logging.debug('Found host interface "%s"', iface)
                return iface

    def create_bridge():
        """
        Create a bridge on host for test
        """
        cmd_create_br = 'nmcli con add type bridge con-name %s ifname %s'
        con_name = 'con_' + utils_misc.generate_random_string(3)
        bridge_name = 'br_' + utils_misc.generate_random_string(3)
        process.run(cmd_create_br % (con_name, bridge_name), verbose=True)
        return con_name, bridge_name

    def create_network_xml(name, network_type, base_if='', **kwargs):
        """
        Create a network xml to be defined
        """
        m_net = NetworkXML(name)
        m_net.forward = {'mode': 'bridge'}
        if network_type in ('bridge', 'openvswitch'):
            m_net.bridge = {'name': kwargs['bridge_name']}
        elif network_type == 'macvtap':
            if base_if:
                m_net.forward_interface = [{'dev': base_if}]
        if network_type == 'openvswitch':
            m_net.virtualport_type = 'openvswitch'
        if 'mtu' in kwargs:
            m_net.mtu = kwargs['mtu']
        logging.debug(m_net)
        return m_net.xml

    def create_iface(iface_type, **kwargs):
        """
        Create a interface to be attached to vm
        """
        m_iface = Interface(iface_type)
        m_iface.mac_address = utils_net.generate_mac_address_simple()
        if 'base_if' in kwargs:
            m_iface.source = {'dev': kwargs['base_if'],
                              'mode': 'vepa'}
        if 'source_net' in kwargs:
            m_iface.source = {'network': kwargs['source_net']}
        if 'mtu' in kwargs:
            m_iface.mtu = {'size': kwargs['mtu']}
        if 'model_net' in kwargs:
            m_iface.model = kwargs['model_net']
        logging.debug(m_iface.get_xml())
        logging.debug(m_iface)
        return m_iface

    def check_mtu(mtu_size, qemu=False):
        """
        Check if mtu meets expectation on host
        """
        error = ''
        live_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        iface_xml = live_vmxml.get_devices('interface')[0]
        logging.debug(iface_xml.target)
        dev = iface_xml.target['dev']
        ifconfig_info = process.run('ifconfig|grep mtu|grep %s' % dev,
                                    shell=True, verbose=True).stdout_text
        if 'mtu %s' % mtu_size in ifconfig_info:
            logging.info('PASS on ifconfig check for vnet.')
        else:
            error += 'Fail on ifconfig check for vnet.'
        if qemu:
            qemu_mtu_info = process.run('ps aux|grep qemu-kvm',
                                        shell=True, verbose=True).stdout_text
            if 'host_mtu=%s' % mtu_size in qemu_mtu_info:
                logging.info('PASS on qemu cmd line check.')
            else:
                error += 'Fail on qemu cmd line check.'
        if error:
            test.fail(error)

    def check_mtu_in_vm(fn_login, mtu_size):
        """
        Check if mtu meets expectations in vm
        """
        session = fn_login()
        check_cmd = 'ifconfig'
        output = session.cmd(check_cmd)
        session.close()
        logging.debug(output)
        if 'mtu %s' % mtu_size not in output:
            test.fail('MTU check inside vm failed.')
        else:
            logging.debug("MTU check inside vm passed.")

    try:
        bk_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
        bk_netxml = NetworkXML.new_from_net_dumpxml(DEFAULT_NET)
        if add_pkg:
            add_pkg = add_pkg.split()
            utils_package.package_install(add_pkg)
        if 'openvswitch' in add_pkg:
            br = 'ovsbr0' + utils_misc.generate_random_string(3)
            process.run('systemctl start openvswitch.service', shell=True, verbose=True)
            process.run('ovs-vsctl add-br %s' % br, shell=True, verbose=True)
            process.run('ovs-vsctl show', shell=True, verbose=True)

        if not check or check in ['save', 'managedsave', 'hotplug_save']:
            # Create bridge or network and set mtu
            iface_type = 'network'
            if net_type in ('bridge', 'openvswitch'):
                if net_type == 'bridge':
                    params['con_name'], br = create_bridge()
                if mtu_type == 'network':
                    test_net = create_network_xml(
                        bridge_name, net_type,
                        bridge_name=br
                    )
                    virsh.net_create(test_net, debug=True)
                    virsh.net_dumpxml(bridge_name, debug=True)
                if mtu_type == 'interface':
                    iface_type = net_type
                    bridge_name = br
            elif net_type == 'network':
                if mtu_type == 'network':
                    set_network(mtu_size)

            iface_mtu = 0
            if mtu_type == 'interface':
                iface_mtu = mtu_size
            if mtu_type == 'network' and with_iface:
                mtu_size = str(int(mtu_size)//2)
                iface_mtu = mtu_size

            source_net = bridge_name if net_type in ('bridge', 'openvswitch') else 'default'

            # set mtu in vm interface
            set_interface(iface_mtu, source_network=source_net, iface_type=iface_type, iface_model=model)
            vm.start()
            vm_login = vm.wait_for_serial_login if net_type in ('bridge', 'openvswitch') else vm.wait_for_login
            vm_login().close()
            check_qemu = True if mtu_type == 'interface' else False

            # Test mtu after save vm
            if check in ('save', 'hotplug_save'):
                if check == 'hotplug_save':
                    iface = create_iface('network', source_net='default',
                                         mtu=mtu_size, model_net=model)
                    params['mac'] = iface.mac_address
                    virsh.attach_device(vm_name, iface.xml, debug=True)
                    virsh.dumpxml(vm_name, debug=True)
                    dom_xml = vm_xml.VMXML.new_from_dumpxml(vm_name)
                    if params['mac'] not in str(dom_xml):
                        test.fail('Failed to attach interface with mtu')
                save_path = os.path.join(data_dir.get_tmp_dir(), vm_name + '.save')
                virsh.save(vm_name, save_path, debug=True)
                virsh.restore(save_path, debug=True)
            if check == 'managedsave':
                virsh.managedsave(vm_name, debug=True)
                virsh.start(vm_name, debug=True)

            # Check in both host and vm
            check_mtu(mtu_size, check_qemu)
            check_mtu_in_vm(vm_login, mtu_size)
            vm_login(timeout=60).close()

            if check == 'hotplug_save':
                virsh.detach_interface(vm_name, 'network %s' % params['mac'], debug=True)
                time.sleep(5)
                dom_xml = vm_xml.VMXML.new_from_dumpxml(vm_name)
                if params['mac'] in str(dom_xml):
                    test.fail('Failed to detach interface with mtu after save-restore')

        else:
            hotplug = 'yes' == params.get('hotplug', 'False')
            if check == 'net_update':
                result = virsh.net_update(
                    DEFAULT_NET, 'modify', 'mtu',
                    '''"<mtu size='%s'/>"''' % mtu_size,
                    debug=True
                )
            if check in ('macvtap', 'bridge_net', 'ovswitch_net'):
                base_if = get_default_if()
                macv_name = 'direct-macvtap' + utils_misc.generate_random_string(3)

                # Test mtu in different type of network
                if mtu_type == 'network':
                    if check == 'macvtap':
                        test_net = create_network_xml(macv_name, 'macvtap',
                                                      base_if, mtu=mtu_size)
                    if check == 'bridge_net':
                        params['con_name'], br = create_bridge()
                        test_net = create_network_xml(
                            bridge_name, 'bridge', mtu=mtu_size,
                            bridge_name=br
                        )
                    if check == 'ovswitch_net':
                        test_net = create_network_xml(
                            bridge_name, 'openvswitch', mtu=mtu_size,
                            bridge_name=br
                        )
                    if 'net_create' in params['id']:
                        result = virsh.net_create(test_net, debug=True)
                    if 'net_define' in params['id']:
                        result = virsh.net_define(test_net, debug=True)

                # Test mtu with or without a binding network
                elif mtu_type == 'interface':
                    vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
                    if with_net:
                        test_net = create_network_xml(macv_name, 'macvtap', base_if)
                        virsh.net_create(test_net, debug=True)
                        iface = create_iface('network', source_net=macv_name, mtu=mtu_size)
                        if hotplug:
                            result = virsh.attach_device(vm_name, iface.xml, debug=True)
                        else:
                            vmxml.add_device(iface)
                            vmxml.sync()
                            result = virsh.start(vm_name)
                    else:
                        iface = create_iface('direct', base_if=base_if, mtu=mtu_size)
                        if hotplug:
                            result = virsh.attach_device(vm_name, iface.xml, debug=True)
                        else:
                            vmxml.add_device(iface)
                            result = virsh.define(vmxml.xml, debug=True)
            if check == 'invalid_val':
                iface = create_iface('network', source_net='default', mtu=mtu_size)
                result = virsh.attach_device(vm_name, iface.xml, debug=True)

            # Check result
            libvirt.check_exit_status(result, status_error)
            libvirt.check_result(result, [error_msg])

    finally:
        bk_xml.sync()
        bk_netxml.sync()
        if 'test_net' in locals():
            virsh.net_destroy(bridge_name, debug=True)
        if params.get('con_name'):
            process.run('nmcli con del %s' % params['con_name'], verbose=True)
        if add_pkg:
            process.run("ovs-vsctl del-br %s" % br, verbose=True)
            utils_package.package_remove(add_pkg)
            net_state = virsh.net_state_dict()
            if (not net_state[net_name]['active']
                    or net_state[net_name]['autostart']
                    or net_state[net_name]['persistent']):
                raise error.TestFail("Found wrong network states"
                                     " after restarting libvirtd: %s" %
                                     net_state)
        edit_net_xml()
        if test_create:
            # Network become persistent after editing
            net_state = virsh.net_state_dict()
            if (not net_state[net_name]['active']
                    or net_state[net_name]['autostart']
                    or not net_state[net_name]['persistent']):
                raise error.TestFail("Found wrong network states"
                                     " after editing: %s" % net_state)

        cmd_result = virsh.net_dumpxml(net_name, '--inactive', debug=True)
        if cmd_result.exit_status:
            raise error.TestFail("Failed to dump xml of virtual network %s" %
                                 net_name)

        # The xml should contain the match_string
        match_string = "100.253"
        xml = cmd_result.stdout.strip()
        if not re.search(match_string, xml):
            raise error.TestFail("The xml is not expected")

    finally:
        test_xml.orbital_nuclear_strike()
示例#17
0
def run(test, params, env):
    """
    Since 3.3.0, Coalesce setting is supported.

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

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

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

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

    1. For default host network

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

    This is default network.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        :return: 0 for successful negative case
                 test.fail is fail for positive/negative case
                 None for successful positive case
        """
        if hotplug_iface:
            iface = Interface(iface_type)
        else:
            vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
            xml_devices = vmxml.devices
            iface_index = xml_devices.index(
                xml_devices.by_device_tag("interface")[0])
            iface = xml_devices[iface_index]

        if iface_type == 'network':
            iface.type_name = iface_type
            source = {iface_type: net_name}
        elif iface_type == 'bridge' and bridge_name:
            iface.type_name = iface_type
            source = {iface_type: bridge_name}
        elif iface_type == 'direct':
            iface.type_name = iface_type
            source = {'dev': interface, 'mode': 'bridge'}

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

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

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

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

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

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

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

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

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

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

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

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

    finally:
        # Recover VM.
        if vm.is_alive():
            vm.destroy(gracefully=False)
        logging.info("Restoring network...")
        if net_name == "default":
            netxml_backup.sync()
        else:
            # Destroy and undefine new created network
            virsh.net_destroy(net_name)
            virsh.net_undefine(net_name)
        # Try to recovery bridge
        if network_type == "bridge" and bridge_name:
            if bridge_name in bridge.list_br():
                bridge.del_bridge(bridge_name)
        elif network_type == "ovsbridge" and bridge_name:
            if utils_net.ovs_br_exists(bridge_name):
                utils_net.del_ovs_bridge(bridge_name)
        vmxml_backup.sync()
示例#18
0
def make_net_persistent(net_name):
    logging.debug(virsh.net_dumpxml(net_name).stdout)
    with open("/tmp/default.xml", "w") as f:
        f.write(virsh.net_dumpxml(net_name).stdout)
    virsh.net_define("/tmp/default.xml", ignore_status=False)
    return None
示例#19
0
def run(test, params, env):
    """
    Test mtu feature from virtual network
    """
    vm_name = params.get('main_vm')
    vm = env.get_vm(vm_name)
    mtu_type = params.get('mtu_type')
    mtu_size = params.get('mtu_size', '')
    net = params.get('net', DEFAULT_NET)
    net_type = params.get('net_type', '')
    with_iface = 'yes' == params.get('with_iface', 'no')
    with_net = 'yes' == params.get('with_net', 'no')
    status_error = 'yes' == params.get('status_error', 'no')
    check = params.get('check', '')
    error_msg = params.get('error_msg', '')
    bridge_name = 'br_mtu' + utils_misc.generate_random_string(3)
    add_pkg = params.get('add_pkg', '')
    model = params.get('model', 'virtio')

    def set_network(size, net='default'):
        """
        Set mtu size to a certain network
        """
        logging.info('Set mtu size of network "%s" to %s', net, size)
        default_xml = NetworkXML.new_from_net_dumpxml(net)
        default_xml.mtu = size
        default_xml.sync()
        logging.debug(virsh.net_dumpxml(net))

    def set_interface(mtu_size='',
                      source_network='default',
                      iface_type='network',
                      iface_model='virtio'):
        """
        Set mtu size to a certain interface
        """
        interface_type = 'bridge' if iface_type in (
            'bridge', 'openvswitch') else iface_type
        iface_dict = {
            'type': interface_type,
            'source': "{'%s': '%s'}" % (interface_type, source_network),
            'model': iface_model
        }

        if iface_type == 'openvswitch':
            iface_dict.update({'virtualport_type': 'openvswitch'})

        if mtu_size:
            iface_dict.update({'mtu': "{'size': %s}" % mtu_size})

        libvirt.modify_vm_iface(vm_name, 'update_iface', iface_dict)
        logging.debug(virsh.dumpxml(vm_name).stdout)

    def get_default_if():
        """
        Get default interface that is using by vm
        """
        ifaces = utils_net.get_sorted_net_if()
        logging.debug('Interfaces on host: %s', ifaces)
        for iface in ifaces[0]:
            if 'Link detected: yes' in process.run('ethtool %s' %
                                                   iface).stdout_text:
                logging.debug('Found host interface "%s"', iface)
                return iface

    def create_bridge():
        """
        Create a bridge on host for test
        """
        cmd_create_br = 'nmcli con add type bridge con-name %s ifname %s'
        con_name = 'con_' + utils_misc.generate_random_string(3)
        bridge_name = 'br_' + utils_misc.generate_random_string(3)
        process.run(cmd_create_br % (con_name, bridge_name), verbose=True)
        return con_name, bridge_name

    def create_network_xml(name, network_type, base_if='', **kwargs):
        """
        Create a network xml to be defined
        """
        m_net = NetworkXML(name)
        m_net.forward = {'mode': 'bridge'}
        if network_type in ('bridge', 'openvswitch'):
            m_net.bridge = {'name': kwargs['bridge_name']}
        elif network_type == 'macvtap':
            if base_if:
                m_net.forward_interface = [{'dev': base_if}]
        if network_type == 'openvswitch':
            m_net.virtualport_type = 'openvswitch'
        if 'mtu' in kwargs:
            m_net.mtu = kwargs['mtu']
        logging.debug(m_net)
        return m_net.xml

    def create_iface(iface_type, **kwargs):
        """
        Create a interface to be attached to vm
        """
        m_iface = Interface(iface_type)
        m_iface.mac_address = utils_net.generate_mac_address_simple()
        if 'base_if' in kwargs:
            m_iface.source = {'dev': kwargs['base_if'], 'mode': 'vepa'}
        if 'source_net' in kwargs:
            m_iface.source = {'network': kwargs['source_net']}
        if 'mtu' in kwargs:
            m_iface.mtu = {'size': kwargs['mtu']}
        if 'model_net' in kwargs:
            m_iface.model = kwargs['model_net']
        logging.debug(m_iface.get_xml())
        logging.debug(m_iface)
        return m_iface

    def check_mtu(mtu_size, qemu=False):
        """
        Check if mtu meets expectation on host
        """
        error = ''
        live_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        iface_xml = live_vmxml.get_devices('interface')[0]
        logging.debug(iface_xml.target)
        dev = iface_xml.target['dev']
        ifconfig_info = process.run('ifconfig|grep mtu|grep %s' % dev,
                                    shell=True,
                                    verbose=True).stdout_text
        if 'mtu %s' % mtu_size in ifconfig_info:
            logging.info('PASS on ifconfig check for vnet.')
        else:
            error += 'Fail on ifconfig check for vnet.'
        if qemu:
            qemu_mtu_info = process.run('ps aux|grep qemu-kvm',
                                        shell=True,
                                        verbose=True).stdout_text
            if 'host_mtu=%s' % mtu_size in qemu_mtu_info:
                logging.info('PASS on qemu cmd line check.')
            else:
                error += 'Fail on qemu cmd line check.'
        if error:
            test.fail(error)

    def check_mtu_in_vm(fn_login, mtu_size):
        """
        Check if mtu meets expectations in vm
        """
        session = fn_login()
        check_cmd = 'ifconfig'
        output = session.cmd(check_cmd)
        session.close()
        logging.debug(output)
        if 'mtu %s' % mtu_size not in output:
            test.fail('MTU check inside vm failed.')
        else:
            logging.debug("MTU check inside vm passed.")

    try:
        bk_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
        bk_netxml = NetworkXML.new_from_net_dumpxml(DEFAULT_NET)
        if add_pkg:
            add_pkg = add_pkg.split()
            if 'openvswitch' in add_pkg and shutil.which('ovs-vsctl'):
                new_pkg = add_pkg.copy()
                new_pkg.remove('openvswitch')
            utils_package.package_install(new_pkg)
        if 'openvswitch' in add_pkg:
            br = 'ovsbr0' + utils_misc.generate_random_string(3)
            process.run('systemctl start openvswitch.service',
                        shell=True,
                        verbose=True)
            process.run('ovs-vsctl add-br %s' % br, shell=True, verbose=True)
            process.run('ovs-vsctl show', shell=True, verbose=True)

        if not check or check in ['save', 'managedsave', 'hotplug_save']:
            # Create bridge or network and set mtu
            iface_type = 'network'
            if net_type in ('bridge', 'openvswitch'):
                if net_type == 'bridge':
                    params['con_name'], br = create_bridge()
                if mtu_type == 'network':
                    test_net = create_network_xml(bridge_name,
                                                  net_type,
                                                  bridge_name=br)
                    virsh.net_create(test_net, debug=True)
                    virsh.net_dumpxml(bridge_name, debug=True)
                if mtu_type == 'interface':
                    iface_type = net_type
                    bridge_name = br
            elif net_type == 'network':
                if mtu_type == 'network':
                    set_network(mtu_size)

            iface_mtu = 0
            if mtu_type == 'interface':
                iface_mtu = mtu_size
            if mtu_type == 'network' and with_iface:
                mtu_size = str(int(mtu_size) // 2)
                iface_mtu = mtu_size

            source_net = bridge_name if net_type in (
                'bridge', 'openvswitch') else 'default'

            # set mtu in vm interface
            set_interface(iface_mtu,
                          source_network=source_net,
                          iface_type=iface_type,
                          iface_model=model)
            vm.start()
            vm_login = vm.wait_for_serial_login if net_type in (
                'bridge', 'openvswitch') else vm.wait_for_login
            vm_login().close()
            check_qemu = True if mtu_type == 'interface' else False

            # Test mtu after save vm
            if check in ('save', 'hotplug_save'):
                if check == 'hotplug_save':
                    iface = create_iface('network',
                                         source_net='default',
                                         mtu=mtu_size,
                                         model_net=model)
                    params['mac'] = iface.mac_address
                    virsh.attach_device(vm_name, iface.xml, debug=True)
                    virsh.dumpxml(vm_name, debug=True)
                    dom_xml = vm_xml.VMXML.new_from_dumpxml(vm_name)
                    if params['mac'] not in str(dom_xml):
                        test.fail('Failed to attach interface with mtu')
                save_path = os.path.join(data_dir.get_tmp_dir(),
                                         vm_name + '.save')
                virsh.save(vm_name, save_path, debug=True)
                virsh.restore(save_path, debug=True)
            if check == 'managedsave':
                virsh.managedsave(vm_name, debug=True)
                virsh.start(vm_name, debug=True)

            # Check in both host and vm
            check_mtu(mtu_size, check_qemu)
            if mtu_type == 'interface' or with_iface:
                check_mtu_in_vm(vm_login, mtu_size)
                vm_login(timeout=60).close()

            if check == 'hotplug_save':
                virsh.detach_interface(vm_name,
                                       'network %s' % params['mac'],
                                       debug=True)
                time.sleep(5)
                dom_xml = vm_xml.VMXML.new_from_dumpxml(vm_name)
                if params['mac'] in str(dom_xml):
                    test.fail(
                        'Failed to detach interface with mtu after save-restore'
                    )

        else:
            hotplug = 'yes' == params.get('hotplug', 'False')
            if check == 'net_update':
                result = virsh.net_update(DEFAULT_NET,
                                          'modify',
                                          'mtu',
                                          '''"<mtu size='%s'/>"''' % mtu_size,
                                          debug=True)
            if check in ('macvtap', 'bridge_net', 'ovswitch_net'):
                base_if = get_default_if()
                macv_name = 'direct-macvtap' + utils_misc.generate_random_string(
                    3)

                # Test mtu in different type of network
                if mtu_type == 'network':
                    if check == 'macvtap':
                        test_net = create_network_xml(macv_name,
                                                      'macvtap',
                                                      base_if,
                                                      mtu=mtu_size)
                    if check == 'bridge_net':
                        params['con_name'], br = create_bridge()
                        test_net = create_network_xml(bridge_name,
                                                      'bridge',
                                                      mtu=mtu_size,
                                                      bridge_name=br)
                    if check == 'ovswitch_net':
                        test_net = create_network_xml(bridge_name,
                                                      'openvswitch',
                                                      mtu=mtu_size,
                                                      bridge_name=br)
                    if 'net_create' in params['id']:
                        result = virsh.net_create(test_net, debug=True)
                    if 'net_define' in params['id']:
                        result = virsh.net_define(test_net, debug=True)

                # Test mtu with or without a binding network
                elif mtu_type == 'interface':
                    vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
                    if with_net:
                        test_net = create_network_xml(macv_name, 'macvtap',
                                                      base_if)
                        virsh.net_create(test_net, debug=True)
                        iface = create_iface('network',
                                             source_net=macv_name,
                                             mtu=mtu_size,
                                             model_net=model)
                        if hotplug:
                            result = virsh.attach_device(vm_name,
                                                         iface.xml,
                                                         debug=True)
                        else:
                            vmxml.add_device(iface)
                            vmxml.sync()
                            result = virsh.start(vm_name)
                    else:
                        iface = create_iface('direct',
                                             base_if=base_if,
                                             mtu=mtu_size,
                                             model_net=model)
                        if hotplug:
                            result = virsh.attach_device(vm_name,
                                                         iface.xml,
                                                         debug=True)
                        else:
                            vmxml.add_device(iface)
                            result = virsh.define(vmxml.xml, debug=True)
            if check == 'invalid_val':
                iface = create_iface('network',
                                     source_net='default',
                                     mtu=mtu_size,
                                     model_net=model)
                result = virsh.attach_device(vm_name, iface.xml, debug=True)

            # Check result
            libvirt.check_exit_status(result, status_error)
            libvirt.check_result(result, [error_msg])

    finally:
        bk_xml.sync()
        bk_netxml.sync()
        if 'test_net' in locals():
            virsh.net_destroy(bridge_name, debug=True)
        if params.get('con_name'):
            process.run('nmcli con del %s' % params['con_name'], verbose=True)
        if add_pkg:
            process.run("ovs-vsctl del-br %s" % br, verbose=True)
            utils_package.package_remove(add_pkg)
示例#20
0
def run(test, params, env):
    """
    Test command: virsh net-destroy.

    The command can forcefully stop a given network.
    1.Make sure the network exists.
    2.Prepare network status.
    3.Perform virsh net-destroy operation.
    4.Check if the network has been destroied.
    5.Recover network environment.
    6.Confirm the test result.
    """

    net_ref = params.get("net_destroy_net_ref")
    extra = params.get("net_destroy_extra", "")
    network_name = params.get("net_destroy_network", "default")
    network_status = params.get("net_destroy_status", "active")
    status_error = params.get("status_error", "no")
    net_persistent = "yes" == params.get("net_persistent", "yes")
    net_cfg_file = params.get("net_cfg_file",
                              "/usr/share/libvirt/networks/default.xml")
    check_libvirtd = "yes" == params.get("check_libvirtd")
    vm_defined = "yes" == params.get("vm_defined")
    check_vm = "yes" == params.get("check_vm")

    # libvirt acl polkit related params
    if not libvirt_version.version_compare(1, 1, 1):
        if params.get('setup_libvirt_polkit') == 'yes':
            test.cancel("API acl test not supported in current"
                        " libvirt version.")

    uri = params.get("virsh_uri")
    unprivileged_user = params.get('unprivileged_user')
    if unprivileged_user:
        if unprivileged_user.count('EXAMPLE'):
            unprivileged_user = '******'

    output_all = virsh.net_list("--all").stdout.strip()
    # prepare the network status: active, persistent
    if not re.search(network_name, output_all):
        if net_persistent:
            virsh.net_define(net_cfg_file, ignore_status=False)
            virsh.net_start(network_name, ignore_status=False)
        else:
            virsh.create(net_cfg_file, ignore_status=False)
    # Backup the current network xml
    net_xml_bk = os.path.join(data_dir.get_tmp_dir(), "%s.xml" % network_name)
    virsh.net_dumpxml(network_name, to_file=net_xml_bk)
    if net_persistent:
        if not virsh.net_state_dict()[network_name]['persistent']:
            logging.debug("make the network persistent...")
            virsh.net_define(net_xml_bk)
    else:
        if virsh.net_state_dict()[network_name]['persistent']:
            virsh.net_undefine(network_name, ignore_status=False)
    if not virsh.net_state_dict()[network_name]['active']:
        if network_status == "active":
            virsh.net_start(network_name, ignore_status=False)
    else:
        if network_status == "inactive":
            logging.debug(
                "destroy network as we need to test inactive network...")
            virsh.net_destroy(network_name, ignore_status=False)
    logging.debug("After prepare: %s" % virsh.net_state_dict())

    # Run test case
    if net_ref == "uuid":
        net_ref = virsh.net_uuid(network_name).stdout.strip()
    elif net_ref == "name":
        net_ref = network_name

    if check_libvirtd or check_vm:
        vm_name = params.get("main_vm")
        if virsh.is_alive(vm_name):
            virsh.destroy(vm_name)
        vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
        vmxml_backup = vmxml
        # make sure there is interface with source network as default
        iface_devices = vmxml.get_devices(device_type="interface")
        has_default_net = False
        for iface in iface_devices:
            source = iface.get_source()
            if 'network' in source.keys() and source['network'] == 'default':
                has_default_net = True
                break
            elif 'bridge' in source.keys() and source['bridge'] == 'virbr0':
                has_default_net = True
                break
        if not has_default_net:
            options = "network default --current"
            virsh.attach_interface(vm_name, options, ignore_status=False)
        try:
            if vm_defined:
                ret = virsh.start(vm_name)
            else:
                logging.debug("undefine the vm, then create the vm...")
                vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
                virsh.undefine(vm_name)
                ret = virsh.create(vmxml.xml)
                logging.debug(ret.stdout)
            # check the create or start cmd status
            utils_test.libvirt.check_exit_status(
                ret, expect_error=(network_status != 'active'))
            status = 1

            if status_error != 'yes':
                libvirtd = utils_libvirtd.Libvirtd("virtqemud")
                daemon_name = libvirtd.service_name
                pid_before_run = utils_misc.get_pid(daemon_name)
                ret = virsh.net_destroy(net_ref,
                                        extra,
                                        uri=uri,
                                        debug=True,
                                        unprivileged_user=unprivileged_user,
                                        ignore_status=True)
                utils_test.libvirt.check_exit_status(ret, expect_error=False)
                # check_libvirtd pid no change
                pid_after_run = utils_misc.get_pid(daemon_name)
                if pid_after_run != pid_before_run:
                    test.fail("libvirtd crash after destroy network!")
                    status = 1
                else:
                    logging.debug(
                        "libvirtd do not crash after destroy network!")
                    status = 0
                if check_libvirtd:
                    # destroy vm, check libvirtd pid no change
                    ret = virsh.destroy(vm_name)
                    utils_test.libvirt.check_exit_status(ret,
                                                         expect_error=False)
                    pid_after_run2 = utils_misc.get_pid(daemon_name)
                    if pid_after_run2 != pid_before_run:
                        test.fail("libvirtd crash after destroy vm!")
                        status = 1
                    else:
                        logging.debug(
                            "libvirtd do not crash after destroy vm!")
                        status = 0
                elif check_vm:
                    # restart libvirtd and check vm is running
                    libvirtd = utils_libvirtd.Libvirtd()
                    libvirtd.restart()
                    if not virsh.is_alive(vm_name):
                        test.fail(
                            "vm shutdown when transient network destroyed then libvirtd restart"
                        )
                    else:
                        status = 0

        finally:
            if not vm_defined:
                vmxml_backup.define()
            vmxml_backup.sync()

    else:
        readonly = (params.get("net_destroy_readonly", "no") == "yes")
        status = virsh.net_destroy(net_ref,
                                   extra,
                                   uri=uri,
                                   readonly=readonly,
                                   debug=True,
                                   unprivileged_user=unprivileged_user,
                                   ignore_status=True).exit_status
        # Confirm the network has been destroyed.
        if net_persistent:
            if virsh.net_state_dict()[network_name]['active']:
                status = 1
        else:
            output_all = virsh.net_list("--all").stdout.strip()
            if re.search(network_name, output_all):
                status = 1
                logging.debug(
                    "transient network should not exists after destroy")

    # Recover network status to system default status
    try:
        if network_name not in virsh.net_state_dict():
            virsh.net_define(net_xml_bk, ignore_status=False)
        if not virsh.net_state_dict()[network_name]['active']:
            virsh.net_start(network_name, ignore_status=False)
        if not virsh.net_state_dict()[network_name]['persistent']:
            virsh.net_define(net_xml_bk, ignore_status=False)
        if not virsh.net_state_dict()[network_name]['autostart']:
            virsh.net_autostart(network_name, ignore_status=False)
    except process.CmdError:
        test.error("Recover network status failed!")

    # Clean up the backup network xml file
    if os.path.isfile(net_xml_bk):
        data_dir.clean_tmp_files()
        logging.debug("Cleaning up the network backup xml")

    # Check status_error
    if status_error == "yes":
        if status == 0:
            test.fail("Run successfully with wrong command!")
    elif status_error == "no":
        if status != 0:
            test.fail("Run failed with right command")
    else:
        test.error("The status_error must be 'yes' or 'no'!")
示例#21
0
    </dhcp>
  </ip>
</network>
""" % (net_name, net_name)

    try:
        test_xml = network_xml.NetworkXML(network_name=net_name)
        test_xml.xml = virtual_net
        test_xml.define()
    except xcepts.LibvirtXMLError, detail:
        raise error.TestNAError("Failed to define a test network.\n"
                                "Detail: %s." % detail)

    # Run test case
    try:
        edit_net_xml()

        cmd_result = virsh.net_dumpxml(net_name, debug=True)
        if cmd_result.exit_status:
            raise error.TestFail("Failed to dump xml of virtual network %s" %
                                 net_name)

        # The xml should contain the match_string
        match_string = "100.253"
        xml = cmd_result.stdout.strip()
        if not re.search(match_string, xml):
            raise error.TestFail("The xml is not expected")

    finally:
        test_xml.undefine()
示例#22
0
def run(test, params, env):
    """
    Test command: virsh net-dumpxml.

    This command can output the network information as an XML dump to stdout.
    1.Get all parameters from config file.
    2.If test case's network status is inactive, destroy it.
    3.Perform virsh net-dumpxml operation.
    4.Recover test environment(network status).
    5.Confirm the test result.
    """
    status_error = params.get("status_error", "no")
    net_ref = params.get("net_dumpxml_net_ref")
    net_name = params.get("net_dumpxml_network", "default")
    net_status = params.get("net_dumpxml_network_status", "active")
    xml_flie = params.get("net_dumpxml_xml_file", "default.xml")
    extra = params.get("net_dumpxml_extra", "")
    network_xml = os.path.join(data_dir.get_tmp_dir(), xml_flie)

    # acl polkit params
    uri = params.get("virsh_uri")
    unprivileged_user = params.get('unprivileged_user')
    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.")

    # Run test case
    if net_ref == "uuid":
        net_ref = virsh.net_uuid(net_name).stdout.strip()
    elif net_ref == "name":
        net_ref = net_name

    net_status_current = "active"
    if not virsh.net_state_dict()[net_name]['active']:
        net_status_current = "inactive"

    if not virsh.net_state_dict()[net_name]['persistent']:
        test.error("Network is transient!")
    try:
        if net_status == "inactive" and net_status_current == "active":
            status_destroy = virsh.net_destroy(net_name,
                                               ignore_status=True).exit_status
            if status_destroy != 0:
                test.error("Network destroied failed!")

        virsh_dargs = {'ignore_status': True}
        if params.get('setup_libvirt_polkit') == 'yes':
            virsh_dargs['unprivileged_user'] = unprivileged_user
            virsh_dargs['uri'] = uri
        result = virsh.net_dumpxml(net_ref, extra, network_xml,
                                   **virsh_dargs)
        status = result.exit_status
        err = result.stderr.strip()
        xml_validate_cmd = "virt-xml-validate %s network" % network_xml
        valid_s = process.run(xml_validate_cmd, ignore_status=True, shell=True).exit_status

        # Check option valid or not.
        if extra.find("--") != -1:
            options = extra.split("--")
            for option in options:
                if option.strip() == "":
                    continue
                if not virsh.has_command_help_match("net-dumpxml",
                                                    option.strip()) and\
                   status_error == "no":
                    test.cancel("The current libvirt version"
                                " doesn't support '%s' option"
                                % option.strip())
    finally:
        # Recover network
        if net_status == "inactive" and net_status_current == "active":
            status_start = virsh.net_start(net_name,
                                           ignore_status=True).exit_status
            if status_start != 0:
                test.error("Network started failed!")

    # Check status_error
    if status_error == "yes":
        if status == 0:
            test.fail("Run successfully with wrong command!")
        if err == "":
            test.fail("The wrong command has no error outputed!")
    elif status_error == "no":
        if status != 0:
            test.fail("Run failed with right command!")
        if valid_s != 0:
            test.fail("Command output is invalid!")
    else:
        test.error("The status_error must be 'yes' or 'no'!")
示例#23
0
def make_net_persistent(net_name):
    logging.debug(virsh.net_dumpxml(net_name).stdout)
    with open("/tmp/default.xml", "w") as f:
        f.write(virsh.net_dumpxml(net_name).stdout)
    virsh.net_define("/tmp/default.xml", ignore_status=False)
    return None
示例#24
0
                                      net_section,
                                      xmlfile, options, debug=True)

        if cmd_result.exit_status:
            err = cmd_result.stderr.strip()
            if re.search("not supported", err):
                raise error.TestNAError("Skip the test: %s" % err)
            else:
                raise error.TestFail("Failed to execute "
                                     "virsh net-update command")

        # Check the actual xml
        virsh_option = ""
        if options == "--config":
            virsh_option = "--inactive"
        cmd_result = virsh.net_dumpxml(net_name, virsh_option)
        actual_net_xml = cmd_result.stdout.strip()
        logging.info("After net-update, the actual net xml is %s",
                     actual_net_xml)

        if update_command == "delete":
            new_xml_obj = network_xml.NetworkXML.new_from_net_dumpxml(
                net_name, extra=virsh_option)
            try:
                section_str = new_xml_obj.get_section_string(xpath=element)
            except xcepts.LibvirtXMLNotFoundError:
                section_str = None
            if section_str is not None:
                raise error.TestFail("The actual net xml is not expected,"
                                     "element still exists")
示例#25
0
def run(test, params, env):
    """
    Since 3.3.0, Coalesce setting is supported.

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

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

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

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

    1. For default host network

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

    This is default network.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        :return: 0 for successful negative case
                 test.fail is fail for positive/negative case
                 None for successful positive case
        """
        if hotplug_iface:
            iface = Interface(iface_type)
        else:
            vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
            xml_devices = vmxml.devices
            iface_index = xml_devices.index(
                xml_devices.by_device_tag("interface")[0])
            iface = xml_devices[iface_index]

        if iface_type == 'network':
            iface.type_name = iface_type
            source = {iface_type: net_name}
        elif iface_type == 'bridge' and bridge_name:
            iface.type_name = iface_type
            source = {iface_type: bridge_name}
        elif iface_type == 'direct':
            iface.type_name = iface_type
            source = {'dev': interface, 'mode': 'bridge'}

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

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

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

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

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

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

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

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

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

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

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

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

    finally:
        # Recover VM.
        if vm.is_alive():
            vm.destroy(gracefully=False)
        logging.info("Restoring network...")
        if net_name == "default":
            netxml_backup.sync()
        else:
            # Destroy and undefine new created network
            virsh.net_destroy(net_name)
            virsh.net_undefine(net_name)
        # Try to recovery bridge
        if network_type == "bridge" and bridge_name:
            if bridge_name in bridge.list_br():
                bridge.del_bridge(bridge_name)
        elif network_type == "ovsbridge" and bridge_name:
            if utils_net.ovs_br_exists(bridge_name):
                utils_net.del_ovs_bridge(bridge_name)
        vmxml_backup.sync()
示例#26
0
def run(test, params, env):
    """
    Test command: virsh net-dumpxml.

    This command can output the network information as an XML dump to stdout.
    1.Get all parameters from config file.
    2.If test case's network status is inactive, destroy it.
    3.Perform virsh net-dumpxml operation.
    4.Recover test environment(network status).
    5.Confirm the test result.
    """
    status_error = params.get("status_error", "no")
    net_ref = params.get("net_dumpxml_net_ref")
    net_name = params.get("net_dumpxml_network", "default")
    net_status = params.get("net_dumpxml_network_status", "active")
    xml_flie = params.get("net_dumpxml_xml_file", "default.xml")
    extra = params.get("net_dumpxml_extra", "")
    network_xml = os.path.join(test.tmpdir, xml_flie)

    # acl polkit params
    uri = params.get("virsh_uri")
    unprivileged_user = params.get('unprivileged_user')
    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.")

    # Run test case
    if net_ref == "uuid":
        net_ref = virsh.net_uuid(net_name).stdout.strip()
    elif net_ref == "name":
        net_ref = net_name

    net_status_current = "active"
    if not virsh.net_state_dict()[net_name]['active']:
        net_status_current = "inactive"

    if not virsh.net_state_dict()[net_name]['persistent']:
        test.error("Network is transient!")
    try:
        if net_status == "inactive" and net_status_current == "active":
            status_destroy = virsh.net_destroy(net_name,
                                               ignore_status=True).exit_status
            if status_destroy != 0:
                test.error("Network destroied failed!")

        virsh_dargs = {'ignore_status': True}
        if params.get('setup_libvirt_polkit') == 'yes':
            virsh_dargs['unprivileged_user'] = unprivileged_user
            virsh_dargs['uri'] = uri
        result = virsh.net_dumpxml(net_ref, extra, network_xml,
                                   **virsh_dargs)
        status = result.exit_status
        err = result.stderr.strip()
        xml_validate_cmd = "virt-xml-validate %s network" % network_xml
        valid_s = process.run(xml_validate_cmd, ignore_status=True, shell=True).exit_status

        # Check option valid or not.
        if extra.find("--") != -1:
            options = extra.split("--")
            for option in options:
                if option.strip() == "":
                    continue
                if not virsh.has_command_help_match("net-dumpxml",
                                                    option.strip()) and\
                   status_error == "no":
                    test.cancel("The current libvirt version"
                                " doesn't support '%s' option"
                                % option.strip())
    finally:
        # Recover network
        if net_status == "inactive" and net_status_current == "active":
            status_start = virsh.net_start(net_name,
                                           ignore_status=True).exit_status
            if status_start != 0:
                test.error("Network started failed!")

    # Check status_error
    if status_error == "yes":
        if status == 0:
            test.fail("Run successfully with wrong command!")
        if err == "":
            test.fail("The wrong command has no error outputed!")
    elif status_error == "no":
        if status != 0:
            test.fail("Run failed with right command!")
        if valid_s != 0:
            test.fail("Command output is invalid!")
    else:
        test.error("The status_error must be 'yes' or 'no'!")
示例#27
0
def run_virsh_net_list(test, params, env):
    """
    Test command: virsh net-list.

    The command returns list of networks.
    1.Get all parameters from configuration.
    2.Get current network's status(State, Autostart).
    3.Do some prepare works for testing.
    4.Perform virsh net-list operation.
    5.Recover network status.
    6.Confirm the result.
    """
    option = params.get("net_list_option", "")
    extra = params.get("net_list_extra", "")
    status_error = params.get("status_error", "no")
    net_name = params.get("net_list_name", "default")
    persistent = params.get("net_list_persistent", "yes")
    net_status = params.get("net_list_error", "active")
    tmp_xml = os.path.join(test.tmpdir, "tmp.xml")
    net_current_status = "active"
    autostart_status = "yes"
    if not virsh.net_state_dict()[net_name]["active"]:
        net_current_status = "inactive"
    if not virsh.net_state_dict()[net_name]["autostart"]:
        autostart_status = "no"

    # Create a transient network.
    try:
        if persistent == "no":
            virsh.net_dumpxml(net_name, to_file=tmp_xml, ignore_status=False)
            if net_current_status == "inactive":
                virsh.net_destroy(net_name, ignore_status=False)
            virsh.net_undefine(net_name, ignore_status=False)
            virsh.net_create(tmp_xml, ignore_status=False)
    except error.CmdError:
        raise error.TestFail("Transient network test failed!")

    # Prepare network's status for testing.
    if net_status == "active":
        try:
            if not virsh.net_state_dict()[net_name]["active"]:
                virsh.net_start(net_name, ignore_status=False)
        except error.CmdError:
            raise error.TestFail("Active network test failed!")
    else:
        try:
            if virsh.net_state_dict()[net_name]["active"]:
                virsh.net_destroy(net_name, ignore_status=False)
        except error.CmdError:
            raise error.TestFail("Inactive network test failed!")

    result = virsh.net_list(option, extra, ignore_status=True)
    status = result.exit_status
    output = result.stdout.strip()

    # Recover network
    try:
        if persistent == "no":
            virsh.net_destroy(net_name, ignore_status=False)
            virsh.net_define(tmp_xml, ignore_status=False)
            if net_current_status == "active":
                virsh.net_start(net_name, ignore_status=False)
            if autostart_status == "yes":
                virsh.net_autostart(net_name, ignore_status=False)
        else:
            if net_current_status == "active" and net_status == "inactive":
                virsh.net_start(net_name, ignore_status=False)
            elif net_current_status == "inactive" and net_status == "active":
                virsh.net_destroy(net_name, ignore_status=False)
    except error.CmdError:
        raise error.TestFail("Recover network failed!")

    # check result
    if status_error == "yes":
        if status == 0:
            raise error.TestFail("Run successfully with wrong command!")
    elif status_error == "no":
        if status != 0:
            raise error.TestFail("Run failed with right command")
        if option == "--inactive":
            if net_status == "active":
                if re.search(net_name, output):
                    raise error.TestFail("Found an active network with" " --inactive option")
            else:
                if persistent == "yes":
                    if not re.search(net_name, output):
                        raise error.TestFail("Found no inactive networks with" " --inactive option")
                else:
                    # If network is transient, after net-destroy it,
                    # it will disapear.
                    if re.search(net_name, output):
                        raise error.TestFail("Found transient inactive networks" " with --inactive option")
        elif option == "":
            if net_status == "active":
                if not re.search(net_name, output):
                    raise error.TestFail("Can't find active network with no" " option")
            else:
                if re.search(net_name, output):
                    raise error.TestFail("Found inactive network with" " no option")
        elif option == "--all":
            if net_status == "active":
                if not re.search(net_name, output):
                    raise error.TestFail("Can't find active network with" " --all option")
            else:
                if persistent == "yes":
                    if not re.search(net_name, output):
                        raise error.TestFail("Can't find inactive network with" " --all option")
                else:
                    # If network is transient, after net-destroy it,
                    # it will disapear.
                    if re.search(net_name, output):
                        raise error.TestFail("Found transient inactive network" " with --all option")
示例#28
0
def run(test, params, env):
    """
    Test command: virsh net-edit <network>

    1) Define a temp virtual network
    2) Execute virsh net-edit to modify it
    3) Dump its xml then check it
    """
    def edit_net_xml():
        edit_cmd = r":%s /100.254/100.253"

        session = aexpect.ShellSession("sudo -s")
        try:
            logging.info("Execute virsh net-edit %s", net_name)
            session.sendline("virsh net-edit %s" % net_name)

            logging.info("Change the ip value of dhcp end")
            session.sendline(edit_cmd)
            session.send('\x1b')
            session.send('ZZ')
            remote.handle_prompts(session, None, None, r"[\#\$]\s*$")
            session.close()
        except (aexpect.ShellError, aexpect.ExpectError) as details:
            log = session.get_output()
            session.close()
            test.fail("Failed to do net-edit: %s\n%s" % (details, log))

    # Gather test parameters
    net_name = params.get("net_edit_net_name", "editnet")
    test_create = "yes" == params.get("test_create", "no")

    virsh_dargs = {'debug': True, 'ignore_status': True}
    virsh_instance = virsh.VirshPersistent(**virsh_dargs)

    # Get all network instance
    nets = network_xml.NetworkXML.new_all_networks_dict(virsh_instance)

    # First check if a bridge of this name already exists
    # Increment suffix integer from 1 then append it to net_name
    # till there is no name conflict.
    if net_name in nets:
        net_name_fmt = net_name + "%d"
        suffix_num = 1
        while ((net_name_fmt % suffix_num) in nets):
            suffix_num += 1

        net_name = net_name_fmt % suffix_num

    virtual_net = """
<network>
  <name>%s</name>
  <forward mode='nat'/>
  <bridge name='%s' stp='on' delay='0' />
  <mac address='52:54:00:03:78:6c'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254' />
    </dhcp>
  </ip>
</network>
""" % (net_name, net_name)

    try:
        test_xml = network_xml.NetworkXML(network_name=net_name)
        test_xml.xml = virtual_net
        if test_create:
            test_xml.create()
        else:
            test_xml.define()
    except xcepts.LibvirtXMLError as detail:
        test.cancel("Failed to define a test network.\n"
                    "Detail: %s." % detail)

    # Run test case
    try:
        libvirtd = utils_libvirtd.Libvirtd()
        if test_create:
            # Restart libvirtd and check state
            libvirtd.restart()
            net_state = virsh.net_state_dict()
            if (not net_state[net_name]['active']
                    or net_state[net_name]['autostart']
                    or net_state[net_name]['persistent']):
                test.fail("Found wrong network states"
                          " after restarting libvirtd: %s" % net_state)
        else:
            libvirtd.restart()
            net_state = virsh.net_state_dict()
            if (net_state[net_name]['active']
                    or net_state[net_name]['autostart']
                    or not net_state[net_name]['persistent']):
                test.fail("Found wrong network states: %s" % net_state)
            virsh.net_start(net_name)
        edit_net_xml()
        if test_create:
            # Network become persistent after editing
            net_state = virsh.net_state_dict()
            if (not net_state[net_name]['active']
                    or net_state[net_name]['autostart']
                    or not net_state[net_name]['persistent']):
                test.fail("Found wrong network states"
                          " after editing: %s" % net_state)

        cmd_result = virsh.net_dumpxml(net_name, '--inactive', debug=True)
        if cmd_result.exit_status:
            test.fail("Failed to dump xml of virtual network %s" % net_name)

        # The xml should contain the match_string
        match_string = "100.253"
        xml = cmd_result.stdout.strip()
        if not re.search(match_string, xml):
            test.fail("The xml is not expected")
        # The active xml should not contain the match_string
        cmd_result = virsh.net_dumpxml(net_name, debug=True)
        if cmd_result.exit_status:
            test.fail("Failed to dump active xml of virtual network %s" %
                      net_name)
        # The xml should contain the match_string
        match_string = "100.253"
        xml = cmd_result.stdout.strip()
        if re.search(match_string, xml):
            test.fail("The active xml should not change")

    finally:
        test_xml.orbital_nuclear_strike()
示例#29
0
def run(test, params, env):

    net_name = params.get("net_update_net_name", "updatenet")
    net_section = params.get("network_section", "ip-dhcp-range")
    update_command = params.get("update_command", "add-last")
    options = params.get("cmd_options", "")
    net_state = params.get("net_state")

    virtual_net = """
<network>
  <name>%s</name>
  <forward mode='nat'/>
  <bridge name='%s' stp='on' delay='0' />
  <mac address='52:54:00:03:78:6c'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254' />
      <host mac='52:54:00:5a:a0:8b' ip='192.168.100.152' />
    </dhcp>
  </ip>
</network>
""" % (net_name, net_name)

    port_group = """
<portgroup name='engineering' default='no'>
  <virtualport type='802.1Qbh'>
    <parameters profileid='test'/>
  </virtualport>
  <bandwidth>
    <inbound average='1000' peak='5000' burst='5120'/>
    <outbound average='1000' peak='5000' burst='5120'/>
  </bandwidth>
</portgroup>
"""
    try:
        test_xml = network_xml.NetworkXML(network_name=net_name)
        test_xml.xml = virtual_net
        if net_section == "portgroup":
            portgroup_xml = network_xml.PortgroupXML()
            portgroup_xml.xml = port_group
            test_xml.portgroup = portgroup_xml
        elif net_section == "forward-interface":
            test_xml.forward = {'mode': 'passthrough'}
            test_xml.forward_interface = [{'dev': 'eth2'}]
            del test_xml.bridge
            del test_xml.mac
            del test_xml.ip
        test_xml.define()
        if net_state == "active":
            test_xml.start()
        test_xml.debug_xml()
        virsh.net_dumpxml(net_name)
    except xcepts.LibvirtXMLError as detail:
        test.error("Failed to define a test network.\n" "Detail: %s." % detail)

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

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

        element = "/%s" % net_section.replace('-', '/')
        section_xml = test_xml.get_section_string(xpath=element)

        flag_list = []
        if update_command == "delete":
            newxml = section_xml
        else:
            if net_section == "bridge":
                new_bridge_name = net_name + "_new"
                flag_list.append(new_bridge_name)
                newxml = section_xml.replace(net_name, new_bridge_name)
                logging.info("The new bridge xml is %s", newxml)

            elif net_section == "forward":
                new_mode = "route"
                flag_list.append(new_mode)
                newxml = section_xml.replace("nat", new_mode)
                logging.info("The new forward xml is %s", newxml)

            elif net_section == "ip":
                new_netmask = "255.255.0.0"
                flag_list.append(new_netmask)
                newxml = section_xml.replace("255.255.255.0", new_netmask)
                logging.info("The new xml of ip section is %s", newxml)

            elif net_section == "ip-dhcp-range":
                new_end_ip = "192.168.100.253"
                flag_list.append(new_end_ip)
                newxml = section_xml.replace("192.168.100.254", new_end_ip)
                logging.info("The new xml of ip-dhcp-range is %s", newxml)
            elif net_section == "portgroup":
                new_inbound_average = "2000"
                flag_list.append(new_inbound_average)
                newxml = section_xml.replace("1000", new_inbound_average)
                newxml = newxml.replace("no", "yes")
                flag_list.append("yes")
                if update_command in ['add-first', 'add-last']:
                    newxml = newxml.replace("engineering", "sales")
                    flag_list.append("sales")
                logging.info("The new xml of portgroup is %s", newxml)
            elif net_section == "forward-interface":
                new_forward_iface = params.get("new_forward_iface", "eth4")
                flag_list.append(new_forward_iface)
                newxml = section_xml.replace("eth2", new_forward_iface)
                logging.info("The new xml of forward-interface is %s", newxml)
            elif net_section == "ip-dhcp-host":
                new_ip_dhcp_host = params.get("new_ip_dhcp_host",
                                              "192.168.100.153")
                flag_list.append(new_ip_dhcp_host)
                newxml = section_xml.replace("192.168.100.152",
                                             new_ip_dhcp_host)
                if update_command in ['add-first', 'add-last']:
                    new_ip_dhcp_mac = params.get("new_ip_dhcp_mac",
                                                 "52:54:00:5a:a0:9b")
                    newxml = newxml.replace("52:54:00:5a:a0:8b",
                                            new_ip_dhcp_mac)
                    flag_list.append(new_ip_dhcp_mac)
                logging.info("The new xml of forward-interface is %s", newxml)
            else:
                test.fail("Unknown network section")

        fd = open(xmlfile, 'w')
        fd.write(newxml)
        fd.close()

        cmd_result = virsh.net_update(net_name,
                                      update_command,
                                      net_section,
                                      xmlfile,
                                      options,
                                      debug=True)

        if cmd_result.exit_status:
            err = cmd_result.stderr.strip()
            if re.search("not supported", err):
                test.cancel("Skip the test: %s" % err)
            else:
                test.fail("Failed to execute " "virsh net-update command")

        # Check the actual xml
        virsh_option = ""
        if options == "--config":
            virsh_option = "--inactive"
        cmd_result = virsh.net_dumpxml(net_name, virsh_option)
        actual_net_xml = cmd_result.stdout.strip()
        logging.info("After net-update, the actual net xml is %s",
                     actual_net_xml)

        if update_command == "delete":
            new_xml_obj = network_xml.NetworkXML.new_from_net_dumpxml(
                net_name, extra=virsh_option)
            try:
                section_str = new_xml_obj.get_section_string(xpath=element)
            except xcepts.LibvirtXMLNotFoundError:
                section_str = None
            if section_str is not None:
                test.fail("The actual net xml is not expected,"
                          "element still exists")

        else:
            for flag_string in flag_list:
                if not re.search(flag_string, actual_net_xml):
                    test.fail("The actual net xml failed to update")

    finally:
        test_xml.undefine()

        if os.path.exists(xmlfile):
            os.remove(xmlfile)
示例#30
0
def run(test, params, env):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return __find_config

        return _find_config

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            names = locals()

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

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

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

            flag_list = []
            flag_list_abs = []

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    session.close()

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

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

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

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

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

        if use_in_guest == "yes":
            vm = env.get_vm(vm_name)
            if vm.is_alive():
                vm.destroy(gracefully=False)
            vmxml_backup.sync()
        for config_file in backup_files:
            config_file._reset_file()
示例#31
0
def run(test, params, env):
    """
    Test command: virsh net-dumpxml.

    This command can output the network information as an XML dump to stdout.
    1.Get all parameters from config file.
    2.If test case's network status is inactive, destroy it.
    3.Perform virsh net-dumpxml operation.
    4.Recover test environment(network status).
    5.Confirm the test result.
    """
    status_error = params.get("status_error", "no")
    net_ref = params.get("net_dumpxml_net_ref")
    net_name = params.get("net_dumpxml_network", "default")
    net_status = params.get("net_dumpxml_network_status", "active")
    xml_flie = params.get("net_dumpxml_xml_file", "default.xml")
    extra = params.get("net_dumpxml_extra", "")
    network_xml = os.path.join(test.tmpdir, xml_flie)

    # Run test case
    if net_ref == "uuid":
        net_ref = virsh.net_uuid(net_name).stdout.strip()
    elif net_ref == "name":
        net_ref = net_name

    net_status_current = "active"
    if not virsh.net_state_dict()[net_name]['active']:
        net_status_current = "inactive"

    if not virsh.net_state_dict()[net_name]['persistent']:
        raise error.TestError("Network is transient!")
    try:
        if net_status == "inactive" and net_status_current == "active":
            status_destroy = virsh.net_destroy(net_name,
                                               ignore_status=True).exit_status
            if status_destroy != 0:
                raise error.TestError("Network destroied failed!")

        result = virsh.net_dumpxml(net_ref, extra, network_xml,
                                   ignore_status=True)
        status = result.exit_status
        err = result.stderr.strip()
        xml_validate_cmd = "virt-xml-validate %s network" % network_xml
        valid_s = utils.run(xml_validate_cmd, ignore_status=True).exit_status

        # Check option valid or not.
        if extra.find("--") != -1:
            options = extra.split("--")
            for option in options:
                if option.strip() == "":
                    continue
                if not virsh.has_command_help_match("net-dumpxml", option.strip()):
                    status_error = "yes"
                    break
    finally:
        # Recover network
        if net_status == "inactive" and net_status_current == "active":
            status_start = virsh.net_start(net_name,
                                           ignore_status=True).exit_status
            if status_start != 0:
                raise error.TestError("Network started failed!")

    # Check status_error
    if status_error == "yes":
        if status == 0:
            raise error.TestFail("Run successfully with wrong command!")
        if err == "":
            raise error.TestFail("The wrong command has no error outputed!")
    elif status_error == "no":
        if status != 0:
            raise error.TestFail("Run failed with right command!")
        if valid_s != 0:
            raise error.TestFail("Command output is invalid!")
    else:
        raise error.TestError("The status_error must be 'yes' or 'no'!")
示例#32
0
def run(test, params, env):
    """
    Test command: virsh net-edit <network>

    1) Define a temp virtual network
    2) Execute virsh net-edit to modify it
    3) Dump its xml then check it
    """

    def edit_net_xml(edit_cmd, expect_error, **dargs):
        """
        Edit net xml with virsh net-edit

        :params edit_cmd: The edit cmd to execute
        :params expect_error: Boolen, expect success or not
        :params **dargs: The virsh edit's option
        """
        logging.debug("edit_cmd: %s", edit_cmd)
        readonly = dargs.get("readonly", False)
        session = aexpect.ShellSession("sudo -s")
        try:
            logging.info("Execute virsh net-edit %s", net_name)
            virsh_cmd = "virsh net-edit %s" % net_name
            if readonly:
                virsh_cmd = "virsh -r net-edit %s" % net_name
            logging.debug("virsh_cmd: %s", virsh_cmd)
            session.sendline(virsh_cmd)
            session.sendline(edit_cmd)
            session.send('\x1b')
            session.send('ZZ')
            remote.handle_prompts(session, None, None, r"[\#\$]\s*$")
            session.close()
        except (aexpect.ShellError, aexpect.ExpectError, remote.LoginTimeoutError) as details:
            log = session.get_output()
            session.close()
            if not expect_error:
                test.fail("Failed to do net-edit: %s\n%s"
                          % (details, log))
            logging.debug("Expected error: %s" % log)
            if readonly and "read only" not in log:
                test.fail("Not expected error")

    # Gather test parameters
    net_name = params.get("net_edit_net_name", "editnet")
    test_create = "yes" == params.get("test_create", "no")

    virsh_dargs = {'debug': True, 'ignore_status': True}
    virsh_instance = virsh.VirshPersistent(**virsh_dargs)

    change_attribute = params.get("attribute", None)
    old_value = params.get("old_value", None)
    new_value = params.get("new_value", None)
    edit_type = params.get("edit_type", "modify")
    status_error = (params.get("status_error", "no") == "yes")
    readonly = (params.get("net_edit_readonly", "no") == "yes")

    # Get all network instance
    nets = network_xml.NetworkXML.new_all_networks_dict(virsh_instance)

    # First check if a bridge of this name already exists
    # Increment suffix integer from 1 then append it to net_name
    # till there is no name conflict.
    if net_name in nets:
        net_name_fmt = net_name + "%d"
        suffix_num = 1
        while ((net_name_fmt % suffix_num) in nets):
            suffix_num += 1

        net_name = net_name_fmt % suffix_num

    virtual_net = """
<network>
  <name>%s</name>
  <forward mode='nat'/>
  <bridge name='%s' stp='on' delay='0' />
  <mac address='52:54:00:03:78:6c'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254' />
    </dhcp>
  </ip>
</network>
""" % (net_name, net_name)

    try:
        test_xml = network_xml.NetworkXML(network_name=net_name)
        test_xml.xml = virtual_net
        if test_create:
            test_xml.create()
        else:
            test_xml.define()
    except xcepts.LibvirtXMLError as detail:
        test.cancel("Failed to define a test network.\n"
                    "Detail: %s." % detail)

    # Run test case
    try:
        libvirtd = utils_libvirtd.Libvirtd()
        if change_attribute == "uuid":
            # if the attribute need to change is uuid, the old uuid should get
            # from current network, and new uuid can generate by uuidgen
            new_value = process.run("uuidgen", shell=True).stdout[:-1]
            old_value = virsh.net_uuid(net_name).stdout.strip()
        if test_create:
            # Restart libvirtd and check state
            libvirtd.restart()
            net_state = virsh.net_state_dict()
            if (not net_state[net_name]['active'] or
                    net_state[net_name]['autostart'] or
                    net_state[net_name]['persistent']):
                test.fail("Found wrong network states"
                          " after restarting libvirtd: %s"
                          % net_state)
        else:
            libvirtd.restart()
            net_state = virsh.net_state_dict()
            if (net_state[net_name]['active'] or
                    net_state[net_name]['autostart'] or
                    not net_state[net_name]['persistent']):
                test.fail("Found wrong network states: %s" % net_state)
            result = virsh.net_start(net_name)
            logging.debug("start the persistent network return: %s", result)

        if edit_type == "modify":
            edit_cmd = r":%%s/%s=\'%s\'/%s=\'%s\'" % (change_attribute, old_value,
                                                      change_attribute, new_value)
            match_string = "%s=\'%s\'" % (change_attribute, new_value)

        if edit_type == "delete":
            match_string = "%s" % change_attribute
            # Pattern to be more accurate
            if old_value and change_attribute != 'uuid':
                match_string = "%s=\'%s\'" % (change_attribute, old_value)
            else:
                match_string = old_value
            edit_cmd = r":/%s/d" % match_string

        edit_net_xml(edit_cmd, status_error, readonly=readonly)

        net_state = virsh.net_state_dict()
        # transient Network become persistent after editing
        if not status_error and (not net_state[net_name]['active'] or
                                 net_state[net_name]['autostart'] or
                                 not net_state[net_name]['persistent']):
            test.fail("Found wrong network states"
                      " after editing: %s"
                      % net_state)

        cmd_result = virsh.net_dumpxml(net_name, '--inactive', debug=True)
        if cmd_result.exit_status:
            test.fail("Failed to dump xml of virtual network %s" %
                      net_name)

        # The inactive xml should contain the match string
        xml = cmd_result.stdout.strip()
        if edit_type == "modify":
            if not status_error and not re.search(match_string, xml):
                test.fail("The inactive xml should contain the change '%s'"
                          % match_string)
            if status_error and re.search(match_string, xml):
                test.fail("Expect to modify failure but run success")

        if edit_type == "delete":
            if not status_error and re.search(match_string, xml):
                test.fail("The inactive xml should delete the change '%s'"
                          % match_string)
            if status_error and not re.search(match_string, xml):
                test.fail("Expect to delete failure but run success")

        # The active xml should not contain the match string
        if net_state[net_name]['active']:
            if not status_error:
                cmd_result = virsh.net_dumpxml(net_name, debug=True)
                if cmd_result.exit_status:
                    test.fail("Failed to dump active xml of virtual network %s" %
                              net_name)
                xml = cmd_result.stdout.strip()
                if edit_type == "modify" and re.search(match_string, xml):
                    test.fail("The active xml should not contain the change '%s'"
                              % match_string)
                if edit_type == "delete" and not re.search(match_string, xml):
                    test.fail("The active xml should not delete the change '%s'"
                              % match_string)
    finally:
        test_xml.orbital_nuclear_strike()