from resources.libraries.python.Constants import Constants
from resources.libraries.python.DUTSetup import DUTSetup
from resources.libraries.python.model.ExportResult import (
- export_hoststack_results
+ export_hoststack_results,
)
from resources.libraries.python.PapiExecutor import PapiSocketExecutor
from resources.libraries.python.ssh import exec_cmd, exec_cmd_no_error
from resources.libraries.python.topology import Topology
-class HoststackUtil():
+
+class HoststackUtil:
"""Utilities for Host Stack tests."""
@staticmethod
'args' - command arguments.
:rtype: dict
"""
- proto = vpp_echo_attributes[u"uri_protocol"]
- addr = vpp_echo_attributes[u"uri_ip4_addr"]
- port = vpp_echo_attributes[u"uri_port"]
+ proto = vpp_echo_attributes["uri_protocol"]
+ addr = vpp_echo_attributes["uri_ip4_addr"]
+ port = vpp_echo_attributes["uri_port"]
vpp_echo_cmd = {}
- vpp_echo_cmd[u"name"] = u"vpp_echo"
- vpp_echo_cmd[u"args"] = f"{vpp_echo_attributes[u'role']} " \
- f"socket-name {vpp_echo_attributes[u'app_api_socket']} " \
- f"{vpp_echo_attributes[u'json_output']} " \
- f"uri {proto}://{addr}/{port} " \
- f"nthreads {vpp_echo_attributes[u'nthreads']} " \
- f"mq-size {vpp_echo_attributes[u'mq_size']} " \
- f"nclients {vpp_echo_attributes[u'nclients']} " \
- f"quic-streams {vpp_echo_attributes[u'quic_streams']} " \
- f"time {vpp_echo_attributes[u'time']} " \
- f"fifo-size {vpp_echo_attributes[u'fifo_size']} " \
- f"TX={vpp_echo_attributes[u'tx_bytes']} " \
- f"RX={vpp_echo_attributes[u'rx_bytes']}"
- if vpp_echo_attributes[u"rx_results_diff"]:
- vpp_echo_cmd[u"args"] += u" rx-results-diff"
- if vpp_echo_attributes[u"tx_results_diff"]:
- vpp_echo_cmd[u"args"] += u" tx-results-diff"
- if vpp_echo_attributes[u"use_app_socket_api"]:
- vpp_echo_cmd[u"args"] += u" use-app-socket-api"
+ vpp_echo_cmd["name"] = "vpp_echo"
+ vpp_echo_cmd["args"] = (
+ f"{vpp_echo_attributes['role']} "
+ f"socket-name {vpp_echo_attributes['app_api_socket']} "
+ f"{vpp_echo_attributes['json_output']} "
+ f"uri {proto}://{addr}/{port} "
+ f"nthreads {vpp_echo_attributes['nthreads']} "
+ f"mq-size {vpp_echo_attributes['mq_size']} "
+ f"nclients {vpp_echo_attributes['nclients']} "
+ f"quic-streams {vpp_echo_attributes['quic_streams']} "
+ f"time {vpp_echo_attributes['time']} "
+ f"fifo-size {vpp_echo_attributes['fifo_size']} "
+ f"TX={vpp_echo_attributes['tx_bytes']} "
+ f"RX={vpp_echo_attributes['rx_bytes']}"
+ )
+ if vpp_echo_attributes["rx_results_diff"]:
+ vpp_echo_cmd["args"] += " rx-results-diff"
+ if vpp_echo_attributes["tx_results_diff"]:
+ vpp_echo_cmd["args"] += " tx-results-diff"
+ if vpp_echo_attributes["use_app_socket_api"]:
+ vpp_echo_cmd["args"] += " use-app-socket-api"
return vpp_echo_cmd
@staticmethod
:rtype: dict
"""
iperf3_cmd = {}
- iperf3_cmd[u"env_vars"] = f"VCL_CONFIG={Constants.REMOTE_FW_DIR}/" \
- f"{Constants.RESOURCES_TPL_VCL}/" \
- f"{iperf3_attributes[u'vcl_config']}"
- if iperf3_attributes[u"ld_preload"]:
+ iperf3_cmd["env_vars"] = (
+ f"VCL_CONFIG={Constants.REMOTE_FW_DIR}/"
+ f"{Constants.RESOURCES_TPL_VCL}/"
+ f"{iperf3_attributes['vcl_config']}"
+ )
+ if iperf3_attributes["ld_preload"]:
ldpreload = HoststackUtil._get_ldpreload_path(node)
- iperf3_cmd[u"env_vars"] += f" LD_PRELOAD={ldpreload}"
- if iperf3_attributes[u'transparent_tls']:
- iperf3_cmd[u"env_vars"] += u" LDP_ENV_TLS_TRANS=1"
-
- json_results = u" --json" if iperf3_attributes[u'json'] else u""
- ip_address = f" {iperf3_attributes[u'ip_address']}" if u"ip_address" \
- in iperf3_attributes else u""
- iperf3_cmd[u"name"] = u"iperf3"
- iperf3_cmd[u"args"] = f"--{iperf3_attributes[u'role']}{ip_address} " \
- f"--interval 0{json_results} " \
- f"--version{iperf3_attributes[u'ip_version']}"
-
- if iperf3_attributes[u"role"] == u"server":
- iperf3_cmd[u"args"] += u" --one-off"
+ iperf3_cmd["env_vars"] += f" LD_PRELOAD={ldpreload}"
+ if iperf3_attributes["transparent_tls"]:
+ iperf3_cmd["env_vars"] += " LDP_ENV_TLS_TRANS=1"
+
+ json_results = " --json" if iperf3_attributes["json"] else ""
+ ip_address = (
+ f" {iperf3_attributes['ip_address']}"
+ if "ip_address" in iperf3_attributes
+ else ""
+ )
+ iperf3_cmd["name"] = "iperf3"
+ iperf3_cmd["args"] = (
+ f"--{iperf3_attributes['role']}{ip_address} "
+ f"--interval 0{json_results} "
+ f"--version{iperf3_attributes['ip_version']}"
+ )
+
+ if iperf3_attributes["role"] == "server":
+ iperf3_cmd["args"] += " --one-off"
else:
- iperf3_cmd[u"args"] += u" --get-server-output"
- if u"parallel" in iperf3_attributes:
- iperf3_cmd[u"args"] += \
- f" --parallel {iperf3_attributes[u'parallel']}"
- if u"time" in iperf3_attributes:
- iperf3_cmd[u"args"] += \
- f" --time {iperf3_attributes[u'time']}"
- if iperf3_attributes[u"udp"]:
- iperf3_cmd[u"args"] += u" --udp"
- iperf3_cmd[u"args"] += \
- f" --bandwidth {iperf3_attributes[u'bandwidth']}"
- if iperf3_attributes[u"length"] > 0:
- iperf3_cmd[u"args"] += \
- f" --length {iperf3_attributes[u'length']}"
+ iperf3_cmd["args"] += " --get-server-output"
+ if "parallel" in iperf3_attributes:
+ iperf3_cmd[
+ "args"
+ ] += f" --parallel {iperf3_attributes['parallel']}"
+ if "time" in iperf3_attributes:
+ iperf3_cmd["args"] += f" --time {iperf3_attributes['time']}"
+ if iperf3_attributes["udp"]:
+ iperf3_cmd["args"] += " --udp"
+ iperf3_cmd[
+ "args"
+ ] += f" --bandwidth {iperf3_attributes['bandwidth']}"
+ if iperf3_attributes["length"] > 0:
+ iperf3_cmd[
+ "args"
+ ] += f" --length {iperf3_attributes['length']}"
return iperf3_cmd
@staticmethod
PapiSocketExecutor.run_cli_cmd(node, cmd)
@staticmethod
- def set_hoststack_quic_crypto_engine(node, quic_crypto_engine,
- fail_on_error=False):
+ def set_hoststack_quic_crypto_engine(
+ node, quic_crypto_engine, fail_on_error=False
+ ):
"""Set the Hoststack QUIC crypto engine on node
:param node: Node to enable/disable HostStack.
:type node: dict
:type quic_crypto_engine: str
"""
- vpp_crypto_engines = {u"openssl", u"native", u"ipsecmb"}
- if quic_crypto_engine == u"nocrypto":
- logger.trace(u"No QUIC crypto engine.")
+ vpp_crypto_engines = {"openssl", "native", "ipsecmb"}
+ if quic_crypto_engine == "nocrypto":
+ logger.trace("No QUIC crypto engine.")
return
if quic_crypto_engine in vpp_crypto_engines:
- cmds = [u"quic set crypto api vpp",
- f"set crypto handler aes-128-gcm {quic_crypto_engine}",
- f"set crypto handler aes-256-gcm {quic_crypto_engine}"]
- elif quic_crypto_engine == u"picotls":
- cmds = [u"quic set crypto api picotls"]
+ cmds = [
+ "quic set crypto api vpp",
+ f"set crypto handler aes-128-gcm {quic_crypto_engine}",
+ f"set crypto handler aes-256-gcm {quic_crypto_engine}",
+ ]
+ elif quic_crypto_engine == "picotls":
+ cmds = ["quic set crypto api picotls"]
else:
raise ValueError(f"Unknown QUIC crypto_engine {quic_crypto_engine}")
:type node: dict
:type program_name: str
"""
- cmd = f"sh -c \'cat /tmp/{program_name}_stdout.log\'"
- stdout_log, _ = exec_cmd_no_error(node, cmd, sudo=True, \
- message=f"Get {program_name} stdout log failed!")
-
- cmd = f"sh -c \'cat /tmp/{program_name}_stderr.log\'"
- stderr_log, _ = exec_cmd_no_error(node, cmd, sudo=True, \
- message=f"Get {program_name} stderr log failed!")
+ cmd = f"sh -c 'cat /tmp/{program_name}_stdout.log'"
+ stdout_log, _ = exec_cmd_no_error(
+ node,
+ cmd,
+ sudo=True,
+ message=f"Get {program_name} stdout log failed!",
+ )
+
+ cmd = f"sh -c 'cat /tmp/{program_name}_stderr.log'"
+ stderr_log, _ = exec_cmd_no_error(
+ node,
+ cmd,
+ sudo=True,
+ message=f"Get {program_name} stderr log failed!",
+ )
return stdout_log, stderr_log
:type node: dict
:type program: dict
"""
- program_name = program[u"name"]
- program_stdout_log, program_stderr_log = \
- HoststackUtil._get_hoststack_test_program_logs(node,
- program_name)
+ program_name = program["name"]
+ program_stdout_log, program_stderr_log = (
+ HoststackUtil._get_hoststack_test_program_logs(node, program_name)
+ )
if len(program_stdout_log) == 0 and len(program_stderr_log) == 0:
logger.trace(f"Retrying {program_name} log retrieval")
- program_stdout_log, program_stderr_log = \
- HoststackUtil._get_hoststack_test_program_logs(node,
- program_name)
+ program_stdout_log, program_stderr_log = (
+ HoststackUtil._get_hoststack_test_program_logs(
+ node, program_name
+ )
+ )
return program_stdout_log, program_stderr_log
@staticmethod
:rtype: dict
"""
nginx_cmd = dict()
- nginx_cmd[u"env_vars"] = f"VCL_CONFIG={Constants.REMOTE_FW_DIR}/" \
- f"{Constants.RESOURCES_TPL_VCL}/" \
- f"{nginx_attributes[u'vcl_config']}"
- if nginx_attributes[u"ld_preload"]:
+ nginx_cmd["env_vars"] = (
+ f"VCL_CONFIG={Constants.REMOTE_FW_DIR}/"
+ f"{Constants.RESOURCES_TPL_VCL}/"
+ f"{nginx_attributes['vcl_config']}"
+ )
+ if nginx_attributes["ld_preload"]:
ldpreload = HoststackUtil._get_ldpreload_path(node)
- nginx_cmd[u"env_vars"] += f" LD_PRELOAD={ldpreload}"
- if nginx_attributes[u'transparent_tls']:
- nginx_cmd[u"env_vars"] += u" LDP_ENV_TLS_TRANS=1"
-
- nginx_cmd[u"name"] = u"nginx"
- nginx_cmd[u"path"] = f"{nginx_ins_dir}nginx-{nginx_version}/sbin/"
- nginx_cmd[u"args"] = f"-c {nginx_ins_dir}/" \
- f"nginx-{nginx_version}/conf/nginx.conf"
+ nginx_cmd["env_vars"] += f" LD_PRELOAD={ldpreload}"
+ if nginx_attributes["transparent_tls"]:
+ nginx_cmd["env_vars"] += " LDP_ENV_TLS_TRANS=1"
+
+ nginx_cmd["name"] = "nginx"
+ nginx_cmd["path"] = f"{nginx_ins_dir}nginx-{nginx_version}/sbin/"
+ nginx_cmd["args"] = (
+ f"-c {nginx_ins_dir}/" f"nginx-{nginx_version}/conf/nginx.conf"
+ )
return nginx_cmd
@staticmethod
:rtype: int
:raises RuntimeError: If node subtype is not a DUT or startup failed.
"""
- if node[u"type"] != u"DUT":
- raise RuntimeError(u"Node type is not a DUT!")
+ if node["type"] != "DUT":
+ raise RuntimeError("Node type is not a DUT!")
- program_name = program[u"name"]
+ program_name = program["name"]
DUTSetup.kill_program(node, program_name, namespace)
- if namespace == u"default":
- shell_cmd = u"sh -c"
+ if namespace == "default":
+ shell_cmd = "sh -c"
else:
shell_cmd = f"ip netns exec {namespace} sh -c"
- env_vars = f"{program[u'env_vars']} " if u"env_vars" in program else u""
- args = program[u"args"]
- program_path = program.get(u"path", u"")
+ env_vars = f"{program['env_vars']} " if "env_vars" in program else ""
+ args = program["args"]
+ program_path = program.get("path", "")
# NGINX used `worker_cpu_affinity` in configuration file
- taskset_cmd = u"" if program_name == u"nginx" else \
- f"taskset --cpu-list {core_list}"
- cmd = f"nohup {taskset_cmd} {shell_cmd} \'{env_vars} " \
- f"{program_path}{program_name} {args} >/tmp/{program_name}_" \
- f"stdout.log 2>/tmp/{program_name}_stderr.log &\'"
+ taskset_cmd = (
+ "" if program_name == "nginx" else f"taskset --cpu-list {core_list}"
+ )
+ cmd = (
+ f"nohup {taskset_cmd} {shell_cmd} '{env_vars} "
+ f"{program_path}{program_name} {args} >/tmp/{program_name}_"
+ f"stdout.log 2>/tmp/{program_name}_stderr.log &'"
+ )
try:
exec_cmd_no_error(node, cmd, sudo=True)
return DUTSetup.get_pid(node, program_name)[0]
except RuntimeError:
- stdout_log, stderr_log = \
- HoststackUtil.get_hoststack_test_program_logs(node,
- program)
- raise RuntimeError(f"Start {program_name} failed!\nSTDERR:\n" \
- f"{stderr_log}\nSTDOUT:\n{stdout_log}")
+ stdout_log, stderr_log = (
+ HoststackUtil.get_hoststack_test_program_logs(node, program)
+ )
+ raise RuntimeError(
+ f"Start {program_name} failed!\nSTDERR:\n"
+ f"{stderr_log}\nSTDOUT:\n{stdout_log}"
+ )
return None
@staticmethod
:type program: dict
:type pid: int
"""
- program_name = program[u"name"]
- if program_name == u"nginx":
- cmd = u"nginx -s quit"
- errmsg = u"Quit nginx failed!"
+ program_name = program["name"]
+ if program_name == "nginx":
+ cmd = "nginx -s quit"
+ errmsg = "Quit nginx failed!"
else:
- cmd = f'if [ -n "$(ps {pid} | grep {program_name})" ] ; ' \
- f'then kill -s SIGTERM {pid}; fi'
+ cmd = (
+ f'if [ -n "$(ps {pid} | grep {program_name})" ] ; '
+ f"then kill -s SIGTERM {pid}; fi"
+ )
errmsg = f"Kill {program_name} ({pid}) failed!"
exec_cmd_no_error(node, cmd, message=errmsg, sudo=True)
sleep(sleep_time + 1)
@staticmethod
- def hoststack_test_program_finished(node, program_pid, program,
- other_node, other_program):
+ def hoststack_test_program_finished(
+ node, program_pid, program, other_node, other_program
+ ):
"""Wait for the specified HostStack test program process to complete.
:param node: DUT node.
:type other_program: dict
:raises RuntimeError: If node subtype is not a DUT.
"""
- if node[u"type"] != u"DUT":
- raise RuntimeError(u"Node type is not a DUT!")
- if other_node[u"type"] != u"DUT":
- raise RuntimeError(u"Other node type is not a DUT!")
+ if node["type"] != "DUT":
+ raise RuntimeError("Node type is not a DUT!")
+ if other_node["type"] != "DUT":
+ raise RuntimeError("Other node type is not a DUT!")
cmd = f"sh -c 'strace -qqe trace=none -p {program_pid}'"
try:
exec_cmd(node, cmd, sudo=True)
except:
sleep(180)
- if u"client" in program[u"args"]:
- role = u"client"
+ if "client" in program["args"]:
+ role = "client"
else:
- role = u"server"
- program_stdout, program_stderr = \
+ role = "server"
+ program_stdout, program_stderr = (
HoststackUtil.get_hoststack_test_program_logs(node, program)
+ )
if len(program_stdout) > 0:
- logger.debug(f"{program[u'name']} {role} stdout log:\n"
- f"{program_stdout}")
+ logger.debug(
+ f"{program['name']} {role} stdout log:\n"
+ f"{program_stdout}"
+ )
else:
- logger.debug(f"Empty {program[u'name']} {role} stdout log :(")
+ logger.debug(f"Empty {program['name']} {role} stdout log :(")
if len(program_stderr) > 0:
- logger.debug(f"{program[u'name']} stderr log:\n"
- f"{program_stderr}")
+ logger.debug(
+ f"{program['name']} stderr log:\n" f"{program_stderr}"
+ )
else:
- logger.debug(f"Empty {program[u'name']} stderr log :(")
- if u"client" in other_program[u"args"]:
- role = u"client"
+ logger.debug(f"Empty {program['name']} stderr log :(")
+ if "client" in other_program["args"]:
+ role = "client"
else:
- role = u"server"
- program_stdout, program_stderr = \
- HoststackUtil.get_hoststack_test_program_logs(other_node,
- other_program)
+ role = "server"
+ program_stdout, program_stderr = (
+ HoststackUtil.get_hoststack_test_program_logs(
+ other_node, other_program
+ )
+ )
if len(program_stdout) > 0:
- logger.debug(f"{other_program[u'name']} {role} stdout log:\n"
- f"{program_stdout}")
+ logger.debug(
+ f"{other_program['name']} {role} stdout log:\n"
+ f"{program_stdout}"
+ )
else:
- logger.debug(f"Empty {other_program[u'name']} "
- f"{role} stdout log :(")
+ logger.debug(
+ f"Empty {other_program['name']} " f"{role} stdout log :("
+ )
if len(program_stderr) > 0:
- logger.debug(f"{other_program[u'name']} {role} stderr log:\n"
- f"{program_stderr}")
+ logger.debug(
+ f"{other_program['name']} {role} stderr log:\n"
+ f"{program_stderr}"
+ )
else:
- logger.debug(f"Empty {other_program[u'name']} "
- f"{role} stderr log :(")
+ logger.debug(
+ f"Empty {other_program['name']} " f"{role} stderr log :("
+ )
raise
# Wait a bit for stdout/stderr to be flushed to log files
sleep(1)
@staticmethod
- def analyze_hoststack_test_program_output(
- node, role, nsim_attr, program):
+ def analyze_hoststack_test_program_output(node, role, nsim_attr, program):
"""Gather HostStack test program output and check for errors.
The [defer_fail] return bool is used instead of failing immediately
:rtype: bool, str
:raises RuntimeError: If node subtype is not a DUT.
"""
- if node[u"type"] != u"DUT":
- raise RuntimeError(u"Node type is not a DUT!")
+ if node["type"] != "DUT":
+ raise RuntimeError("Node type is not a DUT!")
- program_name = program[u"name"]
- program_stdout, program_stderr = \
+ program_name = program["name"]
+ program_stdout, program_stderr = (
HoststackUtil.get_hoststack_test_program_logs(node, program)
+ )
- env_vars = f"{program[u'env_vars']} " if u"env_vars" in program else u""
- program_cmd = f"{env_vars}{program_name} {program[u'args']}"
+ env_vars = f"{program['env_vars']} " if "env_vars" in program else ""
+ program_cmd = f"{env_vars}{program_name} {program['args']}"
test_results = f"Test Results of '{program_cmd}':\n"
- if nsim_attr[u"output_nsim_enable"] or \
- nsim_attr[u"xc_nsim_enable"]:
- if nsim_attr[u"output_nsim_enable"]:
- feature_name = u"output"
+ if nsim_attr["output_nsim_enable"] or nsim_attr["xc_nsim_enable"]:
+ if nsim_attr["output_nsim_enable"]:
+ feature_name = "output"
else:
- feature_name = u"cross-connect"
- test_results += \
- f"NSIM({feature_name}): delay " \
- f"{nsim_attr[u'delay_in_usec']} usecs, " \
- f"avg-pkt-size {nsim_attr[u'average_packet_size']}, " \
- f"bandwidth {nsim_attr[u'bw_in_bits_per_second']} " \
- f"bits/sec, pkt-drop-rate {nsim_attr[u'packets_per_drop']} " \
+ feature_name = "cross-connect"
+ test_results += (
+ f"NSIM({feature_name}): delay "
+ f"{nsim_attr['delay_in_usec']} usecs, "
+ f"avg-pkt-size {nsim_attr['average_packet_size']}, "
+ f"bandwidth {nsim_attr['bw_in_bits_per_second']} "
+ f"bits/sec, pkt-drop-rate {nsim_attr['packets_per_drop']} "
f"pkts/drop\n"
+ )
- if u"error" in program_stderr.lower():
+ if "error" in program_stderr.lower():
test_results += f"ERROR DETECTED:\n{program_stderr}"
return (True, test_results)
if not program_stdout:
test_results += f"\nNo {program} test data retrieved!\n"
- ls_stdout, _ = exec_cmd_no_error(node, u"ls -l /tmp/*.log",
- sudo=True)
+ ls_stdout, _ = exec_cmd_no_error(
+ node, "ls -l /tmp/*.log", sudo=True
+ )
test_results += f"{ls_stdout}\n"
return (True, test_results)
- if program[u"name"] == u"vpp_echo":
- if u"JSON stats" in program_stdout and \
- u'"has_failed": "0"' in program_stdout:
- json_start = program_stdout.find(u"{")
- json_end = program_stdout.find(u',\n "closing"')
+ if program["name"] == "vpp_echo":
+ if (
+ "JSON stats" in program_stdout
+ and '"has_failed": "0"' in program_stdout
+ ):
+ json_start = program_stdout.find("{")
+ json_end = program_stdout.find(',\n "closing"')
json_results = f"{program_stdout[json_start:json_end]}\n}}"
program_json = json.loads(json_results)
export_hoststack_results(
bandwidth=program_json["rx_bits_per_second"],
- duration=float(program_json["time"])
+ duration=float(program_json["time"]),
)
else:
- test_results += u"Invalid test data output!\n" + program_stdout
+ test_results += "Invalid test data output!\n" + program_stdout
return (True, test_results)
- elif program[u"name"] == u"iperf3":
+ elif program["name"] == "iperf3":
test_results += program_stdout
- program_json = json.loads(program_stdout)[u"intervals"][0][u"sum"]
+ program_json = json.loads(program_stdout)["intervals"][0]["sum"]
try:
retransmits = program_json["retransmits"]
except KeyError:
export_hoststack_results(
bandwidth=program_json["bits_per_second"],
duration=program_json["seconds"],
- retransmits=retransmits
+ retransmits=retransmits,
)
else:
- test_results += u"Unknown HostStack Test Program!\n" + \
- program_stdout
+ test_results += "Unknown HostStack Test Program!\n" + program_stdout
return (True, program_stdout)
return (False, json.dumps(program_json))