ovs_qos.py 9.9 KB
Newer Older
1 2 3 4 5 6
import os
import re
import time
import glob
import shutil
import logging
7

X
Xu Han 已提交
8 9
from avocado.utils import process
from avocado.utils import path as utils_path
10

X
Xu Han 已提交
11
from virttest import error_context
12 13
from virttest import utils_netperf
from virttest import data_dir
14 15


X
Xu Han 已提交
16
@error_context.context_aware
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
def run(test, params, env):
    """
     Test Qos between guests in one ovs backend

    1) Boot the vms
    2) Apply QoS limitation to 1Mbps on the tap of a guest.
    3) Start netperf server on another guest.
    4) Start netperf client on guest in step 1 with option -l 60.
    5) Stop netperf client and set QoS to 10Mbps.
    6) Run step 4 again.
    7) Verify vm through out.

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

    def set_ovs_port_attr(iface, attribute, value):
        """
        Set OVS port attribute.
        """
        cmd = "ovs-vsctl set interface %s %s=%s" % (iface, attribute, value)
        logging.info("execute host command: %s" % cmd)
X
Xu Han 已提交
40
        status = process.system(cmd, ignore_status=True)
41 42 43 44
        if status != 0:
            err_msg = "set %s to %s for interface '%s' " % (
                attribute, value, iface)
            err_msg += "exited with nozero statu '%d'" % status
X
Xu Han 已提交
45
            test.error(err_msg)
46 47 48 49 50 51 52 53 54 55 56

    def set_port_qos(vm, rate, burst):
        """
        Set ingress_policing_rate and ingress_policing_burst for tap device
        used by vm.

        :param vm: netperf client vm object
        :param rate: value of ingress_policing_rate
        :param brust: value of ingress_policing_brust
        """
        iface = vm.get_ifname()
X
Xu Han 已提交
57 58
        error_context.context("Set QoS for tap '%s' use by vm '%s'"
                              % (iface, vm.name), logging.info)
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
        attributes = zip(['ingress_policing_rate',
                          'ingress_policing_burst'],
                         [rate, burst])
        for k, v in attributes:
            set_ovs_port_attr(iface, k, v)
            time.sleep(0.1)

    def get_throughout(netperf_server, server_vm, netperf_client,
                       client_vm, client_options=" -l 60"):
        """
        Get network throughout by netperf.

        :param netperf_server: utils_netperf.NetperfServer instance.
        :param server_ip: ip address of netperf server.
        :param netperf_client: utils_netperf.NetperfClient instance.
        :param client_options: netperf client start options.

        :return: float type throughout Kbps.
        """
X
Xu Han 已提交
78 79
        error_context.context("Set '%s' as netperf server" % server_vm.name,
                              logging.info)
80 81 82
        if not netperf_server.is_server_running():
            netperf_server.start()

X
Xu Han 已提交
83 84
        error_context.context("Set '%s' as netperf client" % client_vm.name,
                              logging.info)
85 86
        server_ip = server_vm.get_address()
        output = netperf_client.start(server_ip, client_options)
87
        logging.debug("netperf client output: %s" % output)
88 89 90 91
        regex = r"\d+\s+\d+\s+\d+\s+[\d.]+\s+([\d.]+)"
        try:
            throughout = float(re.search(regex, output, re.M).groups()[0])
            return throughout * 1000
92
        except Exception:
X
Xu Han 已提交
93
            test.error("Invaild output format of netperf client!")
94 95 96 97 98 99 100
        finally:
            netperf_client.stop()

    def is_test_pass(data):
        """
        Check throughout near gress_policing_rate set for tap device.
        """
101
        return data[1] <= data[2] + data[3]
102 103 104 105 106

    def report_test_results(datas):
        """
        Report failed test scenarios.
        """
X
Xu Han 已提交
107
        error_context.context("Analyze guest throughout", logging.info)
108 109 110 111 112
        fails = [_ for _ in datas if not is_test_pass(_)]
        if fails:
            msg = "OVS Qos test failed, "
            for tap, throughout, rate, burst in fails:
                msg += "netperf throughout(%s) on '%s' " % (throughout, tap)
113 114
                msg += "should be near ingress_policing_rate(%s), " % rate
                msg += "ingress_policing_burst is %s;\n" % burst
X
Xu Han 已提交
115
            test.fail(msg)
116 117

    def clear_qos_setting(iface):
X
Xu Han 已提交
118 119
        error_context.context("Clear qos setting for ovs port '%s'" % iface,
                              logging.info)
120
        clear_cmd = "ovs-vsctl clear Port %s qos" % iface
X
Xu Han 已提交
121
        process.system(clear_cmd)
122 123 124 125 126 127 128 129 130 131 132
        logging.info("Clear ovs command: %s" % clear_cmd)

    def setup_netperf_env():
        """
        Setup netperf envrioments in vms
        """
        def __get_vminfo():
            """
            Get vms information;
            """
            login_timeout = float(params.get("login_timeout", 360))
133 134
            stop_firewall_cmd = "systemctl stop firewalld||"
            stop_firewall_cmd += "service firewalld stop"
135 136
            guest_info = ["status_test_command", "shell_linesep", "shell_prompt",
                          "username", "password", "shell_client", "shell_port", "os_type"]
137 138
            vms_info = []
            for _ in params.get("vms").split():
139
                info = list(map(
140
                    lambda x: params.object_params(_).get(x),
141
                    guest_info))
142 143 144
                vm = env.get_vm(_)
                vm.verify_alive()
                session = vm.wait_for_login(timeout=login_timeout)
145
                session.cmd(stop_firewall_cmd, ignore_all_errors=True)
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
                vms_info.append((vm, info))
            return vms_info

        netperf_link = params.get("netperf_link")
        netperf_link = os.path.join(
            data_dir.get_deps_dir("netperf"),
            netperf_link)
        md5sum = params.get("pkg_md5sum")
        netperf_server_link = params.get(
            "netperf_server_link_win",
            netperf_link)
        netperf_server_link = os.path.join(data_dir.get_deps_dir("netperf"),
                                           netperf_server_link)
        netperf_client_link = params.get(
            "netperf_client_link_win",
            netperf_link)
        netperf_client_link = os.path.join(data_dir.get_deps_dir("netperf"),
                                           netperf_client_link)

        server_path_linux = params.get("server_path", "/var/tmp")
        client_path_linux = params.get("client_path", "/var/tmp")
        server_path_win = params.get("server_path_win", "c:\\")
        client_path_win = params.get("client_path_win", "c:\\")
169 170 171
        compile_option_client = params.get("compile_option_client", "")
        compile_option_server = params.get("compile_option_server", "")

172 173 174 175 176 177 178 179 180
        netperf_servers, netperf_clients = [], []
        for idx, (vm, info) in enumerate(__get_vminfo()):
            if idx % 2 == 0:
                if info[-1] == "windows":
                    netperf_link = netperf_server_link
                    server_path = server_path_win
                else:
                    netperf_link = netperf_link
                    server_path = server_path_linux
181 182 183 184 185 186 187 188 189
                server = utils_netperf.NetperfServer(
                    vm.get_address(),
                    server_path,
                    md5sum,
                    netperf_link,
                    port=info[-2],
                    client=info[-3],
                    password=info[-4],
                    username=info[-5],
190
                    prompt=info[-6],
191
                    linesep=info[-7].encode().decode('unicode_escape'),
192
                    status_test_command=info[-8],
193
                    compile_option=compile_option_server)
194 195 196 197 198 199 200 201 202
                netperf_servers.append((server, vm))
                continue
            else:
                if info[-1] == "windows":
                    netperf_link = netperf_client_link
                    client_path = client_path_win
                else:
                    netperf_link = netperf_link
                    client_path = client_path_linux
203 204 205 206 207 208 209 210 211
                client = utils_netperf.NetperfClient(
                    vm.get_address(),
                    client_path,
                    md5sum,
                    netperf_link,
                    port=info[-2],
                    client=info[-3],
                    password=info[-4],
                    username=info[-5],
212
                    prompt=info[-6],
213
                    linesep=info[-7].encode().decode('unicode_escape'),
214
                    status_test_command=info[-8],
215
                    compile_option=compile_option_client)
216 217 218 219
                netperf_clients.append((client, vm))
                continue
        return netperf_clients, netperf_servers

X
Xu Han 已提交
220
    utils_path.find_command("ovs-vsctl")
221 222
    if (params.get("netdst") not in
            process.system_output("ovs-vsctl show").decode()):
X
Xu Han 已提交
223
        test.error("This is a openvswitch only test")
224 225
    extra_options = params.get("netperf_client_options", " -l 60")
    rate_brust_pairs = params.get("rate_brust_pairs").split()
226 227
    rate_brust_pairs = list(
        map(lambda x: map(int, x.split(',')), rate_brust_pairs))
228 229 230 231 232 233 234 235 236
    results = []
    try:
        netperf_clients, netperf_servers = setup_netperf_env()
        for idx in range(len(netperf_clients)):
            netperf_client, client_vm = netperf_clients[idx]
            idx = (idx < len(netperf_servers) and [idx] or [0])[0]
            netperf_server, server_vm = netperf_servers[idx]
            for rate, burst in rate_brust_pairs:
                set_port_qos(client_vm, rate, burst)
237
                time.sleep(3)
238 239 240 241 242 243 244 245 246 247 248 249 250
                throughout = get_throughout(netperf_server,
                                            server_vm,
                                            netperf_client,
                                            client_vm,
                                            extra_options)
                iface = client_vm.get_ifname()
                clear_qos_setting(iface)
                results.append([iface, throughout, rate, burst])
        report_test_results(results)
    finally:
        for f in glob.glob("/var/log/openvswith/*.log"):
            dst = os.path.join(test.resultsdir, os.path.basename(f))
            shutil.copy(f, dst)