aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick')
-rw-r--r--yardstick/benchmark/contexts/kubernetes.py7
-rw-r--r--yardstick/benchmark/scenarios/networking/vnf_generic.py20
-rw-r--r--yardstick/common/exceptions.py13
-rw-r--r--yardstick/common/kubernetes_utils.py6
-rw-r--r--yardstick/common/utils.py39
-rw-r--r--yardstick/network_services/helpers/samplevnf_helper.py121
-rw-r--r--yardstick/network_services/traffic_profile/base.py26
-rw-r--r--yardstick/network_services/traffic_profile/ixia_rfc2544.py1
-rw-r--r--yardstick/network_services/traffic_profile/rfc2544.py398
-rw-r--r--yardstick/network_services/traffic_profile/trex_traffic_profile.py122
-rw-r--r--yardstick/network_services/vnf_generic/vnf/acl_vnf.py207
-rw-r--r--yardstick/network_services/vnf_generic/vnf/sample_vnf.py51
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py18
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py87
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_trex.py26
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vfw_vnf.py18
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py1
-rw-r--r--yardstick/network_services/yang_model.py108
-rw-r--r--yardstick/orchestrator/kubernetes.py112
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/test_model.py4
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_kubernetes.py26
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_duration.py39
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py3
-rw-r--r--yardstick/tests/unit/common/test_utils.py11
-rw-r--r--yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py62
-rw-r--r--yardstick/tests/unit/network_services/test_yang_model.py129
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_base.py17
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_fixed.py3
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_http.py29
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py463
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py154
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py147
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py194
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py225
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py13
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py121
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py196
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py4
-rw-r--r--yardstick/tests/unit/orchestrator/test_kubernetes.py112
-rw-r--r--yardstick/tests/unit/test_cmd/commands/test_env.py70
40 files changed, 1656 insertions, 1747 deletions
diff --git a/yardstick/benchmark/contexts/kubernetes.py b/yardstick/benchmark/contexts/kubernetes.py
index 82435d40c..d322954b2 100644
--- a/yardstick/benchmark/contexts/kubernetes.py
+++ b/yardstick/benchmark/contexts/kubernetes.py
@@ -15,7 +15,7 @@ import pkg_resources
import paramiko
from yardstick.benchmark.contexts.base import Context
-from yardstick.orchestrator.kubernetes import KubernetesTemplate
+from yardstick.orchestrator import kubernetes
from yardstick.common import kubernetes_utils as k8s_utils
from yardstick.common import utils
@@ -38,11 +38,8 @@ class KubernetesContext(Context):
def init(self, attrs):
super(KubernetesContext, self).init(attrs)
- template_cfg = attrs.get('servers', {})
- self.template = KubernetesTemplate(self.name, template_cfg)
-
+ self.template = kubernetes.KubernetesTemplate(self.name, attrs)
self.ssh_key = '{}-key'.format(self.name)
-
self.key_path = self._get_key_path()
self.public_key_path = '{}.pub'.format(self.key_path)
diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py
index 1c3ea1f8d..4d7c4f9be 100644
--- a/yardstick/benchmark/scenarios/networking/vnf_generic.py
+++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py
@@ -133,11 +133,10 @@ class NetworkServiceTestCase(scenario_base.Scenario):
with utils.open_relative_file(profile, path) as infile:
return infile.read()
- def _get_topology(self):
- topology = self.scenario_cfg["topology"]
- path = self.scenario_cfg["task_path"]
- with utils.open_relative_file(topology, path) as infile:
- return infile.read()
+ def _get_duration(self):
+ options = self.scenario_cfg.get('options', {})
+ return options.get('duration',
+ tprofile_base.TrafficProfileConfig.DEFAULT_DURATION)
def _fill_traffic_profile(self):
tprofile = self._get_traffic_profile()
@@ -147,12 +146,17 @@ class NetworkServiceTestCase(scenario_base.Scenario):
'imix': self._get_traffic_imix(),
tprofile_base.TrafficProfile.UPLINK: {},
tprofile_base.TrafficProfile.DOWNLINK: {},
- 'extra_args': extra_args
- }
-
+ 'extra_args': extra_args,
+ 'duration': self._get_duration()}
traffic_vnfd = vnfdgen.generate_vnfd(tprofile, tprofile_data)
self.traffic_profile = tprofile_base.TrafficProfile.get(traffic_vnfd)
+ def _get_topology(self):
+ topology = self.scenario_cfg["topology"]
+ path = self.scenario_cfg["task_path"]
+ with utils.open_relative_file(topology, path) as infile:
+ return infile.read()
+
def _render_topology(self):
topology = self._get_topology()
topology_args = self.scenario_cfg.get('extra_args', {})
diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py
index 954d655cb..650c09edb 100644
--- a/yardstick/common/exceptions.py
+++ b/yardstick/common/exceptions.py
@@ -195,6 +195,10 @@ class WaitTimeout(YardstickException):
message = 'Wait timeout while waiting for condition'
+class KubernetesTemplateInvalidVolumeType(YardstickException):
+ message = 'No valid "volume" types present in %(volume)s'
+
+
class ScenarioCreateNetworkError(YardstickException):
message = 'Create Neutron Network Scenario failed'
@@ -313,3 +317,12 @@ class IxNetworkFieldNotPresentInStackItem(YardstickException):
class SLAValidationError(YardstickException):
message = '%(case_name)s SLA validation failed. Error: %(error_msg)s'
+
+
+class AclMissingActionArguments(YardstickException):
+ message = ('Missing ACL action parameter '
+ '[action=%(action_name)s parameter=%(action_param)s]')
+
+
+class AclUknownActionTemplate(YardstickException):
+ message = 'No ACL CLI template found for "%(action_name)s" action'
diff --git a/yardstick/common/kubernetes_utils.py b/yardstick/common/kubernetes_utils.py
index d60c9b23a..ee8e8edcd 100644
--- a/yardstick/common/kubernetes_utils.py
+++ b/yardstick/common/kubernetes_utils.py
@@ -199,3 +199,9 @@ def get_pod_list(namespace='default'): # pragma: no cover
def get_pod_by_name(name): # pragma: no cover
pod_list = get_pod_list()
return next((n for n in pod_list.items if n.metadata.name.startswith(name)), None)
+
+
+def get_volume_types():
+ """Return the "volume" types supported by the current API"""
+ return [vtype for vtype in client.V1Volume.attribute_map.values()
+ if vtype != 'name']
diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py
index 108ee17bc..f9fe0e336 100644
--- a/yardstick/common/utils.py
+++ b/yardstick/common/utils.py
@@ -306,6 +306,19 @@ def get_ip_version(ip_addr):
return address.version
+def make_ip_addr(ip, mask):
+ """
+ :param ip[str]: ip adddress
+ :param mask[str]: /24 prefix of 255.255.255.0 netmask
+ :return: IPv4Interface object
+ """
+ try:
+ return ipaddress.ip_interface(six.text_type('/'.join([ip, mask])))
+ except (TypeError, ValueError):
+ # None so we can skip later
+ return None
+
+
def ip_to_hex(ip_addr, separator=''):
try:
address = ipaddress.ip_address(six.text_type(ip_addr))
@@ -409,13 +422,18 @@ class ErrorClass(object):
class Timer(object):
- def __init__(self, timeout=None):
+ def __init__(self, timeout=None, raise_exception=True):
super(Timer, self).__init__()
self.start = self.delta = None
self._timeout = int(timeout) if timeout else None
+ self._timeout_flag = False
+ self._raise_exception = raise_exception
def _timeout_handler(self, *args):
- raise exceptions.TimerTimeout(timeout=self._timeout)
+ self._timeout_flag = True
+ if self._raise_exception:
+ raise exceptions.TimerTimeout(timeout=self._timeout)
+ self.__exit__()
def __enter__(self):
self.start = datetime.datetime.now()
@@ -432,6 +450,23 @@ class Timer(object):
def __getattr__(self, item):
return getattr(self.delta, item)
+ def __iter__(self):
+ self._raise_exception = False
+ return self.__enter__()
+
+ def next(self): # pragma: no cover
+ # NOTE(ralonsoh): Python 2 support.
+ if not self._timeout_flag:
+ return datetime.datetime.now()
+ raise StopIteration()
+
+ def __next__(self): # pragma: no cover
+ # NOTE(ralonsoh): Python 3 support.
+ return self.next()
+
+ def __del__(self): # pragma: no cover
+ signal.alarm(0)
+
def read_meminfo(ssh_client):
"""Read "/proc/meminfo" file and parse all keys and values"""
diff --git a/yardstick/network_services/helpers/samplevnf_helper.py b/yardstick/network_services/helpers/samplevnf_helper.py
index 0ab10d7b7..8e6a3a3ea 100644
--- a/yardstick/network_services/helpers/samplevnf_helper.py
+++ b/yardstick/network_services/helpers/samplevnf_helper.py
@@ -23,8 +23,7 @@ from itertools import chain, repeat
import six
from six.moves.configparser import ConfigParser
-
-from yardstick.common.utils import ip_to_hex
+from yardstick.common import utils
LOG = logging.getLogger(__name__)
@@ -34,19 +33,6 @@ link {0} config {1} {2}
link {0} up
"""
-ACTION_TEMPLATE = """\
-p action add {0} accept
-p action add {0} fwd {0}
-p action add {0} count
-"""
-
-FW_ACTION_TEMPLATE = """\
-p action add {0} accept
-p action add {0} fwd {0}
-p action add {0} count
-p action add {0} conntrack
-"""
-
# This sets up a basic passthrough with no rules
SCRIPT_TPL = """
{link_config}
@@ -59,9 +45,7 @@ SCRIPT_TPL = """
{arp_route_tbl6}
-{actions}
-
-{rules}
+{flows}
"""
@@ -182,26 +166,9 @@ class MultiPortConfig(object):
return parser.get(section, key)
return default
- @staticmethod
- def make_ip_addr(ip, mask):
- """
- :param ip: ip adddress
- :type ip: str
- :param mask: /24 prefix of 255.255.255.0 netmask
- :type mask: str
- :return: interface
- :rtype: IPv4Interface
- """
-
- try:
- return ipaddress.ip_interface(six.text_type('/'.join([ip, mask])))
- except (TypeError, ValueError):
- # None so we can skip later
- return None
-
@classmethod
def validate_ip_and_prefixlen(cls, ip_addr, prefixlen):
- ip_addr = cls.make_ip_addr(ip_addr, prefixlen)
+ ip_addr = utils.make_ip_addr(ip_addr, prefixlen)
return ip_addr.ip.exploded, ip_addr.network.prefixlen
def __init__(self, topology_file, config_tpl, tmp_file, vnfd_helper,
@@ -245,7 +212,7 @@ class MultiPortConfig(object):
self.ports_len = 0
self.prv_que_handler = None
self.vnfd = None
- self.rules = None
+ self.flows = None
self.pktq_out = []
@staticmethod
@@ -360,7 +327,7 @@ class MultiPortConfig(object):
"%s/%s" % (interface["dst_ip"], interface["netmask"])))
arp_vars = {
- "port_netmask_hex": ip_to_hex(dst_port_ip.network.netmask.exploded),
+ "port_netmask_hex": utils.ip_to_hex(dst_port_ip.network.netmask.exploded),
# this is the port num that contains port0 subnet and next_hop_ip_hex
# this is LINKID which should be based on DPDK port number
"port_num": dpdk_port_num,
@@ -542,7 +509,7 @@ class MultiPortConfig(object):
self.update_write_parser(self.loadb_tpl)
self.start_core += 1
- for i in range(self.worker_threads):
+ for _ in range(self.worker_threads):
vnf_data = self.generate_vnf_data()
if not self.vnf_tpl:
self.vnf_tpl = {}
@@ -637,65 +604,8 @@ class MultiPortConfig(object):
return '\n'.join(('p {3} arpadd {0} {1} {2}'.format(*values) for values in arp_config6))
- def generate_action_config(self):
- port_list = (self.vnfd_helper.port_num(p) for p in self.all_ports)
- if self.vnf_type == "VFW":
- template = FW_ACTION_TEMPLATE
- else:
- template = ACTION_TEMPLATE
-
- return ''.join((template.format(port) for port in port_list))
-
- def get_ip_from_port(self, port):
- # we can't use gateway because in OpenStack gateways interfer with floating ip routing
- # return self.make_ip_addr(self.get_ports_gateway(port), self.get_netmask_gateway(port))
- vintf = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
- ip = vintf["local_ip"]
- netmask = vintf["netmask"]
- return self.make_ip_addr(ip, netmask)
-
- def get_network_and_prefixlen_from_ip_of_port(self, port):
- ip_addr = self.get_ip_from_port(port)
- # handle cases with no gateway
- if ip_addr:
- return ip_addr.network.network_address.exploded, ip_addr.network.prefixlen
- else:
- return None, None
-
- def generate_rule_config(self):
- cmd = 'acl' if self.vnf_type == "ACL" else "vfw"
- rules_config = self.rules if self.rules else ''
- new_rules = []
- new_ipv6_rules = []
- pattern = 'p {0} add {1} {2} {3} {4} {5} 0 65535 0 65535 0 0 {6}'
- for src_intf, dst_intf in self.port_pair_list:
- src_port = self.vnfd_helper.port_num(src_intf)
- dst_port = self.vnfd_helper.port_num(dst_intf)
-
- src_net, src_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(src_intf)
- dst_net, dst_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(dst_intf)
- # ignore entires with empty values
- if all((src_net, src_prefix_len, dst_net, dst_prefix_len)):
- new_rules.append((cmd, self.txrx_pipeline, src_net, src_prefix_len,
- dst_net, dst_prefix_len, dst_port))
- new_rules.append((cmd, self.txrx_pipeline, dst_net, dst_prefix_len,
- src_net, src_prefix_len, src_port))
-
- # src_net = self.get_ports_gateway6(port_pair[0])
- # src_prefix_len = self.get_netmask_gateway6(port_pair[0])
- # dst_net = self.get_ports_gateway6(port_pair[1])
- # dst_prefix_len = self.get_netmask_gateway6(port_pair[0])
- # # ignore entires with empty values
- # if all((src_net, src_prefix_len, dst_net, dst_prefix_len)):
- # new_ipv6_rules.append((cmd, self.txrx_pipeline, src_net, src_prefix_len,
- # dst_net, dst_prefix_len, dst_port))
- # new_ipv6_rules.append((cmd, self.txrx_pipeline, dst_net, dst_prefix_len,
- # src_net, src_prefix_len, src_port))
-
- acl_apply = "\np %s applyruleset" % cmd
- new_rules_config = '\n'.join(pattern.format(*values) for values
- in chain(new_rules, new_ipv6_rules))
- return ''.join([rules_config, new_rules_config, acl_apply])
+ def get_flows_config(self):
+ return self.flows if self.flows else ''
def generate_script_data(self):
self._port_pairs = PortPairs(self.vnfd_helper.interfaces)
@@ -707,24 +617,15 @@ class MultiPortConfig(object):
# disable IPv6 for now
# 'arp_config6': self.generate_arp_config6(),
'arp_config6': "",
- 'arp_config': self.generate_arp_config(),
'arp_route_tbl': self.generate_arp_route_tbl(),
'arp_route_tbl6': "",
- 'actions': '',
- 'rules': '',
+ 'flows': self.get_flows_config()
}
-
- if self.vnf_type in ('ACL', 'VFW'):
- script_data.update({
- 'actions': self.generate_action_config(),
- 'rules': self.generate_rule_config(),
- })
-
return script_data
- def generate_script(self, vnfd, rules=None):
+ def generate_script(self, vnfd, flows=None):
self.vnfd = vnfd
- self.rules = rules
+ self.flows = flows
script_data = self.generate_script_data()
script = SCRIPT_TPL.format(**script_data)
if self.lb_config == self.HW_LB:
diff --git a/yardstick/network_services/traffic_profile/base.py b/yardstick/network_services/traffic_profile/base.py
index 9eba550aa..f4b5b178c 100644
--- a/yardstick/network_services/traffic_profile/base.py
+++ b/yardstick/network_services/traffic_profile/base.py
@@ -16,6 +16,31 @@ from yardstick.common import exceptions
from yardstick.common import utils
+class TrafficProfileConfig(object):
+ """Class to contain the TrafficProfile class information
+
+ This object will parse and validate the traffic profile information.
+ """
+
+ DEFAULT_SCHEMA = 'nsb:traffic_profile:0.1'
+ DEFAULT_FRAME_RATE = 100
+ DEFAULT_DURATION = 30
+
+ def __init__(self, tp_config):
+ self.schema = tp_config.get('schema', self.DEFAULT_SCHEMA)
+ self.name = tp_config.get('name')
+ self.description = tp_config.get('description')
+ tprofile = tp_config['traffic_profile']
+ self.traffic_type = tprofile.get('traffic_type')
+ self.frame_rate = tprofile.get('frame_rate', self.DEFAULT_FRAME_RATE)
+ self.test_precision = tprofile.get('test_precision')
+ self.packet_sizes = tprofile.get('packet_sizes')
+ self.duration = tprofile.get('duration', self.DEFAULT_DURATION)
+ self.lower_bound = tprofile.get('lower_bound')
+ self.upper_bound = tprofile.get('upper_bound')
+ self.step_interval = tprofile.get('step_interval')
+
+
class TrafficProfile(object):
"""
This class defines the behavior
@@ -43,6 +68,7 @@ class TrafficProfile(object):
# e.g. RFC2544 start_ip, stop_ip, drop_rate,
# IMIX = {"10K": 0.1, "100M": 0.5}
self.params = tp_config
+ self.config = TrafficProfileConfig(tp_config)
def execute_traffic(self, traffic_generator, **kawrgs):
""" This methods defines the behavior of the traffic generator.
diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
index 73806f958..e105c2f55 100644
--- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py
+++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
@@ -95,7 +95,6 @@ class IXIARFC2544Profile(TrexProfile):
if not profile_data:
continue
self.profile_data = profile_data
- self.get_streams(self.profile_data)
self.full_profile.update({vld_id: self.profile_data})
for intf in intfs:
yield traffic_generator.vnfd_helper.port_num(intf)
diff --git a/yardstick/network_services/traffic_profile/rfc2544.py b/yardstick/network_services/traffic_profile/rfc2544.py
index 83020c85c..c24e2f65a 100644
--- a/yardstick/network_services/traffic_profile/rfc2544.py
+++ b/yardstick/network_services/traffic_profile/rfc2544.py
@@ -11,190 +11,288 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-""" RFC2544 Throughput implemenation """
-from __future__ import absolute_import
-from __future__ import division
import logging
-from trex_stl_lib.trex_stl_client import STLStream
-from trex_stl_lib.trex_stl_streams import STLFlowLatencyStats
-from trex_stl_lib.trex_stl_streams import STLTXCont
+from trex_stl_lib import api as Pkt
+from trex_stl_lib import trex_stl_client
+from trex_stl_lib import trex_stl_packet_builder_scapy
+from trex_stl_lib import trex_stl_streams
+
+from yardstick.network_services.traffic_profile import trex_traffic_profile
-from yardstick.network_services.traffic_profile.trex_traffic_profile \
- import TrexProfile
LOGGING = logging.getLogger(__name__)
+SRC_PORT = 'sport'
+DST_PORT = 'dport'
+
+
+class PortPgIDMap(object):
+ """Port and pg_id mapping class
+
+ "pg_id" is the identification STL library gives to each stream. In the
+ RFC2544Profile class, the traffic has a STLProfile per port, which contains
+ one or several streams, one per packet size defined in the IMIX test case
+ description.
+
+ Example of port <-> pg_id map:
+ self._port_pg_id_map = {
+ 0: [1, 2, 3, 4],
+ 1: [5, 6, 7, 8]
+ }
+ """
+
+ def __init__(self):
+ self._pg_id = 0
+ self._last_port = None
+ self._port_pg_id_map = {}
+
+ def add_port(self, port):
+ self._last_port = port
+ self._port_pg_id_map[port] = []
+
+ def get_pg_ids(self, port):
+ return self._port_pg_id_map.get(port)
+
+ def increase_pg_id(self, port=None):
+ port = self._last_port if not port else port
+ if port is None:
+ return
+ pg_id_list = self._port_pg_id_map.get(port)
+ if not pg_id_list:
+ self.add_port(port)
+ pg_id_list = self._port_pg_id_map[port]
+ self._pg_id += 1
+ pg_id_list.append(self._pg_id)
+ return self._pg_id
-class RFC2544Profile(TrexProfile):
- """ This class handles rfc2544 implemenation. """
+class RFC2544Profile(trex_traffic_profile.TrexProfile):
+ """TRex RFC2544 traffic profile"""
+
+ TOLERANCE_LIMIT = 0.05
def __init__(self, traffic_generator):
super(RFC2544Profile, self).__init__(traffic_generator)
self.generator = None
- self.max_rate = None
- self.min_rate = None
- self.ports = None
- self.rate = 100
- self.drop_percent_at_max_tx = None
- self.throughput_max = None
+ self.rate = self.config.frame_rate
+ self.max_rate = self.config.frame_rate
+ self.min_rate = 0
+ self.drop_percent_max = 0
def register_generator(self, generator):
self.generator = generator
- def execute_traffic(self, traffic_generator=None):
- """ Generate the stream and run traffic on the given ports """
+ def stop_traffic(self, traffic_generator=None):
+ """"Stop traffic injection, reset counters and remove streams"""
if traffic_generator is not None and self.generator is None:
self.generator = traffic_generator
- if self.ports is not None:
- return
+ self.generator.client.stop()
+ self.generator.client.reset()
+ self.generator.client.remove_all_streams()
+
+ def execute_traffic(self, traffic_generator=None):
+ """Generate the stream and run traffic on the given ports
+
+ :param traffic_generator: (TrexTrafficGenRFC) traffic generator
+ :return ports: (list of int) indexes of ports
+ port_pg_id: (dict) port indexes and pg_id [1] map
+ [1] https://trex-tgn.cisco.com/trex/doc/cp_stl_docs/api/
+ profile_code.html#stlstream-modes
+ """
+ if traffic_generator is not None and self.generator is None:
+ self.generator = traffic_generator
- self.ports = []
+ port_pg_id = PortPgIDMap()
+ ports = []
for vld_id, intfs in sorted(self.generator.networks.items()):
profile_data = self.params.get(vld_id)
- # no profile for this port
if not profile_data:
continue
- # correlated traffic doesn't use public traffic?
- if vld_id.startswith(self.DOWNLINK) and \
- self.generator.rfc2544_helper.correlated_traffic:
+ if (vld_id.startswith(self.DOWNLINK) and
+ self.generator.rfc2544_helper.correlated_traffic):
continue
for intf in intfs:
- port = self.generator.port_num(intf)
- self.ports.append(port)
- self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
-
- self.max_rate = self.rate
- self.min_rate = 0
- self.generator.client.start(ports=self.ports, mult=self.get_multiplier(),
- duration=30, force=True)
- self.drop_percent_at_max_tx = 0
- self.throughput_max = 0
-
- def get_multiplier(self):
- """ Get the rate at which next iteration to run """
- self.rate = round((self.max_rate + self.min_rate) / 2.0, 2)
- multiplier = round(self.rate / self.pps, 2)
- return str(multiplier)
-
- def get_drop_percentage(self, generator=None):
- """ Calculate the drop percentage and run the traffic """
- if generator is None:
- generator = self.generator
- run_duration = self.generator.RUN_DURATION
- samples = self.generator.generate_samples(self.ports)
-
- in_packets = sum([value['in_packets'] for value in samples.values()])
- out_packets = sum([value['out_packets'] for value in samples.values()])
-
- packet_drop = abs(out_packets - in_packets)
- drop_percent = 100.0
- try:
- drop_percent = round((packet_drop / float(out_packets)) * 100, 5)
- except ZeroDivisionError:
- LOGGING.info('No traffic is flowing')
+ port_num = int(self.generator.port_num(intf))
+ ports.append(port_num)
+ port_pg_id.add_port(port_num)
+ profile = self._create_profile(profile_data,
+ self.rate, port_pg_id)
+ self.generator.client.add_streams(profile, ports=[port_num])
+
+ self.generator.client.start(ports=ports,
+ duration=self.config.duration,
+ force=True)
+ return ports, port_pg_id
+
+ def _create_profile(self, profile_data, rate, port_pg_id):
+ """Create a STL profile (list of streams) for a port"""
+ streams = []
+ for packet_name in profile_data:
+ imix = (profile_data[packet_name].
+ get('outer_l2', {}).get('framesize'))
+ imix_data = self._create_imix_data(imix)
+ self._create_vm(profile_data[packet_name])
+ _streams = self._create_streams(imix_data, rate, port_pg_id)
+ streams.extend(_streams)
+ return trex_stl_streams.STLProfile(streams)
+
+ def _create_imix_data(self, imix):
+ """Generate the IMIX distribution for a STL profile
+
+ The input information is the framesize dictionary in a test case
+ traffic profile definition. E.g.:
+ downlink_0:
+ ipv4:
+ id: 2
+ outer_l2:
+ framesize:
+ 64B: 10
+ 128B: 20
+ ...
+
+ This function normalizes the sum of framesize weights to 100 and
+ returns a dictionary of frame sizes in bytes and weight in percentage.
+ E.g.:
+ imix_count = {64: 25, 128: 75}
+
+ :param imix: (dict) IMIX size and weight
+ """
+ imix_count = {}
+ if not imix:
+ return imix_count
+
+ imix_count = {size.upper().replace('B', ''): int(weight)
+ for size, weight in imix.items()}
+ imix_sum = sum(imix_count.values())
+ if imix_sum <= 0:
+ imix_count = {64: 100}
+ imix_sum = 100
+
+ weight_normalize = float(imix_sum) / 100
+ return {size: float(weight) / weight_normalize
+ for size, weight in imix_count.items()}
+
+ def _create_vm(self, packet_definition):
+ """Create the STL Raw instructions"""
+ self.ether_packet = Pkt.Ether()
+ self.ip_packet = Pkt.IP()
+ self.ip6_packet = None
+ self.udp_packet = Pkt.UDP()
+ self.udp[DST_PORT] = 'UDP.dport'
+ self.udp[SRC_PORT] = 'UDP.sport'
+ self.qinq = False
+ self.vm_flow_vars = []
+ outer_l2 = packet_definition.get('outer_l2')
+ outer_l3v4 = packet_definition.get('outer_l3v4')
+ outer_l3v6 = packet_definition.get('outer_l3v6')
+ outer_l4 = packet_definition.get('outer_l4')
+ if outer_l2:
+ self._set_outer_l2_fields(outer_l2)
+ if outer_l3v4:
+ self._set_outer_l3v4_fields(outer_l3v4)
+ if outer_l3v6:
+ self._set_outer_l3v6_fields(outer_l3v6)
+ if outer_l4:
+ self._set_outer_l4_fields(outer_l4)
+ self.trex_vm = trex_stl_packet_builder_scapy.STLScVmRaw(
+ self.vm_flow_vars)
+
+ def _create_single_packet(self, size=64):
+ size -= 4
+ ether_packet = self.ether_packet
+ ip_packet = self.ip6_packet if self.ip6_packet else self.ip_packet
+ udp_packet = self.udp_packet
+ if self.qinq:
+ qinq_packet = self.qinq_packet
+ base_pkt = ether_packet / qinq_packet / ip_packet / udp_packet
+ else:
+ base_pkt = ether_packet / ip_packet / udp_packet
+ pad = max(0, size - len(base_pkt)) * 'x'
+ return trex_stl_packet_builder_scapy.STLPktBuilder(
+ pkt=base_pkt / pad, vm=self.trex_vm)
+
+ def _create_streams(self, imix_data, rate, port_pg_id):
+ """Create a list of streams per packet size
+
+ The STL TX mode speed of the generated streams will depend on the frame
+ weight and the frame rate. Both the frame weight and the total frame
+ rate are normalized to 100. The STL TX mode speed, defined in
+ percentage, is the combitation of both percentages. E.g.:
+ frame weight = 100
+ rate = 90
+ --> STLTXmode percentage = 10 (%)
+
+ frame weight = 80
+ rate = 50
+ --> STLTXmode percentage = 40 (%)
+
+ :param imix_data: (dict) IMIX size and weight
+ :param rate: (float) normalized [0..100] total weight
+ :param pg_id: (PortPgIDMap) port / pg_id (list) map
+ """
+ streams = []
+ for size, weight in ((int(size), float(weight)) for (size, weight)
+ in imix_data.items() if float(weight) > 0):
+ packet = self._create_single_packet(size)
+ pg_id = port_pg_id.increase_pg_id()
+ stl_flow = trex_stl_streams.STLFlowLatencyStats(pg_id=pg_id)
+ mode = trex_stl_streams.STLTXCont(percentage=weight * rate / 100)
+ streams.append(trex_stl_client.STLStream(
+ packet=packet, flow_stats=stl_flow, mode=mode))
+ return streams
+
+ def get_drop_percentage(self, samples, tol_low, tol_high,
+ correlated_traffic):
+ """Calculate the drop percentage and run the traffic"""
+ tx_rate_fps = 0
+ rx_rate_fps = 0
+ for sample in samples:
+ tx_rate_fps += sum(
+ port['tx_throughput_fps'] for port in sample.values())
+ rx_rate_fps += sum(
+ port['rx_throughput_fps'] for port in sample.values())
+ tx_rate_fps = round(float(tx_rate_fps) / len(samples), 2)
+ rx_rate_fps = round(float(rx_rate_fps) / len(samples), 2)
# TODO(esm): RFC2544 doesn't tolerate packet loss, why do we?
- tolerance_low = generator.rfc2544_helper.tolerance_low
- tolerance_high = generator.rfc2544_helper.tolerance_high
-
- tx_rate = out_packets / run_duration
- rx_rate = in_packets / run_duration
-
- throughput_max = self.throughput_max
- drop_percent_at_max_tx = self.drop_percent_at_max_tx
+ out_packets = sum(port['out_packets'] for port in samples[-1].values())
+ in_packets = sum(port['in_packets'] for port in samples[-1].values())
+ drop_percent = 100.0
- if self.drop_percent_at_max_tx is None:
- self.rate = tx_rate
- self.first_run = False
+ # https://tools.ietf.org/html/rfc2544#section-26.3
+ if out_packets:
+ drop_percent = round(
+ (float(abs(out_packets - in_packets)) / out_packets) * 100, 5)
- if drop_percent > tolerance_high:
- # TODO(esm): why don't we discard results that are out of tolerance?
+ tol_high = tol_high if tol_high > self.TOLERANCE_LIMIT else tol_high
+ tol_low = tol_low if tol_low > self.TOLERANCE_LIMIT else tol_low
+ if drop_percent > tol_high:
self.max_rate = self.rate
- if throughput_max == 0:
- throughput_max = rx_rate
- drop_percent_at_max_tx = drop_percent
-
- elif drop_percent >= tolerance_low:
- # TODO(esm): why do we update the samples dict in this case
- # and not update our tracking values?
- throughput_max = rx_rate
- drop_percent_at_max_tx = drop_percent
-
- elif drop_percent >= self.drop_percent_at_max_tx:
- # TODO(esm): why don't we discard results that are out of tolerance?
+ elif drop_percent < tol_low:
self.min_rate = self.rate
- self.drop_percent_at_max_tx = drop_percent_at_max_tx = drop_percent
- self.throughput_max = throughput_max = rx_rate
+ # else:
+ # NOTE(ralonsoh): the test should finish here
+ # pass
+ last_rate = self.rate
+ self.rate = round(float(self.max_rate + self.min_rate) / 2.0, 5)
- else:
- # TODO(esm): why don't we discard results that are out of tolerance?
- self.min_rate = self.rate
+ throughput = rx_rate_fps * 2 if correlated_traffic else rx_rate_fps
- generator.clear_client_stats(self.ports)
- generator.start_client(self.ports, mult=self.get_multiplier(),
- duration=run_duration, force=True)
+ if drop_percent > self.drop_percent_max:
+ self.drop_percent_max = drop_percent
- # if correlated traffic update the Throughput
- if generator.rfc2544_helper.correlated_traffic:
- throughput_max *= 2
+ latency = {port_num: value['latency']
+ for port_num, value in samples[-1].items()}
- samples.update({
- 'TxThroughput': tx_rate,
- 'RxThroughput': rx_rate,
+ output = {
+ 'TxThroughput': tx_rate_fps,
+ 'RxThroughput': rx_rate_fps,
'CurrentDropPercentage': drop_percent,
- 'Throughput': throughput_max,
- 'DropPercentage': drop_percent_at_max_tx,
- })
-
- return samples
-
- def execute_latency(self, generator=None, samples=None):
- if generator is not None and self.generator is None:
- self.generator = generator
-
- if samples is None:
- samples = self.generator.generate_samples()
-
- self.pps, multiplier = self.calculate_pps(samples)
- self.ports = []
- self.pg_id = self.params['traffic_profile'].get('pg_id', 1)
- for vld_id, intfs in sorted(self.generator.networks.items()):
- profile_data = self.params.get(vld_id)
- if not profile_data:
- continue
- # correlated traffic doesn't use public traffic?
- if vld_id.startswith(self.DOWNLINK) and \
- self.generator.rfc2544_helper.correlated_traffic:
- continue
- for intf in intfs:
- port = self.generator.port_num(intf)
- self.ports.append(port)
- self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
-
- self.generator.start_client(ports=self.ports, mult=str(multiplier),
- duration=120, force=True)
- self.first_run = False
-
- def calculate_pps(self, samples):
- pps = round(samples['Throughput'] / 2, 2)
- multiplier = round(self.rate / self.pps, 2)
- return pps, multiplier
-
- def create_single_stream(self, packet_size, pps, isg=0):
- packet = self._create_single_packet(packet_size)
- if pps:
- stl_mode = STLTXCont(pps=pps)
- else:
- stl_mode = STLTXCont(pps=self.pps)
- if self.pg_id:
- LOGGING.debug("pg_id: %s", self.pg_id)
- stl_flow_stats = STLFlowLatencyStats(pg_id=self.pg_id)
- stream = STLStream(isg=isg, packet=packet, mode=stl_mode,
- flow_stats=stl_flow_stats)
- self.pg_id += 1
- else:
- stream = STLStream(isg=isg, packet=packet, mode=stl_mode)
- return stream
+ 'Throughput': throughput,
+ 'DropPercentage': self.drop_percent_max,
+ 'Rate': last_rate,
+ 'Latency': latency
+ }
+ return output
diff --git a/yardstick/network_services/traffic_profile/trex_traffic_profile.py b/yardstick/network_services/traffic_profile/trex_traffic_profile.py
index f5e3923d5..ed0355fa5 100644
--- a/yardstick/network_services/traffic_profile/trex_traffic_profile.py
+++ b/yardstick/network_services/traffic_profile/trex_traffic_profile.py
@@ -19,21 +19,16 @@ from random import SystemRandom
import ipaddress
import six
-
-from yardstick.common import exceptions as y_exc
-from yardstick.network_services.traffic_profile import base
-from trex_stl_lib.trex_stl_client import STLStream
-from trex_stl_lib.trex_stl_streams import STLFlowLatencyStats
-from trex_stl_lib.trex_stl_streams import STLTXCont
-from trex_stl_lib.trex_stl_streams import STLProfile
from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmWrFlowVar
from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFlowVarRepeatableRandom
from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFlowVar
-from trex_stl_lib.trex_stl_packet_builder_scapy import STLPktBuilder
-from trex_stl_lib.trex_stl_packet_builder_scapy import STLScVmRaw
from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFixIpv4
from trex_stl_lib import api as Pkt
+from yardstick.common import exceptions as y_exc
+from yardstick.network_services.traffic_profile import base
+
+
SRC = 'src'
DST = 'dst'
ETHERNET = 'Ethernet'
@@ -342,115 +337,6 @@ class TrexProfile(base.TrafficProfile):
if 'dstport' in outer_l4:
self._set_proto_addr(UDP, DST_PORT, outer_l4['dstport'], outer_l4['count'])
- def generate_imix_data(self, packet_definition):
- """ generate packet size for a given traffic profile """
- imix_count = {}
- imix_data = {}
- if not packet_definition:
- return imix_count
- imix = packet_definition.get('framesize')
- if imix:
- for size in imix:
- data = imix[size]
- imix_data[int(size[:-1])] = int(data)
- imix_sum = sum(imix_data.values())
- if imix_sum > 100:
- raise SystemExit("Error in IMIX data")
- elif imix_sum < 100:
- imix_data[64] = imix_data.get(64, 0) + (100 - imix_sum)
-
- avg_size = 0.0
- for size in imix_data:
- count = int(imix_data[size])
- if count:
- avg_size += round(size * count / 100, 2)
- pps = round(self.pps * count / 100, 0)
- imix_count[size] = pps
- self.rate = round(1342177280 / avg_size, 0) * 2
- logging.debug("Imax: %s rate: %s", imix_count, self.rate)
- return imix_count
-
- def get_streams(self, profile_data):
- """ generate trex stream
- :param profile_data:
- :type profile_data:
- """
- self.streams = []
- self.pps = self.params['traffic_profile'].get('frame_rate', 100)
- for packet_name in profile_data:
- outer_l2 = profile_data[packet_name].get('outer_l2')
- imix_data = self.generate_imix_data(outer_l2)
- if not imix_data:
- imix_data = {64: self.pps}
- self.generate_vm(profile_data[packet_name])
- for size in imix_data:
- self._generate_streams(size, imix_data[size])
- self._generate_profile()
- return self.profile
-
- def generate_vm(self, packet_definition):
- """ generate trex vm with flows setup """
- self.ether_packet = Pkt.Ether()
- self.ip_packet = Pkt.IP()
- self.ip6_packet = None
- self.udp_packet = Pkt.UDP()
- self.udp[DST_PORT] = 'UDP.dport'
- self.udp[SRC_PORT] = 'UDP.sport'
- self.qinq = False
- self.vm_flow_vars = []
- outer_l2 = packet_definition.get('outer_l2', None)
- outer_l3v4 = packet_definition.get('outer_l3v4', None)
- outer_l3v6 = packet_definition.get('outer_l3v6', None)
- outer_l4 = packet_definition.get('outer_l4', None)
- if outer_l2:
- self._set_outer_l2_fields(outer_l2)
- if outer_l3v4:
- self._set_outer_l3v4_fields(outer_l3v4)
- if outer_l3v6:
- self._set_outer_l3v6_fields(outer_l3v6)
- if outer_l4:
- self._set_outer_l4_fields(outer_l4)
- self.trex_vm = STLScVmRaw(self.vm_flow_vars)
-
- def generate_packets(self):
- """ generate packets from trex TG """
- base_pkt = self.base_pkt
- size = self.fsize - 4
- pad = max(0, size - len(base_pkt)) * 'x'
- self.packets = [STLPktBuilder(pkt=base_pkt / pad,
- vm=vm) for vm in self.vms]
-
- def _create_single_packet(self, size=64):
- size = size - 4
- ether_packet = self.ether_packet
- ip_packet = self.ip6_packet if self.ip6_packet else self.ip_packet
- udp_packet = self.udp_packet
- if self.qinq:
- qinq_packet = self.qinq_packet
- base_pkt = ether_packet / qinq_packet / ip_packet / udp_packet
- else:
- base_pkt = ether_packet / ip_packet / udp_packet
- pad = max(0, size - len(base_pkt)) * 'x'
- packet = STLPktBuilder(pkt=base_pkt / pad, vm=self.trex_vm)
- return packet
-
- def _create_single_stream(self, packet_size, pps, isg=0):
- packet = self._create_single_packet(packet_size)
- if self.pg_id:
- self.pg_id += 1
- stl_flow = STLFlowLatencyStats(pg_id=self.pg_id)
- stream = STLStream(isg=isg, packet=packet, mode=STLTXCont(pps=pps),
- flow_stats=stl_flow)
- else:
- stream = STLStream(isg=isg, packet=packet, mode=STLTXCont(pps=pps))
- return stream
-
- def _generate_streams(self, packet_size, pps):
- self.streams.append(self._create_single_stream(packet_size, pps))
-
- def _generate_profile(self):
- self.profile = STLProfile(self.streams)
-
@classmethod
def _count_ip(cls, start_ip, end_ip):
start = ipaddress.ip_address(six.u(start_ip))
diff --git a/yardstick/network_services/vnf_generic/vnf/acl_vnf.py b/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
index d9719eb4e..1357f6b26 100644
--- a/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
@@ -13,10 +13,14 @@
# limitations under the License.
import logging
-
+import ipaddress
+import six
from yardstick.common import utils
+from yardstick.common import exceptions
+
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
-from yardstick.network_services.yang_model import YangModel
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
+from itertools import chain
LOG = logging.getLogger(__name__)
@@ -38,6 +42,196 @@ class AclApproxSetupEnvSetupEnvHelper(DpdkVnfSetupEnvHelper):
SW_DEFAULT_CORE = 5
DEFAULT_CONFIG_TPL_CFG = "acl.cfg"
VNF_TYPE = "ACL"
+ RULE_CMD = "acl"
+
+ DEFAULT_PRIORITY = 1
+ DEFAULT_PROTOCOL = 0
+ DEFAULT_PROTOCOL_MASK = 0
+ # Default actions to be applied to SampleVNF. Please note,
+ # that this list is extended with `fwd` action when default
+ # actions are generated.
+ DEFAULT_FWD_ACTIONS = ["accept", "count"]
+
+ def __init__(self, vnfd_helper, ssh_helper, scenario_helper):
+ super(AclApproxSetupEnvSetupEnvHelper, self).__init__(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self._action_id = 0
+
+ def get_ip_from_port(self, port):
+ # we can't use gateway because in OpenStack gateways interfere with floating ip routing
+ # return self.make_ip_addr(self.get_ports_gateway(port), self.get_netmask_gateway(port))
+ vintf = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
+ return utils.make_ip_addr(vintf["local_ip"], vintf["netmask"])
+
+ def get_network_and_prefixlen_from_ip_of_port(self, port):
+ ip_addr = self.get_ip_from_port(port)
+ # handle cases with no gateway
+ if ip_addr:
+ return ip_addr.network.network_address.exploded, ip_addr.network.prefixlen
+ else:
+ return None, None
+
+ @property
+ def new_action_id(self):
+ """Get new action id"""
+ self._action_id += 1
+ return self._action_id
+
+ def get_default_flows(self):
+ """Get default actions/rules
+ Returns: (<actions>, <rules>)
+ <actions>:
+ { <action_id>: [ <list of actions> ]}
+ Example:
+ { 0 : [ "accept", "count", {"fwd" : "port": 0} ], ... }
+ <rules>:
+ [ {"src_ip": "x.x.x.x", "src_ip_mask", 24, ...}, ... ]
+ Note:
+ See `generate_rule_cmds()` to get list of possible map keys.
+ """
+ actions, rules = {}, []
+ _port_pairs = PortPairs(self.vnfd_helper.interfaces)
+ port_pair_list = _port_pairs.port_pair_list
+ for src_intf, dst_intf in port_pair_list:
+ # get port numbers of the interfaces
+ src_port = self.vnfd_helper.port_num(src_intf)
+ dst_port = self.vnfd_helper.port_num(dst_intf)
+ # get interface addresses and prefixes
+ src_net, src_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(src_intf)
+ dst_net, dst_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(dst_intf)
+ # ignore entries with empty values
+ if all((src_net, src_prefix_len, dst_net, dst_prefix_len)):
+ # flow: src_net:dst_net -> dst_port
+ action_id = self.new_action_id
+ actions[action_id] = self.DEFAULT_FWD_ACTIONS[:]
+ actions[action_id].append({"fwd": {"port": dst_port}})
+ rules.append({"priority": 1, 'cmd': self.RULE_CMD,
+ "src_ip": src_net, "src_ip_mask": src_prefix_len,
+ "dst_ip": dst_net, "dst_ip_mask": dst_prefix_len,
+ "src_port_from": 0, "src_port_to": 65535,
+ "dst_port_from": 0, "dst_port_to": 65535,
+ "protocol": 0, "protocol_mask": 0,
+ "action_id": action_id})
+ # flow: dst_net:src_net -> src_port
+ action_id = self.new_action_id
+ actions[action_id] = self.DEFAULT_FWD_ACTIONS[:]
+ actions[action_id].append({"fwd": {"port": src_port}})
+ rules.append({"cmd":self.RULE_CMD, "priority": 1,
+ "src_ip": dst_net, "src_ip_mask": dst_prefix_len,
+ "dst_ip": src_net, "dst_ip_mask": src_prefix_len,
+ "src_port_from": 0, "src_port_to": 65535,
+ "dst_port_from": 0, "dst_port_to": 65535,
+ "protocol": 0, "protocol_mask": 0,
+ "action_id": action_id})
+ return actions, rules
+
+ def get_flows(self, options):
+ """Get actions/rules based on provided options.
+ The `options` is a dict representing the ACL rules configuration
+ file. Result is the same as described in `get_default_flows()`.
+ """
+ actions, rules = {}, []
+ for ace in options['access-list-entries']:
+ # Generate list of actions
+ action_id = self.new_action_id
+ actions[action_id] = ace['actions']
+ # Destination nestwork
+ matches = ace['matches']
+ dst_ipv4_net = matches['destination-ipv4-network']
+ dst_ipv4_net_ip = ipaddress.ip_interface(six.text_type(dst_ipv4_net))
+ # Source network
+ src_ipv4_net = matches['source-ipv4-network']
+ src_ipv4_net_ip = ipaddress.ip_interface(six.text_type(src_ipv4_net))
+ # Append the rule
+ rules.append({'action_id': action_id, 'cmd': self.RULE_CMD,
+ 'dst_ip': dst_ipv4_net_ip.network.network_address.exploded,
+ 'dst_ip_mask': dst_ipv4_net_ip.network.prefixlen,
+ 'src_ip': src_ipv4_net_ip.network.network_address.exploded,
+ 'src_ip_mask': src_ipv4_net_ip.network.prefixlen,
+ 'dst_port_from': matches['destination-port-range']['lower-port'],
+ 'dst_port_to': matches['destination-port-range']['upper-port'],
+ 'src_port_from': matches['source-port-range']['lower-port'],
+ 'src_port_to': matches['source-port-range']['upper-port'],
+ 'priority': matches.get('priority', self.DEFAULT_PRIORITY),
+ 'protocol': matches.get('protocol', self.DEFAULT_PROTOCOL),
+ 'protocol_mask': matches.get('protocol_mask',
+ self.DEFAULT_PROTOCOL_MASK)
+ })
+ return actions, rules
+
+ def generate_rule_cmds(self, rules, apply_rules=False):
+ """Convert rules into list of SampleVNF CLI commands"""
+ rule_template = ("p {cmd} add {priority} {src_ip} {src_ip_mask} "
+ "{dst_ip} {dst_ip_mask} {src_port_from} {src_port_to} "
+ "{dst_port_from} {dst_port_to} {protocol} "
+ "{protocol_mask} {action_id}")
+ rule_cmd_list = []
+ for rule in rules:
+ rule_cmd_list.append(rule_template.format(**rule))
+ if apply_rules:
+ # add command to apply all rules at the end
+ rule_cmd_list.append("p {cmd} applyruleset".format(cmd=self.RULE_CMD))
+ return rule_cmd_list
+
+ def generate_action_cmds(self, actions):
+ """Convert actions into list of SampleVNF CLI commands.
+ These method doesn't validate the provided list of actions. Supported
+ list of actions are limited by SampleVNF. Thus, the user should be
+ responsible to specify correct action name(s). Yardstick should take
+ the provided action by user and apply it to SampleVNF.
+ Anyway, some of the actions require addition parameters to be
+ specified. In case of `fwd` & `nat` action used have to specify
+ the port attribute.
+ """
+ _action_template_map = {
+ "fwd": "p action add {action_id} fwd {port}",
+ "nat": "p action add {action_id} nat {port}"
+ }
+ action_cmd_list = []
+ for action_id, actions in actions.items():
+ for action in actions:
+ if isinstance(action, dict):
+ for action_name in action.keys():
+ # user provided an action name with addition options
+ # e.g.: {"fwd": {"port": 0}}
+ # format action CLI command and add it to the list
+ if action_name not in _action_template_map.keys():
+ raise exceptions.AclUknownActionTemplate(
+ action_name=action_name)
+ template = _action_template_map[action_name]
+ try:
+ action_cmd_list.append(template.format(
+ action_id=action_id, **action[action_name]))
+ except KeyError as exp:
+ raise exceptions.AclMissingActionArguments(
+ action_name=action_name,
+ action_param=exp.args[0])
+ else:
+ # user provided an action name w/o addition options
+ # e.g.: "accept", "count"
+ action_cmd_list.append(
+ "p action add {action_id} {action}".format(
+ action_id=action_id, action=action))
+ return action_cmd_list
+
+ def get_flows_config(self, options=None):
+ """Get action/rules configuration commands (string) to be
+ applied to SampleVNF to configure ACL rules (flows).
+ """
+ action_cmd_list, rule_cmd_list = [], []
+ if options:
+ # if file name is set, read actions/rules from the file
+ actions, rules = self.get_flows(options)
+ action_cmd_list = self.generate_action_cmds(actions)
+ rule_cmd_list = self.generate_rule_cmds(rules)
+ # default actions/rules
+ dft_actions, dft_rules = self.get_default_flows()
+ dft_action_cmd_list = self.generate_action_cmds(dft_actions)
+ dft_rule_cmd_list = self.generate_rule_cmds(dft_rules, apply_rules=True)
+ # generate multi-line commands to add actions/rules
+ return '\n'.join(chain(action_cmd_list, dft_action_cmd_list,
+ rule_cmd_list, dft_rule_cmd_list))
class AclApproxVnf(SampleVNF):
@@ -57,12 +251,3 @@ class AclApproxVnf(SampleVNF):
setup_env_helper_type = AclApproxSetupEnvSetupEnvHelper
super(AclApproxVnf, self).__init__(name, vnfd, setup_env_helper_type, resource_helper_type)
- self.acl_rules = None
-
- def _start_vnf(self):
- yang_model_path = utils.find_relative_file(
- self.scenario_helper.options['rules'],
- self.scenario_helper.task_path)
- yang_model = YangModel(yang_model_path)
- self.acl_rules = yang_model.get_rules()
- super(AclApproxVnf, self)._start_vnf()
diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
index ef8b3f126..3976acb76 100644
--- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
@@ -11,20 +11,17 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-""" Base class implementation for generic vnf implementation """
-from collections import Mapping
import logging
from multiprocessing import Queue, Value, Process
import os
import posixpath
import re
+import six
import subprocess
import time
-import six
-
from trex_stl_lib.trex_stl_client import LoggerApi
from trex_stl_lib.trex_stl_client import STLClient
from trex_stl_lib.trex_stl_exceptions import STLError
@@ -32,6 +29,7 @@ from yardstick.benchmark.contexts.base import Context
from yardstick.common import exceptions as y_exceptions
from yardstick.common.process import check_if_process_failed
from yardstick.common import utils
+from yardstick.common import yaml_loader
from yardstick.network_services import constants
from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper, DpdkNode
from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
@@ -144,6 +142,13 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
'vnf_type': self.VNF_TYPE,
}
+ # read actions/rules from file
+ acl_options = None
+ acl_file_name = self.scenario_helper.options.get('rules')
+ if acl_file_name:
+ with utils.open_relative_file(acl_file_name, task_path) as infile:
+ acl_options = yaml_loader.yaml_load(infile)
+
config_tpl_cfg = utils.find_relative_file(self.DEFAULT_CONFIG_TPL_CFG,
task_path)
config_basename = posixpath.basename(self.CFG_CONFIG)
@@ -176,12 +181,17 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
new_config = self._update_packet_type(new_config, traffic_options)
self.ssh_helper.upload_config_file(config_basename, new_config)
self.ssh_helper.upload_config_file(script_basename,
- multiport.generate_script(self.vnfd_helper))
+ multiport.generate_script(self.vnfd_helper,
+ self.get_flows_config(acl_options)))
LOG.info("Provision and start the %s", self.APP_NAME)
self._build_pipeline_kwargs()
return self.PIPELINE_COMMAND.format(**self.pipeline_kwargs)
+ def get_flows_config(self, options=None): # pylint: disable=unused-argument
+ """No actions/rules (flows) by default"""
+ return None
+
def _build_pipeline_kwargs(self):
tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME)
# count the number of actual ports in the list of pairs
@@ -375,39 +385,14 @@ class ClientResourceHelper(ResourceHelper):
LOG.error('TRex client not connected')
return {}
- def generate_samples(self, ports, key=None, default=None):
- # needs to be used ports
- last_result = self.get_stats(ports)
- key_value = last_result.get(key, default)
-
- if not isinstance(last_result, Mapping): # added for mock unit test
- self._terminated.value = 1
- return {}
-
- samples = {}
- # recalculate port for interface and see if it matches ports provided
- for intf in self.vnfd_helper.interfaces:
- name = intf["name"]
- port = self.vnfd_helper.port_num(name)
- if port in ports:
- xe_value = last_result.get(port, {})
- samples[name] = {
- "rx_throughput_fps": float(xe_value.get("rx_pps", 0.0)),
- "tx_throughput_fps": float(xe_value.get("tx_pps", 0.0)),
- "rx_throughput_mbps": float(xe_value.get("rx_bps", 0.0)),
- "tx_throughput_mbps": float(xe_value.get("tx_bps", 0.0)),
- "in_packets": int(xe_value.get("ipackets", 0)),
- "out_packets": int(xe_value.get("opackets", 0)),
- }
- if key:
- samples[name][key] = key_value
- return samples
+ def _get_samples(self, ports, port_pg_id=False):
+ raise NotImplementedError()
def _run_traffic_once(self, traffic_profile):
traffic_profile.execute_traffic(self)
self.client_started.value = 1
time.sleep(self.RUN_DURATION)
- samples = self.generate_samples(traffic_profile.ports)
+ samples = self._get_samples(traffic_profile.ports)
time.sleep(self.QUEUE_WAIT_TIME)
self._queue.put(samples)
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
index 2010546e7..a1f9fbeb4 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
@@ -12,12 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import os
import logging
-import sys
-from yardstick.common import exceptions
from yardstick.common import utils
+from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
@@ -27,14 +25,6 @@ LOG = logging.getLogger(__name__)
WAIT_AFTER_CFG_LOAD = 10
WAIT_FOR_TRAFFIC = 30
-IXIA_LIB = os.path.dirname(os.path.realpath(__file__))
-IXNET_LIB = os.path.join(IXIA_LIB, "../../libs/ixia_libs/IxNet")
-sys.path.append(IXNET_LIB)
-
-try:
- from IxNet import IxNextgen
-except ImportError:
- IxNextgen = exceptions.ErrorClass
class IxiaRfc2544Helper(Rfc2544ResourceHelper):
@@ -51,7 +41,7 @@ class IxiaResourceHelper(ClientResourceHelper):
super(IxiaResourceHelper, self).__init__(setup_helper)
self.scenario_helper = setup_helper.scenario_helper
- self.client = IxNextgen()
+ self.client = ixnet_api.IxNextgen()
if rfc_helper_type is None:
rfc_helper_type = IxiaRfc2544Helper
@@ -69,10 +59,8 @@ class IxiaResourceHelper(ClientResourceHelper):
def stop_collect(self):
self._terminated.value = 1
- if self.client:
- self.client.ix_stop_traffic()
- def generate_samples(self, ports, key=None, default=None):
+ def generate_samples(self, ports, key=None):
stats = self.get_stats()
samples = {}
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
index 4e9f4bdc1..07cec6745 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
@@ -11,74 +11,45 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-""" Trex traffic generation definitions which implements rfc2544 """
-from __future__ import absolute_import
-from __future__ import print_function
-import time
import logging
-from collections import Mapping
-
-from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexTrafficGen
-from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
-from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexResourceHelper
-
-LOGGING = logging.getLogger(__name__)
+import time
+from yardstick.common import utils
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_trex
-class TrexRfc2544ResourceHelper(Rfc2544ResourceHelper):
- def is_done(self):
- return self.latency and self.iteration.value > 10
+LOGGING = logging.getLogger(__name__)
-class TrexRfcResourceHelper(TrexResourceHelper):
+class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
- LATENCY_TIME_SLEEP = 120
- RUN_DURATION = 30
- WAIT_TIME = 3
+ SAMPLING_PERIOD = 2
+ TRANSIENT_PERIOD = 10
- def __init__(self, setup_helper, rfc_helper_type=None):
+ def __init__(self, setup_helper):
super(TrexRfcResourceHelper, self).__init__(setup_helper)
-
- if rfc_helper_type is None:
- rfc_helper_type = TrexRfc2544ResourceHelper
-
- self.rfc2544_helper = rfc_helper_type(self.scenario_helper)
+ self.rfc2544_helper = sample_vnf.Rfc2544ResourceHelper(
+ self.scenario_helper)
def _run_traffic_once(self, traffic_profile):
- if self._terminated.value:
- return
-
- traffic_profile.execute_traffic(self)
self.client_started.value = 1
- time.sleep(self.RUN_DURATION)
- self.client.stop(traffic_profile.ports)
- time.sleep(self.WAIT_TIME)
- samples = traffic_profile.get_drop_percentage(self)
- self._queue.put(samples)
-
- if not self.rfc2544_helper.is_done():
- return
-
- self.client.stop(traffic_profile.ports)
- self.client.reset(ports=traffic_profile.ports)
- self.client.remove_all_streams(traffic_profile.ports)
- traffic_profile.execute_traffic_latency(samples=samples)
- multiplier = traffic_profile.calculate_pps(samples)[1]
- for _ in range(5):
- time.sleep(self.LATENCY_TIME_SLEEP)
- self.client.stop(traffic_profile.ports)
- time.sleep(self.WAIT_TIME)
- last_res = self.client.get_stats(traffic_profile.ports)
- if not isinstance(last_res, Mapping):
- self._terminated.value = 1
- continue
- self.generate_samples(traffic_profile.ports, 'latency', {})
- self._queue.put(samples)
- self.client.start(mult=str(multiplier),
- ports=traffic_profile.ports,
- duration=120, force=True)
+ ports, port_pg_id = traffic_profile.execute_traffic(self)
+
+ samples = []
+ timeout = int(traffic_profile.config.duration) - self.TRANSIENT_PERIOD
+ time.sleep(self.TRANSIENT_PERIOD)
+ for _ in utils.Timer(timeout=timeout):
+ samples.append(self._get_samples(ports, port_pg_id=port_pg_id))
+ time.sleep(self.SAMPLING_PERIOD)
+
+ traffic_profile.stop_traffic(self)
+ output = traffic_profile.get_drop_percentage(
+ samples, self.rfc2544_helper.tolerance_low,
+ self.rfc2544_helper.tolerance_high,
+ self.rfc2544_helper.correlated_traffic)
+ self._queue.put(output)
def start_client(self, ports, mult=None, duration=None, force=True):
self.client.start(ports=ports, mult=mult, duration=duration, force=force)
@@ -86,12 +57,8 @@ class TrexRfcResourceHelper(TrexResourceHelper):
def clear_client_stats(self, ports):
self.client.clear_stats(ports=ports)
- def collect_kpi(self):
- self.rfc2544_helper.iteration.value += 1
- return super(TrexRfcResourceHelper, self).collect_kpi()
-
-class TrexTrafficGenRFC(TrexTrafficGen):
+class TrexTrafficGenRFC(tg_trex.TrexTrafficGen):
"""
This class handles mapping traffic profile and generating
traffic for rfc2544 testcase.
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_trex.py b/yardstick/network_services/vnf_generic/vnf/tg_trex.py
index 0084a124c..80b42e22d 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_trex.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_trex.py
@@ -13,7 +13,6 @@
# limitations under the License.
""" Trex acts as traffic generation and vnf definitions based on IETS Spec """
-from __future__ import absolute_import
import logging
import os
@@ -25,6 +24,7 @@ from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTraff
from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
+
LOG = logging.getLogger(__name__)
@@ -165,6 +165,30 @@ class TrexResourceHelper(ClientResourceHelper):
cmd = "sudo fuser -n tcp %s %s -k > /dev/null 2>&1"
self.ssh_helper.execute(cmd % (self.SYNC_PORT, self.ASYNC_PORT))
+ def _get_samples(self, ports, port_pg_id=None):
+ stats = self.get_stats(ports)
+ samples = {}
+ for pname in (intf['name'] for intf in self.vnfd_helper.interfaces):
+ port_num = self.vnfd_helper.port_num(pname)
+ port_stats = stats.get(port_num, {})
+ samples[pname] = {
+ 'rx_throughput_fps': float(port_stats.get('rx_pps', 0.0)),
+ 'tx_throughput_fps': float(port_stats.get('tx_pps', 0.0)),
+ 'rx_throughput_bps': float(port_stats.get('rx_bps', 0.0)),
+ 'tx_throughput_bps': float(port_stats.get('tx_bps', 0.0)),
+ 'in_packets': int(port_stats.get('ipackets', 0)),
+ 'out_packets': int(port_stats.get('opackets', 0)),
+ }
+
+ pg_id_list = port_pg_id.get_pg_ids(port_num)
+ samples[pname]['latency'] = {}
+ for pg_id in pg_id_list:
+ latency_global = stats.get('latency', {})
+ pg_latency = latency_global.get(pg_id, {}).get('latency')
+ samples[pname]['latency'][pg_id] = pg_latency
+
+ return samples
+
class TrexTrafficGen(SampleVNFTrafficGen):
"""
diff --git a/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py b/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
index 3ba1f91b7..432f30a0c 100644
--- a/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
@@ -14,9 +14,8 @@
import logging
-from yardstick.common import utils
-from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
-from yardstick.network_services.yang_model import YangModel
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
+from yardstick.network_services.vnf_generic.vnf.acl_vnf import AclApproxSetupEnvSetupEnvHelper
LOG = logging.getLogger(__name__)
@@ -27,7 +26,7 @@ FW_COLLECT_KPI = (r"""VFW TOTAL:[^p]+pkts_received"?:\s(\d+),[^p]+pkts_fw_forwar
r"""[^p]+pkts_drop_fw"?:\s(\d+),\s""")
-class FWApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
+class FWApproxSetupEnvHelper(AclApproxSetupEnvSetupEnvHelper):
APP_NAME = "vFW"
CFG_CONFIG = "/tmp/vfw_config"
@@ -37,6 +36,8 @@ class FWApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
SW_DEFAULT_CORE = 5
HW_DEFAULT_CORE = 2
VNF_TYPE = "VFW"
+ RULE_CMD = "vfw"
+ DEFAULT_FWD_ACTIONS = ["accept", "count", "conntrack"]
class FWApproxVnf(SampleVNF):
@@ -56,12 +57,3 @@ class FWApproxVnf(SampleVNF):
setup_env_helper_type = FWApproxSetupEnvHelper
super(FWApproxVnf, self).__init__(name, vnfd, setup_env_helper_type, resource_helper_type)
- self.vfw_rules = None
-
- def _start_vnf(self):
- yang_model_path = utils.find_relative_file(
- self.scenario_helper.options['rules'],
- self.scenario_helper.task_path)
- yang_model = YangModel(yang_model_path)
- self.vfw_rules = yang_model.get_rules()
- super(FWApproxVnf, self)._start_vnf()
diff --git a/yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py b/yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py
index de6fd9329..6c5c6c833 100644
--- a/yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py
+++ b/yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py
@@ -47,6 +47,7 @@ class VnfSshHelper(AutoConnectSSH):
def upload_config_file(self, prefix, content):
cfg_file = os.path.join(constants.REMOTE_TMP, prefix)
+ LOG.debug('Config file name: %s', cfg_file)
LOG.debug(content)
file_obj = StringIO(content)
self.put_file_obj(file_obj, cfg_file)
diff --git a/yardstick/network_services/yang_model.py b/yardstick/network_services/yang_model.py
deleted file mode 100644
index ec00c4513..000000000
--- a/yardstick/network_services/yang_model.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright (c) 2017 Intel Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import absolute_import
-from __future__ import print_function
-import logging
-import ipaddress
-import six
-
-from yardstick.common.yaml_loader import yaml_load
-
-LOG = logging.getLogger(__name__)
-
-
-class YangModel(object):
-
- RULE_TEMPLATE = "p acl add 1 {0} {1} {2} {3} {4} {5} {6} {7} 0 0 {8}"
-
- def __init__(self, config_file):
- super(YangModel, self).__init__()
- self._config_file = config_file
- self._options = {}
- self._rules = ''
-
- @property
- def config_file(self):
- return self._config_file
-
- @config_file.setter
- def config_file(self, value):
- self._config_file = value
- self._options = {}
- self._rules = ''
-
- def _read_config(self):
- # TODO: add some error handling in case of empty or non-existing file
- try:
- with open(self._config_file) as f:
- self._options = yaml_load(f)
- except Exception as e:
- LOG.exception("Failed to load the yaml %s", e)
- raise
-
- def _get_entries(self):
- if not self._options:
- return ''
-
- rule_list = []
- for ace in self._options['access-list1']['acl']['access-list-entries']:
- # TODO: resolve ports using topology file and nodes'
- # ids: public or private.
- matches = ace['ace']['matches']
- dst_ipv4_net = matches['destination-ipv4-network']
- dst_ipv4_net_ip = ipaddress.ip_interface(six.text_type(dst_ipv4_net))
- port0_local_network = dst_ipv4_net_ip.network.network_address.exploded
- port0_prefix = dst_ipv4_net_ip.network.prefixlen
-
- src_ipv4_net = matches['source-ipv4-network']
- src_ipv4_net_ip = ipaddress.ip_interface(six.text_type(src_ipv4_net))
- port1_local_network = src_ipv4_net_ip.network.network_address.exploded
- port1_prefix = src_ipv4_net_ip.network.prefixlen
-
- lower_dport = matches['destination-port-range']['lower-port']
- upper_dport = matches['destination-port-range']['upper-port']
-
- lower_sport = matches['source-port-range']['lower-port']
- upper_sport = matches['source-port-range']['upper-port']
-
- # TODO: proto should be read from file also.
- # Now all rules in sample ACL file are TCP.
- rule_list.append('') # get an extra new line
- rule_list.append(self.RULE_TEMPLATE.format(port0_local_network,
- port0_prefix,
- port1_local_network,
- port1_prefix,
- lower_dport,
- upper_dport,
- lower_sport,
- upper_sport,
- 0))
- rule_list.append(self.RULE_TEMPLATE.format(port1_local_network,
- port1_prefix,
- port0_local_network,
- port0_prefix,
- lower_sport,
- upper_sport,
- lower_dport,
- upper_dport,
- 1))
-
- self._rules = '\n'.join(rule_list)
-
- def get_rules(self):
- if not self._rules:
- self._read_config()
- self._get_entries()
- return self._rules
diff --git a/yardstick/orchestrator/kubernetes.py b/yardstick/orchestrator/kubernetes.py
index ac3a09ed1..e05c971ac 100644
--- a/yardstick/orchestrator/kubernetes.py
+++ b/yardstick/orchestrator/kubernetes.py
@@ -7,25 +7,30 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-from __future__ import absolute_import
-from __future__ import print_function
+import copy
+from yardstick.common import exceptions
from yardstick.common import utils
from yardstick.common import kubernetes_utils as k8s_utils
class KubernetesObject(object):
+ SSH_MOUNT_PATH = '/tmp/.ssh/'
+ IMAGE_DEFAULT = 'openretriever/yardstick'
+ COMMAND_DEFAULT = '/bin/bash'
+ SSHKEY_DEFAULT = 'yardstick_key'
+
def __init__(self, name, **kwargs):
super(KubernetesObject, self).__init__()
self.name = name
- self.image = kwargs.get('image', 'openretriever/yardstick')
- self.command = [kwargs.get('command', '/bin/bash')]
+ self.image = kwargs.get('image', self.IMAGE_DEFAULT)
+ self.command = [kwargs.get('command', self.COMMAND_DEFAULT)]
self.args = kwargs.get('args', [])
- self.ssh_key = kwargs.get('ssh_key', 'yardstick_key')
+ self.ssh_key = kwargs.get('ssh_key', self.SSHKEY_DEFAULT)
self.node_selector = kwargs.get('nodeSelector', {})
-
- self.volumes = []
+ self._volumes = kwargs.get('volumes', [])
+ self._volume_mounts = kwargs.get('volumeMounts', [])
self.template = {
"apiVersion": "v1",
@@ -53,7 +58,6 @@ class KubernetesObject(object):
self._change_value_according_name(name)
self._add_containers()
self._add_node_selector()
- self._add_ssh_key_volume()
self._add_volumes()
def get_template(self):
@@ -67,29 +71,19 @@ class KubernetesObject(object):
name)
def _add_containers(self):
- containers = [self._add_container()]
+ containers = [self._create_container_item()]
utils.set_dict_value(self.template,
'spec.template.spec.containers',
containers)
- def _add_container(self):
+ def _create_container_item(self):
+ """Create a "container" item"""
container_name = '{}-container'.format(self.name)
- ssh_key_mount_path = '/tmp/.ssh/'
-
- container = {
- "args": self.args,
- "command": self.command,
- "image": self.image,
- "name": container_name,
- "volumeMounts": [
- {
- "mountPath": ssh_key_mount_path,
- "name": self.ssh_key
- }
- ]
- }
-
- return container
+ return {'args': self.args,
+ 'command': self.command,
+ 'image': self.image,
+ 'name': container_name,
+ 'volumeMounts': self._create_volume_mounts()}
def _add_node_selector(self):
utils.set_dict_value(self.template,
@@ -97,21 +91,48 @@ class KubernetesObject(object):
self.node_selector)
def _add_volumes(self):
+ """Add "volume" items to container specs, including the SSH one"""
+ volume_items = [self._create_volume_item(vol) for vol in self._volumes]
+ volume_items.append(self._create_ssh_key_volume())
utils.set_dict_value(self.template,
'spec.template.spec.volumes',
- self.volumes)
-
- def _add_volume(self, volume):
- self.volumes.append(volume)
-
- def _add_ssh_key_volume(self):
- key_volume = {
- "configMap": {
- "name": self.ssh_key
- },
- "name": self.ssh_key
- }
- self._add_volume(key_volume)
+ volume_items)
+
+ def _create_ssh_key_volume(self):
+ """Create a "volume" item of type "configMap" for the SSH key"""
+ return {'name': self.ssh_key,
+ 'configMap': {'name': self.ssh_key}}
+
+ @staticmethod
+ def _create_volume_item(volume):
+ """Create a "volume" item"""
+ volume = copy.deepcopy(volume)
+ name = volume.pop('name')
+ for key in (k for k in volume if k in k8s_utils.get_volume_types()):
+ type_name = key
+ type_data = volume[key]
+ break
+ else:
+ raise exceptions.KubernetesTemplateInvalidVolumeType(volume=volume)
+
+ return {'name': name,
+ type_name: type_data}
+
+ def _create_volume_mounts(self):
+ """Return all "volumeMounts" items per container"""
+ volume_mounts_items = [self._create_volume_mounts_item(vol)
+ for vol in self._volume_mounts]
+ ssh_vol = {'name': self.ssh_key,
+ 'mountPath': self.SSH_MOUNT_PATH}
+ volume_mounts_items.append(self._create_volume_mounts_item(ssh_vol))
+ return volume_mounts_items
+
+ @staticmethod
+ def _create_volume_mounts_item(volume_mount):
+ """Create a "volumeMounts" item"""
+ return {'name': volume_mount['name'],
+ 'mountPath': volume_mount['mountPath'],
+ 'readOnly': volume_mount.get('readOnly', False)}
class ServiceObject(object):
@@ -145,15 +166,22 @@ class ServiceObject(object):
class KubernetesTemplate(object):
- def __init__(self, name, template_cfg):
+ def __init__(self, name, context_cfg):
+ """KubernetesTemplate object initialization
+
+ :param name: (str) name of the Kubernetes context
+ :param context_cfg: (dict) context definition
+ """
+ context_cfg = copy.deepcopy(context_cfg)
+ servers_cfg = context_cfg.pop('servers', {})
self.name = name
self.ssh_key = '{}-key'.format(name)
- self.rcs = [self._get_rc_name(rc) for rc in template_cfg]
+ self.rcs = [self._get_rc_name(rc) for rc in servers_cfg]
self.k8s_objs = [KubernetesObject(self._get_rc_name(rc),
ssh_key=self.ssh_key,
**cfg)
- for rc, cfg in template_cfg.items()]
+ for rc, cfg in servers_cfg.items()]
self.service_objs = [ServiceObject(s) for s in self.rcs]
self.pods = []
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
index 2cf1d92d7..246a5b2b9 100644
--- a/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
@@ -549,5 +549,5 @@ class OvsDeployTestCase(unittest.TestCase):
'ovs_version': ovs_version,
'dpdk_version': dpdk_version,
'proxy': 'test_proxy'})
- mock_execute.assert_called_with(cmd)
- mock_env_get.assert_called_with('http_proxy', '')
+ mock_execute.assert_called_once_with(cmd)
+ mock_env_get.assert_has_calls([mock.call('http_proxy', '')])
diff --git a/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py b/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
index 0e11a53e1..0d698c5bd 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
@@ -12,9 +12,10 @@ import unittest
from yardstick.benchmark.contexts import base
from yardstick.benchmark.contexts import kubernetes
+from yardstick.orchestrator import kubernetes as orchestrator_kubernetes
-context_cfg = {
+CONTEXT_CFG = {
'type': 'Kubernetes',
'name': 'k8s',
'task_id': '1234567890',
@@ -22,14 +23,14 @@ context_cfg = {
'host': {
'image': 'openretriever/yardstick',
'command': '/bin/bash',
- 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \
-service ssh restart;while true ; do sleep 10000; done']
+ 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; '
+ 'service ssh restart;while true ; do sleep 10000; done']
},
'target': {
'image': 'openretriever/yardstick',
'command': '/bin/bash',
- 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \
-service ssh restart;while true ; do sleep 10000; done']
+ 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; '
+ 'service ssh restart;while true ; do sleep 10000; done']
}
}
}
@@ -42,7 +43,7 @@ class KubernetesTestCase(unittest.TestCase):
def setUp(self):
self.k8s_context = kubernetes.KubernetesContext()
self.addCleanup(self._remove_contexts)
- self.k8s_context.init(context_cfg)
+ self.k8s_context.init(CONTEXT_CFG)
@staticmethod
def _remove_contexts():
@@ -68,7 +69,8 @@ class KubernetesTestCase(unittest.TestCase):
@mock.patch.object(kubernetes.KubernetesContext, '_create_services')
@mock.patch.object(kubernetes.KubernetesContext, '_wait_until_running')
- @mock.patch.object(kubernetes.KubernetesTemplate, 'get_rc_pods')
+ @mock.patch.object(orchestrator_kubernetes.KubernetesTemplate,
+ 'get_rc_pods')
@mock.patch.object(kubernetes.KubernetesContext, '_create_rcs')
@mock.patch.object(kubernetes.KubernetesContext, '_set_ssh_key')
def test_deploy(self,
@@ -170,3 +172,13 @@ class KubernetesTestCase(unittest.TestCase):
def test_delete_services(self, mock_delete):
self.k8s_context._delete_services()
mock_delete.assert_called()
+
+ def test_init(self):
+ self.k8s_context._delete_context()
+ with mock.patch.object(orchestrator_kubernetes, 'KubernetesTemplate',
+ return_value='fake_template') as mock_k8stemplate:
+ self.k8s_context = kubernetes.KubernetesContext()
+ self.k8s_context.init(CONTEXT_CFG)
+ mock_k8stemplate.assert_called_once_with(self.k8s_context.name,
+ CONTEXT_CFG)
+ self.assertEqual('fake_template', self.k8s_context.template)
diff --git a/yardstick/tests/unit/benchmark/runner/test_duration.py b/yardstick/tests/unit/benchmark/runner/test_duration.py
new file mode 100644
index 000000000..21e3874b8
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/runner/test_duration.py
@@ -0,0 +1,39 @@
+##############################################################################
+# Copyright (c) 2018 Nokia and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+import mock
+import unittest
+import multiprocessing
+import os
+
+from yardstick.benchmark.runners import duration
+
+
+class DurationRunnerTest(unittest.TestCase):
+ def setUp(self):
+ self.scenario_cfg = {
+ 'runner': {'interval': 0, "duration": 0},
+ 'type': 'some_type'
+ }
+
+ @mock.patch.object(os, 'getpid')
+ @mock.patch.object(multiprocessing, 'Process')
+ def test__run_benchmark_called_with(self, mock_multiprocessing_process,
+ mock_os_getpid):
+ mock_os_getpid.return_value = 101
+
+ runner = duration.DurationRunner({})
+ benchmark_cls = mock.Mock()
+ runner._run_benchmark(benchmark_cls, 'my_method', self.scenario_cfg,
+ {})
+ mock_multiprocessing_process.assert_called_once_with(
+ name='Duration-some_type-101',
+ target=duration._worker_process,
+ args=(runner.result_queue, benchmark_cls, 'my_method',
+ self.scenario_cfg, {}, runner.aborted, runner.output_queue))
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
index 2885dc6fb..bb1a7aaca 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
@@ -628,7 +628,8 @@ class TestNetworkServiceTestCase(unittest.TestCase):
'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
'flow': {'flow': {}},
'imix': {'imix': {'64B': 100}},
- 'uplink': {}}
+ 'uplink': {},
+ 'duration': 30}
)
mock_tprofile_get.assert_called_once_with(fake_vnfd)
diff --git a/yardstick/tests/unit/common/test_utils.py b/yardstick/tests/unit/common/test_utils.py
index 5fd91c87f..31b10e6da 100644
--- a/yardstick/tests/unit/common/test_utils.py
+++ b/yardstick/tests/unit/common/test_utils.py
@@ -1174,6 +1174,17 @@ class TimerTestCase(unittest.TestCase):
with utils.Timer(timeout=1):
time.sleep(2)
+ def test__enter_with_timeout_no_exception(self):
+ with utils.Timer(timeout=1, raise_exception=False):
+ time.sleep(2)
+
+ def test__iter(self):
+ iterations = []
+ for i in utils.Timer(timeout=2):
+ iterations.append(i)
+ time.sleep(1.1)
+ self.assertEqual(2, len(iterations))
+
class WaitUntilTrueTestCase(unittest.TestCase):
diff --git a/yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py b/yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py
index 6d5e1da60..e66e7fbb8 100644
--- a/yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py
+++ b/yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py
@@ -223,7 +223,7 @@ class TestMultiPortConfig(unittest.TestCase):
mock.Mock(return_value={'link_config': 0, 'arp_config': '',
'arp_config6': '', 'actions': '',
'arp_route_tbl': '', 'arp_route_tbl6': '',
- 'rules': ''})
+ 'flows': ''})
opnfv_vnf.port_pair_list = [("xe0", "xe1")]
self.assertIsNotNone(opnfv_vnf.generate_script(self.VNFD))
opnfv_vnf.lb_config = 'HW'
@@ -249,66 +249,6 @@ class TestMultiPortConfig(unittest.TestCase):
opnfv_vnf.generate_rule_config = mock.Mock()
self.assertIsNotNone(opnfv_vnf.generate_script_data())
- def test_generate_rule_config(self):
- topology_file = mock.Mock()
- config_tpl = mock.Mock()
- tmp_file = mock.Mock()
- vnfd_mock = mock.MagicMock()
- opnfv_vnf = samplevnf_helper.MultiPortConfig(
- topology_file, config_tpl, tmp_file, vnfd_mock)
- opnfv_vnf.get_config_tpl_data = mock.MagicMock()
- opnfv_vnf.socket = 0
- opnfv_vnf.start_core = 0
- opnfv_vnf.update_write_parser = mock.MagicMock()
- opnfv_vnf.generate_script_data = \
- mock.Mock(return_value={'link_config': 0, 'arp_config': '',
- 'arp_config6': '', 'actions': '',
- 'rules': ''})
- opnfv_vnf.port_pair_list = [("xe0", "xe1")]
- opnfv_vnf.get_port_pairs = mock.Mock()
- opnfv_vnf.vnf_type = 'ACL'
- opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
- opnfv_vnf.get_netmask_gateway = mock.Mock(
- return_value=u'255.255.255.0')
- opnfv_vnf.get_ports_gateway6 = mock.Mock(return_value=u'1.1.1.1')
- opnfv_vnf.get_netmask_gateway6 = mock.Mock(
- return_value=u'255.255.255.0')
- opnfv_vnf.txrx_pipeline = ''
- opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
- opnfv_vnf.rules = ''
- self.assertIsNotNone(opnfv_vnf.generate_rule_config())
- opnfv_vnf.rules = 'new'
- self.assertIsNotNone(opnfv_vnf.generate_rule_config())
-
- def test_generate_action_config(self):
- topology_file = mock.Mock()
- config_tpl = mock.Mock()
- tmp_file = mock.Mock()
- vnfd_mock = mock.MagicMock()
- opnfv_vnf = samplevnf_helper.MultiPortConfig(
- topology_file, config_tpl, tmp_file, vnfd_mock)
- opnfv_vnf.get_config_tpl_data = mock.MagicMock()
- opnfv_vnf.socket = 0
- opnfv_vnf.start_core = 0
- opnfv_vnf.update_write_parser = mock.MagicMock()
- opnfv_vnf.generate_script_data = \
- mock.Mock(return_value={'link_config': 0, 'arp_config': '',
- 'arp_config6': '', 'actions': '',
- 'rules': ''})
- opnfv_vnf.port_pair_list = [("xe0", "xe1")]
- opnfv_vnf.get_port_pairs = mock.Mock()
- opnfv_vnf.vnf_type = 'VFW'
- opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
- opnfv_vnf.get_netmask_gateway = mock.Mock(
- return_value=u'255.255.255.0')
- opnfv_vnf.get_ports_gateway6 = mock.Mock(return_value=u'1.1.1.1')
- opnfv_vnf.get_netmask_gateway6 = mock.Mock(
- return_value=u'255.255.255.0')
- opnfv_vnf.txrx_pipeline = ''
- opnfv_vnf.rules = ''
- self.assertIsNotNone(opnfv_vnf.generate_action_config())
-
def test_generate_arp_config6(self):
topology_file = mock.Mock()
config_tpl = mock.Mock()
diff --git a/yardstick/tests/unit/network_services/test_yang_model.py b/yardstick/tests/unit/network_services/test_yang_model.py
deleted file mode 100644
index cbeb3a1f2..000000000
--- a/yardstick/tests/unit/network_services/test_yang_model.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright (c) 2016-2017 Intel Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import mock
-import unittest
-
-from yardstick.network_services.yang_model import YangModel
-
-
-class YangModelTestCase(unittest.TestCase):
- """Test all Yang Model methods."""
-
- ENTRIES = {
- 'access-list1': {
- 'acl': {
- 'access-list-entries': [{
- 'ace': {
- 'ace-oper-data': {
- 'match-counter': 0},
- 'actions': 'drop,count',
- 'matches': {
- 'destination-ipv4-network':
- '152.16.40.20/24',
- 'destination-port-range': {
- 'lower-port': 0,
- 'upper-port': 65535},
- 'source-ipv4-network': '0.0.0.0/0',
- 'source-port-range': {
- 'lower-port': 0,
- 'upper-port': 65535}},
- 'rule-name': 'rule1588'}},
- {
- 'ace': {
- 'ace-oper-data': {
- 'match-counter': 0},
- 'actions': 'drop,count',
- 'matches': {
- 'destination-ipv4-network':
- '0.0.0.0/0',
- 'destination-port-range': {
- 'lower-port': 0,
- 'upper-port': 65535},
- 'source-ipv4-network':
- '152.16.100.20/24',
- 'source-port-range': {
- 'lower-port': 0,
- 'upper-port': 65535}},
- 'rule-name': 'rule1589'}}],
- 'acl-name': 'sample-ipv4-acl',
- 'acl-type': 'ipv4-acl'}
- }
- }
-
- def test__init__(self):
- cfg = "yang.yaml"
- y = YangModel(cfg)
- self.assertEqual(y.config_file, cfg)
-
- def test_config_file_setter(self):
- cfg = "yang.yaml"
- y = YangModel(cfg)
- self.assertEqual(y.config_file, cfg)
- cfg2 = "yang2.yaml"
- y.config_file = cfg2
- self.assertEqual(y.config_file, cfg2)
-
- def test__get_entries(self):
- cfg = "yang.yaml"
- y = YangModel(cfg)
- y._options = self.ENTRIES
- y._get_entries()
- self.assertIn("p acl add", y._rules)
-
- def test__get_entries_no_options(self):
- cfg = "yang.yaml"
- y = YangModel(cfg)
- y._get_entries()
- self.assertEqual(y._rules, '')
-
- @mock.patch('yardstick.network_services.yang_model.open')
- @mock.patch('yardstick.network_services.yang_model.yaml_load')
- def test__read_config(self, mock_safe_load, *args):
- cfg = "yang.yaml"
- y = YangModel(cfg)
- mock_safe_load.return_value = expected = {'key1': 'value1', 'key2': 'value2'}
- y._read_config()
- self.assertDictEqual(y._options, expected)
-
- @mock.patch('yardstick.network_services.yang_model.open')
- def test__read_config_open_error(self, mock_open):
- cfg = "yang.yaml"
- y = YangModel(cfg)
- mock_open.side_effect = IOError('my error')
-
- self.assertEqual(y._options, {})
- with self.assertRaises(IOError) as raised:
- y._read_config()
-
- self.assertIn('my error', str(raised.exception))
- self.assertEqual(y._options, {})
-
- def test_get_rules(self):
- cfg = "yang.yaml"
- y = YangModel(cfg)
- y._read_config = read_mock = mock.Mock()
- y._get_entries = get_mock = mock.Mock()
-
- y._rules = None
- self.assertIsNone(y.get_rules())
- read_mock.assert_called_once()
- get_mock.assert_called_once()
-
- # True value should prevent calling read and get
- y._rules = 999
- self.assertEqual(y.get_rules(), 999)
- read_mock.assert_called_once()
- get_mock.assert_called_once()
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_base.py b/yardstick/tests/unit/network_services/traffic_profile/test_base.py
index 641064cbe..55276af58 100644
--- a/yardstick/tests/unit/network_services/traffic_profile/test_base.py
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_base.py
@@ -69,5 +69,20 @@ class TestTrafficProfile(unittest.TestCase):
class TestDummyProfile(unittest.TestCase):
def test_execute(self):
- dummy_profile = base.DummyProfile(base.TrafficProfile)
+ tp_config = {'traffic_profile': {'duration': 15}}
+ dummy_profile = base.DummyProfile(tp_config)
self.assertIsNone(dummy_profile.execute({}))
+
+
+class TrafficProfileConfigTestCase(unittest.TestCase):
+
+ def test__init(self):
+ tp_config = {'traffic_profile': {'packet_sizes': {'64B': 100}}}
+ tp_config_obj = base.TrafficProfileConfig(tp_config)
+ self.assertEqual({'64B': 100}, tp_config_obj.packet_sizes)
+ self.assertEqual(base.TrafficProfileConfig.DEFAULT_SCHEMA,
+ tp_config_obj.schema)
+ self.assertEqual(base.TrafficProfileConfig.DEFAULT_FRAME_RATE,
+ tp_config_obj.frame_rate)
+ self.assertEqual(base.TrafficProfileConfig.DEFAULT_DURATION,
+ tp_config_obj.duration)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_fixed.py b/yardstick/tests/unit/network_services/traffic_profile/test_fixed.py
index 39905e6b1..2f6713760 100644
--- a/yardstick/tests/unit/network_services/traffic_profile/test_fixed.py
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_fixed.py
@@ -102,8 +102,7 @@ class TestFixedProfile(unittest.TestCase):
'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
def test___init__(self):
- fixed_profile = \
- FixedProfile(TrafficProfile)
+ fixed_profile = FixedProfile(self.TRAFFIC_PROFILE)
self.assertIsNotNone(fixed_profile)
def test_execute(self):
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_http.py b/yardstick/tests/unit/network_services/traffic_profile/test_http.py
index 0d1b916a7..d44fab2b5 100644
--- a/yardstick/tests/unit/network_services/traffic_profile/test_http.py
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_http.py
@@ -11,30 +11,29 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
import unittest
-from yardstick.network_services.traffic_profile.base import TrafficProfile
-from yardstick.network_services.traffic_profile.http import \
- TrafficProfileGenericHTTP
+from yardstick.network_services.traffic_profile import http
class TestTrafficProfileGenericHTTP(unittest.TestCase):
+
+ TP_CONFIG = {'traffic_profile': {'duration': 10}}
+
def test___init__(self):
- traffic_profile_generic_htt_p = \
- TrafficProfileGenericHTTP(TrafficProfile)
- self.assertIsNotNone(traffic_profile_generic_htt_p)
+ tp_generic_http = http.TrafficProfileGenericHTTP(
+ self.TP_CONFIG)
+ self.assertIsNotNone(tp_generic_http)
def test_execute(self):
- traffic_profile_generic_htt_p = \
- TrafficProfileGenericHTTP(TrafficProfile)
+ tp_generic_http = http.TrafficProfileGenericHTTP(
+ self.TP_CONFIG)
traffic_generator = {}
- self.assertIsNone(
- traffic_profile_generic_htt_p.execute(traffic_generator))
+ self.assertIsNone(tp_generic_http.execute(traffic_generator))
def test__send_http_request(self):
- traffic_profile_generic_htt_p = \
- TrafficProfileGenericHTTP(TrafficProfile)
- self.assertIsNone(traffic_profile_generic_htt_p._send_http_request(
- "10.1.1.1", "250", "/req"))
+ tp_generic_http = http.TrafficProfileGenericHTTP(
+ self.TP_CONFIG)
+ self.assertIsNone(tp_generic_http._send_http_request(
+ '10.1.1.1', '250', '/req'))
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py b/yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py
index 2684e0ba1..0cf93f9ae 100644
--- a/yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py
@@ -11,33 +11,26 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-import unittest
import mock
-from yardstick.tests import STL_MOCKS
-
+from trex_stl_lib import api as Pkt
+from trex_stl_lib import trex_stl_client
+from trex_stl_lib import trex_stl_packet_builder_scapy
+from trex_stl_lib import trex_stl_streams
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.tests.unit import base
-if stl_patch:
- from yardstick.network_services.traffic_profile.trex_traffic_profile \
- import TrexProfile
- from yardstick.network_services.traffic_profile.rfc2544 import \
- RFC2544Profile
-
-class TestRFC2544Profile(unittest.TestCase):
+class TestRFC2544Profile(base.BaseUnitTestCase):
TRAFFIC_PROFILE = {
"schema": "isb:traffic_profile:0.1",
"name": "fixed",
"description": "Fixed traffic profile to run UDP traffic",
"traffic_profile": {
"traffic_type": "FixedTraffic",
- "frame_rate": 100, # pps
+ "frame_rate": 100,
"flow_number": 10,
"frame_size": 64}}
@@ -45,233 +38,251 @@ class TestRFC2544Profile(unittest.TestCase):
'name': 'rfc2544',
'traffic_profile': {'traffic_type': 'RFC2544Profile',
'frame_rate': 100},
- 'downlink_0': {'ipv4':
- {'outer_l2': {'framesize':
- {'64B': '100', '1518B': '0',
- '128B': '0', '1400B': '0',
- '256B': '0', '373b': '0',
- '570B': '0'}},
- 'outer_l3v4': {'dstip4': '1.1.1.1-1.15.255.255',
- 'proto': 'udp',
- 'srcip4': '90.90.1.1-90.105.255.255',
- 'dscp': 0, 'ttl': 32, 'count': 1},
- 'outer_l4': {'srcport': '2001',
- 'dsrport': '1234', 'count': 1}}},
- 'uplink_0': {'ipv4':
- {'outer_l2': {'framesize':
- {'64B': '100', '1518B': '0',
- '128B': '0', '1400B': '0',
- '256B': '0', '373b': '0',
- '570B': '0'}},
- 'outer_l3v4': {'dstip4': '9.9.1.1-90.105.255.255',
- 'proto': 'udp',
- 'srcip4': '1.1.1.1-1.15.255.255',
- 'dscp': 0, 'ttl': 32, 'count': 1},
- 'outer_l4': {'dstport': '2001',
- 'srcport': '1234', 'count': 1}}},
+ 'downlink_0':
+ {'ipv4':
+ {'outer_l2':
+ {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'}},
+ 'outer_l3v4':
+ {'dstip4': '1.1.1.1-1.15.255.255',
+ 'proto': 'udp',
+ 'srcip4': '90.90.1.1-90.105.255.255',
+ 'dscp': 0, 'ttl': 32, 'count': 1},
+ 'outer_l4':
+ {'srcport': '2001',
+ 'dsrport': '1234', 'count': 1}}},
+ 'uplink_0':
+ {'ipv4':
+ {'outer_l2':
+ {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'}},
+ 'outer_l3v4':
+ {'dstip4': '9.9.1.1-90.105.255.255',
+ 'proto': 'udp',
+ 'srcip4': '1.1.1.1-1.15.255.255',
+ 'dscp': 0, 'ttl': 32, 'count': 1},
+ 'outer_l4':
+ {'dstport': '2001',
+ 'srcport': '1234', 'count': 1}}},
'schema': 'isb:traffic_profile:0.1'}
def test___init__(self):
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- self.assertIsNotNone(r_f_c2544_profile.rate)
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ self.assertEqual(rfc2544_profile.max_rate, rfc2544_profile.rate)
+ self.assertEqual(0, rfc2544_profile.min_rate)
- def test_execute(self):
- traffic_generator = mock.Mock(autospec=TrexProfile)
- traffic_generator.networks = {
- "uplink_0": ["xe0"],
- "downlink_0": ["xe1"],
- }
- traffic_generator.client.return_value = True
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile.params = self.PROFILE
- r_f_c2544_profile.first_run = True
- self.assertIsNone(r_f_c2544_profile.execute_traffic(traffic_generator))
+ def test_stop_traffic(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ mock_generator = mock.Mock()
+ rfc2544_profile.stop_traffic(traffic_generator=mock_generator)
+ mock_generator.client.stop.assert_called_once()
+ mock_generator.client.reset.assert_called_once()
+ mock_generator.client.remove_all_streams.assert_called_once()
- def test_get_drop_percentage(self):
- traffic_generator = mock.Mock(autospec=TrexProfile)
- traffic_generator.networks = {
- "uplink_0": ["xe0"],
- "downlink_0": ["xe1"],
- }
- traffic_generator.client.return_value = True
+ def test_execute_traffic(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ mock_generator = mock.Mock()
+ mock_generator.networks = {
+ 'downlink_0': ['xe0', 'xe1'],
+ 'uplink_0': ['xe2', 'xe3'],
+ 'downlink_1': []}
+ mock_generator.port_num.side_effect = [10, 20, 30, 40]
+ mock_generator.rfc2544_helper.correlated_traffic = False
+ rfc2544_profile.params = {
+ 'downlink_0': 'profile1',
+ 'uplink_0': 'profile2'}
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile.params = self.PROFILE
- r_f_c2544_profile.register_generator(traffic_generator)
- self.assertIsNone(r_f_c2544_profile.execute_traffic(traffic_generator))
+ with mock.patch.object(rfc2544_profile, '_create_profile') as \
+ mock_create_profile:
+ rfc2544_profile.execute_traffic(traffic_generator=mock_generator)
+ mock_create_profile.assert_has_calls([
+ mock.call('profile1', rfc2544_profile.rate, mock.ANY),
+ mock.call('profile1', rfc2544_profile.rate, mock.ANY),
+ mock.call('profile2', rfc2544_profile.rate, mock.ANY),
+ mock.call('profile2', rfc2544_profile.rate, mock.ANY)])
+ mock_generator.client.add_streams.assert_has_calls([
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[30]),
+ mock.call(mock.ANY, ports=[40])])
+ mock_generator.client.start(ports=[10, 20, 30, 40],
+ duration=rfc2544_profile.config.duration,
+ force=True)
- samples = {}
- for ifname in range(1):
- name = "xe{}".format(ifname)
- samples[name] = {
- "rx_throughput_fps": 20,
- "tx_throughput_fps": 20,
- "rx_throughput_mbps": 10,
- "tx_throughput_mbps": 10,
- "in_packets": 1000,
- "out_packets": 1000,
- }
+ @mock.patch.object(trex_stl_streams, 'STLProfile')
+ def test__create_profile(self, mock_stl_profile):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ port_pg_id = mock.ANY
+ profile_data = {'packetid_1': {'outer_l2': {'framesize': 'imix_info'}}}
+ rate = 100
+ with mock.patch.object(rfc2544_profile, '_create_imix_data') as \
+ mock_create_imix, \
+ mock.patch.object(rfc2544_profile, '_create_vm') as \
+ mock_create_vm, \
+ mock.patch.object(rfc2544_profile, '_create_streams') as \
+ mock_create_streams:
+ mock_create_imix.return_value = 'imix_data'
+ mock_create_streams.return_value = ['stream1']
+ rfc2544_profile._create_profile(profile_data, rate, port_pg_id)
- expected = {
- 'DropPercentage': 0.0,
- 'RxThroughput': 100 / 3.0,
- 'TxThroughput': 100 / 3.0,
- 'CurrentDropPercentage': 0.0,
- 'Throughput': 66.66666666666667,
- 'xe0': {
- 'tx_throughput_fps': 20,
- 'in_packets': 1000,
- 'out_packets': 1000,
- 'rx_throughput_mbps': 10,
- 'tx_throughput_mbps': 10,
- 'rx_throughput_fps': 20,
- },
- }
- traffic_generator.generate_samples.return_value = samples
- traffic_generator.RUN_DURATION = 30
- traffic_generator.rfc2544_helper.tolerance_low = 0.0001
- traffic_generator.rfc2544_helper.tolerance_high = 0.0001
- result = r_f_c2544_profile.get_drop_percentage(traffic_generator)
- self.assertDictEqual(result, expected)
+ mock_create_imix.assert_called_once_with('imix_info')
+ mock_create_vm.assert_called_once_with(
+ {'outer_l2': {'framesize': 'imix_info'}})
+ mock_create_streams.assert_called_once_with('imix_data', 100,
+ port_pg_id)
+ mock_stl_profile.assert_called_once_with(['stream1'])
- def test_get_drop_percentage_update(self):
- traffic_generator = mock.Mock(autospec=RFC2544Profile)
- traffic_generator.networks = {
- "uplink_0": ["xe0"],
- "downlink_0": ["xe1"],
- }
- traffic_generator.client = mock.Mock(return_value=True)
+ def test__create_imix_data(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ data = {'64B': 50, '128B': 50}
+ self.assertEqual({'64': 50.0, '128': 50.0},
+ rfc2544_profile._create_imix_data(data))
+ data = {'64B': 1, '128b': 3}
+ self.assertEqual({'64': 25.0, '128': 75.0},
+ rfc2544_profile._create_imix_data(data))
+ data = {}
+ self.assertEqual({}, rfc2544_profile._create_imix_data(data))
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile.params = self.PROFILE
- r_f_c2544_profile.register_generator(traffic_generator)
- self.assertIsNone(r_f_c2544_profile.execute_traffic())
+ def test__create_vm(self):
+ packet = {'outer_l2': 'l2_definition'}
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ with mock.patch.object(rfc2544_profile, '_set_outer_l2_fields') as \
+ mock_l2_fileds:
+ rfc2544_profile._create_vm(packet)
+ mock_l2_fileds.assert_called_once_with('l2_definition')
- samples = {}
- for ifname in range(1):
- name = "xe{}".format(ifname)
- samples[name] = {
- "rx_throughput_fps": 20,
- "tx_throughput_fps": 20,
- "rx_throughput_mbps": 10,
- "tx_throughput_mbps": 10,
- "in_packets": 1000,
- "out_packets": 1002,
- }
- expected = {
- 'DropPercentage': 0.1996,
- 'RxThroughput': 33.333333333333336,
- 'TxThroughput': 33.4,
- 'CurrentDropPercentage': 0.1996,
- 'Throughput': 66.66666666666667,
- 'xe0': {
- 'tx_throughput_fps': 20,
- 'in_packets': 1000,
- 'out_packets': 1002,
- 'rx_throughput_mbps': 10,
- 'tx_throughput_mbps': 10,
- 'rx_throughput_fps': 20,
- },
- }
- traffic_generator.generate_samples = mock.MagicMock(
- return_value=samples)
- traffic_generator.RUN_DURATION = 30
- traffic_generator.rfc2544_helper.tolerance_low = 0.0001
- traffic_generator.rfc2544_helper.tolerance_high = 0.0001
- result = r_f_c2544_profile.get_drop_percentage(traffic_generator)
- self.assertDictEqual(expected, result)
+ @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+ return_value='packet')
+ def test__create_single_packet(self, mock_pktbuilder):
+ size = 128
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.ether_packet = Pkt.Eth()
+ rfc2544_profile.ip_packet = Pkt.IP()
+ rfc2544_profile.udp_packet = Pkt.UDP()
+ rfc2544_profile.trex_vm = 'trex_vm'
+ base_pkt = (rfc2544_profile.ether_packet / rfc2544_profile.ip_packet /
+ rfc2544_profile.udp_packet)
+ pad = (size - len(base_pkt)) * 'x'
+ output = rfc2544_profile._create_single_packet(size=size)
+ mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+ vm='trex_vm')
+ self.assertEqual(output, 'packet')
- def test_get_drop_percentage_div_zero(self):
- traffic_generator = mock.Mock(autospec=TrexProfile)
- traffic_generator.networks = {
- "uplink_0": ["xe0"],
- "downlink_0": ["xe1"],
- }
- traffic_generator.client = \
- mock.Mock(return_value=True)
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile.params = self.PROFILE
- self.assertIsNone(
- r_f_c2544_profile.execute_traffic(traffic_generator))
- samples = {}
- for ifname in range(1):
- name = "xe{}".format(ifname)
- samples[name] = {"rx_throughput_fps": 20,
- "tx_throughput_fps": 20,
- "rx_throughput_mbps": 10,
- "tx_throughput_mbps": 10,
- "in_packets": 1000,
- "out_packets": 0}
- r_f_c2544_profile.throughput_max = 0
- expected = {
- 'DropPercentage': 100.0, 'RxThroughput': 100 / 3.0,
- 'TxThroughput': 0.0, 'CurrentDropPercentage': 100.0,
- 'Throughput': 66.66666666666667,
- 'xe0': {
- 'tx_throughput_fps': 20, 'in_packets': 1000,
- 'out_packets': 0, 'rx_throughput_mbps': 10,
- 'tx_throughput_mbps': 10, 'rx_throughput_fps': 20
- }
- }
- traffic_generator.generate_samples = mock.Mock(return_value=samples)
- traffic_generator.RUN_DURATION = 30
- traffic_generator.rfc2544_helper.tolerance_low = 0.0001
- traffic_generator.rfc2544_helper.tolerance_high = 0.0001
- self.assertDictEqual(expected,
- r_f_c2544_profile.get_drop_percentage(traffic_generator))
+ @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+ return_value='packet')
+ def test__create_single_packet_qinq(self, mock_pktbuilder):
+ size = 128
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.ether_packet = Pkt.Eth()
+ rfc2544_profile.ip_packet = Pkt.IP()
+ rfc2544_profile.udp_packet = Pkt.UDP()
+ rfc2544_profile.trex_vm = 'trex_vm'
+ rfc2544_profile.qinq = True
+ rfc2544_profile.qinq_packet = Pkt.Dot1Q(vlan=1) / Pkt.Dot1Q(vlan=2)
+ base_pkt = (rfc2544_profile.ether_packet /
+ rfc2544_profile.qinq_packet / rfc2544_profile.ip_packet /
+ rfc2544_profile.udp_packet)
+ pad = (size - len(base_pkt)) * 'x'
+ output = rfc2544_profile._create_single_packet(size=size)
+ mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+ vm='trex_vm')
+ self.assertEqual(output, 'packet')
+
+ @mock.patch.object(trex_stl_streams, 'STLFlowLatencyStats')
+ @mock.patch.object(trex_stl_streams, 'STLTXCont')
+ @mock.patch.object(trex_stl_client, 'STLStream')
+ def test__create_streams(self, mock_stream, mock_txcont, mock_latency):
+ imix_data = {'64': 25, '512': 75}
+ rate = 35
+ port_pg_id = rfc2544.PortPgIDMap()
+ port_pg_id.add_port(10)
+ mock_stream.side_effect = ['stream1', 'stream2']
+ mock_txcont.side_effect = ['txcont1', 'txcont2']
+ mock_latency.side_effect = ['latency1', 'latency2']
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ with mock.patch.object(rfc2544_profile, '_create_single_packet'):
+ output = rfc2544_profile._create_streams(imix_data, rate,
+ port_pg_id)
+ self.assertEqual(['stream1', 'stream2'], output)
+ mock_latency.assert_has_calls([
+ mock.call(pg_id=1), mock.call(pg_id=2)])
+ mock_txcont.assert_has_calls([
+ mock.call(percentage=float(25 * 35) / 100),
+ mock.call(percentage=float(75 * 35) / 100)], any_order=True)
+
+ def test_get_drop_percentage(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ samples = [
+ {'xe1': {'tx_throughput_fps': 100,
+ 'rx_throughput_fps': 101,
+ 'out_packets': 2000,
+ 'in_packets': 2010},
+ 'xe2': {'tx_throughput_fps': 200,
+ 'rx_throughput_fps': 201,
+ 'out_packets': 4000,
+ 'in_packets': 4010}},
+ {'xe1': {'tx_throughput_fps': 106,
+ 'rx_throughput_fps': 108,
+ 'out_packets': 2031,
+ 'in_packets': 2040,
+ 'latency': 'Latency1'},
+ 'xe2': {'tx_throughput_fps': 203,
+ 'rx_throughput_fps': 215,
+ 'out_packets': 4025,
+ 'in_packets': 4040,
+ 'latency': 'Latency2'}}
+ ]
+ output = rfc2544_profile.get_drop_percentage(samples, 0, 0, False)
+ expected = {'DropPercentage': 0.3963,
+ 'Latency': {'xe1': 'Latency1', 'xe2': 'Latency2'},
+ 'RxThroughput': 312.5,
+ 'TxThroughput': 304.5,
+ 'CurrentDropPercentage': 0.3963,
+ 'Rate': 100,
+ 'Throughput': 312.5}
+ self.assertEqual(expected, output)
- def test_get_multiplier(self):
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile.max_rate = 100
- r_f_c2544_profile.min_rate = 100
- self.assertEqual("1.0", r_f_c2544_profile.get_multiplier())
- def test_calculate_pps(self):
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile.rate = 100
- r_f_c2544_profile.pps = 100
- samples = {'Throughput': 4549093.33}
- self.assertEqual((2274546.67, 1.0),
- r_f_c2544_profile.calculate_pps(samples))
+class PortPgIDMapTestCase(base.BaseUnitTestCase):
- def test_create_single_stream(self):
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile._create_single_packet = mock.MagicMock()
- r_f_c2544_profile.pg_id = 1
- self.assertIsNotNone(
- r_f_c2544_profile.create_single_stream(64, 2274546.67))
+ def test_add_port(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ port_pg_id_map.add_port(10)
+ self.assertEqual(10, port_pg_id_map._last_port)
+ self.assertEqual([], port_pg_id_map._port_pg_id_map[10])
- def test_create_single_stream_no_pg_id(self):
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile._create_single_packet = mock.MagicMock()
- r_f_c2544_profile.pg_id = 0
- self.assertIsNotNone(
- r_f_c2544_profile.create_single_stream(64, 2274546.67))
+ def test_get_pg_ids(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ port_pg_id_map.add_port(10)
+ port_pg_id_map.increase_pg_id()
+ port_pg_id_map.increase_pg_id()
+ port_pg_id_map.add_port(20)
+ port_pg_id_map.increase_pg_id()
+ self.assertEqual([1, 2], port_pg_id_map.get_pg_ids(10))
+ self.assertEqual([3], port_pg_id_map.get_pg_ids(20))
- def test_execute_latency(self):
- traffic_generator = mock.Mock(autospec=TrexProfile)
- traffic_generator.networks = {
- "private_0": ["xe0"],
- "public_0": ["xe1"],
- }
- traffic_generator.client = \
- mock.Mock(return_value=True)
- r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
- r_f_c2544_profile.params = self.PROFILE
- r_f_c2544_profile.first_run = True
- samples = {}
- for ifname in range(1):
- name = "xe{}".format(ifname)
- samples[name] = {"rx_throughput_fps": 20,
- "tx_throughput_fps": 20,
- "rx_throughput_mbps": 10,
- "tx_throughput_mbps": 10,
- "in_packets": 1000,
- "out_packets": 0}
+ def test_increase_pg_id_no_port(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ self.assertIsNone(port_pg_id_map.increase_pg_id())
- samples['Throughput'] = 4549093.33
- r_f_c2544_profile.calculate_pps = mock.Mock(return_value=[2274546.67,
- 1.0])
+ def test_increase_pg_id_last_port(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ port_pg_id_map.add_port(10)
+ self.assertEqual(1, port_pg_id_map.increase_pg_id())
+ self.assertEqual([1], port_pg_id_map.get_pg_ids(10))
+ self.assertEqual(10, port_pg_id_map._last_port)
- self.assertIsNone(r_f_c2544_profile.execute_latency(traffic_generator,
- samples))
+ def test_increase_pg_id(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ port_pg_id_map.add_port(10)
+ port_pg_id_map.increase_pg_id()
+ self.assertEqual(2, port_pg_id_map.increase_pg_id(port=20))
+ self.assertEqual([1], port_pg_id_map.get_pg_ids(10))
+ self.assertEqual([2], port_pg_id_map.get_pg_ids(20))
+ self.assertEqual(20, port_pg_id_map._last_port)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py b/yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py
index 7111c8075..628e85459 100644
--- a/yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py
@@ -14,29 +14,12 @@
import ipaddress
-import mock
import six
import unittest
from yardstick.common import exceptions as y_exc
-from yardstick.tests import STL_MOCKS
-
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
- from yardstick.network_services.traffic_profile.base import TrafficProfile
- from yardstick.network_services.traffic_profile.trex_traffic_profile import TrexProfile
- from yardstick.network_services.traffic_profile.trex_traffic_profile import SRC
- from yardstick.network_services.traffic_profile.trex_traffic_profile import DST
- from yardstick.network_services.traffic_profile.trex_traffic_profile import ETHERNET
- from yardstick.network_services.traffic_profile.trex_traffic_profile import IP
- from yardstick.network_services.traffic_profile.trex_traffic_profile import IPv6
- from yardstick.network_services.traffic_profile.trex_traffic_profile import UDP
- from yardstick.network_services.traffic_profile.trex_traffic_profile import SRC_PORT
- from yardstick.network_services.traffic_profile.trex_traffic_profile import DST_PORT
- from yardstick.network_services.traffic_profile.trex_traffic_profile import TYPE_OF_SERVICE
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import trex_traffic_profile
class TestTrexProfile(unittest.TestCase):
@@ -59,7 +42,7 @@ class TestTrexProfile(unittest.TestCase):
'name': 'rfc2544',
'traffic_profile': {'traffic_type': 'RFC2544Profile',
'frame_rate': 100},
- TrafficProfile.DOWNLINK: {
+ tp_base.TrafficProfile.DOWNLINK: {
'ipv4': {'outer_l2': {'framesize': {'64B': '100',
'1518B': '0',
'128B': '0',
@@ -77,7 +60,7 @@ class TestTrexProfile(unittest.TestCase):
'outer_l4': {'srcport': '2001',
'dsrport': '1234',
'count': 1}}},
- TrafficProfile.UPLINK: {
+ tp_base.TrafficProfile.UPLINK: {
'ipv4':
{'outer_l2': {'framesize':
{'64B': '100', '1518B': '0',
@@ -99,7 +82,7 @@ class TestTrexProfile(unittest.TestCase):
'name': 'rfc2544',
'traffic_profile': {'traffic_type': 'RFC2544Profile',
'frame_rate': 100},
- TrafficProfile.DOWNLINK: {
+ tp_base.TrafficProfile.DOWNLINK: {
'ipv6': {'outer_l2': {'framesize':
{'64B': '100', '1518B': '0',
'128B': '0', '1400B': '0',
@@ -118,7 +101,7 @@ class TestTrexProfile(unittest.TestCase):
'outer_l4': {'srcport': '2001',
'dsrport': '1234',
'count': 1}}},
- TrafficProfile.UPLINK: {
+ tp_base.TrafficProfile.UPLINK: {
'ipv6': {'outer_l2': {'framesize':
{'64B': '100', '1518B': '0',
'128B': '0', '1400B': '0',
@@ -140,17 +123,15 @@ class TestTrexProfile(unittest.TestCase):
'schema': 'isb:traffic_profile:0.1'}
def test___init__(self):
- TrafficProfile.params = self.PROFILE
- trex_profile = \
- TrexProfile(TrafficProfile)
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
self.assertEqual(trex_profile.pps, 100)
def test_qinq(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
"C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
- trex_profile = \
- TrexProfile(TrafficProfile)
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
self.assertIsNone(trex_profile.set_qinq(qinq))
qinq = {"S-VLAN": {"id": "128-130", "priority": 0, "cfi": 0},
@@ -158,64 +139,39 @@ class TestTrexProfile(unittest.TestCase):
self.assertIsNone(trex_profile.set_qinq(qinq))
def test__set_outer_l2_fields(self):
- trex_profile = \
- TrexProfile(TrafficProfile)
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
"C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
- outer_l2 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l2']
+ outer_l2 = self.PROFILE[
+ tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l2']
outer_l2['QinQ'] = qinq
self.assertIsNone(trex_profile._set_outer_l2_fields(outer_l2))
def test__set_outer_l3v4_fields(self):
- trex_profile = \
- TrexProfile(TrafficProfile)
- outer_l3v4 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l3v4']
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ outer_l3v4 = self.PROFILE[
+ tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l3v4']
outer_l3v4['proto'] = 'tcp'
self.assertIsNone(trex_profile._set_outer_l3v4_fields(outer_l3v4))
def test__set_outer_l3v6_fields(self):
- trex_profile = \
- TrexProfile(TrafficProfile)
- outer_l3v6 = self.PROFILE_v6[TrafficProfile.UPLINK]['ipv6']['outer_l3v4']
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ outer_l3v6 = self.PROFILE_v6[
+ tp_base.TrafficProfile.UPLINK]['ipv6']['outer_l3v4']
outer_l3v6['proto'] = 'tcp'
outer_l3v6['tc'] = 1
outer_l3v6['hlim'] = 10
self.assertIsNone(trex_profile._set_outer_l3v6_fields(outer_l3v6))
def test__set_outer_l4_fields(self):
- trex_profile = \
- TrexProfile(TrafficProfile)
- outer_l4 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l4']
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ outer_l4 = self.PROFILE[
+ tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l4']
self.assertIsNone(trex_profile._set_outer_l4_fields(outer_l4))
- def test_get_streams(self):
- trex_profile = \
- TrexProfile(TrafficProfile)
- trex_profile.params = self.PROFILE
- profile_data = self.PROFILE[TrafficProfile.UPLINK]
- self.assertIsNotNone(trex_profile.get_streams(profile_data))
- trex_profile.pg_id = 1
- self.assertIsNotNone(trex_profile.get_streams(profile_data))
- trex_profile.params = self.PROFILE_v6
- trex_profile.profile_data = self.PROFILE_v6[TrafficProfile.UPLINK]
- self.assertIsNotNone(trex_profile.get_streams(profile_data))
- trex_profile.pg_id = 1
- self.assertIsNotNone(trex_profile.get_streams(profile_data))
-
- def test_generate_packets(self):
- trex_profile = \
- TrexProfile(TrafficProfile)
- trex_profile.fsize = 10
- trex_profile.base_pkt = [10]
- self.assertIsNone(trex_profile.generate_packets())
-
- def test_generate_imix_data_error(self):
- trex_profile = \
- TrexProfile(TrafficProfile)
- self.assertEqual({}, trex_profile.generate_imix_data(False))
-
def test__count_ip_ipv4(self):
- start, end, count = TrexProfile._count_ip('1.1.1.1', '1.2.3.4')
+ start, end, count = trex_traffic_profile.TrexProfile._count_ip(
+ '1.1.1.1', '1.2.3.4')
self.assertEqual('1.1.1.1', str(start))
self.assertEqual('1.2.3.4', str(end))
diff = (int(ipaddress.IPv4Address(six.u('1.2.3.4'))) -
@@ -225,7 +181,8 @@ class TestTrexProfile(unittest.TestCase):
def test__count_ip_ipv6(self):
start_ip = '0064:ff9b:0:0:0:0:9810:6414'
end_ip = '0064:ff9b:0:0:0:0:9810:6420'
- start, end, count = TrexProfile._count_ip(start_ip, end_ip)
+ start, end, count = trex_traffic_profile.TrexProfile._count_ip(
+ start_ip, end_ip)
self.assertEqual(0x98106414, start)
self.assertEqual(0x98106420, end)
self.assertEqual(0x98106420 - 0x98106414, count)
@@ -234,10 +191,10 @@ class TestTrexProfile(unittest.TestCase):
start_ip = '0064:ff9b:0:0:0:0:9810:6420'
end_ip = '0064:ff9b:0:0:0:0:9810:6414'
with self.assertRaises(y_exc.IPv6RangeError):
- TrexProfile._count_ip(start_ip, end_ip)
+ trex_traffic_profile.TrexProfile._count_ip(start_ip, end_ip)
def test__dscp_range_action_partial_actual_count_zero(self):
- traffic_profile = TrexProfile(TrafficProfile)
+ traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
dscp_partial = traffic_profile._dscp_range_action_partial()
flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
@@ -245,7 +202,7 @@ class TestTrexProfile(unittest.TestCase):
self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
def test__dscp_range_action_partial_count_greater_than_actual(self):
- traffic_profile = TrexProfile(TrafficProfile)
+ traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
dscp_partial = traffic_profile._dscp_range_action_partial()
flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
@@ -253,7 +210,7 @@ class TestTrexProfile(unittest.TestCase):
self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
def test__udp_range_action_partial_actual_count_zero(self):
- traffic_profile = TrexProfile(TrafficProfile)
+ traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
traffic_profile.udp['field1'] = 'value1'
udp_partial = traffic_profile._udp_range_action_partial('field1')
@@ -262,48 +219,59 @@ class TestTrexProfile(unittest.TestCase):
self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
def test__udp_range_action_partial_count_greater_than_actual(self):
- traffic_profile = TrexProfile(TrafficProfile)
+ traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
traffic_profile.udp['field1'] = 'value1'
- udp_partial = traffic_profile._udp_range_action_partial('field1', 'not_used_count')
-
+ udp_partial = traffic_profile._udp_range_action_partial(
+ 'field1', 'not_used_count')
flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
udp_partial('1', '10', '100')
self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
def test__general_single_action_partial(self):
- trex_profile = TrexProfile(TrafficProfile)
-
- trex_profile._general_single_action_partial(ETHERNET)(SRC)(
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ trex_profile._general_single_action_partial(
+ trex_traffic_profile.ETHERNET)(trex_traffic_profile.SRC)(
self.EXAMPLE_ETHERNET_ADDR)
self.assertEqual(self.EXAMPLE_ETHERNET_ADDR,
trex_profile.ether_packet.src)
- trex_profile._general_single_action_partial(IP)(DST)(
- self.EXAMPLE_IP_ADDR)
+ trex_profile._general_single_action_partial(trex_traffic_profile.IP)(
+ trex_traffic_profile.DST)(self.EXAMPLE_IP_ADDR)
self.assertEqual(self.EXAMPLE_IP_ADDR, trex_profile.ip_packet.dst)
- trex_profile._general_single_action_partial(IPv6)(DST)(
- self.EXAMPLE_IPv6_ADDR)
+ trex_profile._general_single_action_partial(trex_traffic_profile.IPv6)(
+ trex_traffic_profile.DST)(self.EXAMPLE_IPv6_ADDR)
self.assertEqual(self.EXAMPLE_IPv6_ADDR, trex_profile.ip6_packet.dst)
- trex_profile._general_single_action_partial(UDP)(SRC_PORT)(5060)
+ trex_profile._general_single_action_partial(trex_traffic_profile.UDP)(
+ trex_traffic_profile.SRC_PORT)(5060)
self.assertEqual(5060, trex_profile.udp_packet.sport)
- trex_profile._general_single_action_partial(IP)(TYPE_OF_SERVICE)(0)
+ trex_profile._general_single_action_partial(trex_traffic_profile.IP)(
+ trex_traffic_profile.TYPE_OF_SERVICE)(0)
self.assertEqual(0, trex_profile.ip_packet.tos)
def test__set_proto_addr(self):
- trex_profile = TrexProfile(TrafficProfile)
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
ether_range = "00:00:00:00:00:01-00:00:00:00:00:02"
ip_range = "1.1.1.2-1.1.1.10"
ipv6_range = '0064:ff9b:0:0:0:0:9810:6414-0064:ff9b:0:0:0:0:9810:6420'
- trex_profile._set_proto_addr(ETHERNET, SRC, ether_range)
- trex_profile._set_proto_addr(ETHERNET, DST, ether_range)
- trex_profile._set_proto_addr(IP, SRC, ip_range)
- trex_profile._set_proto_addr(IP, DST, ip_range)
- trex_profile._set_proto_addr(IPv6, SRC, ipv6_range)
- trex_profile._set_proto_addr(IPv6, DST, ipv6_range)
- trex_profile._set_proto_addr(UDP, SRC_PORT, "5060-5090")
- trex_profile._set_proto_addr(UDP, DST_PORT, "5060")
+ trex_profile._set_proto_addr(trex_traffic_profile.ETHERNET,
+ trex_traffic_profile.SRC, ether_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.ETHERNET,
+ trex_traffic_profile.DST, ether_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.IP,
+ trex_traffic_profile.SRC, ip_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.IP,
+ trex_traffic_profile.DST, ip_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.IPv6,
+ trex_traffic_profile.SRC, ipv6_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.IPv6,
+ trex_traffic_profile.DST, ipv6_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.UDP,
+ trex_traffic_profile.SRC_PORT,
+ '5060-5090')
+ trex_profile._set_proto_addr(trex_traffic_profile.UDP,
+ trex_traffic_profile.DST_PORT, '5060')
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py
index f75fa226a..ce32a31e2 100644
--- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py
@@ -16,10 +16,13 @@
import unittest
import mock
import os
+import re
+import copy
from yardstick.tests import STL_MOCKS
from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
from yardstick.common import utils
+from yardstick.common import exceptions
STLClient = mock.MagicMock()
@@ -28,6 +31,7 @@ stl_patch.start()
if stl_patch:
from yardstick.network_services.vnf_generic.vnf.acl_vnf import AclApproxVnf
+ from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
from yardstick.network_services.nfvi.resource import ResourceProfile
from yardstick.network_services.vnf_generic.vnf.acl_vnf import AclApproxSetupEnvSetupEnvHelper
@@ -311,7 +315,6 @@ class TestAclApproxVnf(unittest.TestCase):
acl_approx_vnf._run()
acl_approx_vnf.ssh_helper.run.assert_called_once()
- @mock.patch("yardstick.network_services.vnf_generic.vnf.acl_vnf.YangModel")
@mock.patch.object(utils, 'find_relative_file')
@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
@mock.patch(SSH_HELPER)
@@ -350,6 +353,145 @@ class TestAclApproxVnf(unittest.TestCase):
class TestAclApproxSetupEnvSetupEnvHelper(unittest.TestCase):
+ ACL_CONFIG = {"access-list-entries": [{
+ "actions": [
+ "count",
+ {"fwd": {
+ "port": 0
+ }
+ }
+ ],
+ "matches": {
+ "destination-ipv4-network": "152.16.0.0/24",
+ "destination-port-range": {
+ "lower-port": 0,
+ "upper-port": 65535
+ },
+ "source-ipv4-network": "0.0.0.0/0",
+ "source-port-range": {
+ "lower-port": 0,
+ "upper-port": 65535
+ },
+ "protocol-mask": 255,
+ "protocol": 127,
+ "priority": 1
+ },
+ "rule-name": "rule1588"
+ }
+ ]}
+
+ def test_get_default_flows(self):
+ """Check if default ACL SampleVNF CLI commands are
+ generated correctly"""
+ ssh_helper = mock.Mock()
+ vnfd_helper = VnfdHelper({'vdu': [
+ {'external-interface': [
+ {
+ 'virtual-interface': {
+ 'local_ip': '152.16.100.19',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'dst_ip': '152.16.100.20',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'local_ip': '152.16.40.19',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'dst_ip': '152.16.40.20',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ }
+ ]}
+ ]})
+ setup_helper = AclApproxSetupEnvSetupEnvHelper(vnfd_helper, ssh_helper, None)
+ self.check_acl_commands(setup_helper.get_flows_config(), [
+ # format: (<cli pattern>, <number of expected matches>)
+ ("^p action add [0-9]+ accept$", 2),
+ ("^p action add [0-9]+ count$", 2),
+ ("^p action add [0-9]+ fwd 1$", 1),
+ ("^p action add [0-9]+ fwd 0$", 1),
+ ("^p acl add 1 152.16.100.0 24 152.16.40.0 24 0 65535 0 65535 0 0 [0-9]+$", 1),
+ ("^p acl add 1 152.16.40.0 24 152.16.100.0 24 0 65535 0 65535 0 0 [0-9]+$", 1),
+ ("^p acl applyruleset$", 1)
+ ])
+
+ @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+ def test_get_flows_config(self, get_default_flows):
+ """Check if provided ACL config can be converted to
+ ACL SampleVNF CLI commands correctly"""
+ ssh_helper = mock.Mock()
+ setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+ get_default_flows.return_value = ({}, [])
+ self.check_acl_commands(setup_helper.get_flows_config(self.ACL_CONFIG), [
+ # format: (<cli pattern>, <number of expected matches>)
+ ("^p action add [0-9]+ count$", 1),
+ ("^p action add [0-9]+ fwd 0$", 1),
+ ("^p acl add 1 0.0.0.0 0 152.16.0.0 24 0 65535 0 65535 127 0 [0-9]+$", 1),
+ ("^p acl applyruleset$", 1)
+ ])
+
+ @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+ def test_get_flows_config_invalid_action(self, get_default_flows):
+ """Check if incorrect ACL config fails to convert
+ to ACL SampleVNF CLI commands"""
+ ssh_helper = mock.Mock()
+ setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+ get_default_flows.return_value = ({}, [])
+ # duplicate config and add invald action
+ acl_config = copy.deepcopy(self.ACL_CONFIG)
+ acl_config['access-list-entries'][0]["actions"].append({"xnat": {}})
+ self.assertRaises(exceptions.AclUknownActionTemplate,
+ setup_helper.get_flows_config, acl_config)
+
+ @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+ def test_get_flows_config_invalid_action_param(self, get_default_flows):
+ """Check if ACL config with invalid action parameter fails to convert
+ to ACL SampleVNF CLI commands"""
+ ssh_helper = mock.Mock()
+ setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+ get_default_flows.return_value = ({}, [])
+ # duplicate config and add action with invalid parameter
+ acl_config = copy.deepcopy(self.ACL_CONFIG)
+ acl_config['access-list-entries'][0]["actions"].append(
+ {"nat": {"xport": 0}})
+ self.assertRaises(exceptions.AclMissingActionArguments,
+ setup_helper.get_flows_config, acl_config)
+
+ def check_acl_commands(self, config, expected_cli_patterns):
+ """Check if expected ACL CLI commands (given as a list of patterns,
+ `expected_cli_patterns` parameter) present in SampleVNF ACL
+ configuration (given as a multiline string, `config` parameter)"""
+ # Example of expected config:
+ # ---------------------------
+ # p action add 1 accept
+ # p action add 1 fwd 1
+ # p action add 2 accept
+ # p action add 2 count
+ # p action add 2 fwd 0
+ # p acl add 1 152.16.100.0 24 152.16.40.0 24 0 65535 0 65535 0 0 1
+ # p acl add 1 152.16.40.0 24 152.16.100.0 24 0 65535 0 65535 0 0 2
+ # p acl applyruleset
+ # ---------------------------
+ # NOTE: The config above consists of actions ids, which are actually
+ # unknown (generated at runtime), thus it's incorrect just to compare
+ # the example ACL config above with the configuration returned by
+ # get_flows_config() function. It's more correct to use CLI patterns
+ # (RE) to find the required SampleVNF CLI commands in the multiline
+ # string (SampleVNF ACL configuration).
+ for pattern, num_of_match in expected_cli_patterns:
+ # format: (<cli pattern>, <number of expected matches>)
+ result = re.findall(pattern, config, re.MULTILINE)
+ self.assertEqual(len(result), num_of_match)
+
@mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open')
@mock.patch.object(utils, 'find_relative_file')
@mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig')
@@ -359,14 +501,17 @@ class TestAclApproxSetupEnvSetupEnvHelper(unittest.TestCase):
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+ scenario_helper.options = {}
scenario_helper.all_options = {}
acl_approx_setup_helper = AclApproxSetupEnvSetupEnvHelper(vnfd_helper,
ssh_helper,
scenario_helper)
+ acl_approx_setup_helper.get_flows_config = mock.Mock()
acl_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
acl_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
acl_approx_setup_helper.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
expected = 'sudo tool_path -p 0x3 -f /tmp/acl_config -s /tmp/acl_script --hwlb 3'
self.assertEqual(acl_approx_setup_helper.build_config(), expected)
+ acl_approx_setup_helper.get_flows_config.assert_called_once()
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py
index bd8f53e21..6b6f3ef34 100644
--- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py
@@ -11,30 +11,22 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
from copy import deepcopy
-import os
+import time
import mock
import unittest
-
+from yardstick.benchmark.contexts import base as ctx_base
from yardstick.common import utils
-
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-
-
-
-from yardstick.network_services.vnf_generic.vnf.cgnapt_vnf import CgnaptApproxVnf, \
- CgnaptApproxSetupEnvHelper
+from yardstick.common import process
from yardstick.network_services.vnf_generic.vnf import cgnapt_vnf
-from yardstick.network_services.nfvi.resource import ResourceProfile
-
-TEST_FILE_YAML = 'nsb_test_case.yaml'
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.nfvi import resource
+TEST_FILE_YAML = 'nsb_test_case.yaml'
name = 'vnf__0'
@@ -42,8 +34,9 @@ class TestCgnaptApproxSetupEnvHelper(unittest.TestCase):
def test__generate_ip_from_pool(self):
- ip = CgnaptApproxSetupEnvHelper._generate_ip_from_pool("1.2.3.4")
- self.assertEqual(next(ip), '1.2.3.4')
+ _ip = '1.2.3.4'
+ ip = cgnapt_vnf.CgnaptApproxSetupEnvHelper._generate_ip_from_pool(_ip)
+ self.assertEqual(next(ip), _ip)
self.assertEqual(next(ip), '1.2.4.4')
self.assertEqual(next(ip), '1.2.5.4')
@@ -62,19 +55,22 @@ link 1 up
"""
header = "This is a header"
- out = CgnaptApproxSetupEnvHelper._update_cgnat_script_file(header, sample.splitlines())
+ out = cgnapt_vnf.CgnaptApproxSetupEnvHelper._update_cgnat_script_file(
+ header, sample.splitlines())
self.assertNotIn("This is a header", out)
def test__get_cgnapt_config(self):
vnfd_helper = mock.MagicMock()
vnfd_helper.port_pairs.uplink_ports = [{"name": 'a'}, {"name": "b"}, {"name": "c"}]
- helper = CgnaptApproxSetupEnvHelper(vnfd_helper, mock.Mock(), mock.Mock())
+ helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+ vnfd_helper, mock.Mock(), mock.Mock())
result = helper._get_cgnapt_config()
self.assertIsNotNone(result)
def test_scale(self):
- helper = CgnaptApproxSetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock())
+ helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+ mock.Mock(), mock.Mock(), mock.Mock())
with self.assertRaises(NotImplementedError):
helper.scale()
@@ -87,11 +83,11 @@ link 1 up
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+ scenario_helper.options = {}
scenario_helper.all_options = {}
- cgnat_approx_setup_helper = CgnaptApproxSetupEnvHelper(vnfd_helper,
- ssh_helper,
- scenario_helper)
+ cgnat_approx_setup_helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
cgnat_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
cgnat_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
@@ -100,7 +96,7 @@ link 1 up
self.assertEqual(cgnat_approx_setup_helper.build_config(), expected)
-@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
+@mock.patch.object(sample_vnf, 'Process')
class TestCgnaptApproxVnf(unittest.TestCase):
VNFD = {'vnfd:vnfd-catalog':
{'vnfd':
@@ -220,7 +216,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
'ip': '1.2.1.1',
'interfaces':
{'xe0': {'local_iface_name': 'ens513f0',
- 'vld_id': CgnaptApproxVnf.DOWNLINK,
+ 'vld_id': cgnapt_vnf.CgnaptApproxVnf.DOWNLINK,
'netmask': '255.255.255.0',
'local_ip': '152.16.40.20',
'dst_mac': '00:00:00:00:00:01',
@@ -248,7 +244,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
'ip': '1.2.1.1',
'interfaces':
{'xe0': {'local_iface_name': 'ens785f0',
- 'vld_id': CgnaptApproxVnf.UPLINK,
+ 'vld_id': cgnapt_vnf.CgnaptApproxVnf.UPLINK,
'netmask': '255.255.255.0',
'local_ip': '152.16.100.20',
'dst_mac': '00:00:00:00:00:02',
@@ -273,7 +269,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
'ip': '1.2.1.1',
'interfaces':
{'xe0': {'local_iface_name': 'ens786f0',
- 'vld_id': CgnaptApproxVnf.UPLINK,
+ 'vld_id': cgnapt_vnf.CgnaptApproxVnf.UPLINK,
'netmask': '255.255.255.0',
'local_ip': '152.16.100.19',
'dst_mac': '00:00:00:00:00:04',
@@ -283,7 +279,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
'vpci': '0000:05:00.0',
'dpdk_port_num': 0},
'xe1': {'local_iface_name': 'ens786f1',
- 'vld_id': CgnaptApproxVnf.DOWNLINK,
+ 'vld_id': cgnapt_vnf.CgnaptApproxVnf.DOWNLINK,
'netmask': '255.255.255.0',
'local_ip': '152.16.40.19',
'dst_mac': '00:00:00:00:00:03',
@@ -322,81 +318,59 @@ class TestCgnaptApproxVnf(unittest.TestCase):
def test___init__(self, *args):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
self.assertIsNone(cgnapt_approx_vnf._vnf_process)
- @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
- @mock.patch(SSH_HELPER)
- def test_collect_kpi(self, ssh, *args):
- mock_ssh(ssh)
-
+ @mock.patch.object(process, 'check_if_process_failed')
+ def test_collect_kpi(self, *args):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
cgnapt_approx_vnf._vnf_process = mock.MagicMock(
**{"is_alive.return_value": True, "exitcode": None})
cgnapt_approx_vnf.q_in = mock.MagicMock()
cgnapt_approx_vnf.q_out = mock.MagicMock()
cgnapt_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
- cgnapt_approx_vnf.resource = mock.Mock(autospec=ResourceProfile)
+ cgnapt_approx_vnf.resource = mock.Mock(
+ autospec=resource.ResourceProfile)
result = {'packets_dropped': 0, 'packets_fwd': 0, 'packets_in': 0}
- self.assertEqual(result, cgnapt_approx_vnf.collect_kpi())
-
- @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
- @mock.patch(SSH_HELPER)
- def test_vnf_execute_command(self, ssh, *args):
- mock_ssh(ssh)
+ with mock.patch.object(cgnapt_approx_vnf, 'get_stats',
+ return_value=''):
+ self.assertEqual(result, cgnapt_approx_vnf.collect_kpi())
+ @mock.patch.object(time, 'sleep')
+ def test_vnf_execute_command(self, *args):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
- cgnapt_approx_vnf.q_in = mock.MagicMock()
- cgnapt_approx_vnf.q_out = mock.MagicMock()
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.q_in = mock.Mock()
+ cgnapt_approx_vnf.q_out = mock.Mock()
cgnapt_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
- cmd = "quit"
- self.assertEqual("", cgnapt_approx_vnf.vnf_execute(cmd))
-
- @mock.patch(SSH_HELPER)
- def test_get_stats(self, ssh, *args):
- mock_ssh(ssh)
+ self.assertEqual("", cgnapt_approx_vnf.vnf_execute('quit'))
+ def test_get_stats(self, *args):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
- cgnapt_approx_vnf.q_in = mock.MagicMock()
- cgnapt_approx_vnf.q_out = mock.MagicMock()
- cgnapt_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
- result = \
- "CG-NAPT(.*\n)*Received 100, Missed 0, Dropped 0,Translated 100,ingress"
- cgnapt_approx_vnf.vnf_execute = mock.Mock(return_value=result)
- self.assertListEqual(list(result), list(cgnapt_approx_vnf.get_stats()))
-
- def _get_file_abspath(self, filename):
- curr_path = os.path.dirname(os.path.abspath(__file__))
- file_path = os.path.join(curr_path, filename)
- return file_path
-
- @mock.patch("yardstick.network_services.vnf_generic.vnf.cgnapt_vnf.hex")
- @mock.patch("yardstick.network_services.vnf_generic.vnf.cgnapt_vnf.eval")
- @mock.patch('yardstick.network_services.vnf_generic.vnf.cgnapt_vnf.open')
- @mock.patch(SSH_HELPER)
- def test_run_vcgnapt(self, ssh, *args):
- mock_ssh(ssh)
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ with mock.patch.object(cgnapt_approx_vnf, 'vnf_execute') as mock_exec:
+ mock_exec.return_value = 'output'
+ self.assertEqual('output', cgnapt_approx_vnf.get_stats())
+
+ mock_exec.assert_called_once_with('p cgnapt stats')
+ def test_run_vcgnapt(self, *args):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
- cgnapt_approx_vnf._build_config = mock.MagicMock()
- cgnapt_approx_vnf.queue_wrapper = mock.MagicMock()
- cgnapt_approx_vnf.ssh_helper = mock.MagicMock()
- cgnapt_approx_vnf.ssh_helper.run = mock.MagicMock()
- cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
- cgnapt_approx_vnf._run()
- cgnapt_approx_vnf.ssh_helper.run.assert_called_once()
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.ssh_helper = mock.Mock()
+ cgnapt_approx_vnf.setup_helper = mock.Mock()
+ with mock.patch.object(cgnapt_approx_vnf, '_build_config'), \
+ mock.patch.object(cgnapt_approx_vnf, '_build_run_kwargs'):
+ cgnapt_approx_vnf._run()
- @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
- @mock.patch(SSH_HELPER)
- def test_instantiate(self, ssh, *args):
- mock_ssh(ssh)
+ cgnapt_approx_vnf.ssh_helper.run.assert_called_once()
+ cgnapt_approx_vnf.setup_helper.kill_vnf.assert_called_once()
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+ def test_instantiate(self, *args):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
cgnapt_approx_vnf.deploy_helper = mock.MagicMock()
cgnapt_approx_vnf.resource_helper = mock.MagicMock()
cgnapt_approx_vnf._build_config = mock.MagicMock()
@@ -405,51 +379,25 @@ class TestCgnaptApproxVnf(unittest.TestCase):
cgnapt_approx_vnf.q_out.put("pipeline>")
cgnapt_vnf.WAIT_TIME = 3
self.scenario_cfg.update({"nodes": {"vnf__0": ""}})
- self.assertIsNone(cgnapt_approx_vnf.instantiate(self.scenario_cfg,
- self.context_cfg))
-
- @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
- @mock.patch(SSH_HELPER)
- def test_terminate(self, ssh, *args):
- mock_ssh(ssh)
-
- vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
- cgnapt_approx_vnf._vnf_process = mock.MagicMock()
- cgnapt_approx_vnf._vnf_process.terminate = mock.Mock()
- cgnapt_approx_vnf.used_drivers = {"01:01.0": "i40e",
- "01:01.1": "i40e"}
- cgnapt_approx_vnf.vnf_execute = mock.MagicMock()
- cgnapt_approx_vnf.dpdk_nic_bind = "dpdk_nic_bind.py"
- cgnapt_approx_vnf._resource_collect_stop = mock.Mock()
- self.assertIsNone(cgnapt_approx_vnf.terminate())
-
- @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
- @mock.patch(SSH_HELPER)
- def test__vnf_up_post(self, ssh, *args):
- mock_ssh(ssh)
+ with mock.patch.object(cgnapt_approx_vnf, '_start_vnf'):
+ self.assertIsNone(cgnapt_approx_vnf.instantiate(
+ self.scenario_cfg, self.context_cfg))
+ @mock.patch.object(time, 'sleep')
+ def test__vnf_up_post(self, *args):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
self.scenario_cfg['options'][name]['napt'] = 'static'
-
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
- cgnapt_approx_vnf._vnf_process = mock.MagicMock()
- cgnapt_approx_vnf._vnf_process.terminate = mock.Mock()
- cgnapt_approx_vnf.vnf_execute = mock.MagicMock()
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.vnf_execute = mock.Mock()
cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
- cgnapt_approx_vnf._resource_collect_stop = mock.Mock()
- cgnapt_approx_vnf._vnf_up_post()
-
- @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
- @mock.patch(SSH_HELPER)
- def test__vnf_up_post_short(self, ssh, *args):
- mock_ssh(ssh)
+ with mock.patch.object(cgnapt_approx_vnf, 'setup_helper') as \
+ mock_setup_helper:
+ mock_setup_helper._generate_ip_from_pool.return_value = ['ip1']
+ mock_setup_helper._get_cgnapt_config.return_value = ['gw_ip1']
+ cgnapt_approx_vnf._vnf_up_post()
+ def test__vnf_up_post_short(self, *args):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
- cgnapt_approx_vnf._vnf_process = mock.MagicMock()
- cgnapt_approx_vnf._vnf_process.terminate = mock.Mock()
- cgnapt_approx_vnf.vnf_execute = mock.MagicMock()
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
- cgnapt_approx_vnf._resource_collect_stop = mock.Mock()
cgnapt_approx_vnf._vnf_up_post()
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
index 603f05b97..ce849d174 100644
--- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
@@ -11,7 +11,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
from copy import deepcopy
@@ -19,37 +18,29 @@ import unittest
import mock
import six
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-from yardstick.tests import STL_MOCKS
from yardstick.benchmark.contexts.base import Context
from yardstick.common import exceptions as y_exceptions
from yardstick.common import utils
from yardstick.network_services.nfvi.resource import ResourceProfile
from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
-
-
-class MockError(BaseException):
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
+from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base
+
+
+class MockError(Exception):
pass
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
- from yardstick.network_services.vnf_generic.vnf import sample_vnf
- from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
- from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
-
-
class TestVnfSshHelper(unittest.TestCase):
VNFD_0 = {
@@ -572,6 +563,7 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
scenario_helper.vnf_cfg = {}
+ scenario_helper.options = {}
scenario_helper.all_options = {}
dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -583,6 +575,7 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
mock_multi_port_config.generate_config.assert_called()
mock_multi_port_config.generate_script.assert_called()
+ scenario_helper.options = {'rules': 'fake_file'}
scenario_helper.vnf_cfg = {'file': 'fake_file'}
dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
mock_open_rf.side_effect = mock.mock_open(read_data='fake_data')
@@ -590,7 +583,7 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
result = dpdk_setup_helper.build_config()
- mock_open_rf.assert_called_once()
+ mock_open_rf.assert_called()
self.assertEqual(result, expected)
self.assertGreaterEqual(ssh_helper.upload_config_file.call_count, 2)
mock_find.assert_called()
@@ -1001,187 +994,52 @@ class TestClientResourceHelper(unittest.TestCase):
}
@mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
- @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.STLError',
- new_callable=lambda: MockError)
- def test_get_stats_not_connected(self, mock_state_error, *args):
+ @mock.patch.object(sample_vnf, 'STLError', new_callable=lambda: MockError)
+ def test_get_stats_not_connected(self, mock_stl_error, *args):
vnfd_helper = VnfdHelper(self.VNFD_0)
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
- dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+ dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
- client_resource_helper.client = mock.MagicMock()
- client_resource_helper.client.get_stats.side_effect = mock_state_error
+ client_resource_helper.client = mock.Mock()
+ client_resource_helper.client.get_stats.side_effect = mock_stl_error
self.assertEqual(client_resource_helper.get_stats(), {})
client_resource_helper.client.get_stats.assert_called_once()
- def test_generate_samples(self):
- vnfd_helper = VnfdHelper(self.VNFD_0)
- ssh_helper = mock.Mock()
- scenario_helper = mock.Mock()
- dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
- client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
- client_resource_helper.client = mock.MagicMock()
- client_resource_helper.client.get_stats.return_value = {
- 0: {
- 'rx_pps': 5.5,
- 'tx_pps': 4.9,
- 'rx_bps': 234.78,
- 'tx_bps': 243.11,
- 'ipackets': 34251,
- 'opackets': 52342,
- },
- 1: {
- 'tx_pps': 5.9,
- 'rx_bps': 434.78,
- 'opackets': 48791,
- },
- }
-
- expected = {
- 'xe0': {
- "rx_throughput_fps": 5.5,
- "tx_throughput_fps": 4.9,
- "rx_throughput_mbps": 234.78,
- "tx_throughput_mbps": 243.11,
- "in_packets": 34251,
- "out_packets": 52342,
- },
- 'xe1': {
- "rx_throughput_fps": 0.0,
- "tx_throughput_fps": 5.9,
- "rx_throughput_mbps": 434.78,
- "tx_throughput_mbps": 0.0,
- "in_packets": 0,
- "out_packets": 48791,
- },
- }
- ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
- result = client_resource_helper.generate_samples(ports)
- self.assertDictEqual(result, expected)
-
- def test_generate_samples_with_key(self):
- vnfd_helper = VnfdHelper(self.VNFD_0)
- ssh_helper = mock.Mock()
- scenario_helper = mock.Mock()
- dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
- client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
- client_resource_helper.client = mock.MagicMock()
- client_resource_helper.client.get_stats.return_value = {
- 'key_name': 'key_value',
- 0: {
- 'rx_pps': 5.5,
- 'tx_pps': 4.9,
- 'rx_bps': 234.78,
- 'tx_bps': 243.11,
- 'ipackets': 34251,
- 'opackets': 52342,
- },
- 1: {
- 'tx_pps': 5.9,
- 'rx_bps': 434.78,
- 'opackets': 48791,
- },
- }
-
- expected = {
- 'xe0': {
- 'key_name': 'key_value',
- "rx_throughput_fps": 5.5,
- "tx_throughput_fps": 4.9,
- "rx_throughput_mbps": 234.78,
- "tx_throughput_mbps": 243.11,
- "in_packets": 34251,
- "out_packets": 52342,
- },
- 'xe1': {
- 'key_name': 'key_value',
- "rx_throughput_fps": 0.0,
- "tx_throughput_fps": 5.9,
- "rx_throughput_mbps": 434.78,
- "tx_throughput_mbps": 0.0,
- "in_packets": 0,
- "out_packets": 48791,
- },
- }
- ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
- result = client_resource_helper.generate_samples(ports, 'key_name')
- self.assertDictEqual(result, expected)
-
- def test_generate_samples_with_key_and_default(self):
- vnfd_helper = VnfdHelper(self.VNFD_0)
- ssh_helper = mock.Mock()
- scenario_helper = mock.Mock()
- dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
- client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
- client_resource_helper.client = mock.MagicMock()
- client_resource_helper.client.get_stats.return_value = {
- 0: {
- 'rx_pps': 5.5,
- 'tx_pps': 4.9,
- 'rx_bps': 234.78,
- 'tx_bps': 243.11,
- 'ipackets': 34251,
- 'opackets': 52342,
- },
- 1: {
- 'tx_pps': 5.9,
- 'rx_bps': 434.78,
- 'opackets': 48791,
- },
- }
-
- expected = {
- 'xe0': {
- 'key_name': 'default',
- "rx_throughput_fps": 5.5,
- "tx_throughput_fps": 4.9,
- "rx_throughput_mbps": 234.78,
- "tx_throughput_mbps": 243.11,
- "in_packets": 34251,
- "out_packets": 52342,
- },
- 'xe1': {
- 'key_name': 'default',
- "rx_throughput_fps": 0.0,
- "tx_throughput_fps": 5.9,
- "rx_throughput_mbps": 434.78,
- "tx_throughput_mbps": 0.0,
- "in_packets": 0,
- "out_packets": 48791,
- },
- }
- ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
- result = client_resource_helper.generate_samples(ports, 'key_name', 'default')
- self.assertDictEqual(result, expected)
-
def test_clear_stats(self):
vnfd_helper = VnfdHelper(self.VNFD_0)
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
- dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+ dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
client_resource_helper.client = mock.Mock()
self.assertIsNone(client_resource_helper.clear_stats())
- client_resource_helper.client.clear_stats.assert_called_once()
+ self.assertEqual(
+ client_resource_helper.client.clear_stats.call_count, 1)
def test_clear_stats_of_ports(self):
vnfd_helper = VnfdHelper(self.VNFD_0)
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
- dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+ dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
client_resource_helper.client = mock.Mock()
self.assertIsNone(client_resource_helper.clear_stats([3, 4]))
- client_resource_helper.client.clear_stats.assert_called_once()
+ self.assertEqual(
+ client_resource_helper.client.clear_stats.call_count, 1)
def test_start(self):
vnfd_helper = VnfdHelper(self.VNFD_0)
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
- dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+ dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
client_resource_helper.client = mock.Mock()
@@ -1192,7 +1050,8 @@ class TestClientResourceHelper(unittest.TestCase):
vnfd_helper = VnfdHelper(self.VNFD_0)
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
- dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+ dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
client_resource_helper.client = mock.Mock()
@@ -1219,17 +1078,15 @@ class TestClientResourceHelper(unittest.TestCase):
self.assertDictEqual(result, expected)
@mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
- @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
- @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.STLError',
- new_callable=lambda: MockError)
- def test__connect_with_failures(self, mock_error, *args):
+ @mock.patch.object(sample_vnf, 'STLError')
+ def test__connect_with_failures(self, mock_stl_error, *args):
vnfd_helper = VnfdHelper(self.VNFD_0)
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
client = mock.MagicMock()
- client.connect.side_effect = mock_error
+ client.connect.side_effect = mock_stl_error(msg='msg')
self.assertIs(client_resource_helper._connect(client), client)
@@ -1678,7 +1535,7 @@ class TestSampleVnf(unittest.TestCase):
@mock.patch("yardstick.ssh.SSH")
def test_instantiate(self, ssh):
- mock_ssh(ssh)
+ test_base.mock_ssh(ssh)
nodes = {
'vnf1': 'name1',
@@ -1778,7 +1635,7 @@ class TestSampleVnf(unittest.TestCase):
@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
@mock.patch("yardstick.ssh.SSH")
def test_wait_for_instantiate_empty_queue(self, ssh, *args):
- mock_ssh(ssh, exec_result=(1, "", ""))
+ test_base.mock_ssh(ssh, exec_result=(1, "", ""))
queue_size_list = [
0,
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py
index 8cc118a31..dca8098fa 100644
--- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py
@@ -18,8 +18,9 @@ import mock
import six
import unittest
-from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_ixia
+from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_ixia
TEST_FILE_YAML = 'nsb_test_case.yaml'
@@ -30,8 +31,7 @@ NAME = "tg__1"
class TestIxiaResourceHelper(unittest.TestCase):
def setUp(self):
- self._mock_IxNextgen = mock.patch.object(tg_rfc2544_ixia,
- 'IxNextgen')
+ self._mock_IxNextgen = mock.patch.object(ixnet_api, 'IxNextgen')
self.mock_IxNextgen = self._mock_IxNextgen.start()
self.addCleanup(self._stop_mocks)
@@ -48,12 +48,10 @@ class TestIxiaResourceHelper(unittest.TestCase):
def test_stop_collect_with_client(self):
mock_client = mock.Mock()
-
ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock())
-
ixia_resource_helper.client = mock_client
ixia_resource_helper.stop_collect()
- mock_client.ix_stop_traffic.assert_called_once()
+ self.assertEqual(1, ixia_resource_helper._terminated.value)
def test_run_traffic(self):
mock_tprofile = mock.Mock()
@@ -70,8 +68,7 @@ class TestIxiaResourceHelper(unittest.TestCase):
self.assertEqual('fake_samples', ixia_rhelper._queue.get())
-@mock.patch(
- "yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.IxNextgen")
+@mock.patch.object(tg_rfc2544_ixia, 'ixnet_api')
class TestIXIATrafficGen(unittest.TestCase):
VNFD = {'vnfd:vnfd-catalog':
{'vnfd':
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py
index 8b1b8a39c..9531b90c4 100644
--- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py
@@ -11,44 +11,37 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-import unittest
import mock
+import unittest
-from yardstick.tests import STL_MOCKS
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
-
-
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
- from yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex import TrexTrafficGenRFC, \
- TrexRfcResourceHelper
- from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_trex
- from yardstick.network_services.traffic_profile.base import TrafficProfile
- from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base \
- import FileAbsPath, mock_ssh
-
-MODULE_PATH = FileAbsPath(__file__)
-get_file_abspath = MODULE_PATH.get_path
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_trex
class TestTrexRfcResouceHelper(unittest.TestCase):
- @mock.patch('yardstick.network_services.helpers.samplevnf_helper.MultiPortConfig')
- @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex.time")
- @mock.patch(SSH_HELPER)
- def test__run_traffic_once(self, ssh, *_):
- mock_ssh(ssh)
+ def test__run_traffic_once(self):
+ mock_setup_helper = mock.Mock()
+ mock_traffic_profile = mock.Mock()
+ mock_traffic_profile.config.duration = 3
+ mock_traffic_profile.execute_traffic.return_value = ('fake_ports',
+ 'port_pg_id_map')
+ mock_traffic_profile.get_drop_percentage.return_value = 'percentage'
+ rfc_rh = tg_rfc2544_trex.TrexRfcResourceHelper(mock_setup_helper)
+ rfc_rh.TRANSIENT_PERIOD = 0
+ rfc_rh.rfc2544_helper = mock.Mock()
- mock_traffic_profile = mock.MagicMock(autospec=TrafficProfile,
- **{'get_drop_percentage.return_value': {}})
- sut = TrexRfcResourceHelper(mock.MagicMock(), mock.MagicMock())
- sut.client = mock.MagicMock()
- sut._run_traffic_once(mock_traffic_profile)
+ with mock.patch.object(rfc_rh, '_get_samples') as mock_get_samples:
+ rfc_rh._run_traffic_once(mock_traffic_profile)
+
+ mock_traffic_profile.execute_traffic.assert_called_once_with(rfc_rh)
+ mock_traffic_profile.stop_traffic.assert_called_once_with(rfc_rh)
+ mock_traffic_profile.stop_traffic.assert_called_once()
+ mock_get_samples.assert_has_calls([
+ mock.call('fake_ports', port_pg_id='port_pg_id_map'),
+ mock.call('fake_ports', port_pg_id='port_pg_id_map')])
class TestTrexTrafficGenRFC(unittest.TestCase):
@@ -219,33 +212,24 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
'schema': 'yardstick:task:0.1',
}
- @mock.patch(SSH_HELPER)
- def test___init__(self, ssh):
- mock_ssh(ssh)
- trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
- self.assertIsNotNone(trex_traffic_gen.resource_helper._terminated.value)
+ def setUp(self):
+ self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+ self.mock_ssh_helper = self._mock_ssh_helper.start()
+ self.addCleanup(self._stop_mocks)
- @mock.patch(SSH_HELPER)
- def test_collect_kpi(self, ssh):
- mock_ssh(ssh)
- trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
- self.assertEqual(trex_traffic_gen.collect_kpi(), {})
+ def _stop_mocks(self):
+ self._mock_ssh_helper.stop()
- @mock.patch(SSH_HELPER)
- def test_listen_traffic(self, ssh):
- mock_ssh(ssh)
- trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
- self.assertIsNone(trex_traffic_gen.listen_traffic({}))
-
- @mock.patch(SSH_HELPER)
- def test_instantiate(self, ssh):
- mock_ssh(ssh)
+ def test___init__(self):
+ trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
+ self.assertIsNotNone(trex_traffic_gen.resource_helper._terminated.value)
- mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+ def test_instantiate(self):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
mock_traffic_profile.get_traffic_definition.return_value = "64"
mock_traffic_profile.params = self.TRAFFIC_PROFILE
- trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
+ trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
trex_traffic_gen._start_server = mock.Mock(return_value=0)
trex_traffic_gen.resource_helper = mock.MagicMock()
trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
@@ -274,15 +258,12 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
scenario_cfg.update({"nodes": ["tg_1", "vnf_1"]})
self.assertIsNone(trex_traffic_gen.instantiate(scenario_cfg, {}))
- @mock.patch(SSH_HELPER)
- def test_instantiate_error(self, ssh):
- mock_ssh(ssh, exec_result=(1, "", ""))
-
- mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+ def test_instantiate_error(self):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
mock_traffic_profile.get_traffic_definition.return_value = "64"
mock_traffic_profile.params = self.TRAFFIC_PROFILE
- trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
+ trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
trex_traffic_gen.resource_helper = mock.MagicMock()
trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
scenario_cfg = {
@@ -310,29 +291,3 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
},
}
trex_traffic_gen.instantiate(scenario_cfg, {})
-
- @mock.patch(SSH_HELPER)
- def test__start_server(self, ssh):
- mock_ssh(ssh)
- trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
- trex_traffic_gen.resource_helper = mock.MagicMock()
- self.assertIsNone(trex_traffic_gen._start_server())
-
- @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex.time")
- @mock.patch(SSH_HELPER)
- def test__generate_trex_cfg(self, ssh, _):
- mock_ssh(ssh)
-
- trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
- trex_traffic_gen.ssh_helper = mock.MagicMock()
- trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
- self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
-
- def test_terminate(self):
- with mock.patch(SSH_HELPER) as ssh:
- ssh_mock = mock.Mock(autospec=ssh.SSH)
- ssh_mock.execute = mock.Mock(return_value=(0, "", ""))
- ssh.from_node.return_value = ssh_mock
- trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
- trex_traffic_gen.resource_helper = mock.MagicMock()
- self.assertIsNone(trex_traffic_gen.terminate())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py
index aae3d468f..4f8742477 100644
--- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py
@@ -11,31 +11,23 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
import copy
import mock
import unittest
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-from yardstick.tests import STL_MOCKS
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_trex
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
NAME = 'vnf_1'
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
- from yardstick.network_services.vnf_generic.vnf.tg_trex import \
- TrexTrafficGen, TrexResourceHelper
- from yardstick.network_services.traffic_profile.base import TrafficProfile
-
class TestTrexTrafficGen(unittest.TestCase):
+
VNFD = {'vnfd:vnfd-catalog':
{'vnfd':
[{'short-name': 'VpeVnf',
@@ -168,7 +160,7 @@ class TestTrexTrafficGen(unittest.TestCase):
"interfaces": {
"xe0": {
"local_iface_name": "ens786f0",
- "vld_id": TrafficProfile.UPLINK,
+ "vld_id": tp_base.TrafficProfile.UPLINK,
"netmask": "255.255.255.0",
"vpci": "0000:05:00.0",
"local_ip": "152.16.100.19",
@@ -180,7 +172,7 @@ class TestTrexTrafficGen(unittest.TestCase):
},
"xe1": {
"local_iface_name": "ens786f1",
- "vld_id": TrafficProfile.DOWNLINK,
+ "vld_id": tp_base.TrafficProfile.DOWNLINK,
"netmask": "255.255.255.0",
"vpci": "0000:05:00.1",
"local_ip": "152.16.40.19",
@@ -236,7 +228,7 @@ class TestTrexTrafficGen(unittest.TestCase):
"interfaces": {
"xe0": {
"local_iface_name": "ens513f0",
- "vld_id": TrafficProfile.DOWNLINK,
+ "vld_id": tp_base.TrafficProfile.DOWNLINK,
"netmask": "255.255.255.0",
"vpci": "0000:02:00.0",
"local_ip": "152.16.40.20",
@@ -270,7 +262,7 @@ class TestTrexTrafficGen(unittest.TestCase):
"interfaces": {
"xe0": {
"local_iface_name": "ens785f0",
- "vld_id": TrafficProfile.UPLINK,
+ "vld_id": tp_base.TrafficProfile.UPLINK,
"netmask": "255.255.255.0",
"vpci": "0000:05:00.0",
"local_ip": "152.16.100.20",
@@ -297,36 +289,35 @@ class TestTrexTrafficGen(unittest.TestCase):
}
}
- @mock.patch(SSH_HELPER)
- def test___init__(self, ssh):
- mock_ssh(ssh)
+ def setUp(self):
+ self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+ self.mock_ssh_helper = self._mock_ssh_helper.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_ssh_helper.stop()
+
+ def test___init__(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
- self.assertIsInstance(
- trex_traffic_gen.resource_helper, TrexResourceHelper)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ self.assertIsInstance(trex_traffic_gen.resource_helper,
+ tg_trex.TrexResourceHelper)
- @mock.patch(SSH_HELPER)
- def test_collect_kpi(self, ssh):
- mock_ssh(ssh)
+ def test_collect_kpi(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
trex_traffic_gen.resource_helper._queue.put({})
result = trex_traffic_gen.collect_kpi()
self.assertEqual({}, result)
- @mock.patch(SSH_HELPER)
- def test_listen_traffic(self, ssh):
- mock_ssh(ssh)
+ def test_listen_traffic(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
self.assertIsNone(trex_traffic_gen.listen_traffic({}))
- @mock.patch(SSH_HELPER)
- def test_instantiate(self, ssh):
- mock_ssh(ssh)
-
+ def test_instantiate(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
trex_traffic_gen._start_server = mock.Mock(return_value=0)
trex_traffic_gen._tg_process = mock.MagicMock()
trex_traffic_gen._tg_process.start = mock.Mock()
@@ -335,16 +326,12 @@ class TestTrexTrafficGen(unittest.TestCase):
trex_traffic_gen.ssh_helper = mock.MagicMock()
trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+ self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG,
+ self.CONTEXT_CFG))
- self.assertIsNone(trex_traffic_gen.instantiate(
- self.SCENARIO_CFG, self.CONTEXT_CFG))
-
- @mock.patch(SSH_HELPER)
- def test_instantiate_error(self, ssh):
- mock_ssh(ssh, exec_result=(1, "", ""))
-
+ def test_instantiate_error(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
trex_traffic_gen._start_server = mock.Mock(return_value=0)
trex_traffic_gen._tg_process = mock.MagicMock()
trex_traffic_gen._tg_process.start = mock.Mock()
@@ -352,62 +339,53 @@ class TestTrexTrafficGen(unittest.TestCase):
trex_traffic_gen.ssh_helper = mock.MagicMock()
trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
- self.assertIsNone(trex_traffic_gen.instantiate(
- self.SCENARIO_CFG, self.CONTEXT_CFG))
+ self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG,
+ self.CONTEXT_CFG))
- @mock.patch(SSH_HELPER)
- def test__start_server(self, ssh):
- mock_ssh(ssh)
+ def test__start_server(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
trex_traffic_gen.ssh_helper = mock.MagicMock()
trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
trex_traffic_gen.scenario_helper.scenario_cfg = {}
self.assertIsNone(trex_traffic_gen._start_server())
- @mock.patch(SSH_HELPER)
- def test__start_server_multiple_queues(self, ssh):
- mock_ssh(ssh)
+ def test__start_server_multiple_queues(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
trex_traffic_gen.ssh_helper = mock.MagicMock()
trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
trex_traffic_gen.scenario_helper.scenario_cfg = {
"options": {NAME: {"queues_per_port": 2}}}
self.assertIsNone(trex_traffic_gen._start_server())
- @mock.patch(SSH_HELPER)
- def test__traffic_runner(self, ssh):
- mock_ssh(ssh)
-
- mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+ def test__traffic_runner(self):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
mock_traffic_profile.get_traffic_definition.return_value = "64"
mock_traffic_profile.execute_traffic.return_value = "64"
mock_traffic_profile.params = self.TRAFFIC_PROFILE
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- self.sut = TrexTrafficGen(NAME, vnfd)
+ self.sut = tg_trex.TrexTrafficGen(NAME, vnfd)
self.sut.ssh_helper = mock.Mock()
self.sut.ssh_helper.run = mock.Mock()
- self.sut._connect_client = mock.Mock(autospec=STLClient)
+ self.sut._connect_client = mock.Mock()
self.sut._connect_client.get_stats = mock.Mock(return_value="0")
self.sut.resource_helper.RUN_DURATION = 0
self.sut.resource_helper.QUEUE_WAIT_TIME = 0
- # must generate cfg before we can run traffic so Trex port mapping is created
+ # must generate cfg before we can run traffic so Trex port mapping is
+ # created
self.sut.resource_helper.generate_cfg()
- self.sut._traffic_runner(mock_traffic_profile)
+ with mock.patch.object(self.sut.resource_helper, 'run_traffic'):
+ self.sut._traffic_runner(mock_traffic_profile)
- @mock.patch(SSH_HELPER)
- def test__generate_trex_cfg(self, ssh):
- mock_ssh(ssh)
+ def test__generate_trex_cfg(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
- @mock.patch(SSH_HELPER)
- def test_build_ports_reversed_pci_ordering(self, ssh):
- mock_ssh(ssh)
+ def test_build_ports_reversed_pci_ordering(self):
vnfd = copy.deepcopy(self.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
vnfd['vdu'][0]['external-interface'] = [
{'virtual-interface':
@@ -442,26 +420,24 @@ class TestTrexTrafficGen(unittest.TestCase):
'local_mac': '00:00:00:00:00:01'},
'vnfd-connection-point-ref': 'xe1',
'name': 'xe1'}]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
trex_traffic_gen.resource_helper.generate_cfg()
trex_traffic_gen.resource_helper._build_ports()
- self.assertEqual(
- sorted(trex_traffic_gen.resource_helper.all_ports), [0, 1])
+ self.assertEqual(sorted(trex_traffic_gen.resource_helper.all_ports),
+ [0, 1])
# there is a gap in ordering
- self.assertEqual(dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map),
- {0: 0, 2: 1})
-
- @mock.patch(SSH_HELPER)
- def test_run_traffic(self, ssh):
- mock_ssh(ssh)
+ self.assertEqual(
+ {0: 0, 2: 1},
+ dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map))
- mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+ def test_run_traffic(self):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
mock_traffic_profile.get_traffic_definition.return_value = "64"
mock_traffic_profile.params = self.TRAFFIC_PROFILE
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- self.sut = TrexTrafficGen(NAME, vnfd)
+ self.sut = tg_trex.TrexTrafficGen(NAME, vnfd)
self.sut.ssh_helper = mock.Mock()
self.sut.ssh_helper.run = mock.Mock()
self.sut._traffic_runner = mock.Mock(return_value=0)
@@ -470,20 +446,60 @@ class TestTrexTrafficGen(unittest.TestCase):
self.sut._traffic_process.terminate()
self.assertIsNotNone(result)
- @mock.patch(SSH_HELPER)
- def test_terminate(self, ssh):
- mock_ssh(ssh)
+ def test_terminate(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
trex_traffic_gen.ssh_helper = mock.MagicMock()
trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
self.assertIsNone(trex_traffic_gen.terminate())
- @mock.patch(SSH_HELPER)
- def test__connect_client(self, ssh):
- mock_ssh(ssh)
+ def test__connect_client(self):
vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
- trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
- client = mock.Mock(autospec=STLClient)
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ client = mock.Mock()
client.connect = mock.Mock(return_value=0)
self.assertIsNotNone(trex_traffic_gen.resource_helper._connect(client))
+
+
+class TrexResourceHelperTestCase(unittest.TestCase):
+
+ def test__get_samples(self):
+ mock_setup_helper = mock.Mock()
+ trex_rh = tg_trex.TrexResourceHelper(mock_setup_helper)
+ trex_rh.vnfd_helper.interfaces = [
+ {'name': 'interface1'},
+ {'name': 'interface2'}]
+ stats = {
+ 10: {'rx_pps': 5, 'ipackets': 200},
+ 20: {'rx_pps': 10, 'ipackets': 300},
+ 'latency': {1: {'latency': 'latency_port_10_pg_id_1'},
+ 2: {'latency': 'latency_port_10_pg_id_2'},
+ 3: {'latency': 'latency_port_20_pg_id_3'},
+ 4: {'latency': 'latency_port_20_pg_id_4'}}
+ }
+ port_pg_id = rfc2544.PortPgIDMap()
+ port_pg_id.add_port(10)
+ port_pg_id.increase_pg_id()
+ port_pg_id.increase_pg_id()
+ port_pg_id.add_port(20)
+ port_pg_id.increase_pg_id()
+ port_pg_id.increase_pg_id()
+
+ with mock.patch.object(trex_rh, 'get_stats') as mock_get_stats, \
+ mock.patch.object(trex_rh.vnfd_helper, 'port_num') as \
+ mock_port_num:
+ mock_get_stats.return_value = stats
+ mock_port_num.side_effect = [10, 20]
+ output = trex_rh._get_samples([10, 20], port_pg_id=port_pg_id)
+
+ interface = output['interface1']
+ self.assertEqual(5.0, interface['rx_throughput_fps'])
+ self.assertEqual(200, interface['in_packets'])
+ self.assertEqual('latency_port_10_pg_id_1', interface['latency'][1])
+ self.assertEqual('latency_port_10_pg_id_2', interface['latency'][2])
+
+ interface = output['interface2']
+ self.assertEqual(10.0, interface['rx_throughput_fps'])
+ self.assertEqual(300, interface['in_packets'])
+ self.assertEqual('latency_port_20_pg_id_3', interface['latency'][3])
+ self.assertEqual('latency_port_20_pg_id_4', interface['latency'][4])
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py
index ffb5cd6f0..a0a0794ea 100644
--- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py
@@ -334,7 +334,6 @@ pipeline>
vfw_approx_vnf.ssh_helper.run.assert_called_once()
@mock.patch.object(utils, 'find_relative_file')
- @mock.patch("yardstick.network_services.vnf_generic.vnf.vfw_vnf.YangModel")
@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
@mock.patch(SSH_HELPER)
def test_instantiate(self, ssh, *args):
@@ -363,12 +362,15 @@ class TestFWApproxSetupEnvHelper(unittest.TestCase):
ssh_helper = mock.Mock()
scenario_helper = mock.Mock()
scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+ scenario_helper.options = {}
scenario_helper.all_options = {}
vfw_approx_setup_helper = FWApproxSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+ vfw_approx_setup_helper.get_flows_config = mock.Mock()
vfw_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
vfw_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
vfw_approx_setup_helper.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
expected = 'sudo tool_path -p 0x3 -f /tmp/vfw_config -s /tmp/vfw_script --hwlb 3'
self.assertEqual(vfw_approx_setup_helper.build_config(), expected)
+ vfw_approx_setup_helper.get_flows_config.assert_called_once()
diff --git a/yardstick/tests/unit/orchestrator/test_kubernetes.py b/yardstick/tests/unit/orchestrator/test_kubernetes.py
index 58971f515..21a12a0d3 100644
--- a/yardstick/tests/unit/orchestrator/test_kubernetes.py
+++ b/yardstick/tests/unit/orchestrator/test_kubernetes.py
@@ -7,15 +7,17 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-# Unittest for yardstick.benchmark.orchestrator.heat
-import unittest
+import copy
+
import mock
-from yardstick.orchestrator.kubernetes import KubernetesObject
-from yardstick.orchestrator.kubernetes import KubernetesTemplate
+from yardstick.common import exceptions
+from yardstick.common import kubernetes_utils
+from yardstick.orchestrator import kubernetes
+from yardstick.tests.unit import base
-class GetTemplateTestCase(unittest.TestCase):
+class GetTemplateTestCase(base.BaseUnitTestCase):
def test_get_template(self):
output_t = {
@@ -48,7 +50,8 @@ service ssh restart;while true ; do sleep 10000; done"
"volumeMounts": [
{
"mountPath": "/tmp/.ssh/",
- "name": "k8s-86096c30-key"
+ "name": "k8s-86096c30-key",
+ "readOnly": False
}
]
}
@@ -73,14 +76,15 @@ service ssh restart;while true ; do sleep 10000; done"
'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \
service ssh restart;while true ; do sleep 10000; done'],
'ssh_key': 'k8s-86096c30-key',
- 'nodeSelector': {'kubernetes.io/hostname': 'node-01'}
+ 'nodeSelector': {'kubernetes.io/hostname': 'node-01'},
+ 'volumes': []
}
name = 'host-k8s-86096c30'
- output_r = KubernetesObject(name, **input_s).get_template()
+ output_r = kubernetes.KubernetesObject(name, **input_s).get_template()
self.assertEqual(output_r, output_t)
-class GetRcPodsTestCase(unittest.TestCase):
+class GetRcPodsTestCase(base.BaseUnitTestCase):
@mock.patch('yardstick.orchestrator.kubernetes.k8s_utils.get_pod_list')
def test_get_rc_pods(self, mock_get_pod_list):
@@ -98,7 +102,95 @@ service ssh restart;while true ; do sleep 10000; done']
service ssh restart;while true ; do sleep 10000; done']
}
}
- k8s_template = KubernetesTemplate('k8s-86096c30', servers)
+ k8s_template = kubernetes.KubernetesTemplate('k8s-86096c30', servers)
mock_get_pod_list.return_value.items = []
pods = k8s_template.get_rc_pods()
self.assertEqual(pods, [])
+
+
+class KubernetesObjectTestCase(base.BaseUnitTestCase):
+
+ def test__add_volumes(self):
+ volume1 = {'name': 'fake_sshkey',
+ 'configMap': {'name': 'fake_sshkey'}}
+ volume2 = {'name': 'volume2',
+ 'configMap': 'data'}
+ k8s_obj = kubernetes.KubernetesObject('name', ssh_key='fake_sshkey',
+ volumes=[volume2])
+ k8s_obj._add_volumes()
+ volumes = k8s_obj.template['spec']['template']['spec']['volumes']
+ self.assertEqual(sorted([volume1, volume2], key=lambda k: k['name']),
+ sorted(volumes, key=lambda k: k['name']))
+
+ def test__add_volumes_no_volumes(self):
+ volume1 = {'name': 'fake_sshkey',
+ 'configMap': {'name': 'fake_sshkey'}}
+ k8s_obj = kubernetes.KubernetesObject('name', ssh_key='fake_sshkey')
+ k8s_obj._add_volumes()
+ volumes = k8s_obj.template['spec']['template']['spec']['volumes']
+ self.assertEqual([volume1], volumes)
+
+ def test__create_ssh_key_volume(self):
+ expected = {'name': 'fake_sshkey',
+ 'configMap': {'name': 'fake_sshkey'}}
+ k8s_obj = kubernetes.KubernetesObject('name', ssh_key='fake_sshkey')
+ self.assertEqual(expected, k8s_obj._create_ssh_key_volume())
+
+ def test__create_volume_item(self):
+ for vol_type in kubernetes_utils.get_volume_types():
+ volume = {'name': 'vol_name',
+ vol_type: 'data'}
+ self.assertEqual(
+ volume,
+ kubernetes.KubernetesObject._create_volume_item(volume))
+
+ def test__create_volume_item_invalid_type(self):
+ volume = {'name': 'vol_name',
+ 'invalid_type': 'data'}
+ with self.assertRaises(exceptions.KubernetesTemplateInvalidVolumeType):
+ kubernetes.KubernetesObject._create_volume_item(volume)
+
+ def test__create_volume_mounts(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ ssh_vol = {'name': kubernetes.KubernetesObject.SSHKEY_DEFAULT,
+ 'mountPath': kubernetes.KubernetesObject.SSH_MOUNT_PATH,
+ 'readOnly': False}
+ expected = copy.deepcopy(volume_mount)
+ expected['readOnly'] = False
+ expected = [expected, ssh_vol]
+ k8s_obj = kubernetes.KubernetesObject('name',
+ volumeMounts=[volume_mount])
+ output = k8s_obj._create_volume_mounts()
+ self.assertEqual(expected, output)
+
+ def test__create_volume_mounts_no_volume_mounts(self):
+ ssh_vol = {'name': kubernetes.KubernetesObject.SSHKEY_DEFAULT,
+ 'mountPath': kubernetes.KubernetesObject.SSH_MOUNT_PATH,
+ 'readOnly': False}
+ k8s_obj = kubernetes.KubernetesObject('name')
+ output = k8s_obj._create_volume_mounts()
+ self.assertEqual([ssh_vol], output)
+
+ def test__create_volume_mounts_item(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ expected = copy.deepcopy(volume_mount)
+ expected['readOnly'] = False
+ output = kubernetes.KubernetesObject._create_volume_mounts_item(
+ volume_mount)
+ self.assertEqual(expected, output)
+
+ def test__create_container_item(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ args = ['arg1', 'arg2']
+ k8s_obj = kubernetes.KubernetesObject(
+ 'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+ args=args)
+ expected = {'args': args,
+ 'command': [kubernetes.KubernetesObject.COMMAND_DEFAULT],
+ 'image': kubernetes.KubernetesObject.IMAGE_DEFAULT,
+ 'name': 'cname-container',
+ 'volumeMounts': k8s_obj._create_volume_mounts()}
+ self.assertEqual(expected, k8s_obj._create_container_item())
diff --git a/yardstick/tests/unit/test_cmd/commands/test_env.py b/yardstick/tests/unit/test_cmd/commands/test_env.py
index 57dacbcd3..5d3520986 100644
--- a/yardstick/tests/unit/test_cmd/commands/test_env.py
+++ b/yardstick/tests/unit/test_cmd/commands/test_env.py
@@ -6,60 +6,64 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-from __future__ import absolute_import
-import unittest
+
+import os
+import sys
+
import mock
import uuid
-from yardstick.cmd.commands.env import EnvCommand
+from yardstick.cmd.commands import env
+from yardstick.tests.unit import base
-class EnvCommandTestCase(unittest.TestCase):
+class EnvCommandTestCase(base.BaseUnitTestCase):
- @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task')
- @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status')
+ @mock.patch.object(env.EnvCommand, '_start_async_task')
+ @mock.patch.object(env.EnvCommand, '_check_status')
def test_do_influxdb(self, check_status_mock, start_async_task_mock):
- env = EnvCommand()
- env.do_influxdb({})
+ _env = env.EnvCommand()
+ _env.do_influxdb({})
start_async_task_mock.assert_called_once()
check_status_mock.assert_called_once()
- @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task')
- @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status')
+ @mock.patch.object(env.EnvCommand, '_start_async_task')
+ @mock.patch.object(env.EnvCommand, '_check_status')
def test_do_grafana(self, check_status_mock, start_async_task_mock):
- env = EnvCommand()
- env.do_grafana({})
+ _env = env.EnvCommand()
+ _env.do_grafana({})
start_async_task_mock.assert_called_once()
check_status_mock.assert_called_once()
- @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task')
- @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status')
+ @mock.patch.object(env.EnvCommand, '_start_async_task')
+ @mock.patch.object(env.EnvCommand, '_check_status')
def test_do_prepare(self, check_status_mock, start_async_task_mock):
- env = EnvCommand()
- env.do_prepare({})
+ _env = env.EnvCommand()
+ _env.do_prepare({})
start_async_task_mock.assert_called_once()
check_status_mock.assert_called_once()
- @mock.patch('yardstick.cmd.commands.env.HttpClient.post')
+ @mock.patch.object(env.HttpClient, 'post')
def test_start_async_task(self, post_mock):
data = {'action': 'create_grafana'}
- EnvCommand()._start_async_task(data)
+ env.EnvCommand()._start_async_task(data)
post_mock.assert_called_once()
- @mock.patch('yardstick.cmd.commands.env.HttpClient.get')
- @mock.patch('yardstick.cmd.commands.env.EnvCommand._print_status')
- def test_check_status(self, print_mock, get_mock):
- # pylint: disable=unused-argument
- # NOTE(ralonsoh): the pylint exception must be removed. The mocked
- # command call must be tested.
+ @mock.patch.object(env.HttpClient, 'get')
+ @mock.patch.object(env.EnvCommand, '_print_status')
+ def test_check_status(self, mock_print, mock_get):
task_id = str(uuid.uuid4())
- get_mock.return_value = {'status': 2, 'result': 'error'}
- status = EnvCommand()._check_status(task_id, 'hello world')
- self.assertEqual(status, 2)
+ mock_get.return_value = {'status': 2, 'result': 'error'}
+ self.assertEqual(
+ 2, env.EnvCommand()._check_status(task_id, 'hello world'))
+ self.assertEqual(2, mock_print.call_count)
- def test_print_status(self):
- try:
- EnvCommand()._print_status('hello', 'word')
- except Exception as e: # pylint: disable=broad-except
- # NOTE(ralonsoh): try to reduce the scope of this exception.
- self.assertIsInstance(e, IndexError)
+ @mock.patch.object(sys, 'stdout')
+ @mock.patch.object(os, 'popen')
+ def test_print_status(self, mock_popen, mock_stdout):
+ mock_popen_obj = mock.Mock()
+ mock_popen_obj.read.return_value = ''
+ mock_popen.return_value = mock_popen_obj
+ env.EnvCommand()._print_status('hello', 'word')
+ mock_stdout.write.assert_not_called()
+ mock_stdout.flush.assert_not_called()