aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick')
-rw-r--r--yardstick/benchmark/contexts/kubernetes.py35
-rw-r--r--yardstick/benchmark/core/task.py17
-rw-r--r--yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py66
-rw-r--r--yardstick/benchmark/scenarios/availability/attacker_conf.yaml1
-rwxr-xr-xyardstick/benchmark/scenarios/networking/netperf.py4
-rw-r--r--yardstick/benchmark/scenarios/networking/netperf_install_arm64.patch42
-rw-r--r--yardstick/common/kubernetes_utils.py59
-rw-r--r--yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py46
-rw-r--r--yardstick/network_services/nfvi/collectd.conf95
-rwxr-xr-xyardstick/network_services/nfvi/collectd.sh3
-rw-r--r--yardstick/network_services/nfvi/resource.py95
-rw-r--r--yardstick/network_services/traffic_profile/ixia_rfc2544.py62
-rw-r--r--yardstick/network_services/vnf_generic/vnf/base.py9
-rw-r--r--yardstick/network_services/vnf_generic/vnf/sample_vnf.py23
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py43
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vpe_vnf.py47
-rw-r--r--yardstick/orchestrator/kubernetes.py43
17 files changed, 464 insertions, 226 deletions
diff --git a/yardstick/benchmark/contexts/kubernetes.py b/yardstick/benchmark/contexts/kubernetes.py
index a39f63137..2334e5076 100644
--- a/yardstick/benchmark/contexts/kubernetes.py
+++ b/yardstick/benchmark/contexts/kubernetes.py
@@ -54,6 +54,7 @@ class KubernetesContext(Context):
LOG.info('Launch containers')
self._create_rcs()
+ self._create_services()
time.sleep(1)
self.template.get_rc_pods()
@@ -63,6 +64,7 @@ class KubernetesContext(Context):
self._delete_ssh_key()
self._delete_rcs()
self._delete_pods()
+ self._delete_services()
super(KubernetesContext, self).undeploy()
@@ -80,6 +82,14 @@ class KubernetesContext(Context):
return False
return True
+ def _create_services(self):
+ for obj in self.template.service_objs:
+ obj.create()
+
+ def _delete_services(self):
+ for obj in self.template.service_objs:
+ obj.delete()
+
def _create_rcs(self):
for obj in self.template.k8s_objs:
self._create_rc(obj.get_template())
@@ -126,15 +136,22 @@ class KubernetesContext(Context):
utils.remove_file(self.public_key_path)
def _get_server(self, name):
- resp = k8s_utils.get_pod_list()
- hosts = ({'name': n.metadata.name,
- 'ip': n.status.pod_ip,
- 'user': 'root',
- 'key_filename': self.key_path,
- 'private_ip': n.status.pod_ip}
- for n in resp.items if n.metadata.name.startswith(name))
-
- return next(hosts, None)
+ service_name = '{}-service'.format(name)
+ service = k8s_utils.get_service_by_name(service_name).ports[0]
+
+ host = {
+ 'name': service.name,
+ 'ip': self._get_node_ip(),
+ 'private_ip': k8s_utils.get_pod_by_name(name).status.pod_ip,
+ 'ssh_port': service.node_port,
+ 'user': 'root',
+ 'key_filename': self.key_path,
+ }
+
+ return host
+
+ def _get_node_ip(self):
+ return k8s_utils.get_node_list().items[0].status.addresses[0].address
def _get_network(self, attr_name):
return None
diff --git a/yardstick/benchmark/core/task.py b/yardstick/benchmark/core/task.py
index 0b6e3230b..c175a950b 100644
--- a/yardstick/benchmark/core/task.py
+++ b/yardstick/benchmark/core/task.py
@@ -125,9 +125,10 @@ class Task(object): # pragma: no cover
except KeyboardInterrupt:
raise
except Exception:
- LOG.exception("Running test case %s failed!", case_name)
+ LOG.error('Testcase: "%s" FAILED!!!', case_name, exc_info=True)
testcases[case_name] = {'criteria': 'FAIL', 'tc_data': []}
else:
+ LOG.info('Testcase: "%s" SUCCESS!!!', case_name)
testcases[case_name] = {'criteria': 'PASS', 'tc_data': data}
if args.keep_deploy:
@@ -272,7 +273,9 @@ class Task(object): # pragma: no cover
runner = self.run_one_scenario(scenario, output_file)
status = runner_join(runner)
if status != 0:
- LOG.error('Scenario: %s ERROR', scenario.get('type'))
+ LOG.error('Scenario NO.%s: "%s" ERROR!',
+ scenarios.index(scenario) + 1,
+ scenario.get('type'))
raise RuntimeError
self.outputs.update(runner.get_output())
result.extend(runner.get_result())
@@ -333,7 +336,7 @@ class Task(object): # pragma: no cover
context_cfg['target'] = {"ipaddr": target}
else:
context_cfg['target'] = Context.get_server(target)
- if self._is_same_heat_context(cfg["host"], target):
+ if self._is_same_context(cfg["host"], target):
context_cfg['target']["ipaddr"] = context_cfg['target']["private_ip"]
else:
context_cfg['target']["ipaddr"] = context_cfg['target']["ip"]
@@ -358,8 +361,8 @@ class Task(object): # pragma: no cover
context_cfg['target'] = {}
else:
context_cfg['target'] = Context.get_server(target)
- if self._is_same_heat_context(scenario_cfg["host"],
- target):
+ if self._is_same_context(scenario_cfg["host"],
+ target):
ip_list.append(context_cfg["target"]["private_ip"])
else:
ip_list.append(context_cfg["target"]["ip"])
@@ -377,7 +380,7 @@ class Task(object): # pragma: no cover
return runner
- def _is_same_heat_context(self, host_attr, target_attr):
+ def _is_same_context(self, host_attr, target_attr):
"""check if two servers are in the same heat context
host_attr: either a name for a server created by yardstick or a dict
with attribute name mapping when using external heat templates
@@ -385,7 +388,7 @@ class Task(object): # pragma: no cover
with attribute name mapping when using external heat templates
"""
for context in self.contexts:
- if context.__context_type__ != "Heat":
+ if context.__context_type__ not in {"Heat", "Kubernetes"}:
continue
host = context._get_server(host_attr)
diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py
index 50d44c1ca..979e3ab14 100644
--- a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py
+++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py
@@ -40,6 +40,21 @@ class BaremetalAttacker(BaseAttacker):
self.connection = ssh.SSH.from_node(host, defaults={"user": "root"})
self.connection.wait(timeout=600)
LOG.debug("ssh host success!")
+
+ jump_host_name = self._config.get("jump_host", None)
+ self.jump_connection = None
+ if jump_host_name is not None:
+ jump_host = self._context.get(jump_host_name, None)
+
+ LOG.debug("jump_host ip:%s user:%s", jump_host['ip'], jump_host['user'])
+ self.jump_connection = ssh.SSH.from_node(
+ jump_host,
+ # why do we allow pwd for password?
+ defaults={"user": "root", "password": jump_host.get("pwd")}
+ )
+ self.jump_connection.wait(timeout=600)
+ LOG.debug("ssh jump host success!")
+
self.host_ip = host['ip']
self.ipmi_ip = host.get("ipmi_ip", None)
@@ -49,6 +64,7 @@ class BaremetalAttacker(BaseAttacker):
self.fault_cfg = BaseAttacker.attacker_cfgs.get('bare-metal-down')
self.check_script = self.get_script_fullpath(
self.fault_cfg['check_script'])
+ self.inject_script = self.get_script_fullpath(self.fault_cfg['inject_script'])
self.recovery_script = self.get_script_fullpath(
self.fault_cfg['recovery_script'])
@@ -70,39 +86,27 @@ class BaremetalAttacker(BaseAttacker):
return True
def inject_fault(self):
- exit_status, stdout, stderr = self.connection.execute(
- "sudo shutdown -h now")
- LOG.debug("inject fault ret: %s out:%s err:%s",
- exit_status, stdout, stderr)
- if not exit_status:
- LOG.info("inject fault success")
+ LOG.info("Inject fault START")
+ cmd = "sudo /bin/bash -s {0} {1} {2} {3}".format(
+ self.ipmi_ip, self.ipmi_user, self.ipmi_pwd, "off")
+ with open(self.inject_script, "r") as stdin_file:
+ if self.jump_connection is not None:
+ LOG.info("Power off node via IPMI")
+ self.jump_connection.execute(cmd, stdin=stdin_file)
+ else:
+ _execute_shell_command(cmd, stdin=stdin_file)
+ LOG.info("Inject fault END")
def recover(self):
- jump_host_name = self._config.get("jump_host", None)
- self.jump_connection = None
- if jump_host_name is not None:
- host = self._context.get(jump_host_name, None)
-
- LOG.debug("jump_host ip:%s user:%s", host['ip'], host['user'])
- self.jump_connection = ssh.SSH.from_node(
- host,
- # why do we allow pwd for password?
- defaults={"user": "root", "password": host.get("pwd")}
- )
- self.jump_connection.wait(timeout=600)
- LOG.debug("ssh jump host success!")
-
- if self.jump_connection is not None:
- with open(self.recovery_script, "r") as stdin_file:
- self.jump_connection.execute(
- "sudo /bin/bash -s {0} {1} {2} {3}".format(
- self.ipmi_ip, self.ipmi_user, self.ipmi_pwd, "on"),
- stdin=stdin_file)
- else:
- _execute_shell_command(
- "sudo /bin/bash -s {0} {1} {2} {3}".format(
- self.ipmi_ip, self.ipmi_user, self.ipmi_pwd, "on"),
- stdin=open(self.recovery_script, "r"))
+ LOG.info("Recover fault START")
+ cmd = "sudo /bin/bash -s {0} {1} {2} {3}".format(
+ self.ipmi_ip, self.ipmi_user, self.ipmi_pwd, "on")
+ with open(self.recovery_script, "r") as stdin_file:
+ if self.jump_connection is not None:
+ self.jump_connection.execute(cmd, stdin=stdin_file)
+ else:
+ _execute_shell_command(cmd, stdin=stdin_file)
+ LOG.info("Recover fault END")
def _test(): # pragma: no cover
diff --git a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
index ee7ea7d83..5f43a701a 100644
--- a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
+++ b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
@@ -23,6 +23,7 @@ kill-lxc-process:
bare-metal-down:
check_script: ha_tools/check_host_ping.bash
+ inject_script: ha_tools/ipmi_power.bash
recovery_script: ha_tools/ipmi_power.bash
stop-service:
diff --git a/yardstick/benchmark/scenarios/networking/netperf.py b/yardstick/benchmark/scenarios/networking/netperf.py
index 08d5dd166..a8d9010ed 100755
--- a/yardstick/benchmark/scenarios/networking/netperf.py
+++ b/yardstick/benchmark/scenarios/networking/netperf.py
@@ -114,6 +114,10 @@ class Netperf(base.Scenario):
cmd_args += " %s %s" % (option_pair[1],
options[option_pair[0]])
+ # Enable IP routing for UDP_STREAM test
+ if testname == "UDP_STREAM":
+ cmd_args += " -R 1"
+
cmd = "sudo bash netperf.sh %s" % (cmd_args)
LOG.debug("Executing command: %s", cmd)
status, stdout, stderr = self.client.execute(cmd)
diff --git a/yardstick/benchmark/scenarios/networking/netperf_install_arm64.patch b/yardstick/benchmark/scenarios/networking/netperf_install_arm64.patch
new file mode 100644
index 000000000..b41c1d207
--- /dev/null
+++ b/yardstick/benchmark/scenarios/networking/netperf_install_arm64.patch
@@ -0,0 +1,42 @@
+diff --git a/yardstick/benchmark/scenarios/networking/netperf_install.bash b/yardstick/benchmark/scenarios/networking/netperf_install.bash
+index 0e3808f..f9362eb 100755
+--- a/yardstick/benchmark/scenarios/networking/netperf_install.bash
++++ b/yardstick/benchmark/scenarios/networking/netperf_install.bash
+@@ -1,9 +1,9 @@
+ #!/bin/bash
+
+ ##############################################################################
+-# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
++# Copyright (c) 2017, Arm Limited. All rights reserved.
+ #
+-# All rights reserved. This program and the accompanying materials
++# 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
+@@ -19,21 +19,11 @@ then
+ fi
+
+ echo "===Install netperf before test begin!!!==="
+-cp /etc/apt/sources.list /etc/apt/sources.list_bkp
+-cp /etc/resolv.conf /etc/resolv.conf_bkp
+-echo "nameserver 8.8.4.4" >> /etc/resolv.conf
+-
+-cat <<EOF >/etc/apt/sources.list
+-deb http://archive.ubuntu.com/ubuntu/ trusty main restricted universe multiverse
+-deb http://archive.ubuntu.com/ubuntu/ trusty-security main restricted universe multiverse
+-deb http://archive.ubuntu.com/ubuntu/ trusty-updates main restricted universe multiverse
+-deb http://archive.ubuntu.com/ubuntu/ trusty-proposed main restricted universe multiverse
+-deb http://archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse
+-EOF
+-
+-sudo apt-get update
+-sudo apt-get install -y netperf
+
++apt-get update -y
++apt-get install -y wget
++wget http://launchpadlibrarian.net/155043952/netperf_2.6.0-2_arm64.deb
++dpkg -i ./netperf_2.6.0-2_arm64.deb
+ service netperf start
+
+ echo "===Install netperf before test end!!!==="
diff --git a/yardstick/common/kubernetes_utils.py b/yardstick/common/kubernetes_utils.py
index e4c232830..0cf7b9eab 100644
--- a/yardstick/common/kubernetes_utils.py
+++ b/yardstick/common/kubernetes_utils.py
@@ -28,6 +28,60 @@ def get_core_api(): # pragma: no cover
return client.CoreV1Api()
+def get_node_list(**kwargs): # pragma: no cover
+ core_v1_api = get_core_api()
+ try:
+ return core_v1_api.list_node(**kwargs)
+ except ApiException:
+ LOG.exception('Get node list failed')
+ raise
+
+
+def create_service(template,
+ namespace='default',
+ wait=False,
+ **kwargs): # pragma: no cover
+ core_v1_api = get_core_api()
+ metadata = client.V1ObjectMeta(**template.get('metadata', {}))
+
+ ports = [client.V1ServicePort(**port) for port in
+ template.get('spec', {}).get('ports', [])]
+ template['spec']['ports'] = ports
+ spec = client.V1ServiceSpec(**template.get('spec', {}))
+
+ service = client.V1Service(metadata=metadata, spec=spec)
+
+ try:
+ core_v1_api.create_namespaced_service('default', service)
+ except ApiException:
+ LOG.exception('Create Service failed')
+ raise
+
+
+def delete_service(name,
+ namespace='default',
+ **kwargs): # pragma: no cover
+ core_v1_api = get_core_api()
+ try:
+ core_v1_api.delete_namespaced_service(name, namespace, **kwargs)
+ except ApiException:
+ LOG.exception('Delete Service failed')
+
+
+def get_service_list(namespace='default', **kwargs):
+ core_v1_api = get_core_api()
+ try:
+ return core_v1_api.list_namespaced_service(namespace, **kwargs)
+ except ApiException:
+ LOG.exception('Get Service list failed')
+ raise
+
+
+def get_service_by_name(name): # pragma: no cover
+ service_list = get_service_list()
+ return next((s.spec for s in service_list.items if s.metadata.name == name), None)
+
+
def create_replication_controller(template,
namespace='default',
wait=False,
@@ -135,3 +189,8 @@ def get_pod_list(namespace='default'): # pragma: no cover
except ApiException:
LOG.exception('Get pod list failed')
raise
+
+
+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)
diff --git a/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py b/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py
index 4b906508c..358e6e761 100644
--- a/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py
+++ b/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py
@@ -113,10 +113,10 @@ class IxNextgen(object):
}
MODE_SEEDS_MAP = {
- 0: ('uplink_0', ['256', '2048']),
+ 0: ('uplink', ['256', '2048']),
}
- MODE_SEEDS_DEFAULT = 'downlink_0', ['2048', '256']
+ MODE_SEEDS_DEFAULT = 'downlink', ['2048', '256']
@staticmethod
def find_view_obj(view_name, views):
@@ -125,24 +125,27 @@ class IxNextgen(object):
@staticmethod
def get_config(tg_cfg):
+ card = []
+ port = []
external_interface = tg_cfg["vdu"][0]["external-interface"]
- card_port0 = external_interface[0]["virtual-interface"]["vpci"]
- card_port1 = external_interface[1]["virtual-interface"]["vpci"]
- card0, port0 = card_port0.split(':')[:2]
- card1, port1 = card_port1.split(':')[:2]
+ for intf in external_interface:
+ card_port0 = intf["virtual-interface"]["vpci"]
+ card0, port0 = card_port0.split(':')[:2]
+ card.append(card0)
+ port.append(port0)
+
cfg = {
'py_lib_path': tg_cfg["mgmt-interface"]["tg-config"]["py_lib_path"],
'machine': tg_cfg["mgmt-interface"]["ip"],
'port': tg_cfg["mgmt-interface"]["tg-config"]["tcl_port"],
'chassis': tg_cfg["mgmt-interface"]["tg-config"]["ixchassis"],
- 'card1': card0,
- 'port1': port0,
- 'card2': card1,
- 'port2': port1,
+ 'cards': card,
+ 'ports': port,
'output_dir': tg_cfg["mgmt-interface"]["tg-config"]["dut_result_dir"],
'version': tg_cfg["mgmt-interface"]["tg-config"]["version"],
'bidir': True,
}
+
return cfg
def __init__(self, ixnet=None):
@@ -183,9 +186,13 @@ class IxNextgen(object):
self.set_random_ip_multi_attribute(ip, seeds[1], fixed_bits, random_mask, l3_count)
def add_ip_header(self, params, version):
- for it, ep, i in self.iter_over_get_lists('/traffic', 'trafficItem', "configElement"):
- mode, seeds = self.MODE_SEEDS_MAP.get(i, self.MODE_SEEDS_DEFAULT)
- l3 = params[mode]['outer_l3']
+ for it, ep, i in self.iter_over_get_lists('/traffic', 'trafficItem', "configElement", 1):
+ iter1 = (v['outer_l3'] for v in params.values() if str(v['id']) == str(i))
+ try:
+ l3 = next(iter1, {})
+ seeds = self.MODE_SEEDS_MAP.get(i, self.MODE_SEEDS_DEFAULT)[1]
+ except (KeyError, IndexError):
+ continue
for ip, ip_bits, _ in self.iter_over_get_lists(ep, 'stack', 'field'):
self.set_random_ip_multi_attributes(ip_bits, version, seeds, l3)
@@ -222,10 +229,11 @@ class IxNextgen(object):
def ix_assign_ports(self):
vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
- ports = [
- (self._cfg['chassis'], self._cfg['card1'], self._cfg['port1']),
- (self._cfg['chassis'], self._cfg['card2'], self._cfg['port2']),
- ]
+ ports = []
+
+ chassis = self._cfg['chassis']
+ ports = [(chassis, card, port) for card, port in
+ zip(self._cfg['cards'], self._cfg['ports'])]
vport_list = self.ixnet.getList("/", "vport")
self.ixnet.execute('assignPorts', ports, [], vport_list, True)
@@ -276,10 +284,10 @@ class IxNextgen(object):
def update_ether_multi_attributes(self, ether, l2):
if "ethernet.header.destinationAddress" in ether:
- self.update_ether_multi_attribute(ether, str(l2['dstmac']))
+ self.update_ether_multi_attribute(ether, str(l2.get('dstmac', "00:00:00:00:00:02")))
if "ethernet.header.sourceAddress" in ether:
- self.update_ether_multi_attribute(ether, str(l2['srcmac']))
+ self.update_ether_multi_attribute(ether, str(l2.get('srcmac', "00:00:00:00:00:01")))
def ix_update_ether(self, params):
for ti, ep, index in self.iter_over_get_lists('/traffic', 'trafficItem',
diff --git a/yardstick/network_services/nfvi/collectd.conf b/yardstick/network_services/nfvi/collectd.conf
index 3928dcbca..22bd5d49d 100644
--- a/yardstick/network_services/nfvi/collectd.conf
+++ b/yardstick/network_services/nfvi/collectd.conf
@@ -15,7 +15,7 @@
Hostname "nsb_stats"
FQDNLookup true
-Interval {interval}
+Interval {{ interval }}
##############################################################################
# LoadPlugin section #
@@ -24,7 +24,9 @@ Interval {interval}
##############################################################################
#LoadPlugin syslog
-{loadplugin}
+{% for plugin in loadplugins %}
+LoadPlugin {{ plugin }}
+{% endfor %}
##############################################################################
# Plugin configuration #
@@ -38,42 +40,31 @@ Interval {interval}
#</Plugin>
<Plugin amqp>
- <Publish "name">
- Host "0.0.0.0"
- Port "5672"
- VHost "/"
- User "admin"
- Password "admin"
- Exchange "amq.fanout"
- RoutingKey "collectd"
- Persistent false
- StoreRates false
- ConnectionRetryDelay 0
- </Publish>
+ <Publish "name">
+ Host "0.0.0.0"
+ Port "5672"
+ VHost "/"
+ User "admin"
+ Password "admin"
+ Exchange "amq.fanout"
+ RoutingKey "collectd"
+ Persistent false
+ StoreRates false
+ ConnectionRetryDelay 0
+ </Publish>
</Plugin>
<Plugin cpu>
- ReportByCpu true
- ReportByState true
- ValuesPercentage true
+ ReportByCpu true
+ ReportByState true
+ ValuesPercentage true
</Plugin>
<Plugin memory>
- ValuesAbsolute true
- ValuesPercentage false
-</Plugin>
-
-<Plugin "intel_rdt">
- Cores ""
+ ValuesAbsolute true
+ ValuesPercentage false
</Plugin>
-<Plugin intel_pmu>
- ReportHardwareCacheEvents true
- ReportKernelPMUEvents true
- ReportSoftwareEvents true
- EventList "/root/.cache/pmu-events/GenuineIntel-6-2D-core.json"
- HardwareEvents "L2_RQSTS.CODE_RD_HIT,L2_RQSTS.CODE_RD_MISS" "L2_RQSTS.ALL_CODE_RD"
-</Plugin>
<Plugin hugepages>
ReportPerNodeHP true
@@ -83,15 +74,25 @@ Interval {interval}
ValuesPercentage false
</Plugin>
-<Plugin hugepages>
- ReportPerNodeHP true
- ReportRootHP true
- ValuesPages true
- ValuesBytes false
- ValuesPercentage false
+
+{% if "intel_rdt" in plugins %}
+<Plugin "intel_rdt">
+ Cores ""
+</Plugin>
+{% endif %}
+
+{% if "intel_pmu" in plugins %}
+<Plugin intel_pmu>
+ ReportHardwareCacheEvents true
+ ReportKernelPMUEvents true
+ ReportSoftwareEvents true
+ EventList "/root/.cache/pmu-events/GenuineIntel-6-2D-core.json"
+ HardwareEvents "L2_RQSTS.CODE_RD_HIT,L2_RQSTS.CODE_RD_MISS" "L2_RQSTS.ALL_CODE_RD"
</Plugin>
+{% endif %}
-<Plugin dpdkstat>
+{% if "dpdkstat" in plugins %}
+<Plugin "dpdkstat">
<EAL>
Coremask "0x1"
MemoryChannels "4"
@@ -100,20 +101,24 @@ Interval {interval}
</EAL>
SharedMemObj "dpdk_collectd_stats_0"
EnabledPortMask 0xffff
- {dpdk_interface}
+{% for port_name in port_names %}
+ PortName {{ port_name }}
+{% endfor %}
</Plugin>
+{% endif %}
-<Plugin virt>
- Domain "samplevnf"
+{% if "virt" in plugins %}
+<Plugin "virt">
+# monitor all domains
</Plugin>
+{% endif %}
-<Plugin ovs_stats>
+{% if "ovs_stats" in plugins %}
+<Plugin "ovs_stats">
Port "6640"
Address "127.0.0.1"
Socket "/usr/local/var/run/openvswitch/db.sock"
- Bridges "br0" "br_ext"
+# don't specify bridges, monitor all bridges
</Plugin>
+{% endif %}
-<Include "/etc/collectd/collectd.conf.d">
- Filter "*.conf"
-</Include>
diff --git a/yardstick/network_services/nfvi/collectd.sh b/yardstick/network_services/nfvi/collectd.sh
index 296c4a213..bdc5abd03 100755
--- a/yardstick/network_services/nfvi/collectd.sh
+++ b/yardstick/network_services/nfvi/collectd.sh
@@ -142,7 +142,8 @@ else
fi
modprobe msr
-cp $INSTALL_NSB_BIN/collectd.conf /opt/collectd/etc/
+# we overwrite the config file during _start_collectd so don't copy it
+#cp $INSTALL_NSB_BIN/collectd.conf /opt/nsb_bin/collectd/etc/
sudo service rabbitmq-server restart
echo "Check if admin user already created"
rabbitmqctl list_users | grep '^admin$' > /dev/null
diff --git a/yardstick/network_services/nfvi/resource.py b/yardstick/network_services/nfvi/resource.py
index fa32a4dcf..d807f5e46 100644
--- a/yardstick/network_services/nfvi/resource.py
+++ b/yardstick/network_services/nfvi/resource.py
@@ -15,16 +15,22 @@
from __future__ import absolute_import
from __future__ import print_function
-import tempfile
+
import logging
+from itertools import chain
+
+import jinja2
import os
import os.path
import re
import multiprocessing
+import pkg_resources
from oslo_config import cfg
+from oslo_utils.encodeutils import safe_decode
from yardstick import ssh
+from yardstick.common.task_template import finalize_for_yaml
from yardstick.common.utils import validate_non_string_sequence
from yardstick.network_services.nfvi.collectd import AmqpConsumer
from yardstick.network_services.utils import get_nsb_option
@@ -34,26 +40,36 @@ LOG = logging.getLogger(__name__)
CONF = cfg.CONF
ZMQ_OVS_PORT = 5567
ZMQ_POLLING_TIME = 12000
-LIST_PLUGINS_ENABLED = ["amqp", "cpu", "cpufreq", "intel_rdt", "memory",
- "hugepages", "dpdkstat", "virt", "ovs_stats", "intel_pmu"]
+LIST_PLUGINS_ENABLED = ["amqp", "cpu", "cpufreq", "memory",
+ "hugepages"]
class ResourceProfile(object):
"""
This profile adds a resource at the beginning of the test session
"""
+ COLLECTD_CONF = "collectd.conf"
+ AMPQ_PORT = 5672
+ DEFAULT_INTERVAL = 25
- def __init__(self, mgmt, interfaces=None, cores=None):
+ def __init__(self, mgmt, port_names=None, cores=None, plugins=None, interval=None):
+ if plugins is None:
+ self.plugins = {}
+ else:
+ self.plugins = plugins
+ if interval is None:
+ self.interval = self.DEFAULT_INTERVAL
+ else:
+ self.interval = interval
self.enable = True
self.cores = validate_non_string_sequence(cores, default=[])
self._queue = multiprocessing.Queue()
self.amqp_client = None
- self.interfaces = validate_non_string_sequence(interfaces, default=[])
+ self.port_names = validate_non_string_sequence(port_names, default=[])
- # why the host or ip?
- self.vnfip = mgmt.get("host", mgmt["ip"])
- self.connection = ssh.SSH.from_node(mgmt, overrides={"ip": self.vnfip})
- self.connection.wait()
+ # we need to save mgmt so we can connect to port 5672
+ self.mgmt = mgmt
+ self.connection = ssh.AutoConnectSSH.from_node(mgmt)
def check_if_sa_running(self, process):
""" verify if system agent is running """
@@ -62,7 +78,7 @@ class ResourceProfile(object):
def run_collectd_amqp(self):
""" run amqp consumer to collect the NFVi data """
- amqp_url = 'amqp://admin:admin@{}:5672/%2F'.format(self.vnfip)
+ amqp_url = 'amqp://admin:admin@{}:{}/%2F'.format(self.mgmt['ip'], self.AMPQ_PORT)
amqp = AmqpConsumer(amqp_url, self._queue)
try:
amqp.run()
@@ -124,7 +140,9 @@ class ResourceProfile(object):
}
testcase = ""
- for key, value in metrics.items():
+ # unicode decode
+ decoded = ((safe_decode(k, 'utf-8'), safe_decode(v, 'utf-8')) for k, v in metrics.items())
+ for key, value in decoded:
key_split = key.split("/")
res_key_iter = (key for key in key_split if "nsb_stats" not in key)
res_key0 = next(res_key_iter)
@@ -176,35 +194,36 @@ class ResourceProfile(object):
msg = self.parse_collectd_result(metric, self.cores)
return msg
- def _provide_config_file(self, bin_path, nfvi_cfg, kwargs):
- with open(os.path.join(bin_path, nfvi_cfg), 'r') as cfg:
- template = cfg.read()
- cfg, cfg_content = tempfile.mkstemp()
- with os.fdopen(cfg, "w+") as cfg:
- cfg.write(template.format(**kwargs))
- cfg_file = os.path.join(bin_path, nfvi_cfg)
- self.connection.put(cfg_content, cfg_file)
-
- def _prepare_collectd_conf(self, bin_path):
+ def _provide_config_file(self, config_file_path, nfvi_cfg, template_kwargs):
+ template = pkg_resources.resource_string("yardstick.network_services.nfvi",
+ nfvi_cfg).decode('utf-8')
+ cfg_content = jinja2.Template(template, trim_blocks=True, lstrip_blocks=True,
+ finalize=finalize_for_yaml).render(
+ **template_kwargs)
+ # cfg_content = io.StringIO(template.format(**template_kwargs))
+ cfg_file = os.path.join(config_file_path, nfvi_cfg)
+ # must write as root, so use sudo
+ self.connection.execute("cat | sudo tee {}".format(cfg_file), stdin=cfg_content)
+
+ def _prepare_collectd_conf(self, config_file_path):
""" Prepare collectd conf """
- loadplugin = "\n".join("LoadPlugin {0}".format(plugin)
- for plugin in LIST_PLUGINS_ENABLED)
-
- interfaces = "\n".join("PortName '{0[name]}'".format(interface)
- for interface in self.interfaces)
kwargs = {
- "interval": '25',
- "loadplugin": loadplugin,
- "dpdk_interface": interfaces,
+ "interval": self.interval,
+ "loadplugins": set(chain(LIST_PLUGINS_ENABLED, self.plugins.keys())),
+ # Optional fields PortName is descriptive only, use whatever is present
+ "port_names": self.port_names,
+ # "ovs_bridge_interfaces": ["br-int"],
+ "plugins": self.plugins,
}
- self._provide_config_file(bin_path, 'collectd.conf', kwargs)
+ self._provide_config_file(config_file_path, self.COLLECTD_CONF, kwargs)
def _start_collectd(self, connection, bin_path):
LOG.debug("Starting collectd to collect NFVi stats")
- connection.execute('sudo pkill -9 collectd')
+ connection.execute('sudo pkill -x -9 collectd')
bin_path = get_nsb_option("bin_path")
- collectd_path = os.path.join(bin_path, "collectd", "collectd")
+ collectd_path = os.path.join(bin_path, "collectd", "sbin", "collectd")
+ config_file_path = os.path.join(bin_path, "collectd", "etc")
exit_status = connection.execute("which %s > /dev/null 2>&1" % collectd_path)[0]
if exit_status != 0:
LOG.warning("%s is not present disabling", collectd_path)
@@ -217,7 +236,9 @@ class ResourceProfile(object):
# collectd_installer, http_proxy, https_proxy))
return
LOG.debug("Starting collectd to collect NFVi stats")
- self._prepare_collectd_conf(bin_path)
+ # ensure collectd.conf.d exists to avoid error/warning
+ connection.execute("sudo mkdir -p /etc/collectd/collectd.conf.d")
+ self._prepare_collectd_conf(config_file_path)
# Reset amqp queue
LOG.debug("reset and setup amqp to collect data from collectd")
@@ -228,7 +249,7 @@ class ResourceProfile(object):
connection.execute("sudo rabbitmqctl start_app")
connection.execute("sudo service rabbitmq-server restart")
- LOG.debug("Creating amdin user for rabbitmq in order to collect data from collectd")
+ LOG.debug("Creating admin user for rabbitmq in order to collect data from collectd")
connection.execute("sudo rabbitmqctl delete_user guest")
connection.execute("sudo rabbitmqctl add_user admin admin")
connection.execute("sudo rabbitmqctl authenticate_user admin admin")
@@ -241,7 +262,11 @@ class ResourceProfile(object):
def initiate_systemagent(self, bin_path):
""" Start system agent for NFVi collection on host """
if self.enable:
- self._start_collectd(self.connection, bin_path)
+ try:
+ self._start_collectd(self.connection, bin_path)
+ except Exception:
+ LOG.exception("Exception during collectd start")
+ raise
def start(self):
""" start nfvi collection """
diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
index ee58172d8..28480b8e9 100644
--- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py
+++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
@@ -43,35 +43,39 @@ class IXIARFC2544Profile(TrexProfile):
traffic = static_traffic[traffickey]
# outer_l2
index = 0
- for key, value in profile_data[traffickey].items():
- framesize = value['outer_l2']['framesize']
- traffic['outer_l2']['framesize'] = framesize
- traffic['framesPerSecond'] = True
- traffic['bidir'] = False
- traffic['outer_l2']['srcmac'] = \
- mac["src_mac_{}".format(traffic['id'])]
- traffic['outer_l2']['dstmac'] = \
- mac["dst_mac_{}".format(traffic['id'])]
-
- # outer_l3
- if "outer_l3v6" in list(value.keys()):
- traffic['outer_l3'] = value['outer_l3v6']
- srcip4 = value['outer_l3v6']['srcip6']
- traffic['outer_l3']['srcip4'] = srcip4.split("-")[0]
- dstip4 = value['outer_l3v6']['dstip6']
- traffic['outer_l3']['dstip4'] = dstip4.split("-")[0]
- else:
- traffic['outer_l3'] = value['outer_l3v4']
- srcip4 = value['outer_l3v4']['srcip4']
- traffic['outer_l3']['srcip4'] = srcip4.split("-")[0]
- dstip4 = value['outer_l3v4']['dstip4']
- traffic['outer_l3']['dstip4'] = dstip4.split("-")[0]
-
- traffic['outer_l3']['type'] = key
- traffic['outer_l3']['count'] = value['outer_l3v4']['count']
- # outer_l4
- traffic['outer_l4'] = value['outer_l4']
- index = index + 1
+ try:
+ for key, value in profile_data[traffickey].items():
+ framesize = value['outer_l2']['framesize']
+ traffic['outer_l2']['framesize'] = framesize
+ traffic['framesPerSecond'] = True
+ traffic['bidir'] = False
+ traffic['outer_l2']['srcmac'] = \
+ mac["src_mac_{}".format(traffic['id'])]
+ traffic['outer_l2']['dstmac'] = \
+ mac["dst_mac_{}".format(traffic['id'])]
+
+ # outer_l3
+ if "outer_l3v6" in list(value.keys()):
+ traffic['outer_l3'] = value['outer_l3v6']
+ srcip4 = value['outer_l3v6']['srcip6']
+ traffic['outer_l3']['srcip4'] = srcip4.split("-")[0]
+ dstip4 = value['outer_l3v6']['dstip6']
+ traffic['outer_l3']['dstip4'] = dstip4.split("-")[0]
+ else:
+ traffic['outer_l3'] = value['outer_l3v4']
+ srcip4 = value['outer_l3v4']['srcip4']
+ traffic['outer_l3']['srcip4'] = srcip4.split("-")[0]
+ dstip4 = value['outer_l3v4']['dstip4']
+ traffic['outer_l3']['dstip4'] = dstip4.split("-")[0]
+
+ traffic['outer_l3']['type'] = key
+ traffic['outer_l3']['count'] = value['outer_l3v4']['count']
+ # outer_l4
+ traffic['outer_l4'] = value['outer_l4']
+ index = index + 1
+ except Exception:
+ continue
+
result.update({traffickey: traffic})
return result
diff --git a/yardstick/network_services/vnf_generic/vnf/base.py b/yardstick/network_services/vnf_generic/vnf/base.py
index cccc0652d..67634a79c 100644
--- a/yardstick/network_services/vnf_generic/vnf/base.py
+++ b/yardstick/network_services/vnf_generic/vnf/base.py
@@ -106,15 +106,18 @@ class VnfdHelper(dict):
if int(virtual_intf['dpdk_port_num']) == port:
return interface
- def port_num(self, name):
+ def port_num(self, port):
# we need interface name -> DPDK port num (PMD ID) -> LINK ID
# LINK ID -> PMD ID is governed by the port mask
"""
:rtype: int
- :type name: str
+ :type port: str
"""
- intf = self.find_interface(name=name)
+ if isinstance(port, dict):
+ intf = port
+ else:
+ intf = self.find_interface(name=port)
return int(intf["virtual-interface"]["dpdk_port_num"])
def port_nums(self, intfs):
diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
index 557009d30..91530860e 100644
--- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
@@ -282,9 +282,11 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
def setup_vnf_environment(self):
self._setup_dpdk()
- resource = self._setup_resources()
+ self.bound_pci = [v['virtual-interface']["vpci"] for v in self.vnfd_helper.interfaces]
self.kill_vnf()
+ # bind before _setup_resources so we can use dpdk_port_num
self._detect_and_bind_drivers()
+ resource = self._setup_resources()
return resource
def kill_vnf(self):
@@ -307,10 +309,13 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
if exit_status != 0:
self.ssh_helper.execute("bash %s dpdk >/dev/null 2>&1" % dpdk_setup)
- def _setup_resources(self):
- interfaces = self.vnfd_helper.interfaces
- self.bound_pci = [v['virtual-interface']["vpci"] for v in interfaces]
+ def get_collectd_options(self):
+ options = self.scenario_helper.all_options.get("collectd", {})
+ # override with specific node settings
+ options.update(self.scenario_helper.options.get("collectd", {}))
+ return options
+ def _setup_resources(self):
# what is this magic? how do we know which socket is for which port?
# what about quad-socket?
if any(v[5] == "0" for v in self.bound_pci):
@@ -319,8 +324,14 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
self.socket = 1
cores = self._validate_cpu_cfg()
- return ResourceProfile(self.vnfd_helper.mgmt_interface,
- interfaces=self.vnfd_helper.interfaces, cores=cores)
+ # implicit ordering, presumably by DPDK port num, so pre-sort by port_num
+ # this won't work because we don't have DPDK port numbers yet
+ ports = sorted(self.vnfd_helper.interfaces, key=self.vnfd_helper.port_num)
+ port_names = (intf["name"] for intf in ports)
+ collectd_options = self.get_collectd_options()
+ plugins = collectd_options.get("plugins", {})
+ return ResourceProfile(self.vnfd_helper.mgmt_interface, port_names=port_names, cores=cores,
+ plugins=plugins, interval=collectd_options.get("interval"))
def _detect_and_bind_drivers(self):
interfaces = self.vnfd_helper.interfaces
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 cd9553d12..22aaf6dfb 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
@@ -81,11 +81,13 @@ class IxiaResourceHelper(ClientResourceHelper):
latency = stats[0]
samples = {}
- for port_name in ports:
+ # this is not DPDK port num, but this is whatever number we gave
+ # when we selected ports and programmed the profile
+ for port_num in ports:
try:
- # this is not DPDK port num, but this is whatever number we gave
- # when we selected ports and programmed the profile
- port_num = self.vnfd_helper.port_num(port_name)
+ # reverse lookup port name from port_num so the stats dict is descriptive
+ intf = self.vnfd_helper.find_interface_by_port(port_num)
+ port_name = intf["name"]
samples[port_name] = {
"rx_throughput_kps": float(last_result["Rx_Rate_Kbps"][port_num]),
"tx_throughput_kps": float(last_result["Tx_Rate_Kbps"][port_num]),
@@ -140,9 +142,9 @@ class IxiaResourceHelper(ClientResourceHelper):
mac = {}
for vld_id, traffic in static_traffic.items():
intfs = self.vnfd_helper.port_pairs.networks.get(vld_id, [])
- interface = next(intfs, None)
+ interface = next(iter(intfs), None)
if interface:
- virt_intf = interface["virtual-interface"]
+ virt_intf = self.vnfd_helper.find_interface(name=interface)["virtual-interface"]
# we only know static traffic id by reading the json
# this is used by _get_ixia_traffic_profile
mac["src_mac_{}".format(traffic["id"])] = virt_intf.get("local_mac", default)
@@ -168,24 +170,25 @@ class IxiaResourceHelper(ClientResourceHelper):
self.client.ix_stop_traffic()
self._queue.put(samples)
- except Exception:
- LOG.info("Run Traffic terminated")
- if not self.rfc_helper.is_done():
- self._terminated.value = 1
- return
+ if not self.rfc_helper.is_done():
+ self._terminated.value = 1
+ return
+
+ traffic_profile.execute_traffic(self, self.client, mac, ixia_file)
+ for _ in range(5):
+ time.sleep(self.LATENCY_TIME_SLEEP)
+ self.client.ix_stop_traffic()
+ samples = self.generate_samples(traffic_profile.ports, 'latency', {})
+ self._queue.put(samples)
+ traffic_profile.start_ixia_latency(self, self.client, mac, ixia_file)
+ if self._terminated.value:
+ break
- traffic_profile.execute_traffic(self, self.client, mac, ixia_file)
- for _ in range(5):
- time.sleep(self.LATENCY_TIME_SLEEP)
self.client.ix_stop_traffic()
- samples = self.generate_samples(traffic_profile.ports, 'latency', {})
- self._queue.put(samples)
- traffic_profile.start_ixia_latency(self, self.client, mac, ixia_file)
- if self._terminated.value:
- break
+ except Exception:
+ LOG.exception("Run Traffic terminated")
- self.client.ix_stop_traffic()
self._terminated.value = 1
def collect_kpi(self):
diff --git a/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py b/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
index cd4a008ce..5f1c4d4d3 100644
--- a/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
@@ -50,13 +50,14 @@ class ConfigCreate(object):
config.set(tm_q, 'cfg', '/tmp/full_tm_profile_10G.cfg')
return config
- def __init__(self, uplink_ports, downlink_ports, socket):
+ def __init__(self, vnfd_helper, socket):
super(ConfigCreate, self).__init__()
self.sw_q = -1
self.sink_q = -1
self.n_pipeline = 1
- self.uplink_ports = uplink_ports
- self.downlink_ports = downlink_ports
+ self.vnfd_helper = vnfd_helper
+ self.uplink_ports = self.vnfd_helper.port_pairs.uplink_ports
+ self.downlink_ports = self.vnfd_helper.port_pairs.downlink_ports
self.pipeline_per_port = 9
self.socket = socket
@@ -77,7 +78,7 @@ class ConfigCreate(object):
def vpe_rxq(self, config):
for port in self.downlink_ports:
- new_section = 'RXQ{0}.0'.format(port)
+ new_section = 'RXQ{0}.0'.format(self.vnfd_helper.port_num(port))
config.add_section(new_section)
config.set(new_section, 'mempool', 'MEMPOOL1')
@@ -102,7 +103,8 @@ class ConfigCreate(object):
for k, v in parser.items(pipeline):
if k == "pktq_in":
if "RXQ" in v:
- value = "RXQ{0}.0".format(self.uplink_ports[index])
+ port = self.vnfd_helper.port_num(self.uplink_ports[index])
+ value = "RXQ{0}.0".format(port)
else:
value = self.get_sink_swq(parser, pipeline, k, index)
@@ -110,7 +112,8 @@ class ConfigCreate(object):
elif k == "pktq_out":
if "TXQ" in v:
- value = "TXQ{0}.0".format(self.downlink_ports[index])
+ port = self.vnfd_helper.port_num(self.downlink_ports[index])
+ value = "TXQ{0}.0".format(port)
else:
self.sw_q += 1
value = self.get_sink_swq(parser, pipeline, k, index)
@@ -131,23 +134,25 @@ class ConfigCreate(object):
for k, v in parser.items(pipeline):
if k == "pktq_in":
+ port = self.vnfd_helper.port_num(self.downlink_ports[index])
if "RXQ" not in v:
value = self.get_sink_swq(parser, pipeline, k, index)
elif "TM" in v:
- value = "RXQ{0}.0 TM{1}".format(self.downlink_ports[index], index)
+ value = "RXQ{0}.0 TM{1}".format(port, index)
else:
- value = "RXQ{0}.0".format(self.downlink_ports[index])
+ value = "RXQ{0}.0".format(port)
parser.set(pipeline, k, value)
if k == "pktq_out":
+ port = self.vnfd_helper.port_num(self.uplink_ports[index])
if "TXQ" not in v:
self.sw_q += 1
value = self.get_sink_swq(parser, pipeline, k, index)
elif "TM" in v:
- value = "TXQ{0}.0 TM{1}".format(self.uplink_ports[index], index)
+ value = "TXQ{0}.0 TM{1}".format(port, index)
else:
- value = "TXQ{0}.0".format(self.uplink_ports[index])
+ value = "TXQ{0}.0".format(port)
parser.set(pipeline, k, value)
@@ -174,14 +179,19 @@ class ConfigCreate(object):
def generate_vpe_script(self, interfaces):
rules = PipelineRules(pipeline_id=1)
- for priv_port, pub_port in zip(self.uplink_ports, self.downlink_ports):
- priv_intf = interfaces[priv_port]["virtual-interface"]
- pub_intf = interfaces[pub_port]["virtual-interface"]
+ for uplink_port, downlink_port in zip(self.uplink_ports, self.downlink_ports):
- dst_port0_ip = priv_intf["dst_ip"]
- dst_port1_ip = pub_intf["dst_ip"]
- dst_port0_mac = priv_intf["dst_mac"]
- dst_port1_mac = pub_intf["dst_mac"]
+ uplink_intf = \
+ next(intf["virtual-interface"] for intf in interfaces
+ if intf["name"] == uplink_port)
+ downlink_intf = \
+ next(intf["virtual-interface"] for intf in interfaces
+ if intf["name"] == downlink_port)
+
+ dst_port0_ip = uplink_intf["dst_ip"]
+ dst_port1_ip = downlink_intf["dst_ip"]
+ dst_port0_mac = uplink_intf["dst_mac"]
+ dst_port1_mac = downlink_intf["dst_mac"]
rules.add_firewall_script(dst_port0_ip)
rules.next_pipeline()
@@ -226,8 +236,7 @@ class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
}
self._build_vnf_ports()
- vpe_conf = ConfigCreate(self.vnfd_helper.port_pairs.uplink_ports,
- self.vnfd_helper.port_pairs.downlink_ports, self.socket)
+ vpe_conf = ConfigCreate(self.vnfd_helper, self.socket)
vpe_conf.create_vpe_config(self.scenario_helper.vnf_cfg)
config_basename = posixpath.basename(self.CFG_CONFIG)
diff --git a/yardstick/orchestrator/kubernetes.py b/yardstick/orchestrator/kubernetes.py
index 6d7045f58..198eeac6d 100644
--- a/yardstick/orchestrator/kubernetes.py
+++ b/yardstick/orchestrator/kubernetes.py
@@ -23,6 +23,7 @@ class KubernetesObject(object):
self.command = [kwargs.get('command', '/bin/bash')]
self.args = kwargs.get('args', [])
self.ssh_key = kwargs.get('ssh_key', 'yardstick_key')
+ self.node_selector = kwargs.get('nodeSelector', {})
self.volumes = []
@@ -37,12 +38,13 @@ class KubernetesObject(object):
"template": {
"metadata": {
"labels": {
- "app": ""
+ "app": name
}
},
"spec": {
"containers": [],
- "volumes": []
+ "volumes": [],
+ "nodeSelector": {}
}
}
}
@@ -50,6 +52,7 @@ class KubernetesObject(object):
self._change_value_according_name(name)
self._add_containers()
+ self._add_node_selector()
self._add_ssh_key_volume()
self._add_volumes()
@@ -88,6 +91,11 @@ class KubernetesObject(object):
return container
+ def _add_node_selector(self):
+ utils.set_dict_value(self.template,
+ 'spec.template.spec.nodeSelector',
+ self.node_selector)
+
def _add_volumes(self):
utils.set_dict_value(self.template,
'spec.template.spec.volumes',
@@ -106,6 +114,35 @@ class KubernetesObject(object):
self._add_volume(key_volume)
+class ServiceObject(object):
+
+ def __init__(self, name):
+ self.name = '{}-service'.format(name)
+ self.template = {
+ 'metadata': {
+ 'name': '{}-service'.format(name)
+ },
+ 'spec': {
+ 'type': 'NodePort',
+ 'ports': [
+ {
+ 'port': 22,
+ 'protocol': 'TCP'
+ }
+ ],
+ 'selector': {
+ 'app': name
+ }
+ }
+ }
+
+ def create(self):
+ k8s_utils.create_service(self.template)
+
+ def delete(self):
+ k8s_utils.delete_service(self.name)
+
+
class KubernetesTemplate(object):
def __init__(self, name, template_cfg):
@@ -117,6 +154,8 @@ class KubernetesTemplate(object):
ssh_key=self.ssh_key,
**cfg)
for rc, cfg in template_cfg.items()]
+ self.service_objs = [ServiceObject(s) for s in self.rcs]
+
self.pods = []
def _get_rc_name(self, rc_name):