aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick')
-rw-r--r--yardstick/__init__.py3
-rw-r--r--yardstick/benchmark/contexts/base.py48
-rw-r--r--yardstick/benchmark/contexts/dummy.py24
-rw-r--r--yardstick/benchmark/contexts/heat.py143
-rw-r--r--yardstick/benchmark/contexts/kubernetes.py3
-rw-r--r--yardstick/benchmark/contexts/model.py45
-rw-r--r--yardstick/benchmark/contexts/node.py8
-rw-r--r--yardstick/benchmark/contexts/standalone/ovs_dpdk.py3
-rw-r--r--yardstick/benchmark/contexts/standalone/sriov.py3
-rw-r--r--yardstick/benchmark/core/__init__.py1
-rw-r--r--yardstick/benchmark/core/report.py8
-rw-r--r--yardstick/benchmark/core/task.py236
-rw-r--r--yardstick/benchmark/scenarios/availability/operation_conf.yaml3
-rw-r--r--yardstick/benchmark/scenarios/networking/moongen_testpmd.bash62
-rw-r--r--yardstick/benchmark/scenarios/networking/moongen_testpmd.py378
-rw-r--r--yardstick/benchmark/scenarios/networking/sfc_openstack.py16
-rw-r--r--yardstick/benchmark/scenarios/networking/vnf_generic.py274
-rw-r--r--yardstick/benchmark/scenarios/storage/fio.py16
-rw-r--r--yardstick/cmd/cli.py7
-rw-r--r--yardstick/cmd/commands/task.py9
-rw-r--r--yardstick/common/constants.py4
-rw-r--r--yardstick/common/exceptions.py32
-rw-r--r--yardstick/common/import_tools.py31
-rw-r--r--yardstick/common/openstack_utils.py51
-rw-r--r--yardstick/common/packages.py87
-rw-r--r--yardstick/common/privsep.py23
-rw-r--r--yardstick/common/utils.py72
-rw-r--r--yardstick/error.py48
-rw-r--r--yardstick/network_services/constants.py17
-rw-r--r--yardstick/network_services/helpers/dpdkbindnic_helper.py313
-rw-r--r--yardstick/network_services/traffic_profile/__init__.py33
-rw-r--r--yardstick/network_services/traffic_profile/base.py12
-rw-r--r--yardstick/network_services/traffic_profile/ixia_rfc2544.py2
-rw-r--r--yardstick/network_services/traffic_profile/prox_binsearch.py51
-rw-r--r--yardstick/network_services/traffic_profile/prox_profile.py16
-rw-r--r--yardstick/network_services/traffic_profile/rfc2544.py2
-rw-r--r--yardstick/network_services/traffic_profile/trex_traffic_profile.py (renamed from yardstick/network_services/traffic_profile/traffic_profile.py)6
-rw-r--r--yardstick/network_services/utils.py1
-rw-r--r--yardstick/network_services/vnf_generic/vnf/acl_vnf.py9
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_helpers.py47
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_vnf.py29
-rw-r--r--yardstick/network_services/vnf_generic/vnf/sample_vnf.py135
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_ixload.py13
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_prox.py18
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py11
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vfw_vnf.py8
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py61
-rw-r--r--yardstick/orchestrator/heat.py59
-rw-r--r--yardstick/ssh.py68
-rw-r--r--yardstick/tests/__init__.py75
-rw-r--r--yardstick/tests/functional/base.py46
-rw-r--r--yardstick/tests/functional/benchmark/__init__.py0
-rw-r--r--yardstick/tests/functional/benchmark/scenarios/__init__.py0
-rw-r--r--yardstick/tests/functional/benchmark/scenarios/networking/__init__.py0
-rw-r--r--yardstick/tests/functional/benchmark/scenarios/networking/test_vnf_generic.py195
-rw-r--r--yardstick/tests/functional/common/fake_directory_package/README.md2
-rw-r--r--yardstick/tests/functional/common/fake_directory_package/setup.py29
-rw-r--r--yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/__init__.py0
-rw-r--r--yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/__init__.py0
-rw-r--r--yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/__init__.py0
-rw-r--r--yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/dummy2/__init__.py0
-rw-r--r--yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/dummy2/dummy2.py40
-rw-r--r--yardstick/tests/functional/common/fake_pip_package/yardstick_new_plugin-1.0.0.tar.gzbin0 -> 1650 bytes
-rw-r--r--yardstick/tests/functional/common/test_packages.py94
-rw-r--r--yardstick/tests/unit/__init__.py65
-rw-r--r--yardstick/tests/unit/apiserver/resources/test_env_action.py8
-rw-r--r--yardstick/tests/unit/apiserver/utils/test_influx.py8
-rw-r--r--yardstick/tests/unit/base.py23
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py70
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py58
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_base.py43
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_dummy.py52
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_heat.py332
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_kubernetes.py17
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_model.py13
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_node.py193
-rw-r--r--yardstick/tests/unit/benchmark/core/test_report.py2
-rw-r--r--yardstick/tests/unit/benchmark/core/test_task.py279
-rw-r--r--yardstick/tests/unit/benchmark/core/test_testcase.py10
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_base.py8
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_search.py11
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py4
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_director.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_util.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py10
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py10
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py10
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py7
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_moongen_testpmd.py353
-rwxr-xr-xyardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py9
-rwxr-xr-xyardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py316
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py10
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py8
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py12
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py26
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/test_base.py7
-rw-r--r--yardstick/tests/unit/common/banned_modules/__init__.py0
-rw-r--r--yardstick/tests/unit/common/banned_modules/banned_module.py17
-rw-r--r--yardstick/tests/unit/common/banned_modules/importing_module.py21
-rw-r--r--yardstick/tests/unit/common/test_ansible_common.py4
-rw-r--r--yardstick/tests/unit/common/test_httpClient.py8
-rw-r--r--yardstick/tests/unit/common/test_import_tools.py46
-rw-r--r--yardstick/tests/unit/common/test_openstack_utils.py2
-rw-r--r--yardstick/tests/unit/common/test_packages.py88
-rw-r--r--yardstick/tests/unit/common/test_template_format.py7
-rw-r--r--yardstick/tests/unit/common/test_utils.py92
-rw-r--r--yardstick/tests/unit/common/test_yaml_loader.py8
-rw-r--r--yardstick/tests/unit/dispatcher/test_influxdb.py10
-rw-r--r--yardstick/tests/unit/orchestrator/test_heat.py104
-rw-r--r--yardstick/tests/unit/orchestrator/test_kubernetes.py10
-rw-r--r--yardstick/tests/unit/test_cmd/commands/test_env.py8
-rw-r--r--yardstick/tests/unit/test_cmd/commands/test_testcase.py8
-rw-r--r--yardstick/tests/unit/test_cmd/test_NSBperf.py10
-rw-r--r--yardstick/tests/unit/test_ssh.py62
177 files changed, 4022 insertions, 1912 deletions
diff --git a/yardstick/__init__.py b/yardstick/__init__.py
index f95b0a906..9eb5db9b1 100644
--- a/yardstick/__init__.py
+++ b/yardstick/__init__.py
@@ -14,8 +14,9 @@ import errno
# this module must only import other modules that do
# not require loggers to be created, so this cannot
-# include yardstick.common.utils
from yardstick.common import constants
+from yardstick.common import exceptions
+
try:
# do not use yardstick.common.utils.makedirs
diff --git a/yardstick/benchmark/contexts/base.py b/yardstick/benchmark/contexts/base.py
index c9b5b51c9..ae8319e37 100644
--- a/yardstick/benchmark/contexts/base.py
+++ b/yardstick/benchmark/contexts/base.py
@@ -6,17 +6,41 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-from __future__ import absolute_import
import abc
import six
import yardstick.common.utils as utils
+class Flags(object):
+ """Class to represent the status of the flags in a context"""
+
+ _FLAGS = {'no_setup': False,
+ 'no_teardown': False}
+
+ def __init__(self, **kwargs):
+ for name, value in self._FLAGS.items():
+ setattr(self, name, value)
+
+ for name, value in ((name, value) for (name, value) in kwargs.items()
+ if name in self._FLAGS):
+ setattr(self, name, value)
+
+ def parse(self, **kwargs):
+ """Read in values matching the flags stored in this object"""
+ if not kwargs:
+ return
+
+ for name, value in ((name, value) for (name, value) in kwargs.items()
+ if name in self._FLAGS):
+ setattr(self, name, value)
+
+
@six.add_metaclass(abc.ABCMeta)
class Context(object):
"""Class that represents a context in the logical model"""
list = []
+ SHORT_TASK_ID_LEN = 8
@staticmethod
def split_name(name, sep='.'):
@@ -29,10 +53,28 @@ class Context(object):
def __init__(self):
Context.list.append(self)
+ self._flags = Flags()
+ self._name = None
+ self._task_id = None
- @abc.abstractmethod
def init(self, attrs):
- """Initiate context."""
+ """Initiate context"""
+ self._name = attrs['name']
+ self._task_id = attrs['task_id']
+ self._flags.parse(**attrs.get('flags', {}))
+ self._name_task_id = '{}-{}'.format(
+ self._name, self._task_id[:self.SHORT_TASK_ID_LEN])
+
+ @property
+ def name(self):
+ if self._flags.no_setup or self._flags.no_teardown:
+ return self._name
+ else:
+ return self._name_task_id
+
+ @property
+ def assigned_name(self):
+ return self._name
@staticmethod
def get_cls(context_type):
diff --git a/yardstick/benchmark/contexts/dummy.py b/yardstick/benchmark/contexts/dummy.py
index 8ae4b65b8..a9e4564fe 100644
--- a/yardstick/benchmark/contexts/dummy.py
+++ b/yardstick/benchmark/contexts/dummy.py
@@ -7,33 +7,25 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-from __future__ import absolute_import
-import logging
-
from yardstick.benchmark.contexts.base import Context
-LOG = logging.getLogger(__name__)
-
-
class DummyContext(Context):
- """Class that handle dummy info"""
-
- __context_type__ = "Dummy"
+ """Class that handle dummy info.
- def __init__(self):
- super(DummyContext, self).__init__()
+ This class is also used to test the abstract class Context because it
+ provides a minimal concrete implementation of a subclass.
+ """
- def init(self, attrs):
- pass
+ __context_type__ = "Dummy"
def deploy(self):
- """don't need to deploy"""
+ """Don't need to deploy"""
pass
def undeploy(self):
- """don't need to undeploy"""
- super(DummyContext, self).undeploy()
+ """Don't need to undeploy"""
+ pass
def _get_server(self, attr_name):
return None
diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py
index 7b7f1be32..0d1dfb86f 100644
--- a/yardstick/benchmark/contexts/heat.py
+++ b/yardstick/benchmark/contexts/heat.py
@@ -13,7 +13,6 @@ from __future__ import print_function
import collections
import logging
import os
-import uuid
import errno
from collections import OrderedDict
@@ -25,9 +24,12 @@ from yardstick.benchmark.contexts.model import Network
from yardstick.benchmark.contexts.model import PlacementGroup, ServerGroup
from yardstick.benchmark.contexts.model import Server
from yardstick.benchmark.contexts.model import update_scheduler_hints
-from yardstick.common.openstack_utils import get_neutron_client
-from yardstick.orchestrator.heat import HeatTemplate, get_short_key_uuid
+from yardstick.common import exceptions as y_exc
+from yardstick.common.openstack_utils import get_shade_client
+from yardstick.orchestrator.heat import HeatStack
+from yardstick.orchestrator.heat import HeatTemplate
from yardstick.common import constants as consts
+from yardstick.common import utils
from yardstick.common.utils import source_env
from yardstick.ssh import SSH
@@ -50,7 +52,6 @@ class HeatContext(Context):
__context_type__ = "Heat"
def __init__(self):
- self.name = None
self.stack = None
self.networks = OrderedDict()
self.heat_timeout = None
@@ -67,14 +68,9 @@ class HeatContext(Context):
self._user = None
self.template_file = None
self.heat_parameters = None
- self.neutron_client = None
- # generate an uuid to identify yardstick_key
- # the first 8 digits of the uuid will be used
- self.key_uuid = uuid.uuid4()
+ self.shade_client = None
self.heat_timeout = None
- self.key_filename = ''.join(
- [consts.YARDSTICK_ROOT_PATH, 'yardstick/resources/files/yardstick_key-',
- get_short_key_uuid(self.key_uuid)])
+ self.key_filename = None
super(HeatContext, self).__init__()
@staticmethod
@@ -95,10 +91,10 @@ class HeatContext(Context):
return sorted_networks
def init(self, attrs):
- """initializes itself from the supplied arguments"""
- self.check_environment()
- self.name = attrs["name"]
+ """Initializes itself from the supplied arguments"""
+ super(HeatContext, self).init(attrs)
+ self.check_environment()
self._user = attrs.get("user")
self.template_file = attrs.get("heat_template")
@@ -137,7 +133,6 @@ class HeatContext(Context):
self._server_map[server.dn] = server
self.attrs = attrs
- SSH.gen_keys(self.key_filename)
def check_environment(self):
try:
@@ -176,10 +171,13 @@ class HeatContext(Context):
template.add_flavor(**self.flavor)
self.flavors.add(flavor)
- template.add_keypair(self.keypair_name, self.key_uuid)
+ template.add_keypair(self.keypair_name, self.name)
template.add_security_group(self.secgroup_name)
for network in self.networks.values():
+ # Using existing network
+ if network.is_existing():
+ continue
template.add_network(network.stack_name,
network.physical_network,
network.provider,
@@ -285,38 +283,65 @@ class HeatContext(Context):
scheduler_hints)
def get_neutron_info(self):
- if not self.neutron_client:
- self.neutron_client = get_neutron_client()
+ if not self.shade_client:
+ self.shade_client = get_shade_client()
- networks = self.neutron_client.list_networks()
+ networks = self.shade_client.list_networks()
for network in self.networks.values():
- for neutron_net in networks['networks']:
- if neutron_net['name'] == network.stack_name:
+ for neutron_net in (net for net in networks if net.name == network.stack_name):
network.segmentation_id = neutron_net.get('provider:segmentation_id')
# we already have physical_network
# network.physical_network = neutron_net.get('provider:physical_network')
network.network_type = neutron_net.get('provider:network_type')
network.neutron_info = neutron_net
+ def _create_new_stack(self, heat_template):
+ try:
+ return heat_template.create(block=True,
+ timeout=self.heat_timeout)
+ except KeyboardInterrupt:
+ raise y_exc.StackCreationInterrupt
+ except Exception:
+ LOG.exception("stack failed")
+ # let the other failures happen, we want stack trace
+ raise
+
+ def _retrieve_existing_stack(self, stack_name):
+ stack = HeatStack(stack_name)
+ if stack.get():
+ return stack
+ else:
+ LOG.warning("Stack %s does not exist", self.name)
+ return None
+
def deploy(self):
"""deploys template into a stack using cloud"""
LOG.info("Deploying context '%s' START", self.name)
+ self.key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.name])
+ # Permissions may have changed since creation; this can be fixed. If we
+ # overwrite the file, we lose future access to VMs using this key.
+ # As long as the file exists, even if it is unreadable, keep it intact
+ if not os.path.exists(self.key_filename):
+ SSH.gen_keys(self.key_filename)
+
heat_template = HeatTemplate(self.name, self.template_file,
self.heat_parameters)
if self.template_file is None:
self._add_resources_to_template(heat_template)
- try:
- self.stack = heat_template.create(block=True,
- timeout=self.heat_timeout)
- except KeyboardInterrupt:
- raise SystemExit("\nStack create interrupted")
- except:
- LOG.exception("stack failed")
- # let the other failures happen, we want stack trace
- raise
+ if self._flags.no_setup:
+ # Try to get an existing stack, returns a stack or None
+ self.stack = self._retrieve_existing_stack(self.name)
+ if not self.stack:
+ self.stack = self._create_new_stack(heat_template)
+
+ else:
+ self.stack = self._create_new_stack(heat_template)
# TODO: use Neutron to get segmentation-id
self.get_neutron_info()
@@ -332,18 +357,35 @@ class HeatContext(Context):
LOG.info("Deploying context '%s' DONE", self.name)
+ @staticmethod
+ def _port_net_is_existing(port_info):
+ net_flags = port_info.get('net_flags', {})
+ return net_flags.get(consts.IS_EXISTING)
+
+ @staticmethod
+ def _port_net_is_public(port_info):
+ net_flags = port_info.get('net_flags', {})
+ return net_flags.get(consts.IS_PUBLIC)
+
def add_server_port(self, server):
- # use private ip from first port in first network
- try:
- private_port = next(iter(server.ports.values()))[0]
- except IndexError:
- LOG.exception("Unable to find first private port in %s", server.ports)
- raise
- server.private_ip = self.stack.outputs[private_port["stack_name"]]
+ server_ports = server.ports.values()
+ for server_port in server_ports:
+ port_info = server_port[0]
+ port_ip = self.stack.outputs[port_info["stack_name"]]
+ port_net_is_existing = self._port_net_is_existing(port_info)
+ port_net_is_public = self._port_net_is_public(port_info)
+ if port_net_is_existing and (port_net_is_public or
+ len(server_ports) == 1):
+ server.public_ip = port_ip
+ if not server.private_ip or len(server_ports) == 1:
+ server.private_ip = port_ip
+
server.interfaces = {}
for network_name, ports in server.ports.items():
for port in ports:
# port['port'] is either port name from mapping or default network_name
+ if self._port_net_is_existing(port):
+ continue
server.interfaces[port['port']] = self.make_interface_dict(network_name,
port['port'],
port['stack_name'],
@@ -380,20 +422,27 @@ class HeatContext(Context):
"local_ip": private_ip,
}
+ def _delete_key_file(self):
+ try:
+ utils.remove_file(self.key_filename)
+ utils.remove_file(self.key_filename + ".pub")
+ except OSError:
+ LOG.exception("There was an error removing the key file %s",
+ self.key_filename)
+
def undeploy(self):
"""undeploys stack from cloud"""
+ if self._flags.no_teardown:
+ LOG.info("Undeploying context '%s' SKIP", self.name)
+ return
+
if self.stack:
LOG.info("Undeploying context '%s' START", self.name)
self.stack.delete()
self.stack = None
LOG.info("Undeploying context '%s' DONE", self.name)
- if os.path.exists(self.key_filename):
- try:
- os.remove(self.key_filename)
- os.remove(self.key_filename + ".pub")
- except OSError:
- LOG.exception("Key filename %s", self.key_filename)
+ self._delete_key_file()
super(HeatContext, self).undeploy()
@@ -429,13 +478,17 @@ class HeatContext(Context):
server.private_ip = self.stack.outputs.get(
attr_name.get("private_ip_attr", object()), None)
else:
- server = self._server_map.get(attr_name, None)
+ try:
+ server = self._server_map[attr_name]
+ except KeyError:
+ attr_name_no_suffix = attr_name.split("-")[0]
+ server = self._server_map.get(attr_name_no_suffix, None)
if server is None:
return None
pkey = pkg_resources.resource_string(
'yardstick.resources',
- h_join('files/yardstick_key', get_short_key_uuid(self.key_uuid))).decode('utf-8')
+ h_join('files/yardstick_key', self.name)).decode('utf-8')
result = {
"user": server.context.user,
diff --git a/yardstick/benchmark/contexts/kubernetes.py b/yardstick/benchmark/contexts/kubernetes.py
index 2334e5076..4bea991ea 100644
--- a/yardstick/benchmark/contexts/kubernetes.py
+++ b/yardstick/benchmark/contexts/kubernetes.py
@@ -29,7 +29,6 @@ class KubernetesContext(Context):
__context_type__ = "Kubernetes"
def __init__(self):
- self.name = ''
self.ssh_key = ''
self.key_path = ''
self.public_key_path = ''
@@ -38,7 +37,7 @@ class KubernetesContext(Context):
super(KubernetesContext, self).__init__()
def init(self, attrs):
- self.name = attrs.get('name', '')
+ super(KubernetesContext, self).init(attrs)
template_cfg = attrs.get('servers', {})
self.template = KubernetesTemplate(self.name, template_cfg)
diff --git a/yardstick/benchmark/contexts/model.py b/yardstick/benchmark/contexts/model.py
index ae56066ee..a55c11f79 100644
--- a/yardstick/benchmark/contexts/model.py
+++ b/yardstick/benchmark/contexts/model.py
@@ -18,6 +18,8 @@ import logging
from collections import Mapping
from six.moves import range
+from yardstick.common import constants as consts
+
LOG = logging.getLogger(__name__)
@@ -132,11 +134,28 @@ class Network(Object):
if self.gateway_ip is None:
self.gateway_ip = "null"
- if "external_network" in attrs:
- self.router = Router("router", self.name,
- context, attrs["external_network"])
-
- Network.list.append(self)
+ self.net_flags = attrs.get('net_flags', {})
+ if self.is_existing():
+ self.subnet = attrs.get('subnet')
+ if not self.subnet:
+ raise Warning('No subnet set in existing netwrok!')
+ else:
+ if "external_network" in attrs:
+ self.router = Router("router", self.name,
+ context, attrs["external_network"])
+ Network.list.append(self)
+
+ def is_existing(self):
+ net_is_existing = self.net_flags.get(consts.IS_EXISTING)
+ if net_is_existing and not isinstance(net_is_existing, bool):
+ raise SyntaxError('Network flags should be bool type!')
+ return net_is_existing
+
+ def is_public(self):
+ net_is_public = self.net_flags.get(consts.IS_PUBLIC)
+ if net_is_public and not isinstance(net_is_public, bool):
+ raise SyntaxError('Network flags should be bool type!')
+ return net_is_public
def has_route_to(self, network_name):
"""determines if this network has a route to the named network"""
@@ -302,10 +321,13 @@ class Server(Object): # pragma: no cover
# otherwise add a port for every network with port name as network name
else:
ports = [network.name]
+ net_flags = network.net_flags
for port in ports:
port_name = "{0}-{1}-port".format(server_name, port)
- self.ports.setdefault(network.name, []).append(
- {"stack_name": port_name, "port": port})
+ port_info = {"stack_name": port_name, "port": port}
+ if net_flags:
+ port_info['net_flags'] = net_flags
+ self.ports.setdefault(network.name, []).append(port_info)
# we can't use secgroups if port_security_enabled is False
if network.port_security_enabled is False:
sec_group_id = None
@@ -314,11 +336,14 @@ class Server(Object): # pragma: no cover
sec_group_id = self.secgroup_name
# don't refactor to pass in network object, that causes JSON
# circular ref encode errors
- template.add_port(port_name, network.stack_name, network.subnet_stack_name,
- network.vnic_type, sec_group_id=sec_group_id,
+ template.add_port(port_name, network,
+ sec_group_id=sec_group_id,
provider=network.provider,
allowed_address_pairs=network.allowed_address_pairs)
- port_name_list.append(port_name)
+ if network.is_public():
+ port_name_list.insert(0, port_name)
+ else:
+ port_name_list.append(port_name)
if self.floating_ip:
external_network = self.floating_ip["external_network"]
diff --git a/yardstick/benchmark/contexts/node.py b/yardstick/benchmark/contexts/node.py
index ffc82c8ed..fa619a9aa 100644
--- a/yardstick/benchmark/contexts/node.py
+++ b/yardstick/benchmark/contexts/node.py
@@ -35,7 +35,6 @@ class NodeContext(Context):
__context_type__ = "Node"
def __init__(self):
- self.name = None
self.file_path = None
self.nodes = []
self.networks = {}
@@ -60,7 +59,8 @@ class NodeContext(Context):
def init(self, attrs):
"""initializes itself from the supplied arguments"""
- self.name = attrs["name"]
+ super(NodeContext, self).init(attrs)
+
self.file_path = file_path = attrs.get("file", "pod.yaml")
try:
@@ -157,7 +157,7 @@ class NodeContext(Context):
except StopIteration:
pass
else:
- raise ValueError("Duplicate nodes!!! Nodes: %s %s",
+ raise ValueError("Duplicate nodes!!! Nodes: %s %s" %
(node, duplicate))
node["name"] = attr_name
@@ -204,7 +204,7 @@ class NodeContext(Context):
self.client._put_file_shell(script_file, '~/{}'.format(script))
cmd = 'sudo bash {} {}'.format(script, options)
- status, stdout, stderr = self.client.execute(cmd)
+ status, _, stderr = self.client.execute(cmd)
if status:
raise RuntimeError(stderr)
diff --git a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
index c931d85d0..a18b42ea5 100644
--- a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
+++ b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
@@ -59,7 +59,6 @@ class OvsDpdkContext(Context):
self.first_run = True
self.dpdk_devbind = ''
self.vm_names = []
- self.name = None
self.nfvi_host = []
self.nodes = []
self.networks = {}
@@ -74,8 +73,8 @@ class OvsDpdkContext(Context):
def init(self, attrs):
"""initializes itself from the supplied arguments"""
+ super(OvsDpdkContext, self).init(attrs)
- self.name = attrs["name"]
self.file_path = attrs.get("file", "pod.yaml")
self.nodes, self.nfvi_host, self.host_mgmt = \
diff --git a/yardstick/benchmark/contexts/standalone/sriov.py b/yardstick/benchmark/contexts/standalone/sriov.py
index 9cca3e15c..d7620552b 100644
--- a/yardstick/benchmark/contexts/standalone/sriov.py
+++ b/yardstick/benchmark/contexts/standalone/sriov.py
@@ -43,7 +43,6 @@ class SriovContext(Context):
self.first_run = True
self.dpdk_devbind = ''
self.vm_names = []
- self.name = None
self.nfvi_host = []
self.nodes = []
self.networks = {}
@@ -57,8 +56,8 @@ class SriovContext(Context):
def init(self, attrs):
"""initializes itself from the supplied arguments"""
+ super(SriovContext, self).init(attrs)
- self.name = attrs["name"]
self.file_path = attrs.get("file", "pod.yaml")
self.nodes, self.nfvi_host, self.host_mgmt = \
diff --git a/yardstick/benchmark/core/__init__.py b/yardstick/benchmark/core/__init__.py
index 3e3aa99a1..3914e3237 100644
--- a/yardstick/benchmark/core/__init__.py
+++ b/yardstick/benchmark/core/__init__.py
@@ -23,6 +23,7 @@ class Param(object):
self.task_args_file = kwargs.get('task-args-file')
self.keep_deploy = kwargs.get('keep-deploy')
self.parse_only = kwargs.get('parse-only')
+ self.render_only = kwargs.get('render-only')
self.output_file = kwargs.get('output-file', '/tmp/yardstick.out')
self.suite = kwargs.get('suite')
self.task_id = kwargs.get('task_id')
diff --git a/yardstick/benchmark/core/report.py b/yardstick/benchmark/core/report.py
index 997a125e7..199602444 100644
--- a/yardstick/benchmark/core/report.py
+++ b/yardstick/benchmark/core/report.py
@@ -45,7 +45,7 @@ class Report(object):
self.task_id = ""
def _validate(self, yaml_name, task_id):
- if re.match("^[a-z0-9_-]+$", yaml_name):
+ if re.match(r"^[\w-]+$", yaml_name):
self.yaml_name = yaml_name
else:
raise ValueError("invalid yaml_name", yaml_name)
@@ -102,10 +102,12 @@ class Report(object):
task_time = str(task_time, 'utf8')
key = str(key, 'utf8')
task_time = task_time[11:]
- head, sep, tail = task_time.partition('.')
+ head, _, tail = task_time.partition('.')
task_time = head + "." + tail[:6]
self.Timestamp.append(task_time)
- if isinstance(task[key], float) is True:
+ if task[key] is None:
+ values.append('')
+ elif isinstance(task[key], (int, float)) is True:
values.append(task[key])
else:
values.append(ast.literal_eval(task[key]))
diff --git a/yardstick/benchmark/core/task.py b/yardstick/benchmark/core/task.py
index f5d2b18ac..7f6309a7e 100644
--- a/yardstick/benchmark/core/task.py
+++ b/yardstick/benchmark/core/task.py
@@ -7,10 +7,6 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-""" Handler for yardstick command 'task' """
-
-from __future__ import absolute_import
-from __future__ import print_function
import sys
import os
from collections import OrderedDict
@@ -31,9 +27,10 @@ from yardstick.benchmark.runners import base as base_runner
from yardstick.common.constants import CONF_FILE
from yardstick.common.yaml_loader import yaml_load
from yardstick.dispatcher.base import Base as DispatcherBase
-from yardstick.common.task_template import TaskTemplate
-from yardstick.common import utils
from yardstick.common import constants
+from yardstick.common import exceptions as y_exc
+from yardstick.common import task_template
+from yardstick.common import utils
from yardstick.common.html_template import report_template
output_file_default = "/tmp/yardstick.out"
@@ -57,7 +54,7 @@ class Task(object): # pragma: no cover
out_types = [s.strip() for s in dispatchers.split(',')]
output_config['DEFAULT']['dispatcher'] = out_types
- def start(self, args):
+ def start(self, args, **kwargs): # pylint: disable=unused-argument
"""Start a benchmark scenario."""
atexit.register(self.atexit_handler)
@@ -89,8 +86,7 @@ class Task(object): # pragma: no cover
if args.suite:
# 1.parse suite, return suite_params info
- task_files, task_args, task_args_fnames = \
- parser.parse_suite()
+ task_files, task_args, task_args_fnames = parser.parse_suite()
else:
task_files = [parser.path]
task_args = [args.task_args]
@@ -103,32 +99,33 @@ class Task(object): # pragma: no cover
sys.exit(0)
testcases = {}
- # parse task_files
- for i in range(0, len(task_files)):
- one_task_start_time = time.time()
- parser.path = task_files[i]
- scenarios, run_in_parallel, meet_precondition, contexts = \
- parser.parse_task(self.task_id, task_args[i],
- task_args_fnames[i])
-
- self.contexts.extend(contexts)
+ tasks = self._parse_tasks(parser, task_files, args, task_args,
+ task_args_fnames)
- if not meet_precondition:
- LOG.info("meet_precondition is %s, please check envrionment",
- meet_precondition)
+ # Execute task files.
+ for i, _ in enumerate(task_files):
+ one_task_start_time = time.time()
+ self.contexts.extend(tasks[i]['contexts'])
+ if not tasks[i]['meet_precondition']:
+ LOG.info('"meet_precondition" is %s, please check environment',
+ tasks[i]['meet_precondition'])
continue
- case_name = os.path.splitext(os.path.basename(task_files[i]))[0]
try:
- data = self._run(scenarios, run_in_parallel, output_config)
+ data = self._run(tasks[i]['scenarios'],
+ tasks[i]['run_in_parallel'],
+ output_config)
except KeyboardInterrupt:
raise
except Exception: # pylint: disable=broad-except
- LOG.error('Testcase: "%s" FAILED!!!', case_name, exc_info=True)
- testcases[case_name] = {'criteria': 'FAIL', 'tc_data': []}
+ LOG.error('Testcase: "%s" FAILED!!!', tasks[i]['case_name'],
+ exc_info=True)
+ testcases[tasks[i]['case_name']] = {'criteria': 'FAIL',
+ 'tc_data': []}
else:
- LOG.info('Testcase: "%s" SUCCESS!!!', case_name)
- testcases[case_name] = {'criteria': 'PASS', 'tc_data': data}
+ LOG.info('Testcase: "%s" SUCCESS!!!', tasks[i]['case_name'])
+ testcases[tasks[i]['case_name']] = {'criteria': 'PASS',
+ 'tc_data': data}
if args.keep_deploy:
# keep deployment, forget about stack
@@ -151,9 +148,8 @@ class Task(object): # pragma: no cover
LOG.info("Total finished in %d secs",
total_end_time - total_start_time)
- scenario = scenarios[0]
- LOG.info("To generate report, execute command "
- "'yardstick report generate %(task_id)s %(tc)s'", scenario)
+ LOG.info('To generate report, execute command "yardstick report '
+ 'generate %(task_id)s <yaml_name>s"', self.task_id)
LOG.info("Task ALL DONE, exiting")
return result
@@ -314,6 +310,30 @@ class Task(object): # pragma: no cover
else:
return op
+ def _parse_tasks(self, parser, task_files, args, task_args,
+ task_args_fnames):
+ tasks = []
+
+ # Parse task_files.
+ for i, _ in enumerate(task_files):
+ parser.path = task_files[i]
+ tasks.append(parser.parse_task(self.task_id, task_args[i],
+ task_args_fnames[i]))
+ tasks[i]['case_name'] = os.path.splitext(
+ os.path.basename(task_files[i]))[0]
+
+ if args.render_only:
+ utils.makedirs(args.render_only)
+ for idx, task in enumerate(tasks):
+ output_file_name = os.path.abspath(os.path.join(
+ args.render_only,
+ '{0:03d}-{1}.yml'.format(idx, task['case_name'])))
+ utils.write_file(output_file_name, task['rendered'])
+
+ sys.exit(0)
+
+ return tasks
+
def run_one_scenario(self, scenario_cfg, output_config):
"""run one scenario using context"""
runner_cfg = scenario_cfg["runner"]
@@ -345,7 +365,7 @@ class Task(object): # pragma: no cover
try:
config_context_target(item)
except KeyError:
- pass
+ LOG.debug("Got a KeyError in config_context_target(%s)", item)
else:
break
@@ -479,33 +499,42 @@ class TaskParser(object): # pragma: no cover
return valid_task_files, valid_task_args, valid_task_args_fnames
- def parse_task(self, task_id, task_args=None, task_args_file=None):
- """parses the task file and return an context and scenario instances"""
- LOG.info("Parsing task config: %s", self.path)
+ def _render_task(self, task_args, task_args_file):
+ """Render the input task with the given arguments
+ :param task_args: (dict) arguments to render the task
+ :param task_args_file: (str) file containing the arguments to render
+ the task
+ :return: (str) task file rendered
+ """
try:
kw = {}
if task_args_file:
with open(task_args_file) as f:
- kw.update(parse_task_args("task_args_file", f.read()))
- kw.update(parse_task_args("task_args", task_args))
+ kw.update(parse_task_args('task_args_file', f.read()))
+ kw.update(parse_task_args('task_args', task_args))
except TypeError:
- raise TypeError()
+ raise y_exc.TaskRenderArgumentError()
+ input_task = None
try:
with open(self.path) as f:
- try:
- input_task = f.read()
- rendered_task = TaskTemplate.render(input_task, **kw)
- except Exception as e:
- LOG.exception('Failed to render template:\n%s\n', input_task)
- raise e
- LOG.debug("Input task is:\n%s\n", rendered_task)
-
- cfg = yaml_load(rendered_task)
- except IOError as ioerror:
- sys.exit(ioerror)
+ input_task = f.read()
+ rendered_task = task_template.TaskTemplate.render(input_task, **kw)
+ LOG.debug('Input task is:\n%s', rendered_task)
+ parsed_task = yaml_load(rendered_task)
+ except (IOError, OSError):
+ raise y_exc.TaskReadError(task_file=self.path)
+ except Exception:
+ raise y_exc.TaskRenderError(input_task=input_task)
+
+ return parsed_task, rendered_task
+ def parse_task(self, task_id, task_args=None, task_args_file=None):
+ """parses the task file and return an context and scenario instances"""
+ LOG.info("Parsing task config: %s", self.path)
+
+ cfg, rendered = self._render_task(task_args, task_args_file)
self._check_schema(cfg["schema"], "task")
meet_precondition = self._check_precondition(cfg)
@@ -519,17 +548,15 @@ class TaskParser(object): # pragma: no cover
context_cfgs = [{"type": "Dummy"}]
contexts = []
- name_suffix = '-{}'.format(task_id[:8])
for cfg_attrs in context_cfgs:
- try:
- cfg_attrs['name'] = '{}{}'.format(cfg_attrs['name'],
- name_suffix)
- except KeyError:
- pass
+
+ cfg_attrs['task_id'] = task_id
# default to Heat context because we are testing OpenStack
context_type = cfg_attrs.get("type", "Heat")
context = Context.get(context_type)
context.init(cfg_attrs)
+ # Update the name in case the context has used the name_suffix
+ cfg_attrs['name'] = context.name
contexts.append(context)
run_in_parallel = cfg.get("run_in_parallel", False)
@@ -543,16 +570,74 @@ class TaskParser(object): # pragma: no cover
# relative to task path
scenario["task_path"] = os.path.dirname(self.path)
- change_server_name(scenario, name_suffix)
-
- try:
- for node in scenario['nodes']:
- scenario['nodes'][node] += name_suffix
- except KeyError:
- pass
+ self._change_node_names(scenario, contexts)
# TODO we need something better here, a class that represent the file
- return cfg["scenarios"], run_in_parallel, meet_precondition, contexts
+ return {'scenarios': cfg['scenarios'],
+ 'run_in_parallel': run_in_parallel,
+ 'meet_precondition': meet_precondition,
+ 'contexts': contexts,
+ 'rendered': rendered}
+
+ @staticmethod
+ def _change_node_names(scenario, contexts):
+ """Change the node names in a scenario, depending on the context config
+
+ The nodes (VMs or physical servers) are referred in the context section
+ with the name of the server and the name of the context:
+ <server name>.<context name>
+
+ If the context is going to be undeployed at the end of the test, the
+ task ID is suffixed to the name to avoid interferences with previous
+ deployments. If the context needs to be deployed at the end of the
+ test, the name assigned is kept.
+
+ There are several places where a node name could appear in the scenario
+ configuration:
+ scenario:
+ host: athena.demo
+ target: kratos.demo
+ targets:
+ - athena.demo
+ - kratos.demo
+
+ scenario:
+ options:
+ server_name: # JIRA: YARDSTICK-810
+ host: athena.demo
+ target: kratos.demo
+
+ scenario:
+ nodes:
+ tg__0: tg_0.yardstick
+ vnf__0: vnf_0.yardstick
+ """
+ def qualified_name(name):
+ node_name, context_name = name.split('.')
+ try:
+ ctx = next((context for context in contexts
+ if context.assigned_name == context_name))
+ except StopIteration:
+ raise y_exc.ScenarioConfigContextNameNotFound(
+ context_name=context_name)
+
+ return '{}.{}'.format(node_name, ctx.name)
+
+ if 'host' in scenario:
+ scenario['host'] = qualified_name(scenario['host'])
+ if 'target' in scenario:
+ scenario['target'] = qualified_name(scenario['target'])
+ server_name = scenario.get('options', {}).get('server_name', {})
+ if 'host' in server_name:
+ server_name['host'] = qualified_name(server_name['host'])
+ if 'target' in server_name:
+ server_name['target'] = qualified_name(server_name['target'])
+ if 'targets' in scenario:
+ for idx, target in enumerate(scenario['targets']):
+ scenario['targets'][idx] = qualified_name(target)
+ if 'nodes' in scenario:
+ for scenario_node, target in scenario['nodes'].items():
+ scenario['nodes'][scenario_node] = qualified_name(target)
def _check_schema(self, cfg_schema, schema_type):
"""Check if config file is using the correct schema type"""
@@ -686,30 +771,3 @@ def parse_task_args(src_name, args):
% {"src": src_name, "src_type": type(kw)})
raise TypeError()
return kw
-
-
-def change_server_name(scenario, suffix):
-
- def add_suffix(cfg, key):
- try:
- value = cfg[key]
- except KeyError:
- pass
- else:
- try:
- value['name'] += suffix
- except TypeError:
- cfg[key] += suffix
-
- server_name = scenario.get('options', {}).get('server_name', {})
-
- add_suffix(scenario, 'host')
- add_suffix(scenario, 'target')
- add_suffix(server_name, 'host')
- add_suffix(server_name, 'target')
-
- try:
- key = 'targets'
- scenario[key] = ['{}{}'.format(a, suffix) for a in scenario[key]]
- except KeyError:
- pass
diff --git a/yardstick/benchmark/scenarios/availability/operation_conf.yaml b/yardstick/benchmark/scenarios/availability/operation_conf.yaml
index dc5169196..0ca88393b 100644
--- a/yardstick/benchmark/scenarios/availability/operation_conf.yaml
+++ b/yardstick/benchmark/scenarios/availability/operation_conf.yaml
@@ -35,3 +35,6 @@ get-vip-host:
action_script: ha_tools/pacemaker/get_vip_host.bash
rollback_script: ha_tools/pacemaker/get_resource_status.bash
+start-service:
+ action_script: ha_tools/start_service.bash
+ rollback_script: ha_tools/check_process_python.bash
diff --git a/yardstick/benchmark/scenarios/networking/moongen_testpmd.bash b/yardstick/benchmark/scenarios/networking/moongen_testpmd.bash
new file mode 100644
index 000000000..3e92cc900
--- /dev/null
+++ b/yardstick/benchmark/scenarios/networking/moongen_testpmd.bash
@@ -0,0 +1,62 @@
+##############################################################################
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd 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
+##############################################################################
+#!/bin/bash
+
+set -e
+
+# Commandline arguments
+MOONGEN_PORT1_MAC=$1 # MAC address of the peer port
+MOONGEN_PORT2_MAC=$2 # MAC address of the peer port
+TESTPMD_QUEUE=$3
+
+BIND_ROOT='/opt/nsb_bin'
+DRIVER_ROOT='/opt/tempT/dpdk-17.02/'
+
+load_modules()
+{
+ if ! lsmod | grep "uio" &> /dev/null; then
+ modprobe uio
+ fi
+
+ if ! lsmod | grep "igb_uio" &> /dev/null; then
+ insmod ${DRIVER_ROOT}/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko
+ fi
+
+ if ! lsmod | grep "rte_kni" &> /dev/null; then
+ insmod ${DRIVER_ROOT}/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko
+ fi
+}
+
+change_permissions()
+{
+ chmod 777 /sys/bus/pci/drivers/virtio-pci/*
+ chmod 777 /sys/bus/pci/drivers/igb_uio/*
+}
+
+add_interface_to_dpdk(){
+ interfaces=$(lspci |grep Eth |tail -n +2 |awk '{print $1}')
+ ${BIND_ROOT}/dpdk_nic_bind.py --bind=igb_uio $interfaces &> /dev/null
+}
+
+run_testpmd()
+{
+ blacklist=$(lspci |grep Eth |awk '{print $1}'|head -1)
+ cd ${DRIVER_ROOT}
+ sudo ./x86_64-native-linuxapp-gcc/app/testpmd -c 0x3f -n 4 -b $blacklist -- -a --nb-cores=4 --coremask=0x3c --burst=64 --txd=4096 --rxd=4096 --rxq=$TESTPMD_QUEUE --txq=$TESTPMD_QUEUE --rss-udp --eth-peer=0,$MOONGEN_PORT1_MAC --eth-peer=1,$MOONGEN_PORT2_MAC --forward-mode=mac
+}
+
+main()
+{
+ load_modules
+ change_permissions
+ add_interface_to_dpdk
+ run_testpmd
+}
+
+main
diff --git a/yardstick/benchmark/scenarios/networking/moongen_testpmd.py b/yardstick/benchmark/scenarios/networking/moongen_testpmd.py
new file mode 100644
index 000000000..86173c9da
--- /dev/null
+++ b/yardstick/benchmark/scenarios/networking/moongen_testpmd.py
@@ -0,0 +1,378 @@
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd and others.
+#
+# 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.
+""" VsperfDPDK specific scenario definition """
+
+from __future__ import absolute_import
+import pkg_resources
+import logging
+import subprocess
+import time
+import re
+from oslo_serialization import jsonutils
+
+import yardstick.ssh as ssh
+import yardstick.common.utils as utils
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+
+
+class MoongenTestPMD(base.Scenario):
+ """Execute vsperf with defined parameters
+
+ Parameters:
+ frame_size - a frame size for which test should be executed;
+ Multiple frame sizes can be tested by modification of sequence runner
+ section inside TC YAML definition.
+ type: string
+ default: "64"
+ multistream - the number of simulated streams
+ type: string
+ default: 0 (disabled)
+ testpmd_queue - specifies how many queues you will use the VM
+ only useful when forward_type is true.
+ type: int
+ default: 1(one queue)
+ trafficgen_port1 - specifies device name of 1st interface connected to
+ the trafficgen
+ type: string
+ default: NA
+ trafficgen_port2 - specifies device name of 2nd interface connected to
+ the trafficgen
+ type: string
+ default: NA
+ moongen_host_user - specifies moongen host ssh user name
+ type: string
+ default: root
+ moongen_host_passwd - specifies moongen host ssh user password
+ type: string
+ default: root
+ moongen_host_ip - specifies moongen host ssh ip address
+ type: string
+ default NA
+ moongen_dir - specifies where is the moongen installtion dir
+ type: string
+ default NA
+ moongen_runBidirec - specifies moongen will run in one traffic
+ or two traffic.
+ type: string
+ default true
+ Package_Loss - specifies the package_Loss number in moongen server.
+ type: int
+ default 0(0%)
+ SearchRuntime - specifies the SearchRuntime and validation time
+ on moongen server.
+ type: int
+ default 60(s)
+ moongen_port1_mac - moongen server port1 mac address.
+ type: string
+ default NA
+ moongen_port2_mac - moongen server port2 mac address.
+ type: string
+ default NA
+ forward_type - VM forward type is l2fwd or testpmd.
+ type: string
+ default: testpmd
+ """
+ __scenario_type__ = "MoongenTestPMD"
+
+ TESTPMD_SCRIPT = 'moongen_testpmd.bash'
+ VSPERF_CONFIG = '/tmp/opnfv-vsperf-cfg.lua'
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+ self.forward_setup_done = False
+ self.options = scenario_cfg.get('options', {})
+ self.moongen_host_user = \
+ self.options.get('moongen_host_user', "root")
+ self.moongen_host_passwd = \
+ self.options.get('moongen_host_passwd', "r00t")
+ self.moongen_dir = \
+ self.options.get('moongen_dir', '~/moongen.py')
+ self.testpmd_queue = \
+ self.options.get('testpmd_queue', 1)
+ self.moongen_host_ip = \
+ self.options.get('moongen_host_ip', "127.0.0.1")
+ self.moongen_port1_mac = \
+ self.options.get('moongen_port1_mac', None)
+ self.moongen_port2_mac = \
+ self.options.get('moongen_port2_mac', None)
+ self.tg_port1 = \
+ self.options.get('trafficgen_port1', "enp2s0f0")
+ self.tg_port2 = \
+ self.options.get('trafficgen_port2', "enp2s0f1")
+ self.forward_type = \
+ self.options.get('forward_type', 'testpmd')
+ self.tgen_port1_mac = None
+ self.tgen_port2_mac = None
+
+ def setup(self):
+ """scenario setup"""
+ host = self.context_cfg['host']
+
+ task_id = self.scenario_cfg['task_id']
+ context_number = task_id.split('-')[0]
+ self.tg_port1_nw = 'demo' + \
+ "-" + context_number + "-" + \
+ self.options.get('trafficgen_port1_nw', 'test2')
+ self.tg_port2_nw = 'demo' + \
+ "-" + context_number + "-" + \
+ self.options.get('trafficgen_port2_nw', 'test3')
+
+ # copy vsperf conf to VM
+ self.client = ssh.SSH.from_node(host, defaults={"user": "ubuntu"})
+ # traffic generation could last long
+ self.client.wait(timeout=1800)
+
+ self.server = ssh.SSH(
+ self.moongen_host_user,
+ self.moongen_host_ip,
+ password=self.moongen_host_passwd
+ )
+ # traffic generation could last long
+ self.server.wait(timeout=1800)
+
+ self.setup_done = True
+
+ def forward_setup(self):
+ """forward tool setup"""
+
+ # setup forward loopback in VM
+ self.testpmd_script = pkg_resources.resource_filename(
+ 'yardstick.benchmark.scenarios.networking',
+ self.TESTPMD_SCRIPT)
+
+ self.client._put_file_shell(self.testpmd_script,
+ '~/testpmd_vsperf.sh')
+
+ # disable Address Space Layout Randomization (ASLR)
+ cmd = "echo 0 | sudo tee /proc/sys/kernel/randomize_va_space"
+ self.client.send_command(cmd)
+
+ if not self._is_forward_setup():
+ self.tgen_port1_ip = \
+ utils.get_port_ip(self.client, self.tg_port1)
+ self.tgen_port1_mac = \
+ utils.get_port_mac(self.client, self.tg_port1)
+ self.client.run("tee ~/.testpmd.ipaddr.port1 > /dev/null",
+ stdin=self.tgen_port1_ip)
+ self.client.run("tee ~/.testpmd.macaddr.port1 > /dev/null",
+ stdin=self.tgen_port1_mac)
+ self.tgen_port2_ip = \
+ utils.get_port_ip(self.client, self.tg_port2)
+ self.tgen_port2_mac = \
+ utils.get_port_mac(self.client, self.tg_port2)
+ self.client.run("tee ~/.testpmd.ipaddr.port2 > /dev/null",
+ stdin=self.tgen_port2_ip)
+ self.client.run("tee ~/.testpmd.macaddr.port2 > /dev/null",
+ stdin=self.tgen_port2_mac)
+ else:
+ cmd = "cat ~/.testpmd.macaddr.port1"
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ self.tgen_port1_mac = stdout
+ cmd = "cat ~/.testpmd.ipaddr.port1"
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ self.tgen_port1_ip = stdout
+ cmd = "cat ~/.testpmd.macaddr.port2"
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ self.tgen_port2_mac = stdout
+ cmd = "cat ~/.testpmd.ipaddr.port2"
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ self.tgen_port2_ip = stdout
+
+ LOG.info("forward type is %s", self.forward_type)
+ if self.forward_type == 'testpmd':
+ cmd = "sudo ip link set %s down" % (self.tg_port1)
+ LOG.debug("Executing command: %s", cmd)
+ self.client.execute(cmd)
+ cmd = "sudo ip link set %s down" % (self.tg_port2)
+ LOG.debug("Executing command: %s", cmd)
+ self.client.execute(cmd)
+ cmd = "screen -d -m sudo -E bash ~/testpmd_vsperf.sh %s %s %d" % \
+ (self.moongen_port1_mac, self.moongen_port2_mac,
+ self.testpmd_queue)
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ elif self.forward_type == 'l2fwd':
+ cmd = ('sed -i "s/static char *net1 = \\\"eth1\\\";'
+ '/static char *net1 = \\\"%s %s %s\\\";/g" /home/l2fwd/l2fwd.c'
+ % (self.tg_port1, self.tgen_port1_ip, self.moongen_port1_mac))
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+
+ cmd = ('sed -i "s/static char *net2 = \\\"eth2\\\";'
+ '/static char *net2 = \\\"%s %s %s\\\";/g" /home/l2fwd/l2fwd.c'
+ % (self.tg_port2, self.tgen_port2_ip, self.moongen_port2_mac))
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+
+ cmd = ('cd /home/l2fwd/;make;./gen_debian_package.sh;'
+ 'sudo dpkg -i *.deb;'
+ 'sudo modprobe l2fwd')
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+
+ time.sleep(1)
+
+ self.forward_setup_done = True
+
+ def _is_forward_setup(self):
+ """Is forward already setup in the host?"""
+ if self.forward_type is 'testpmd':
+ is_run = True
+ cmd = "ip a | grep %s 2>/dev/null" % (self.tg_port1)
+ LOG.debug("Executing command: %s", cmd)
+ _, stdout, _ = self.client.execute(cmd)
+ if stdout:
+ is_run = False
+ return is_run
+ elif self.forward_type is 'l2fwd':
+ cmd = ('sudo lsmod |grep l2fwd')
+ LOG.debug("Executing command: %s", cmd)
+ _, stdout, _ = self.client.execute(cmd)
+ if stdout:
+ return True
+ else:
+ return False
+
+ def generate_config_file(self, frame_size, multistream,
+ runBidirec, tg_port1_vlan, tg_port2_vlan,
+ SearchRuntime, Package_Loss):
+ out_text = """\
+VSPERF {
+testType = 'throughput',
+nrFlows = %d,
+runBidirec = %s,
+frameSize = %d,
+srcMacs = {\'%s\', \'%s\'},
+dstMacs = {\'%s\', \'%s\'},
+vlanIds = {%d, %d},
+searchRunTime = %d,
+validationRunTime = %d,
+acceptableLossPct = %d,
+ports = {0,1},
+}
+""" % (multistream, runBidirec, frame_size, self.moongen_port1_mac,
+ self.moongen_port2_mac, self.tgen_port1_mac, self.tgen_port2_mac,
+ tg_port1_vlan, tg_port2_vlan, SearchRuntime, SearchRuntime, Package_Loss)
+ with open(self.VSPERF_CONFIG, "wt") as out_file:
+ out_file.write(out_text)
+ self.CONFIG_FILE = True
+
+ def result_to_data(self, result):
+ search_pattern = re.compile(
+ r'\[REPORT\]\s+total\:\s+'
+ r'Tx\s+frames\:\s+(\d+)\s+'
+ r'Rx\s+Frames\:\s+(\d+)\s+'
+ r'frame\s+loss\:\s+(\d+)\,'
+ r'\s+(\d+\.\d+|\d+)%\s+'
+ r'Tx\s+Mpps\:\s+(\d+.\d+|\d+)\s+'
+ r'Rx\s+Mpps\:\s+(\d+\.\d+|\d+)',
+ re.IGNORECASE)
+ results_match = search_pattern.search(result)
+ if results_match:
+ rx_mpps = float(results_match.group(6))
+ tx_mpps = float(results_match.group(5))
+ else:
+ rx_mpps = 0
+ tx_mpps = 0
+ test_result = {"rx_mpps": rx_mpps, "tx_mpps": tx_mpps}
+ self.TO_DATA = True
+ return test_result
+
+ def run(self, result):
+ """ execute the vsperf benchmark and return test results
+ within result dictionary
+ """
+
+ if not self.setup_done:
+ self.setup()
+
+ # get vsperf options
+ multistream = self.options.get("multistream", 1)
+
+ if not self.forward_setup_done:
+ self.forward_setup()
+
+ if 'frame_size' in self.options:
+ frame_size = self.options.get("frame_size", 64)
+ Package_Loss = self.options.get("Package_Loss", 0)
+ runBidirec = self.options.get("moongen_runBidirec",
+ "true")
+ SearchRuntime = self.options.get("SearchRuntime", 10)
+
+ cmd = "openstack network show %s --format json -c " \
+ "provider:segmentation_id" % (self.tg_port1_nw)
+ LOG.debug("Executing command: %s", cmd)
+ output = subprocess.check_output(cmd, shell=True)
+ try:
+ tg_port1_vlan = jsonutils.loads(output).get("provider:segmentation_id", 1)
+ except TypeError:
+ tg_port1_vlan = 1
+
+ cmd = "openstack network show %s --format json -c " \
+ "provider:segmentation_id" % (self.tg_port2_nw)
+ LOG.debug("Executing command: %s", cmd)
+ output = subprocess.check_output(cmd, shell=True)
+ try:
+ tg_port2_vlan = jsonutils.loads(output).get("provider:segmentation_id", 2)
+ except TypeError:
+ tg_port2_vlan = 2
+
+ self.generate_config_file(frame_size, multistream,
+ runBidirec, tg_port1_vlan,
+ tg_port2_vlan, SearchRuntime, Package_Loss)
+
+ self.server.execute("rm -f -- %s/opnfv-vsperf-cfg.lua" %
+ (self.moongen_dir))
+ self.server._put_file_shell(self.VSPERF_CONFIG,
+ "%s/opnfv-vsperf-cfg.lua"
+ % (self.moongen_dir))
+
+ # execute moongen
+ cmd = ("cd %s;./MoonGen/build/MoonGen ./trafficgen.lua"
+ % (self.moongen_dir))
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ moongen_result = self.result_to_data(stdout)
+ LOG.info(moongen_result)
+ result.update(moongen_result)
+
+ if "sla" in self.scenario_cfg:
+ throughput_rx_mpps = int(
+ self.scenario_cfg["sla"]["throughput_rx_mpps"])
+
+ assert throughput_rx_mpps <= moongen_result["tx_mpps"], \
+ "sla_throughput_rx_mpps %f > throughput_rx_mpps(%f); " % \
+ (throughput_rx_mpps, moongen_result["tx_mpps"])
+
+ def teardown(self):
+ """cleanup after the test execution"""
+
+ # execute external setup script
+ self.setup_done = False
diff --git a/yardstick/benchmark/scenarios/networking/sfc_openstack.py b/yardstick/benchmark/scenarios/networking/sfc_openstack.py
index d5feabbbe..aaab2131a 100644
--- a/yardstick/benchmark/scenarios/networking/sfc_openstack.py
+++ b/yardstick/benchmark/scenarios/networking/sfc_openstack.py
@@ -34,11 +34,13 @@ def get_credentials(service): # pragma: no cover
# The most common way to pass these info to the script is to do it through
# environment variables.
+ # NOTE(ralonsoh): OS_TENANT_NAME is deprecated.
+ project_name = os.environ.get('OS_PROJECT_NAME', 'admin')
creds.update({
"username": os.environ.get('OS_USERNAME', "admin"),
password: os.environ.get("OS_PASSWORD", 'admin'),
"auth_url": os.environ.get("OS_AUTH_URL"),
- tenant: os.environ.get("OS_TENANT_NAME", "admin"),
+ tenant: os.environ.get("OS_TENANT_NAME", project_name),
})
cacert = os.environ.get("OS_CACERT")
if cacert is not None:
@@ -59,7 +61,7 @@ def get_instances(nova_client): # pragma: no cover
try:
instances = nova_client.servers.list(search_opts={'all_tenants': 1})
return instances
- except Exception as e:
+ except Exception as e: # pylint: disable=broad-except
print("Error [get_instances(nova_client)]:", e)
return None
@@ -72,7 +74,7 @@ def get_SFs(nova_client): # pragma: no cover
if "sfc_test" not in instance.name:
SFs.append(instance)
return SFs
- except Exception as e:
+ except Exception as e: # pylint: disable=broad-except
print("Error [get_SFs(nova_client)]:", e)
return None
@@ -93,7 +95,7 @@ def create_floating_ips(neutron_client): # pragma: no cover
ip_json = neutron_client.create_floatingip({'floatingip': props})
fip_addr = ip_json['floatingip']['floating_ip_address']
ips.append(fip_addr)
- except Exception as e:
+ except Exception as e: # pylint: disable=broad-except
print("Error [create_floating_ip(neutron_client)]:", e)
return None
return ips
@@ -106,7 +108,7 @@ def floatIPtoSFs(SFs, floatips): # pragma: no cover
SF.add_floating_ip(floatips[i])
i = i + 1
return True
- except Exception as e:
+ except Exception as e: # pylint: disable=broad-except
print(("Error [add_floating_ip(nova_client, '%s', '%s')]:" %
(SF, floatips[i]), e))
return False
@@ -122,7 +124,3 @@ def get_an_IP(): # pragma: no cover
floatips = create_floating_ips(neutron_client)
floatIPtoSFs(SFs, floatips)
return floatips
-
-
-if __name__ == '__main__': # pragma: no cover
- get_an_IP()
diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py
index b94bfc9ab..0e4785294 100644
--- a/yardstick/benchmark/scenarios/networking/vnf_generic.py
+++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py
@@ -11,115 +11,38 @@
# 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.
-""" NSPerf specific scenario definition """
-
-from __future__ import absolute_import
+import copy
import logging
-import errno
import ipaddress
-
-import copy
+from itertools import chain
import os
import sys
-import re
-from itertools import chain
import six
import yaml
-from collections import defaultdict
-from yardstick.benchmark.scenarios import base
+from yardstick.benchmark.scenarios import base as scenario_base
+from yardstick.error import IncorrectConfig
from yardstick.common.constants import LOG_DIR
from yardstick.common.process import terminate_children
-from yardstick.common.utils import import_modules_from_package, itersubclasses
-from yardstick.common.yaml_loader import yaml_load
+from yardstick.common import utils
from yardstick.network_services.collector.subscriber import Collector
from yardstick.network_services.vnf_generic import vnfdgen
from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
-from yardstick.network_services.traffic_profile.base import TrafficProfile
+from yardstick.network_services import traffic_profile
+from yardstick.network_services.traffic_profile import base as tprofile_base
from yardstick.network_services.utils import get_nsb_option
from yardstick import ssh
-
-LOG = logging.getLogger(__name__)
-
-
-class SSHError(Exception):
- """Class handles ssh connection error exception"""
- pass
-
-
-class SSHTimeout(SSHError):
- """Class handles ssh connection timeout exception"""
- pass
-
-
-class IncorrectConfig(Exception):
- """Class handles incorrect configuration during setup"""
- pass
-
-
-class IncorrectSetup(Exception):
- """Class handles incorrect setup during setup"""
- pass
+traffic_profile.register_modules()
-class SshManager(object):
- def __init__(self, node, timeout=120):
- super(SshManager, self).__init__()
- self.node = node
- self.conn = None
- self.timeout = timeout
-
- def __enter__(self):
- """
- args -> network device mappings
- returns -> ssh connection ready to be used
- """
- try:
- self.conn = ssh.SSH.from_node(self.node)
- self.conn.wait(timeout=self.timeout)
- except SSHError as error:
- LOG.info("connect failed to %s, due to %s", self.node["ip"], error)
- # self.conn defaults to None
- return self.conn
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- if self.conn:
- self.conn.close()
-
-
-def find_relative_file(path, task_path):
- """
- Find file in one of places: in abs of path or
- relative to TC scenario file. In this order.
-
- :param path:
- :param task_path:
- :return str: full path to file
- """
- # fixme: create schema to validate all fields have been provided
- for lookup in [os.path.abspath(path), os.path.join(task_path, path)]:
- try:
- with open(lookup):
- return lookup
- except IOError:
- pass
- raise IOError(errno.ENOENT, 'Unable to find {} file'.format(path))
-
-
-def open_relative_file(path, task_path):
- try:
- return open(path)
- except IOError as e:
- if e.errno == errno.ENOENT:
- return open(os.path.join(task_path, path))
- raise
+LOG = logging.getLogger(__name__)
-class NetworkServiceTestCase(base.Scenario):
+class NetworkServiceTestCase(scenario_base.Scenario):
"""Class handles Generic framework to do pre-deployment VNF &
Network service testing """
@@ -130,16 +53,12 @@ class NetworkServiceTestCase(base.Scenario):
self.scenario_cfg = scenario_cfg
self.context_cfg = context_cfg
- # fixme: create schema to validate all fields have been provided
- with open_relative_file(scenario_cfg["topology"],
- scenario_cfg['task_path']) as stream:
- topology_yaml = yaml_load(stream)
-
- self.topology = topology_yaml["nsd:nsd-catalog"]["nsd"][0]
+ self._render_topology()
self.vnfs = []
self.collector = None
self.traffic_profile = None
self.node_netdevs = {}
+ self.bin_path = get_nsb_option('bin_path', '')
def _get_ip_flow_range(self, ip_start_range):
@@ -211,37 +130,47 @@ class NetworkServiceTestCase(base.Scenario):
def _get_traffic_profile(self):
profile = self.scenario_cfg["traffic_profile"]
path = self.scenario_cfg["task_path"]
- with open_relative_file(profile, path) as infile:
+ 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 _fill_traffic_profile(self):
- traffic_mapping = self._get_traffic_profile()
- traffic_map_data = {
+ tprofile = self._get_traffic_profile()
+ extra_args = self.scenario_cfg.get('extra_args', {})
+ tprofile_data = {
'flow': self._get_traffic_flow(),
'imix': self._get_traffic_imix(),
- TrafficProfile.UPLINK: {},
- TrafficProfile.DOWNLINK: {},
+ tprofile_base.TrafficProfile.UPLINK: {},
+ tprofile_base.TrafficProfile.DOWNLINK: {},
+ 'extra_args': extra_args
}
- traffic_vnfd = vnfdgen.generate_vnfd(traffic_mapping, traffic_map_data)
- self.traffic_profile = TrafficProfile.get(traffic_vnfd)
- return self.traffic_profile
+ traffic_vnfd = vnfdgen.generate_vnfd(tprofile, tprofile_data)
+ self.traffic_profile = tprofile_base.TrafficProfile.get(traffic_vnfd)
+
+ def _render_topology(self):
+ topology = self._get_topology()
+ topology_args = self.scenario_cfg.get('extra_args', {})
+ topolgy_data = {
+ 'extra_args': topology_args
+ }
+ topology_yaml = vnfdgen.generate_vnfd(topology, topolgy_data)
+ self.topology = topology_yaml["nsd:nsd-catalog"]["nsd"][0]
def _find_vnf_name_from_id(self, vnf_id):
return next((vnfd["vnfd-id-ref"]
for vnfd in self.topology["constituent-vnfd"]
if vnf_id == vnfd["member-vnf-index"]), None)
- @staticmethod
- def get_vld_networks(networks):
- # network name is vld_id
- vld_map = {}
- for name, n in networks.items():
- try:
- vld_map[n['vld_id']] = n
- except KeyError:
- vld_map[name] = n
- return vld_map
+ def _find_vnfd_from_vnf_idx(self, vnf_id):
+ return next((vnfd
+ for vnfd in self.topology["constituent-vnfd"]
+ if vnf_id == vnfd["member-vnf-index"]), None)
@staticmethod
def find_node_if(nodes, name, if_name, vld_id):
@@ -293,7 +222,9 @@ class NetworkServiceTestCase(base.Scenario):
node1_if["peer_ifname"] = node0_if_name
# just load the network
- vld_networks = self.get_vld_networks(self.context_cfg["networks"])
+ vld_networks = {n.get('vld_id', name): n for name, n in
+ self.context_cfg["networks"].items()}
+
node0_if["network"] = vld_networks.get(vld["id"], {})
node1_if["network"] = vld_networks.get(vld["id"], {})
@@ -332,10 +263,6 @@ class NetworkServiceTestCase(base.Scenario):
node0_if["peer_intf"] = node1_copy
node1_if["peer_intf"] = node0_copy
- def _find_vnfd_from_vnf_idx(self, vnf_idx):
- return next((vnfd for vnfd in self.topology["constituent-vnfd"]
- if vnf_idx == vnfd["member-vnf-index"]), None)
-
def _update_context_with_topology(self):
for vnfd in self.topology["constituent-vnfd"]:
vnf_idx = vnfd["member-vnf-index"]
@@ -343,43 +270,6 @@ class NetworkServiceTestCase(base.Scenario):
vnfd = self._find_vnfd_from_vnf_idx(vnf_idx)
self.context_cfg["nodes"][vnf_name].update(vnfd)
- def _probe_netdevs(self, node, node_dict, timeout=120):
- try:
- return self.node_netdevs[node]
- except KeyError:
- pass
-
- netdevs = {}
- cmd = "PATH=$PATH:/sbin:/usr/sbin ip addr show"
-
- with SshManager(node_dict, timeout=timeout) as conn:
- if conn:
- exit_status = conn.execute(cmd)[0]
- if exit_status != 0:
- raise IncorrectSetup("Node's %s lacks ip tool." % node)
- exit_status, stdout, _ = conn.execute(
- self.FIND_NETDEVICE_STRING)
- if exit_status != 0:
- raise IncorrectSetup(
- "Cannot find netdev info in sysfs" % node)
- netdevs = node_dict['netdevs'] = self.parse_netdev_info(stdout)
-
- self.node_netdevs[node] = netdevs
- return netdevs
-
- @classmethod
- def _probe_missing_values(cls, netdevs, network):
-
- mac_lower = network['local_mac'].lower()
- for netdev in netdevs.values():
- if netdev['address'].lower() != mac_lower:
- continue
- network.update({
- 'driver': netdev['driver'],
- 'vpci': netdev['pci_bus_id'],
- 'ifindex': netdev['ifindex'],
- })
-
def _generate_pod_yaml(self):
context_yaml = os.path.join(LOG_DIR, "pod-{}.yaml".format(self.scenario_cfg['task_id']))
# convert OrderedDict to a list
@@ -405,82 +295,16 @@ class NetworkServiceTestCase(base.Scenario):
pass
return new_node
- TOPOLOGY_REQUIRED_KEYS = frozenset({
- "vpci", "local_ip", "netmask", "local_mac", "driver"})
-
def map_topology_to_infrastructure(self):
""" This method should verify if the available resources defined in pod.yaml
match the topology.yaml file.
:return: None. Side effect: context_cfg is updated
"""
- num_nodes = len(self.context_cfg["nodes"])
- # OpenStack instance creation time is probably proportional to the number
- # of instances
- timeout = 120 * num_nodes
- for node, node_dict in self.context_cfg["nodes"].items():
-
- for network in node_dict["interfaces"].values():
- missing = self.TOPOLOGY_REQUIRED_KEYS.difference(network)
- if not missing:
- continue
-
- # only ssh probe if there are missing values
- # ssh probe won't work on Ixia, so we had better define all our values
- try:
- netdevs = self._probe_netdevs(node, node_dict, timeout=timeout)
- except (SSHError, SSHTimeout):
- raise IncorrectConfig(
- "Unable to probe missing interface fields '%s', on node %s "
- "SSH Error" % (', '.join(missing), node))
- try:
- self._probe_missing_values(netdevs, network)
- except KeyError:
- pass
- else:
- missing = self.TOPOLOGY_REQUIRED_KEYS.difference(
- network)
- if missing:
- raise IncorrectConfig(
- "Require interface fields '%s' not found, topology file "
- "corrupted" % ', '.join(missing))
-
- # we have to generate pod.yaml here so we have vpci and driver
- self._generate_pod_yaml()
# 3. Use topology file to find connections & resolve dest address
self._resolve_topology()
self._update_context_with_topology()
- FIND_NETDEVICE_STRING = r"""find /sys/devices/pci* -type d -name net -exec sh -c '{ grep -sH ^ \
-$1/ifindex $1/address $1/operstate $1/device/vendor $1/device/device \
-$1/device/subsystem_vendor $1/device/subsystem_device ; \
-printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
-' sh \{\}/* \;
-"""
- BASE_ADAPTER_RE = re.compile(
- '^/sys/devices/(.*)/net/([^/]*)/([^:]*):(.*)$', re.M)
-
- @classmethod
- def parse_netdev_info(cls, stdout):
- network_devices = defaultdict(dict)
- matches = cls.BASE_ADAPTER_RE.findall(stdout)
- for bus_path, interface_name, name, value in matches:
- dirname, bus_id = os.path.split(bus_path)
- if 'virtio' in bus_id:
- # for some stupid reason VMs include virtio1/
- # in PCI device path
- bus_id = os.path.basename(dirname)
- # remove extra 'device/' from 'device/vendor,
- # device/subsystem_vendor', etc.
- if 'device/' in name:
- name = name.split('/')[1]
- network_devices[interface_name][name] = value
- network_devices[interface_name][
- 'interface_name'] = interface_name
- network_devices[interface_name]['pci_bus_id'] = bus_id
- # convert back to regular dict
- return dict(network_devices)
-
@classmethod
def get_vnf_impl(cls, vnf_model_id):
""" Find the implementing class from vnf_model["vnf"]["name"] field
@@ -488,13 +312,14 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
:param vnf_model_id: parsed vnfd model ID field
:return: subclass of GenericVNF
"""
- import_modules_from_package(
+ utils.import_modules_from_package(
"yardstick.network_services.vnf_generic.vnf")
expected_name = vnf_model_id
classes_found = []
def impl():
- for name, class_ in ((c.__name__, c) for c in itersubclasses(GenericVNF)):
+ for name, class_ in ((c.__name__, c) for c in
+ utils.itersubclasses(GenericVNF)):
if name == expected_name:
yield class_
classes_found.append(name)
@@ -547,7 +372,7 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
context_cfg = self.context_cfg
vnfs = []
- # we assume OrderedDict for consistenct in instantiation
+ # we assume OrderedDict for consistency in instantiation
for node_name, node in context_cfg["nodes"].items():
LOG.debug(node)
try:
@@ -556,7 +381,7 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
LOG.debug("no model for %s, skipping", node_name)
continue
file_path = scenario_cfg['task_path']
- with open_relative_file(file_name, file_path) as stream:
+ with utils.open_relative_file(file_name, file_path) as stream:
vnf_model = stream.read()
vnfd = vnfdgen.generate_vnfd(vnf_model, node)
# TODO: here add extra context_cfg["nodes"] regardless of template
@@ -606,6 +431,9 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
vnf.terminate()
raise
+ # we have to generate pod.yaml here after VNF has probed so we know vpci and driver
+ self._generate_pod_yaml()
+
# 3. Run experiment
# Start listeners first to avoid losing packets
for traffic_gen in traffic_runners:
diff --git a/yardstick/benchmark/scenarios/storage/fio.py b/yardstick/benchmark/scenarios/storage/fio.py
index 125bc7ed4..d3ed840d8 100644
--- a/yardstick/benchmark/scenarios/storage/fio.py
+++ b/yardstick/benchmark/scenarios/storage/fio.py
@@ -124,12 +124,16 @@ class Fio(base.Scenario):
if mount_dir:
LOG.debug("Formating volume...")
- self.client.execute("sudo mkfs.ext4 /dev/vdb")
- cmd = "sudo mkdir %s" % mount_dir
- self.client.execute(cmd)
- LOG.debug("Mounting volume at: %s", mount_dir)
- cmd = "sudo mount /dev/vdb %s" % mount_dir
- self.client.execute(cmd)
+ _, stdout, _ = self.client.execute(
+ "lsblk -dps | grep -m 1 disk | awk '{print $1}'")
+ block_device = stdout.strip()
+ if block_device:
+ self.client.execute("sudo mkfs.ext4 %s" % block_device)
+ cmd = "sudo mkdir %s" % mount_dir
+ self.client.execute(cmd)
+ LOG.debug("Mounting volume at: %s", mount_dir)
+ cmd = "sudo mount %s %s" % (block_device, mount_dir)
+ self.client.execute(cmd)
self.setup_done = True
diff --git a/yardstick/cmd/cli.py b/yardstick/cmd/cli.py
index 67ce11451..0bc7c1617 100644
--- a/yardstick/cmd/cli.py
+++ b/yardstick/cmd/cli.py
@@ -28,6 +28,8 @@ from yardstick.cmd.commands import testcase
from yardstick.cmd.commands import plugin
from yardstick.cmd.commands import env
from yardstick.cmd.commands import report
+from yardstick.common import import_tools
+
CONF = cfg.CONF
cli_opts = [
@@ -53,7 +55,8 @@ def find_config_files(path_list):
return None
-class YardstickCLI(): # pragma: no cover
+@import_tools.decorator_banned_modules
+class YardstickCLI(object): # pragma: no cover
"""Command-line interface to yardstick"""
# Command categories
@@ -108,7 +111,7 @@ class YardstickCLI(): # pragma: no cover
# register subcommands to parse additional command line arguments
def parser(subparsers):
- self._add_command_parsers(YardstickCLI.categories, subparsers)
+ self._add_command_parsers(self.categories, subparsers)
category_opt = cfg.SubCommandOpt("category",
title="Command categories",
diff --git a/yardstick/cmd/commands/task.py b/yardstick/cmd/commands/task.py
index e2e8bf67d..a3488a23d 100644
--- a/yardstick/cmd/commands/task.py
+++ b/yardstick/cmd/commands/task.py
@@ -7,10 +7,6 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-""" Handler for yardstick command 'task' """
-from __future__ import print_function
-from __future__ import absolute_import
-
import logging
from yardstick.benchmark.core.task import Task
@@ -42,6 +38,8 @@ class TaskCommands(object): # pragma: no cover
action="store_true")
@cliargs("--parse-only", help="parse the config file and exit",
action="store_true")
+ @cliargs("--render-only", help="Render the tasks files, store the result "
+ "in the directory given and exit", type=str, dest="render_only")
@cliargs("--output-file", help="file where output is stored, default %s" %
output_file_default, default=output_file_default)
@cliargs("--suite", help="process test suite file instead of a task file",
@@ -54,9 +52,8 @@ class TaskCommands(object): # pragma: no cover
LOG.info('Task START')
try:
result = Task().start(param, **kwargs)
- except Exception as e:
+ except Exception as e: # pylint: disable=broad-except
self._write_error_data(e)
- LOG.exception("")
if result.get('result', {}).get('criteria') == 'PASS':
LOG.info('Task SUCCESS')
diff --git a/yardstick/common/constants.py b/yardstick/common/constants.py
index 43c2c19cb..153bd4bf4 100644
--- a/yardstick/common/constants.py
+++ b/yardstick/common/constants.py
@@ -145,6 +145,10 @@ BASE_URL = 'http://localhost:5000'
ENV_ACTION_API = BASE_URL + '/yardstick/env/action'
ASYNC_TASK_API = BASE_URL + '/yardstick/asynctask'
+# flags
+IS_EXISTING = 'is_existing'
+IS_PUBLIC = 'is_public'
+
# general
TESTCASE_PRE = 'opnfv_yardstick_'
TESTSUITE_PRE = 'opnfv_'
diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py
index 3e0635e46..7f72887e1 100644
--- a/yardstick/common/exceptions.py
+++ b/yardstick/common/exceptions.py
@@ -59,14 +59,44 @@ class FunctionNotImplemented(YardstickException):
'"%(class_name)" class.')
+class YardstickBannedModuleImported(YardstickException):
+ # pragma: no cover
+ message = 'Module "%(module)s" cannnot be imported. Reason: "%(reason)s"'
+
+
class HeatTemplateError(YardstickException):
"""Error in Heat during the stack deployment"""
message = ('Error in Heat during the creation of the OpenStack stack '
- '"%(stack_name)"')
+ '"%(stack_name)s"')
class IPv6RangeError(YardstickException):
message = 'Start IP "%(start_ip)s" is greater than end IP "%(end_ip)s"'
+
+class TrafficProfileNotImplemented(YardstickException):
+ message = 'No implementation for traffic profile %(profile_class)s.'
+
+
class DPDKSetupDriverError(YardstickException):
message = '"igb_uio" driver is not loaded'
+
+
+class ScenarioConfigContextNameNotFound(YardstickException):
+ message = 'Context name "%(context_name)s" not found'
+
+
+class StackCreationInterrupt(YardstickException):
+ message = 'Stack create interrupted.'
+
+
+class TaskRenderArgumentError(YardstickException):
+ message = 'Error reading the task input arguments'
+
+
+class TaskReadError(YardstickException):
+ message = 'Failed to read task %(task_file)s'
+
+
+class TaskRenderError(YardstickException):
+ message = 'Failed to render template:\n%(input_task)s'
diff --git a/yardstick/common/import_tools.py b/yardstick/common/import_tools.py
new file mode 100644
index 000000000..bf8dc7e07
--- /dev/null
+++ b/yardstick/common/import_tools.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2018 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 sys
+
+from yardstick.common import exceptions
+
+
+BANNED_MODULES = {'ansible': 'Module with GPLv3 license'}
+
+
+def decorator_banned_modules(cls):
+ def _class(*args, **kwargs):
+ for module in sys.modules:
+ for banned_module, reason in BANNED_MODULES.items():
+ if module.startswith(banned_module):
+ raise exceptions.YardstickBannedModuleImported(
+ module=banned_module, reason=reason)
+ return cls(*args, **kwargs)
+ return _class
diff --git a/yardstick/common/openstack_utils.py b/yardstick/common/openstack_utils.py
index 8f666e268..e3f67baa5 100644
--- a/yardstick/common/openstack_utils.py
+++ b/yardstick/common/openstack_utils.py
@@ -33,38 +33,22 @@ DEFAULT_API_VERSION = '2'
# CREDENTIALS
# *********************************************
def get_credentials():
- """Returns a creds dictionary filled with parsed from env"""
- creds = {}
-
- keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
-
- if keystone_api_version is None or keystone_api_version == '2':
- keystone_v3 = False
- tenant_env = 'OS_TENANT_NAME'
- tenant = 'tenant_name'
- else:
- keystone_v3 = True
- tenant_env = 'OS_PROJECT_NAME'
- tenant = 'project_name'
-
- # The most common way to pass these info to the script is to do it
- # through environment variables.
- creds.update({
- "username": os.environ.get("OS_USERNAME"),
- "password": os.environ.get("OS_PASSWORD"),
- "auth_url": os.environ.get("OS_AUTH_URL"),
- tenant: os.environ.get(tenant_env)
- })
-
- if keystone_v3:
- if os.getenv('OS_USER_DOMAIN_NAME') is not None:
- creds.update({
- "user_domain_name": os.getenv('OS_USER_DOMAIN_NAME')
- })
- if os.getenv('OS_PROJECT_DOMAIN_NAME') is not None:
- creds.update({
- "project_domain_name": os.getenv('OS_PROJECT_DOMAIN_NAME')
- })
+ """Returns a creds dictionary filled with parsed from env
+
+ Keystone API version used is 3; v2 was deprecated in 2014 (Icehouse). Along
+ with this deprecation, environment variable 'OS_TENANT_NAME' is replaced by
+ 'OS_PROJECT_NAME'.
+ """
+ creds = {'username': os.environ.get('OS_USERNAME'),
+ 'password': os.environ.get('OS_PASSWORD'),
+ 'auth_url': os.environ.get('OS_AUTH_URL'),
+ 'project_name': os.environ.get('OS_PROJECT_NAME')
+ }
+
+ if os.getenv('OS_USER_DOMAIN_NAME'):
+ creds['user_domain_name'] = os.getenv('OS_USER_DOMAIN_NAME')
+ if os.getenv('OS_PROJECT_DOMAIN_NAME'):
+ creds['project_domain_name'] = os.getenv('OS_PROJECT_DOMAIN_NAME')
return creds
@@ -294,8 +278,7 @@ def create_instance_and_wait_for_active(json_body): # pragma: no cover
VM_BOOT_TIMEOUT = 180
nova_client = get_nova_client()
instance = create_instance(json_body)
- count = VM_BOOT_TIMEOUT / SLEEP
- for _ in range(count, -1, -1):
+ for _ in range(int(VM_BOOT_TIMEOUT / SLEEP)):
status = get_instance_status(nova_client, instance)
if status.lower() == "active":
return instance
diff --git a/yardstick/common/packages.py b/yardstick/common/packages.py
new file mode 100644
index 000000000..f20217fdc
--- /dev/null
+++ b/yardstick/common/packages.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2018 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 logging
+import re
+
+import pip
+from pip import exceptions as pip_exceptions
+from pip.operations import freeze
+
+from yardstick.common import privsep
+
+
+LOG = logging.getLogger(__name__)
+
+ACTION_INSTALL = 'install'
+ACTION_UNINSTALL = 'uninstall'
+
+
+@privsep.yardstick_root.entrypoint
+def _pip_main(package, action, target=None):
+ if action == ACTION_UNINSTALL:
+ cmd = [action, package, '-y']
+ elif action == ACTION_INSTALL:
+ cmd = [action, package, '--upgrade']
+ if target:
+ cmd.append('--target=%s' % target)
+ return pip.main(cmd)
+
+
+def _pip_execute_action(package, action=ACTION_INSTALL, target=None):
+ """Execute an action with a PIP package.
+
+ According to [1], a package could be a URL, a local directory, a local dist
+ file or a requirements file.
+
+ [1] https://pip.pypa.io/en/stable/reference/pip_install/#argument-handling
+ """
+ try:
+ status = _pip_main(package, action, target)
+ except pip_exceptions.PipError:
+ status = 1
+
+ if not status:
+ LOG.info('Action "%s" executed, package %s', package, action)
+ else:
+ LOG.info('Error executing action "%s", package %s', package, action)
+ return status
+
+
+def pip_remove(package):
+ """Remove an installed PIP package"""
+ return _pip_execute_action(package, action=ACTION_UNINSTALL)
+
+
+def pip_install(package, target=None):
+ """Install a PIP package"""
+ return _pip_execute_action(package, action=ACTION_INSTALL, target=target)
+
+
+def pip_list(pkg_name=None):
+ """Dict of installed PIP packages with version.
+
+ If 'pkg_name' is not None, will return only those packages matching the
+ name."""
+ pip_regex = re.compile(r"(?P<name>.*)==(?P<version>[\w\.]+)")
+ git_regex = re.compile(r".*@(?P<version>[\w]+)#egg=(?P<name>[\w]+)")
+
+ pkg_dict = {}
+ for _pkg in freeze.freeze(local_only=True):
+ match = pip_regex.match(_pkg) or git_regex.match(_pkg)
+ if match and (not pkg_name or (
+ pkg_name and match.group('name').find(pkg_name) != -1)):
+ pkg_dict[match.group('name')] = match.group('version')
+
+ return pkg_dict
diff --git a/yardstick/common/privsep.py b/yardstick/common/privsep.py
new file mode 100644
index 000000000..4ae510489
--- /dev/null
+++ b/yardstick/common/privsep.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2018 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 oslo_privsep import capabilities as c
+from oslo_privsep import priv_context
+
+yardstick_root = priv_context.PrivContext(
+ "yardstick",
+ cfg_section="yardstick_privileged",
+ pypath=__name__ + ".yardstick_root",
+ capabilities=[c.CAP_SYS_ADMIN]
+)
diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py
index 8604e900f..357f66be8 100644
--- a/yardstick/common/utils.py
+++ b/yardstick/common/utils.py
@@ -22,6 +22,7 @@ import ipaddress
import logging
import os
import random
+import re
import socket
import subprocess
import sys
@@ -30,6 +31,7 @@ import six
from flask import jsonify
from six.moves import configparser
from oslo_serialization import jsonutils
+from oslo_utils import encodeutils
import yardstick
@@ -64,7 +66,7 @@ def itersubclasses(cls, _seen=None):
yield sub
-def import_modules_from_package(package):
+def import_modules_from_package(package, raise_exception=False):
"""Import modules given a package name
:param: package - Full package name. For example: rally.deploy.engines
@@ -85,10 +87,27 @@ def import_modules_from_package(package):
for module_name in missing_modules:
try:
importlib.import_module(module_name)
- except (ImportError, SyntaxError):
+ except (ImportError, SyntaxError) as exc:
+ if raise_exception:
+ raise exc
logger.exception('Unable to import module %s', module_name)
+NON_NONE_DEFAULT = object()
+
+
+def get_key_with_default(data, key, default=NON_NONE_DEFAULT):
+ value = data.get(key, default)
+ if value is NON_NONE_DEFAULT:
+ raise KeyError(key)
+ return value
+
+
+def make_dict_from_map(data, key_map):
+ return {dest_key: get_key_with_default(data, src_key, default)
+ for dest_key, (src_key, default) in key_map.items()}
+
+
def makedirs(d):
try:
os.makedirs(d)
@@ -105,13 +124,12 @@ def remove_file(path):
raise
-def execute_command(cmd):
+def execute_command(cmd, **kwargs):
exec_msg = "Executing command: '%s'" % cmd
logger.debug(exec_msg)
- output = subprocess.check_output(cmd.split()).split(os.linesep)
-
- return output
+ output = subprocess.check_output(cmd.split(), **kwargs)
+ return encodeutils.safe_decode(output, incoming='utf-8').split(os.linesep)
def source_env(env_file):
@@ -395,3 +413,45 @@ class Timer(object):
def __getattr__(self, item):
return getattr(self.delta, item)
+
+
+def read_meminfo(ssh_client):
+ """Read "/proc/meminfo" file and parse all keys and values"""
+
+ cpuinfo = six.BytesIO()
+ ssh_client.get_file_obj('/proc/meminfo', cpuinfo)
+ lines = cpuinfo.getvalue().decode('utf-8')
+ matches = re.findall(r"([\w\(\)]+):\s+(\d+)( kB)*", lines)
+ output = {}
+ for match in matches:
+ output[match[0]] = match[1]
+
+ return output
+
+
+def find_relative_file(path, task_path):
+ """
+ Find file in one of places: in abs of path or relative to a directory path,
+ in this order.
+
+ :param path:
+ :param task_path:
+ :return str: full path to file
+ """
+ # fixme: create schema to validate all fields have been provided
+ for lookup in [os.path.abspath(path), os.path.join(task_path, path)]:
+ try:
+ with open(lookup):
+ return lookup
+ except IOError:
+ pass
+ raise IOError(errno.ENOENT, 'Unable to find {} file'.format(path))
+
+
+def open_relative_file(path, task_path):
+ try:
+ return open(path)
+ except IOError as e:
+ if e.errno == errno.ENOENT:
+ return open(os.path.join(task_path, path))
+ raise
diff --git a/yardstick/error.py b/yardstick/error.py
new file mode 100644
index 000000000..9b84de1af
--- /dev/null
+++ b/yardstick/error.py
@@ -0,0 +1,48 @@
+# 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.
+
+
+class SSHError(Exception):
+ """Class handles ssh connection error exception"""
+ pass
+
+
+class SSHTimeout(SSHError):
+ """Class handles ssh connection timeout exception"""
+ pass
+
+
+class IncorrectConfig(Exception):
+ """Class handles incorrect configuration during setup"""
+ pass
+
+
+class IncorrectSetup(Exception):
+ """Class handles incorrect setup during setup"""
+ pass
+
+
+class IncorrectNodeSetup(IncorrectSetup):
+ """Class handles incorrect setup during setup"""
+ pass
+
+
+class ErrorClass(object):
+
+ def __init__(self, *args, **kwargs):
+ if 'test' not in kwargs:
+ raise RuntimeError
+
+ def __getattr__(self, item):
+ raise AttributeError
diff --git a/yardstick/network_services/constants.py b/yardstick/network_services/constants.py
new file mode 100644
index 000000000..79951e353
--- /dev/null
+++ b/yardstick/network_services/constants.py
@@ -0,0 +1,17 @@
+# 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.
+
+REMOTE_TMP = "/tmp"
+DEFAULT_VNF_TIMEOUT = 3600
+PROCESS_JOIN_TIMEOUT = 3
diff --git a/yardstick/network_services/helpers/dpdkbindnic_helper.py b/yardstick/network_services/helpers/dpdkbindnic_helper.py
index 8c44b26c2..05b822c2e 100644
--- a/yardstick/network_services/helpers/dpdkbindnic_helper.py
+++ b/yardstick/network_services/helpers/dpdkbindnic_helper.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2018 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,11 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
+import os
import re
-import itertools
+from collections import defaultdict
+from itertools import chain
-import six
+from yardstick.common.utils import validate_non_string_sequence
+from yardstick.error import IncorrectConfig
+from yardstick.error import IncorrectSetup
+from yardstick.error import IncorrectNodeSetup
+from yardstick.error import SSHTimeout
+from yardstick.error import SSHError
NETWORK_KERNEL = 'network_kernel'
NETWORK_DPDK = 'network_dpdk'
@@ -25,7 +32,6 @@ CRYPTO_KERNEL = 'crypto_kernel'
CRYPTO_DPDK = 'crypto_dpdk'
CRYPTO_OTHER = 'crypto_other'
-
LOG = logging.getLogger(__name__)
@@ -33,6 +39,166 @@ class DpdkBindHelperException(Exception):
pass
+class DpdkInterface(object):
+ TOPOLOGY_REQUIRED_KEYS = frozenset({
+ "vpci", "local_ip", "netmask", "local_mac", "driver"})
+
+ def __init__(self, dpdk_node, interface):
+ super(DpdkInterface, self).__init__()
+ self.dpdk_node = dpdk_node
+ self.interface = interface
+
+ try:
+ assert self.local_mac
+ except (AssertionError, KeyError):
+ raise IncorrectConfig
+
+ @property
+ def local_mac(self):
+ return self.interface['local_mac']
+
+ @property
+ def mac_lower(self):
+ return self.local_mac.lower()
+
+ @property
+ def missing_fields(self):
+ return self.TOPOLOGY_REQUIRED_KEYS.difference(self.interface)
+
+ @staticmethod
+ def _detect_socket(netdev):
+ try:
+ socket = netdev['numa_node']
+ except KeyError:
+ # Where is this documented?
+ # It seems for dual-sockets systems the second socket PCI bridge
+ # will have an address > 0x0f, e.g.
+ # Bridge PCI->PCI (P#524320 busid=0000:80:02.0 id=8086:6f04
+ if netdev['pci_bus_id'][5] == "0":
+ socket = 0
+ else:
+ # this doesn't handle quad-sockets
+ # TODO: fix this for quad-socket
+ socket = 1
+ return socket
+
+ def probe_missing_values(self):
+ try:
+ for netdev in self.dpdk_node.netdevs.values():
+ if netdev['address'].lower() == self.mac_lower:
+ socket = self._detect_socket(netdev)
+ self.interface.update({
+ 'vpci': netdev['pci_bus_id'],
+ 'driver': netdev['driver'],
+ 'socket': socket,
+ # don't need ifindex
+ })
+
+ except KeyError:
+ # if we don't find all the keys then don't update
+ pass
+
+ except (IncorrectNodeSetup, SSHError, SSHTimeout):
+ raise IncorrectConfig(
+ "Unable to probe missing interface fields '%s', on node %s "
+ "SSH Error" % (', '.join(self.missing_fields), self.dpdk_node.node_key))
+
+
+class DpdkNode(object):
+
+ def __init__(self, node_name, interfaces, ssh_helper, timeout=120):
+ super(DpdkNode, self).__init__()
+ self.interfaces = interfaces
+ self.ssh_helper = ssh_helper
+ self.node_key = node_name
+ self.timeout = timeout
+ self._dpdk_helper = None
+ self.netdevs = {}
+
+ try:
+ self.dpdk_interfaces = {intf['name']: DpdkInterface(self, intf['virtual-interface'])
+ for intf in self.interfaces}
+ except IncorrectConfig:
+ template = "MAC address is required for all interfaces, missing on: {}"
+ errors = (intf['name'] for intf in self.interfaces if
+ 'local_mac' not in intf['virtual-interface'])
+ raise IncorrectSetup(template.format(", ".join(errors)))
+
+ @property
+ def dpdk_helper(self):
+ if not isinstance(self._dpdk_helper, DpdkBindHelper):
+ self._dpdk_helper = DpdkBindHelper(self.ssh_helper)
+ return self._dpdk_helper
+
+ @property
+ def _interface_missing_iter(self):
+ return chain.from_iterable(self._interface_missing_map.values())
+
+ @property
+ def _interface_missing_map(self):
+ return {name: intf.missing_fields for name, intf in self.dpdk_interfaces.items()}
+
+ def _probe_netdevs(self):
+ self.netdevs.update(self.dpdk_helper.find_net_devices())
+
+ def _force_rebind(self):
+ return self.dpdk_helper.force_dpdk_rebind()
+
+ def _probe_dpdk_drivers(self):
+ self.dpdk_helper.probe_real_kernel_drivers()
+ for pci, driver in self.dpdk_helper.real_kernel_interface_driver_map.items():
+ for intf in self.interfaces:
+ vintf = intf['virtual-interface']
+ # stupid substring matches
+ # don't use netdev use interface
+ if vintf['vpci'].endswith(pci):
+ vintf['driver'] = driver
+ # we can't update netdevs because we may not have netdev info
+
+ def _probe_missing_values(self):
+ for intf in self.dpdk_interfaces.values():
+ intf.probe_missing_values()
+
+ def check(self):
+ # only ssh probe if there are missing values
+ # ssh probe won't work on Ixia, so we had better define all our values
+ try:
+ missing_fields_set = set(self._interface_missing_iter)
+
+ # if we are only missing driver then maybe we can get kernel module
+ # this requires vpci
+ if missing_fields_set == {'driver'}:
+ self._probe_dpdk_drivers()
+ # we can't reprobe missing values because we may not have netdev info
+
+ # if there are any other missing then we have to netdev probe
+ if missing_fields_set.difference({'driver'}):
+ self._probe_netdevs()
+ try:
+ self._probe_missing_values()
+ except IncorrectConfig:
+ # ignore for now
+ pass
+
+ # check again and verify we have all the fields
+ if set(self._interface_missing_iter):
+ # last chance fallback, rebind everything and probe
+ # this probably won't work
+ self._force_rebind()
+ self._probe_netdevs()
+ self._probe_missing_values()
+
+ errors = ("{} missing: {}".format(name, ", ".join(missing_fields)) for
+ name, missing_fields in self._interface_missing_map.items() if
+ missing_fields)
+ errors = "\n".join(errors)
+ if errors:
+ raise IncorrectSetup(errors)
+
+ finally:
+ self._dpdk_helper = None
+
+
class DpdkBindHelper(object):
DPDK_STATUS_CMD = "{dpdk_devbind} --status"
DPDK_BIND_CMD = "sudo {dpdk_devbind} {force} -b {driver} {vpci}"
@@ -42,6 +208,8 @@ class DpdkBindHelper(object):
SKIP_RE = re.compile('(====|<none>|^$)')
NIC_ROW_FIELDS = ['vpci', 'dev_type', 'iface', 'driver', 'unused', 'active']
+ UIO_DRIVER = "uio"
+
HEADER_DICT_PAIRS = [
(re.compile('^Network.*DPDK.*$'), NETWORK_DPDK),
(re.compile('^Network.*kernel.*$'), NETWORK_KERNEL),
@@ -51,6 +219,42 @@ class DpdkBindHelper(object):
(re.compile('^Other crypto.*$'), CRYPTO_OTHER),
]
+ FIND_NETDEVICE_STRING = r"""\
+find /sys/devices/pci* -type d -name net -exec sh -c '{ grep -sH ^ \
+$1/ifindex $1/address $1/operstate $1/device/vendor $1/device/device \
+$1/device/subsystem_vendor $1/device/subsystem_device $1/device/numa_node ; \
+printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
+' sh \{\}/* \;
+"""
+
+ BASE_ADAPTER_RE = re.compile('^/sys/devices/(.*)/net/([^/]*)/([^:]*):(.*)$', re.M)
+ DPDK_DEVBIND = "dpdk-devbind.py"
+
+ @classmethod
+ def parse_netdev_info(cls, stdout):
+ network_devices = defaultdict(dict)
+ match_iter = (match.groups() for match in cls.BASE_ADAPTER_RE.finditer(stdout))
+ for bus_path, interface_name, name, value in match_iter:
+ dir_name, bus_id = os.path.split(bus_path)
+ if 'virtio' in bus_id:
+ # for some stupid reason VMs include virtio1/
+ # in PCI device path
+ bus_id = os.path.basename(dir_name)
+
+ # remove extra 'device/' from 'device/vendor,
+ # device/subsystem_vendor', etc.
+ if 'device' in name:
+ name = name.split('/')[1]
+
+ network_devices[interface_name].update({
+ name: value,
+ 'interface_name': interface_name,
+ 'pci_bus_id': bus_id,
+ })
+
+ # convert back to regular dict
+ return dict(network_devices)
+
def clean_status(self):
self.dpdk_status = {
NETWORK_KERNEL: [],
@@ -61,11 +265,17 @@ class DpdkBindHelper(object):
CRYPTO_OTHER: [],
}
- def __init__(self, ssh_helper):
+ # TODO: add support for driver other than igb_uio
+ def __init__(self, ssh_helper, dpdk_driver="igb_uio"):
+ self.ssh_helper = ssh_helper
+ self.real_kernel_interface_driver_map = {}
+ self.dpdk_driver = dpdk_driver
self.dpdk_status = None
self.status_nic_row_re = None
- self._dpdk_devbind = None
+ self.dpdk_devbind = self.ssh_helper.join_bin_path(self.DPDK_DEVBIND)
self._status_cmd_attr = None
+ self.used_drivers = None
+ self.real_kernel_drivers = {}
self.ssh_helper = ssh_helper
self.clean_status()
@@ -73,15 +283,16 @@ class DpdkBindHelper(object):
def _dpdk_execute(self, *args, **kwargs):
res = self.ssh_helper.execute(*args, **kwargs)
if res[0] != 0:
- raise DpdkBindHelperException('{} command failed with rc={}'.format(
- self.dpdk_devbind, res[0]))
+ template = '{} command failed with rc={}'
+ raise DpdkBindHelperException(template.format(self.dpdk_devbind, res[0]))
return res
- @property
- def dpdk_devbind(self):
- if self._dpdk_devbind is None:
- self._dpdk_devbind = self.ssh_helper.provision_tool(tool_file="dpdk-devbind.py")
- return self._dpdk_devbind
+ def load_dpdk_driver(self):
+ cmd_template = "sudo modprobe {} && sudo modprobe {}"
+ self.ssh_helper.execute(cmd_template.format(self.UIO_DRIVER, self.dpdk_driver))
+
+ def check_dpdk_driver(self):
+ return self.ssh_helper.execute("lsmod | grep -i {}".format(self.dpdk_driver))[0]
@property
def _status_cmd(self):
@@ -89,12 +300,14 @@ class DpdkBindHelper(object):
self._status_cmd_attr = self.DPDK_STATUS_CMD.format(dpdk_devbind=self.dpdk_devbind)
return self._status_cmd_attr
- def _addline(self, active_list, line):
+ def _add_line(self, active_list, line):
if active_list is None:
return
+
res = self.NIC_ROW_RE.match(line)
if res is None:
return
+
new_data = {k: v for k, v in zip(self.NIC_ROW_FIELDS, res.groups())}
new_data['active'] = bool(new_data['active'])
self.dpdk_status[active_list].append(new_data)
@@ -106,14 +319,14 @@ class DpdkBindHelper(object):
return a_dict
return active_dict
- def parse_dpdk_status_output(self, input):
+ def _parse_dpdk_status_output(self, output):
active_dict = None
self.clean_status()
- for a_row in input.splitlines():
+ for a_row in output.splitlines():
if self.SKIP_RE.match(a_row):
continue
active_dict = self._switch_active_dict(a_row, active_dict)
- self._addline(active_dict, a_row)
+ self._add_line(active_dict, a_row)
return self.dpdk_status
def _get_bound_pci_addresses(self, active_dict):
@@ -130,31 +343,85 @@ class DpdkBindHelper(object):
@property
def interface_driver_map(self):
return {interface['vpci']: interface['driver']
- for interface in itertools.chain.from_iterable(self.dpdk_status.values())}
+ for interface in chain.from_iterable(self.dpdk_status.values())}
def read_status(self):
- return self.parse_dpdk_status_output(self._dpdk_execute(self._status_cmd)[1])
+ return self._parse_dpdk_status_output(self._dpdk_execute(self._status_cmd)[1])
+
+ def find_net_devices(self):
+ exit_status, stdout, _ = self.ssh_helper.execute(self.FIND_NETDEVICE_STRING)
+ if exit_status != 0:
+ return {}
+
+ return self.parse_netdev_info(stdout)
def bind(self, pci_addresses, driver, force=True):
- # accept single PCI or list of PCI
- if isinstance(pci_addresses, six.string_types):
- pci_addresses = [pci_addresses]
+ # accept single PCI or sequence of PCI
+ pci_addresses = validate_non_string_sequence(pci_addresses, [pci_addresses])
+
cmd = self.DPDK_BIND_CMD.format(dpdk_devbind=self.dpdk_devbind,
driver=driver,
vpci=' '.join(list(pci_addresses)),
force='--force' if force else '')
LOG.debug(cmd)
self._dpdk_execute(cmd)
+
# update the inner status dict
self.read_status()
+ def probe_real_kernel_drivers(self):
+ self.read_status()
+ self.save_real_kernel_interface_driver_map()
+
+ def force_dpdk_rebind(self):
+ self.load_dpdk_driver()
+ self.read_status()
+ self.save_real_kernel_interface_driver_map()
+ self.save_used_drivers()
+
+ real_driver_map = {}
+ # only rebind devices that are bound to DPDK
+ for pci in self.dpdk_bound_pci_addresses:
+ # messy
+ real_driver = self.real_kernel_interface_driver_map[pci]
+ real_driver_map.setdefault(real_driver, []).append(pci)
+ for real_driver, pcis in real_driver_map.items():
+ self.bind(pcis, real_driver, force=True)
+
def save_used_drivers(self):
# invert the map, so we can bind by driver type
self.used_drivers = {}
- # sort for stabililty
+ # sort for stability
for vpci, driver in sorted(self.interface_driver_map.items()):
self.used_drivers.setdefault(driver, []).append(vpci)
+ KERNEL_DRIVER_RE = re.compile(r"Kernel modules: (\S+)", re.M)
+ VIRTIO_DRIVER_RE = re.compile(r"Ethernet.*Virtio network device", re.M)
+ VIRTIO_DRIVER = "virtio-pci"
+
+ def save_real_kernel_drivers(self):
+ # invert the map, so we can bind by driver type
+ self.real_kernel_drivers = {}
+ # sort for stability
+ for vpci, driver in sorted(self.real_kernel_interface_driver_map.items()):
+ self.used_drivers.setdefault(driver, []).append(vpci)
+
+ def get_real_kernel_driver(self, pci):
+ out = self.ssh_helper.execute('lspci -k -s %s' % pci)[1]
+ match = self.KERNEL_DRIVER_RE.search(out)
+ if match:
+ return match.group(1)
+
+ match = self.VIRTIO_DRIVER_RE.search(out)
+ if match:
+ return self.VIRTIO_DRIVER
+
+ return None
+
+ def save_real_kernel_interface_driver_map(self):
+ iter1 = ((pci, self.get_real_kernel_driver(pci)) for pci in self.interface_driver_map)
+ self.real_kernel_interface_driver_map = {pci: driver for pci, driver in iter1 if driver}
+
def rebind_drivers(self, force=True):
for driver, vpcis in self.used_drivers.items():
self.bind(vpcis, driver, force)
diff --git a/yardstick/network_services/traffic_profile/__init__.py b/yardstick/network_services/traffic_profile/__init__.py
index e69de29bb..356b36bd9 100644
--- a/yardstick/network_services/traffic_profile/__init__.py
+++ b/yardstick/network_services/traffic_profile/__init__.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2018 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 importlib
+
+
+def register_modules():
+ modules = [
+ 'yardstick.network_services.traffic_profile.trex_traffic_profile',
+ 'yardstick.network_services.traffic_profile.fixed',
+ 'yardstick.network_services.traffic_profile.http',
+ 'yardstick.network_services.traffic_profile.http_ixload',
+ 'yardstick.network_services.traffic_profile.ixia_rfc2544',
+ 'yardstick.network_services.traffic_profile.prox_ACL',
+ 'yardstick.network_services.traffic_profile.prox_binsearch',
+ 'yardstick.network_services.traffic_profile.prox_profile',
+ 'yardstick.network_services.traffic_profile.prox_ramp',
+ 'yardstick.network_services.traffic_profile.rfc2544',
+ ]
+
+ for module in modules:
+ importlib.import_module(module)
diff --git a/yardstick/network_services/traffic_profile/base.py b/yardstick/network_services/traffic_profile/base.py
index ad256b444..162bab2bc 100644
--- a/yardstick/network_services/traffic_profile/base.py
+++ b/yardstick/network_services/traffic_profile/base.py
@@ -11,10 +11,9 @@
# 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 for the generic traffic profile implementation """
-from __future__ import absolute_import
-from yardstick.common.utils import import_modules_from_package, itersubclasses
+from yardstick.common import exceptions
+from yardstick.common import utils
class TrafficProfile(object):
@@ -33,13 +32,12 @@ class TrafficProfile(object):
:return:
"""
profile_class = tp_config["traffic_profile"]["traffic_type"]
- import_modules_from_package(
- "yardstick.network_services.traffic_profile")
try:
- return next(c for c in itersubclasses(TrafficProfile)
+ return next(c for c in utils.itersubclasses(TrafficProfile)
if c.__name__ == profile_class)(tp_config)
except StopIteration:
- raise RuntimeError("No implementation for %s", profile_class)
+ raise exceptions.TrafficProfileNotImplemented(
+ profile_class=profile_class)
def __init__(self, tp_config):
# e.g. RFC2544 start_ip, stop_ip, drop_rate,
diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
index 3ab157dc7..7f047226b 100644
--- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py
+++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
@@ -15,7 +15,7 @@
from __future__ import absolute_import
import logging
-from yardstick.network_services.traffic_profile.traffic_profile import \
+from yardstick.network_services.traffic_profile.trex_traffic_profile import \
TrexProfile
LOG = logging.getLogger(__name__)
diff --git a/yardstick/network_services/traffic_profile/prox_binsearch.py b/yardstick/network_services/traffic_profile/prox_binsearch.py
index 1fd6ec41a..5700f98e5 100644
--- a/yardstick/network_services/traffic_profile/prox_binsearch.py
+++ b/yardstick/network_services/traffic_profile/prox_binsearch.py
@@ -16,6 +16,8 @@
from __future__ import absolute_import
import logging
+import datetime
+import time
from yardstick.network_services.traffic_profile.prox_profile import ProxProfile
@@ -81,19 +83,66 @@ class ProxBinSearchProfile(ProxProfile):
# success, the binary search will complete on an integer multiple
# of the precision, rather than on a fraction of it.
+ theor_max_thruput = 0
+
+ result_samples = {}
+
+ # Store one time only value in influxdb
+ single_samples = {
+ "test_duration" : traffic_gen.scenario_helper.scenario_cfg["runner"]["duration"],
+ "test_precision" : self.params["traffic_profile"]["test_precision"],
+ "tolerated_loss" : self.params["traffic_profile"]["tolerated_loss"],
+ "duration" : duration
+ }
+ self.queue.put(single_samples)
+ self.prev_time = time.time()
+
# throughput and packet loss from the most recent successful test
successful_pkt_loss = 0.0
for test_value in self.bounds_iterator(LOG):
result, port_samples = self._profile_helper.run_test(pkt_size, duration,
test_value, self.tolerated_loss)
+ self.curr_time = time.time()
+ diff_time = self.curr_time - self.prev_time
+ self.prev_time = self.curr_time
if result.success:
LOG.debug("Success! Increasing lower bound")
self.current_lower = test_value
successful_pkt_loss = result.pkt_loss
+ samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
+ samples["TxThroughput"] = samples["TxThroughput"] * 1000 * 1000
+
+ # store results with success tag in influxdb
+ success_samples = {'Success_' + key: value for key, value in samples.items()}
+
+ success_samples["Success_rx_total"] = int(result.rx_total / diff_time)
+ success_samples["Success_tx_total"] = int(result.tx_total / diff_time)
+ success_samples["Success_can_be_lost"] = int(result.can_be_lost / diff_time)
+ success_samples["Success_drop_total"] = int(result.drop_total / diff_time)
+ self.queue.put(success_samples)
+
+ # Store Actual throughput for result samples
+ result_samples["Result_Actual_throughput"] = \
+ success_samples["Success_RxThroughput"]
else:
LOG.debug("Failure... Decreasing upper bound")
self.current_upper = test_value
+ samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
+
+ for k in samples:
+ tmp = samples[k]
+ if isinstance(tmp, dict):
+ for k2 in tmp:
+ samples[k][k2] = int(samples[k][k2] / diff_time)
- samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
+ if theor_max_thruput < samples["TxThroughput"]:
+ theor_max_thruput = samples['TxThroughput']
+ self.queue.put({'theor_max_throughput': theor_max_thruput})
+
+ LOG.debug("Collect TG KPIs %s %s", datetime.datetime.now(), samples)
self.queue.put(samples)
+
+ result_samples["Result_pktSize"] = pkt_size
+ result_samples["Result_theor_max_throughput"] = theor_max_thruput/ (1000 * 1000)
+ self.queue.put(result_samples)
diff --git a/yardstick/network_services/traffic_profile/prox_profile.py b/yardstick/network_services/traffic_profile/prox_profile.py
index 170dfd96f..343ef1da2 100644
--- a/yardstick/network_services/traffic_profile/prox_profile.py
+++ b/yardstick/network_services/traffic_profile/prox_profile.py
@@ -29,8 +29,22 @@ class ProxProfile(TrafficProfile):
"""
@staticmethod
+ def sort_vpci(traffic_gen):
+ """Return the list of external interfaces ordered by vpci and name
+
+ :param traffic_gen: (ProxTrafficGen) traffic generator
+ :return: list of ordered interfaces
+ """
+ def key_func(interface):
+ return interface['virtual-interface']['vpci'], interface['name']
+
+ return sorted(traffic_gen.vnfd_helper['vdu'][0]['external-interface'],
+ key=key_func)
+
+ @staticmethod
def fill_samples(samples, traffic_gen):
- for vpci_idx, intf in enumerate(traffic_gen.vpci_if_name_ascending):
+ vpci_if_name_ascending = ProxProfile.sort_vpci(traffic_gen)
+ for vpci_idx, intf in enumerate(vpci_if_name_ascending):
name = intf[1]
# TODO: VNFDs KPIs values needs to be mapped to TRex structure
xe_port = traffic_gen.resource_helper.sut.port_stats([vpci_idx])
diff --git a/yardstick/network_services/traffic_profile/rfc2544.py b/yardstick/network_services/traffic_profile/rfc2544.py
index b1ca8a345..83020c85c 100644
--- a/yardstick/network_services/traffic_profile/rfc2544.py
+++ b/yardstick/network_services/traffic_profile/rfc2544.py
@@ -21,7 +21,7 @@ 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 yardstick.network_services.traffic_profile.traffic_profile \
+from yardstick.network_services.traffic_profile.trex_traffic_profile \
import TrexProfile
LOGGING = logging.getLogger(__name__)
diff --git a/yardstick/network_services/traffic_profile/traffic_profile.py b/yardstick/network_services/traffic_profile/trex_traffic_profile.py
index 8cde5e4a7..f5e3923d5 100644
--- a/yardstick/network_services/traffic_profile/traffic_profile.py
+++ b/yardstick/network_services/traffic_profile/trex_traffic_profile.py
@@ -21,7 +21,7 @@ import ipaddress
import six
from yardstick.common import exceptions as y_exc
-from yardstick.network_services.traffic_profile.base import TrafficProfile
+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
@@ -48,7 +48,7 @@ TYPE_OF_SERVICE = 'tos'
LOG = logging.getLogger(__name__)
-class TrexProfile(TrafficProfile):
+class TrexProfile(base.TrafficProfile):
""" This class handles Trex Traffic profile generation and execution """
PROTO_MAP = {
@@ -127,7 +127,7 @@ class TrexProfile(TrafficProfile):
self.vm_flow_vars.append(stl_vm_wr_flow_var)
return partial
- def _dscp_range_action_partial(self, *_):
+ def _dscp_range_action_partial(self, *args):
def partial(min_value, max_value, count):
# pylint: disable=unused-argument
stl_vm_flow_var = STLVmFlowVar(name="dscp",
diff --git a/yardstick/network_services/utils.py b/yardstick/network_services/utils.py
index 7a1815eb9..4b987fafe 100644
--- a/yardstick/network_services/utils.py
+++ b/yardstick/network_services/utils.py
@@ -121,7 +121,6 @@ def provision_tool(connection, tool_path, tool_file=None):
tool_path = get_nsb_option('tool_path')
if tool_file:
tool_path = os.path.join(tool_path, tool_file)
- bin_path = get_nsb_option("bin_path")
exit_status = connection.execute("which %s > /dev/null 2>&1" % tool_path)[0]
if exit_status == 0:
return encodeutils.safe_decode(tool_path, incoming='utf-8').rstrip()
diff --git a/yardstick/network_services/vnf_generic/vnf/acl_vnf.py b/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
index 1390dd02e..f3cafef7a 100644
--- a/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
@@ -12,11 +12,9 @@
# 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
-from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file
+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
@@ -62,8 +60,9 @@ class AclApproxVnf(SampleVNF):
self.acl_rules = None
def _start_vnf(self):
- yang_model_path = find_relative_file(self.scenario_helper.options['rules'],
- self.scenario_helper.task_path)
+ 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/prox_helpers.py b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
index 285ead3b6..29f9c7bba 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
@@ -30,7 +30,6 @@ import six
from six.moves import cStringIO
from six.moves import zip, StringIO
-from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file
from yardstick.common import utils
from yardstick.common.utils import SocketTopology, join_non_strings, try_int
from yardstick.network_services.helpers.iniparser import ConfigParser
@@ -798,7 +797,7 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
options = self.scenario_helper.options
config_path = options['prox_config']
config_file = os.path.basename(config_path)
- config_path = find_relative_file(config_path, task_path)
+ config_path = utils.find_relative_file(config_path, task_path)
self.additional_files = {}
try:
@@ -815,7 +814,7 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
prox_files = [prox_files]
for key_prox_file in prox_files:
base_prox_file = os.path.basename(key_prox_file)
- key_prox_path = find_relative_file(key_prox_file, task_path)
+ key_prox_path = utils.find_relative_file(key_prox_file, task_path)
remote_prox_file = self.copy_to_target(key_prox_path, base_prox_file)
self.additional_files[base_prox_file] = remote_prox_file
@@ -929,6 +928,7 @@ class ProxResourceHelper(ClientResourceHelper):
func = getattr(self.sut, cmd, None)
if func:
return func(*args, **kwargs)
+ return None
def _connect(self, client=None):
"""Run and connect to prox on the remote system """
@@ -1005,11 +1005,18 @@ class ProxDataHelper(object):
def samples(self):
samples = {}
for port_name, port_num in self.vnfd_helper.ports_iter():
- port_rx_total, port_tx_total = self.sut.port_stats([port_num])[6:8]
- samples[port_name] = {
- "in_packets": port_rx_total,
- "out_packets": port_tx_total,
- }
+ try:
+ port_rx_total, port_tx_total = self.sut.port_stats([port_num])[6:8]
+ samples[port_name] = {
+ "in_packets": port_rx_total,
+ "out_packets": port_tx_total,
+ }
+ except (KeyError, TypeError, NameError, MemoryError, ValueError,
+ SystemError, BufferError):
+ samples[port_name] = {
+ "in_packets": 0,
+ "out_packets": 0,
+ }
return samples
def __enter__(self):
@@ -1127,7 +1134,7 @@ class ProxProfileHelper(object):
for key, value in section:
if key == "mode" and value == mode:
core_tuple = CoreSocketTuple(section_name)
- core = core_tuple.find_in_topology(self.cpu_topology)
+ core = core_tuple.core_id
cores.append(core)
return cores
@@ -1149,6 +1156,10 @@ class ProxProfileHelper(object):
:return: return lat_min, lat_max, lat_avg
:rtype: list
"""
+
+ if not self._latency_cores:
+ self._latency_cores = self.get_cores(self.PROX_CORE_LAT_MODE)
+
if self._latency_cores:
return self.sut.lat_stats(self._latency_cores)
return []
@@ -1198,12 +1209,12 @@ class ProxMplsProfileHelper(ProxProfileHelper):
if item_value.startswith("tag"):
core_tuple = CoreSocketTuple(section_name)
- core_tag = core_tuple.find_in_topology(self.cpu_topology)
+ core_tag = core_tuple.core_id
cores_tagged.append(core_tag)
elif item_value.startswith("udp"):
core_tuple = CoreSocketTuple(section_name)
- core_udp = core_tuple.find_in_topology(self.cpu_topology)
+ core_udp = core_tuple.core_id
cores_plain.append(core_udp)
return cores_tagged, cores_plain
@@ -1276,23 +1287,23 @@ class ProxBngProfileHelper(ProxProfileHelper):
if item_value.startswith("cpe"):
core_tuple = CoreSocketTuple(section_name)
- cpe_core = core_tuple.find_in_topology(self.cpu_topology)
+ cpe_core = core_tuple.core_id
cpe_cores.append(cpe_core)
elif item_value.startswith("inet"):
core_tuple = CoreSocketTuple(section_name)
- inet_core = core_tuple.find_in_topology(self.cpu_topology)
+ inet_core = core_tuple.core_id
inet_cores.append(inet_core)
elif item_value.startswith("arp"):
core_tuple = CoreSocketTuple(section_name)
- arp_core = core_tuple.find_in_topology(self.cpu_topology)
+ arp_core = core_tuple.core_id
arp_cores.append(arp_core)
# We check the tasks/core separately
if item_value.startswith("arp_task"):
core_tuple = CoreSocketTuple(section_name)
- arp_task_core = core_tuple.find_in_topology(self.cpu_topology)
+ arp_task_core = core_tuple.core_id
arp_tasks_core.append(arp_task_core)
return cpe_cores, inet_cores, arp_cores, arp_tasks_core
@@ -1455,12 +1466,12 @@ class ProxVpeProfileHelper(ProxProfileHelper):
if item_value.startswith("cpe"):
core_tuple = CoreSocketTuple(section_name)
- core_tag = core_tuple.find_in_topology(self.cpu_topology)
+ core_tag = core_tuple.core_id
cpe_cores.append(core_tag)
elif item_value.startswith("inet"):
core_tuple = CoreSocketTuple(section_name)
- inet_core = core_tuple.find_in_topology(self.cpu_topology)
+ inet_core = core_tuple.core_id
inet_cores.append(inet_core)
return cpe_cores, inet_cores
@@ -1639,7 +1650,7 @@ class ProxlwAFTRProfileHelper(ProxProfileHelper):
continue
core_tuple = CoreSocketTuple(section_name)
- core_tag = core_tuple.find_in_topology(self.cpu_topology)
+ core_tag = core_tuple.core_id
for item_value in (v for k, v in section if k == 'name'):
if item_value.startswith('tun'):
tun_cores.append(core_tag)
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_vnf.py b/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
index b7d295eee..2cdb3f904 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
@@ -14,12 +14,15 @@
import errno
import logging
+import datetime
+import time
from yardstick.common.process import check_if_process_failed
from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxDpdkVnfSetupEnvHelper
from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxResourceHelper
-from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, PROCESS_JOIN_TIMEOUT
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
+from yardstick.network_services.constants import PROCESS_JOIN_TIMEOUT
LOG = logging.getLogger(__name__)
@@ -39,6 +42,9 @@ class ProxApproxVnf(SampleVNF):
if resource_helper_type is None:
resource_helper_type = ProxResourceHelper
+ self.prev_packets_in = 0
+ self.prev_packets_sent = 0
+ self.prev_time = time.time()
super(ProxApproxVnf, self).__init__(name, vnfd, setup_env_helper_type,
resource_helper_type)
@@ -79,12 +85,13 @@ class ProxApproxVnf(SampleVNF):
raise RuntimeError("Failed ..Invalid no of ports .. "
"1, 2 or 4 ports only supported at this time")
- port_stats = self.vnf_execute('port_stats', range(port_count))
+ self.port_stats = self.vnf_execute('port_stats', range(port_count))
+ curr_time = time.time()
try:
- rx_total = port_stats[6]
- tx_total = port_stats[7]
+ rx_total = self.port_stats[6]
+ tx_total = self.port_stats[7]
except IndexError:
- LOG.error("port_stats parse fail %s", port_stats)
+ LOG.debug("port_stats parse fail ")
# return empty dict so we don't mess up existing KPIs
return {}
@@ -96,7 +103,17 @@ class ProxApproxVnf(SampleVNF):
# collectd KPIs here and not TG KPIs, so use a different method name
"collect_stats": self.resource_helper.collect_collectd_kpi(),
}
- LOG.debug("%s collect KPIs %s", self.APP_NAME, result)
+ curr_packets_in = int((rx_total - self.prev_packets_in) / (curr_time - self.prev_time))
+ curr_packets_fwd = int((tx_total - self.prev_packets_sent) / (curr_time - self.prev_time))
+
+ result["curr_packets_in"] = curr_packets_in
+ result["curr_packets_fwd"] = curr_packets_fwd
+
+ self.prev_packets_in = rx_total
+ self.prev_packets_sent = tx_total
+ self.prev_time = curr_time
+
+ LOG.debug("%s collect KPIs %s %s", self.APP_NAME, datetime.datetime.now(), result)
return result
def _tear_down(self):
diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
index 8d02446c2..ad78774f0 100644
--- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2018 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,78 +16,39 @@
from collections import Mapping
import logging
from multiprocessing import Queue, Value, Process
+
import os
import posixpath
import re
-from six.moves import cStringIO
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
from yardstick.benchmark.contexts.base import Context
-from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file
from yardstick.common import exceptions as y_exceptions
from yardstick.common.process import check_if_process_failed
-from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper
-from yardstick.network_services.helpers.samplevnf_helper import PortPairs
+from yardstick.common import utils
+from yardstick.network_services.constants import DEFAULT_VNF_TIMEOUT
+from yardstick.network_services.constants import PROCESS_JOIN_TIMEOUT
+from yardstick.network_services.constants import REMOTE_TMP
+from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper, DpdkNode
from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
from yardstick.network_services.nfvi.resource import ResourceProfile
from yardstick.network_services.utils import get_nsb_option
-from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen
+from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
-from yardstick.ssh import AutoConnectSSH
+from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
-DPDK_VERSION = "dpdk-16.07"
-
LOG = logging.getLogger(__name__)
-REMOTE_TMP = "/tmp"
-DEFAULT_VNF_TIMEOUT = 3600
-PROCESS_JOIN_TIMEOUT = 3
-
-
-class VnfSshHelper(AutoConnectSSH):
-
- def __init__(self, node, bin_path, wait=None):
- self.node = node
- kwargs = self.args_from_node(self.node)
- if wait:
- kwargs.setdefault('wait', wait)
-
- super(VnfSshHelper, self).__init__(**kwargs)
- self.bin_path = bin_path
-
- @staticmethod
- def get_class():
- # must return static class name, anything else refers to the calling class
- # i.e. the subclass, not the superclass
- return VnfSshHelper
-
- def copy(self):
- # this copy constructor is different from SSH classes, since it uses node
- return self.get_class()(self.node, self.bin_path)
-
- def upload_config_file(self, prefix, content):
- cfg_file = os.path.join(REMOTE_TMP, prefix)
- LOG.debug(content)
- file_obj = cStringIO(content)
- self.put_file_obj(file_obj, cfg_file)
- return cfg_file
-
- def join_bin_path(self, *args):
- return os.path.join(self.bin_path, *args)
-
- def provision_tool(self, tool_path=None, tool_file=None):
- if tool_path is None:
- tool_path = self.bin_path
- return super(VnfSshHelper, self).provision_tool(tool_path, tool_file)
-
-
class SetupEnvHelper(object):
CFG_CONFIG = os.path.join(REMOTE_TMP, "sample_config")
@@ -119,6 +80,8 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
APP_NAME = 'DpdkVnf'
FIND_NET_CMD = "find /sys/class/net -lname '*{}*' -printf '%f'"
+ NR_HUGEPAGES_PATH = '/proc/sys/vm/nr_hugepages'
+ HUGEPAGES_KB = 1024 * 1024 * 16
@staticmethod
def _update_packet_type(ip_pipeline_cfg, traffic_options):
@@ -155,24 +118,22 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
self.dpdk_bind_helper = DpdkBindHelper(ssh_helper)
def _setup_hugepages(self):
- cmd = "awk '/Hugepagesize/ { print $2$3 }' < /proc/meminfo"
- hugepages = self.ssh_helper.execute(cmd)[1].rstrip()
-
- memory_path = \
- '/sys/kernel/mm/hugepages/hugepages-%s/nr_hugepages' % hugepages
- self.ssh_helper.execute("awk -F: '{ print $1 }' < %s" % memory_path)
-
- if hugepages == "2048kB":
- pages = 8192
- else:
- pages = 16
-
- self.ssh_helper.execute("echo %s | sudo tee %s" % (pages, memory_path))
+ meminfo = utils.read_meminfo(self.ssh_helper)
+ hp_size_kb = int(meminfo['Hugepagesize'])
+ nr_hugepages = int(abs(self.HUGEPAGES_KB / hp_size_kb))
+ self.ssh_helper.execute('echo %s | sudo tee %s' %
+ (nr_hugepages, self.NR_HUGEPAGES_PATH))
+ hp = six.BytesIO()
+ self.ssh_helper.get_file_obj(self.NR_HUGEPAGES_PATH, hp)
+ nr_hugepages_set = int(hp.getvalue().decode('utf-8').splitlines()[0])
+ LOG.info('Hugepages size (kB): %s, number claimed: %s, number set: %s',
+ hp_size_kb, nr_hugepages, nr_hugepages_set)
def build_config(self):
vnf_cfg = self.scenario_helper.vnf_cfg
task_path = self.scenario_helper.task_path
+ config_file = vnf_cfg.get('file')
lb_count = vnf_cfg.get('lb_count', 3)
lb_config = vnf_cfg.get('lb_config', 'SW')
worker_config = vnf_cfg.get('worker_config', '1C/1T')
@@ -185,7 +146,8 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
'vnf_type': self.VNF_TYPE,
}
- config_tpl_cfg = find_relative_file(self.DEFAULT_CONFIG_TPL_CFG, task_path)
+ config_tpl_cfg = utils.find_relative_file(self.DEFAULT_CONFIG_TPL_CFG,
+ task_path)
config_basename = posixpath.basename(self.CFG_CONFIG)
script_basename = posixpath.basename(self.CFG_SCRIPT)
multiport = MultiPortConfig(self.scenario_helper.topology,
@@ -200,12 +162,20 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
self.socket)
multiport.generate_config()
- with open(self.CFG_CONFIG) as handle:
- new_config = handle.read()
-
- new_config = self._update_traffic_type(new_config, traffic_options)
- new_config = self._update_packet_type(new_config, traffic_options)
-
+ if config_file:
+ with utils.open_relative_file(config_file, task_path) as infile:
+ new_config = ['[EAL]']
+ vpci = []
+ for port in self.vnfd_helper.port_pairs.all_ports:
+ interface = self.vnfd_helper.find_interface(name=port)
+ vpci.append(interface['virtual-interface']["vpci"])
+ new_config.extend('w = {0}'.format(item) for item in vpci)
+ new_config = '\n'.join(new_config) + '\n' + infile.read()
+ else:
+ with open(self.CFG_CONFIG) as handle:
+ new_config = handle.read()
+ new_config = self._update_traffic_type(new_config, traffic_options)
+ 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))
@@ -234,7 +204,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
def setup_vnf_environment(self):
self._setup_dpdk()
- 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()
@@ -252,10 +221,11 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
def _setup_dpdk(self):
"""Setup DPDK environment needed for VNF to run"""
self._setup_hugepages()
- self.ssh_helper.execute('sudo modprobe uio && sudo modprobe igb_uio')
- exit_status = self.ssh_helper.execute('lsmod | grep -i igb_uio')[0]
- if exit_status:
- raise y_exceptions.DPDKSetupDriverError()
+ self.dpdk_bind_helper.load_dpdk_driver()
+
+ exit_status = self.dpdk_bind_helper.check_dpdk_driver()
+ if exit_status == 0:
+ return
def get_collectd_options(self):
options = self.scenario_helper.all_options.get("collectd", {})
@@ -282,9 +252,22 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
plugins=plugins, interval=collectd_options.get("interval"),
timeout=self.scenario_helper.timeout)
+ def _check_interface_fields(self):
+ num_nodes = len(self.scenario_helper.nodes)
+ # OpenStack instance creation time is probably proportional to the number
+ # of instances
+ timeout = 120 * num_nodes
+ dpdk_node = DpdkNode(self.scenario_helper.name, self.vnfd_helper.interfaces,
+ self.ssh_helper, timeout)
+ dpdk_node.check()
+
def _detect_and_bind_drivers(self):
interfaces = self.vnfd_helper.interfaces
+ self._check_interface_fields()
+ # check for bound after probe
+ self.bound_pci = [v['virtual-interface']["vpci"] for v in interfaces]
+
self.dpdk_bind_helper.read_status()
self.dpdk_bind_helper.save_used_drivers()
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_ixload.py b/yardstick/network_services/vnf_generic/vnf/tg_ixload.py
index 3ab30b53e..02e7803f7 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_ixload.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_ixload.py
@@ -22,10 +22,10 @@ import shutil
from collections import OrderedDict
from subprocess import call
-from yardstick.common.utils import makedirs
+from yardstick.common import utils
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
-from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file
+
LOG = logging.getLogger(__name__)
@@ -93,9 +93,10 @@ class IxLoadResourceHelper(ClientResourceHelper):
def setup(self):
# NOTE: fixup scenario_helper to hanlde ixia
self.resource_file_name = \
- find_relative_file(self.scenario_helper.scenario_cfg['ixia_profile'],
- self.scenario_helper.scenario_cfg["task_path"])
- makedirs(self.RESULTS_MOUNT)
+ utils.find_relative_file(
+ self.scenario_helper.scenario_cfg['ixia_profile'],
+ self.scenario_helper.scenario_cfg["task_path"])
+ utils.makedirs(self.RESULTS_MOUNT)
cmd = MOUNT_CMD.format(self.vnfd_helper.mgmt_interface, self)
LOG.debug(cmd)
@@ -103,7 +104,7 @@ class IxLoadResourceHelper(ClientResourceHelper):
call(cmd, shell=True)
shutil.rmtree(self.RESULTS_MOUNT, ignore_errors=True)
- makedirs(self.RESULTS_MOUNT)
+ utils.makedirs(self.RESULTS_MOUNT)
shutil.copy(self.resource_file_name, self.RESULTS_MOUNT)
def make_aggregates(self):
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_prox.py b/yardstick/network_services/vnf_generic/vnf/tg_prox.py
index 151252ce8..282dd92c5 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_prox.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_prox.py
@@ -30,20 +30,6 @@ class ProxTrafficGen(SampleVNFTrafficGen):
LUA_PARAMETER_NAME = "gen"
WAIT_TIME = 1
- @staticmethod
- def _sort_vpci(vnfd):
- """
-
- :param vnfd: vnfd.yaml
- :return: trex_cfg.yaml file
- """
-
- def key_func(interface):
- return interface["virtual-interface"]["vpci"], interface["name"]
-
- ext_intf = vnfd["vdu"][0]["external-interface"]
- return sorted(ext_intf, key=key_func)
-
def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
# don't call superclass, use custom wrapper of ProxApproxVnf
self._vnf_wrapper = ProxApproxVnf(name, vnfd, setup_env_helper_type, resource_helper_type)
@@ -59,10 +45,6 @@ class ProxTrafficGen(SampleVNFTrafficGen):
self._tg_process = None
self._traffic_process = None
- # used for generating stats
- self.vpci_if_name_ascending = self._sort_vpci(vnfd)
- self.resource_helper.vpci_if_name_ascending = self._sort_vpci(vnfd)
-
def terminate(self):
self._vnf_wrapper.terminate()
super(ProxTrafficGen, self).terminate()
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 12510db96..265d0b7a9 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
@@ -19,11 +19,11 @@ import os
import logging
import sys
-from yardstick.common.utils import ErrorClass
+from yardstick.common import utils
+from yardstick import error
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
-from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file
LOG = logging.getLogger(__name__)
@@ -36,7 +36,7 @@ sys.path.append(IXNET_LIB)
try:
from IxNet import IxNextgen
except ImportError:
- IxNextgen = ErrorClass
+ IxNextgen = error.ErrorClass
class IxiaRfc2544Helper(Rfc2544ResourceHelper):
@@ -122,8 +122,9 @@ class IxiaResourceHelper(ClientResourceHelper):
# we don't know client_file_name until runtime as instantiate
client_file_name = \
- find_relative_file(self.scenario_helper.scenario_cfg['ixia_profile'],
- self.scenario_helper.scenario_cfg["task_path"])
+ utils.find_relative_file(
+ self.scenario_helper.scenario_cfg['ixia_profile'],
+ self.scenario_helper.scenario_cfg["task_path"])
self.client.ix_load_config(client_file_name)
time.sleep(WAIT_AFTER_CFG_LOAD)
diff --git a/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py b/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
index 6c95648ce..61e99855f 100644
--- a/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
@@ -12,10 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from __future__ import absolute_import
import logging
-from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file
+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
@@ -60,8 +59,9 @@ class FWApproxVnf(SampleVNF):
self.vfw_rules = None
def _start_vnf(self):
- yang_model_path = find_relative_file(self.scenario_helper.options['rules'],
- self.scenario_helper.task_path)
+ 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
new file mode 100644
index 000000000..8e02cf3ac
--- /dev/null
+++ b/yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py
@@ -0,0 +1,61 @@
+# 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 logging
+import os
+
+from six.moves import StringIO
+
+from yardstick.network_services.constants import REMOTE_TMP
+from yardstick.ssh import AutoConnectSSH
+
+LOG = logging.getLogger(__name__)
+
+
+class VnfSshHelper(AutoConnectSSH):
+
+ def __init__(self, node, bin_path, wait=None):
+ self.node = node
+ kwargs = self.args_from_node(self.node)
+ if wait:
+ # if wait is defined here we want to override
+ kwargs['wait'] = wait
+
+ super(VnfSshHelper, self).__init__(**kwargs)
+ self.bin_path = bin_path
+
+ @staticmethod
+ def get_class():
+ # must return static class name, anything else refers to the calling class
+ # i.e. the subclass, not the superclass
+ return VnfSshHelper
+
+ def copy(self):
+ # this copy constructor is different from SSH classes, since it uses node
+ return self.get_class()(self.node, self.bin_path)
+
+ def upload_config_file(self, prefix, content):
+ cfg_file = os.path.join(REMOTE_TMP, prefix)
+ LOG.debug(content)
+ file_obj = StringIO(content)
+ self.put_file_obj(file_obj, cfg_file)
+ return cfg_file
+
+ def join_bin_path(self, *args):
+ return os.path.join(self.bin_path, *args)
+
+ def provision_tool(self, tool_path=None, tool_file=None):
+ if tool_path is None:
+ tool_path = self.bin_path
+ return super(VnfSshHelper, self).provision_tool(tool_path, tool_file)
diff --git a/yardstick/orchestrator/heat.py b/yardstick/orchestrator/heat.py
index 3c3d28146..d69f86044 100644
--- a/yardstick/orchestrator/heat.py
+++ b/yardstick/orchestrator/heat.py
@@ -26,21 +26,16 @@ import shade
import yardstick.common.openstack_utils as op_utils
from yardstick.common import exceptions
from yardstick.common import template_format
+from yardstick.common import constants as consts
log = logging.getLogger(__name__)
-HEAT_KEY_UUID_LENGTH = 8
-
PROVIDER_SRIOV = "sriov"
_DEPLOYED_STACKS = {}
-def get_short_key_uuid(uuid):
- return str(uuid)[:HEAT_KEY_UUID_LENGTH]
-
-
class HeatStack(object):
"""Represents a Heat stack (deployed template) """
@@ -50,6 +45,13 @@ class HeatStack(object):
self._cloud = shade.openstack_cloud()
self._stack = None
+ def _update_stack_tracking(self):
+ outputs = self._stack.outputs
+ self.outputs = {output['output_key']: output['output_value'] for output
+ in outputs}
+ if self.uuid:
+ _DEPLOYED_STACKS[self.uuid] = self._stack
+
def create(self, template, heat_parameters, wait, timeout):
"""Creates an OpenStack stack from a template"""
with tempfile.NamedTemporaryFile('wb', delete=False) as template_file:
@@ -58,11 +60,21 @@ class HeatStack(object):
self._stack = self._cloud.create_stack(
self.name, template_file=template_file.name, wait=wait,
timeout=timeout, **heat_parameters)
- outputs = self._stack.outputs
- self.outputs = {output['output_key']: output['output_value'] for output
- in outputs}
- if self.uuid:
- _DEPLOYED_STACKS[self.uuid] = self._stack
+
+ self._update_stack_tracking()
+
+ def get(self):
+ """Retrieves an existing stack from the target cloud
+
+ Returns a bool indicating whether the stack exists in the target cloud
+ If the stack exists, it will be stored as self._stack
+ """
+ self._stack = self._cloud.get_stack(self.name)
+ if not self._stack:
+ return False
+
+ self._update_stack_tracking()
+ return True
@staticmethod
def stacks_exist():
@@ -322,21 +334,24 @@ name (i.e. %s).
}
}
- def add_port(self, name, network_name, subnet_name, vnic_type, sec_group_id=None,
+ def add_port(self, name, network, sec_group_id=None,
provider=None, allowed_address_pairs=None):
"""add to the template a named Neutron Port
"""
- log.debug("adding Neutron::Port '%s', network:'%s', subnet:'%s', vnic_type:'%s', "
- "secgroup:%s", name, network_name, subnet_name, vnic_type, sec_group_id)
+ net_is_existing = network.net_flags.get(consts.IS_EXISTING)
+ depends_on = [] if net_is_existing else [network.subnet_stack_name]
+ fixed_ips = [{'subnet': network.subnet}] if net_is_existing else [
+ {'subnet': {'get_resource': network.subnet_stack_name}}]
+ network_ = network.name if net_is_existing else {
+ 'get_resource': network.stack_name}
self.resources[name] = {
'type': 'OS::Neutron::Port',
- 'depends_on': [subnet_name],
+ 'depends_on': depends_on,
'properties': {
'name': name,
- 'binding:vnic_type': vnic_type,
- 'fixed_ips': [{'subnet': {'get_resource': subnet_name}}],
- 'network_id': {'get_resource': network_name},
- 'replacement_policy': 'AUTO',
+ 'binding:vnic_type': network.vnic_type,
+ 'fixed_ips': fixed_ips,
+ 'network': network_,
}
}
@@ -353,6 +368,8 @@ name (i.e. %s).
self.resources[name]['properties'][
'allowed_address_pairs'] = allowed_address_pairs
+ log.debug("adding Neutron::Port %s", self.resources[name])
+
self._template['outputs'][name] = {
'description': 'Address for interface %s' % name,
'value': {'get_attr': [name, 'fixed_ips', 0, 'ip_address']}
@@ -413,7 +430,7 @@ name (i.e. %s).
}
}
- def add_keypair(self, name, key_uuid):
+ def add_keypair(self, name, key_id):
"""add to the template a Nova KeyPair"""
log.debug("adding Nova::KeyPair '%s'", name)
self.resources[name] = {
@@ -425,7 +442,7 @@ name (i.e. %s).
pkg_resources.resource_string(
'yardstick.resources',
'files/yardstick_key-' +
- get_short_key_uuid(key_uuid) + '.pub'),
+ key_id + '.pub'),
'utf-8')
}
}
diff --git a/yardstick/ssh.py b/yardstick/ssh.py
index 6ddf327f2..d7adc0d05 100644
--- a/yardstick/ssh.py
+++ b/yardstick/ssh.py
@@ -78,7 +78,7 @@ from oslo_utils import encodeutils
from scp import SCPClient
import six
-from yardstick.common.utils import try_int
+from yardstick.common.utils import try_int, NON_NONE_DEFAULT, make_dict_from_map
from yardstick.network_services.utils import provision_tool
@@ -102,6 +102,7 @@ class SSH(object):
"""Represent ssh connection."""
SSH_PORT = paramiko.config.SSH_PORT
+ DEFAULT_WAIT_TIMEOUT = 120
@staticmethod
def gen_keys(key_filename, bit_count=2048):
@@ -120,6 +121,18 @@ class SSH(object):
# i.e. the subclass, not the superclass
return SSH
+ @classmethod
+ def get_arg_key_map(cls):
+ return {
+ 'user': ('user', NON_NONE_DEFAULT),
+ 'host': ('ip', NON_NONE_DEFAULT),
+ 'port': ('ssh_port', cls.SSH_PORT),
+ 'pkey': ('pkey', None),
+ 'key_filename': ('key_filename', None),
+ 'password': ('password', None),
+ 'name': ('name', None),
+ }
+
def __init__(self, user, host, port=None, pkey=None,
key_filename=None, password=None, name=None):
"""Initialize SSH client.
@@ -137,6 +150,7 @@ class SSH(object):
else:
self.log = logging.getLogger(__name__)
+ self.wait_timeout = self.DEFAULT_WAIT_TIMEOUT
self.user = user
self.host = host
# everybody wants to debug this in the caller, do it here instead
@@ -162,16 +176,9 @@ class SSH(object):
overrides = {}
if defaults is None:
defaults = {}
+
params = ChainMap(overrides, node, defaults)
- return {
- 'user': params['user'],
- 'host': params['ip'],
- 'port': params.get('ssh_port', cls.SSH_PORT),
- 'pkey': params.get('pkey'),
- 'key_filename': params.get('key_filename'),
- 'password': params.get('password'),
- 'name': params.get('name'),
- }
+ return make_dict_from_map(params, cls.get_arg_key_map())
@classmethod
def from_node(cls, node, overrides=None, defaults=None):
@@ -186,7 +193,7 @@ class SSH(object):
return key_class.from_private_key(key)
except paramiko.SSHException as e:
errors.append(e)
- raise SSHError("Invalid pkey: %s" % (errors))
+ raise SSHError("Invalid pkey: %s" % errors)
@property
def is_connected(self):
@@ -287,7 +294,7 @@ class SSH(object):
while True:
# Block until data can be read/write.
- r, w, e = select.select([session], writes, [session], 1)
+ e = select.select([session], writes, [session], 1)[2]
if session.recv_ready():
data = encodeutils.safe_decode(session.recv(4096), 'utf-8')
@@ -361,17 +368,20 @@ class SSH(object):
stderr.seek(0)
return exit_status, stdout.read(), stderr.read()
- def wait(self, timeout=120, interval=1):
+ def wait(self, timeout=None, interval=1):
"""Wait for the host will be available via ssh."""
- start_time = time.time()
+ if timeout is None:
+ timeout = self.wait_timeout
+
+ end_time = time.time() + timeout
while True:
try:
return self.execute("uname")
except (socket.error, SSHError) as e:
self.log.debug("Ssh is still unavailable: %r", e)
time.sleep(interval)
- if time.time() > (start_time + timeout):
- raise SSHTimeout("Timeout waiting for '%s'", self.host)
+ if time.time() > end_time:
+ raise SSHTimeout("Timeout waiting for '%s'" % self.host)
def put(self, files, remote_path=b'.', recursive=False):
client = self._get_client()
@@ -447,24 +457,40 @@ class SSH(object):
class AutoConnectSSH(SSH):
+ @classmethod
+ def get_arg_key_map(cls):
+ arg_key_map = super(AutoConnectSSH, cls).get_arg_key_map()
+ arg_key_map['wait'] = ('wait', True)
+ return arg_key_map
+
# always wait or we will get OpenStack SSH errors
def __init__(self, user, host, port=None, pkey=None,
key_filename=None, password=None, name=None, wait=True):
super(AutoConnectSSH, self).__init__(user, host, port, pkey, key_filename, password, name)
- self._wait = wait
+ if wait and wait is not True:
+ self.wait_timeout = int(wait)
def _make_dict(self):
data = super(AutoConnectSSH, self)._make_dict()
data.update({
- 'wait': self._wait
+ 'wait': self.wait_timeout
})
return data
def _connect(self):
if not self.is_connected:
- self._get_client()
- if self._wait:
- self.wait()
+ interval = 1
+ timeout = self.wait_timeout
+
+ end_time = time.time() + timeout
+ while True:
+ try:
+ return self._get_client()
+ except (socket.error, SSHError) as e:
+ self.log.debug("Ssh is still unavailable: %r", e)
+ time.sleep(interval)
+ if time.time() > end_time:
+ raise SSHTimeout("Timeout waiting for '%s'" % self.host)
def drop_connection(self):
""" Don't close anything, just force creation of a new client """
diff --git a/yardstick/tests/__init__.py b/yardstick/tests/__init__.py
index e69de29bb..56e3106b8 100644
--- a/yardstick/tests/__init__.py
+++ b/yardstick/tests/__init__.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2018 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
+
+
+STL_MOCKS = {
+ 'trex_stl_lib': mock.MagicMock(),
+ 'trex_stl_lib.base64': mock.MagicMock(),
+ 'trex_stl_lib.binascii': mock.MagicMock(),
+ 'trex_stl_lib.collections': mock.MagicMock(),
+ 'trex_stl_lib.copy': mock.MagicMock(),
+ 'trex_stl_lib.datetime': mock.MagicMock(),
+ 'trex_stl_lib.functools': mock.MagicMock(),
+ 'trex_stl_lib.imp': mock.MagicMock(),
+ 'trex_stl_lib.inspect': mock.MagicMock(),
+ 'trex_stl_lib.json': mock.MagicMock(),
+ 'trex_stl_lib.linecache': mock.MagicMock(),
+ 'trex_stl_lib.math': mock.MagicMock(),
+ 'trex_stl_lib.os': mock.MagicMock(),
+ 'trex_stl_lib.platform': mock.MagicMock(),
+ 'trex_stl_lib.pprint': mock.MagicMock(),
+ 'trex_stl_lib.random': mock.MagicMock(),
+ 'trex_stl_lib.re': mock.MagicMock(),
+ 'trex_stl_lib.scapy': mock.MagicMock(),
+ 'trex_stl_lib.socket': mock.MagicMock(),
+ 'trex_stl_lib.string': mock.MagicMock(),
+ 'trex_stl_lib.struct': mock.MagicMock(),
+ 'trex_stl_lib.sys': mock.MagicMock(),
+ 'trex_stl_lib.threading': mock.MagicMock(),
+ 'trex_stl_lib.time': mock.MagicMock(),
+ 'trex_stl_lib.traceback': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_async_client': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_client': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_exceptions': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_ext': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_jsonrpc_client': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_packet_builder_interface': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_packet_builder_scapy': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_port': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_stats': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_streams': mock.MagicMock(),
+ 'trex_stl_lib.trex_stl_types': mock.MagicMock(),
+ 'trex_stl_lib.types': mock.MagicMock(),
+ 'trex_stl_lib.utils': mock.MagicMock(),
+ 'trex_stl_lib.utils.argparse': mock.MagicMock(),
+ 'trex_stl_lib.utils.collections': mock.MagicMock(),
+ 'trex_stl_lib.utils.common': mock.MagicMock(),
+ 'trex_stl_lib.utils.json': mock.MagicMock(),
+ 'trex_stl_lib.utils.os': mock.MagicMock(),
+ 'trex_stl_lib.utils.parsing_opts': mock.MagicMock(),
+ 'trex_stl_lib.utils.pwd': mock.MagicMock(),
+ 'trex_stl_lib.utils.random': mock.MagicMock(),
+ 'trex_stl_lib.utils.re': mock.MagicMock(),
+ 'trex_stl_lib.utils.string': mock.MagicMock(),
+ 'trex_stl_lib.utils.sys': mock.MagicMock(),
+ 'trex_stl_lib.utils.text_opts': mock.MagicMock(),
+ 'trex_stl_lib.utils.text_tables': mock.MagicMock(),
+ 'trex_stl_lib.utils.texttable': mock.MagicMock(),
+ 'trex_stl_lib.warnings': mock.MagicMock(),
+ 'trex_stl_lib.yaml': mock.MagicMock(),
+ 'trex_stl_lib.zlib': mock.MagicMock(),
+ 'trex_stl_lib.zmq': mock.MagicMock(),
+}
diff --git a/yardstick/tests/functional/base.py b/yardstick/tests/functional/base.py
new file mode 100644
index 000000000..51be013a1
--- /dev/null
+++ b/yardstick/tests/functional/base.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2018 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 abc
+import six
+
+from oslo_config import cfg
+from oslotest import base
+
+
+CONF = cfg.CONF
+
+
+@six.add_metaclass(abc.ABCMeta)
+class BaseFunctionalTestCase(base.BaseTestCase):
+ """Base class for functional tests."""
+
+ def setUp(self):
+ super(BaseFunctionalTestCase, self).setUp()
+
+ def config(self, **kw):
+ """Override some configuration values.
+
+ The keyword arguments are the names of configuration options to
+ override and their values.
+
+ If a group argument is supplied, the overrides are applied to
+ the specified configuration option group.
+
+ All overrides are automatically cleared at the end of the current
+ test by the fixtures cleanup process.
+ """
+ group = kw.pop('group', None)
+ for k, v in kw.items():
+ CONF.set_override(k, v, group)
diff --git a/yardstick/tests/functional/benchmark/__init__.py b/yardstick/tests/functional/benchmark/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/functional/benchmark/__init__.py
diff --git a/yardstick/tests/functional/benchmark/scenarios/__init__.py b/yardstick/tests/functional/benchmark/scenarios/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/functional/benchmark/scenarios/__init__.py
diff --git a/yardstick/tests/functional/benchmark/scenarios/networking/__init__.py b/yardstick/tests/functional/benchmark/scenarios/networking/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/functional/benchmark/scenarios/networking/__init__.py
diff --git a/yardstick/tests/functional/benchmark/scenarios/networking/test_vnf_generic.py b/yardstick/tests/functional/benchmark/scenarios/networking/test_vnf_generic.py
new file mode 100644
index 000000000..38f1a978d
--- /dev/null
+++ b/yardstick/tests/functional/benchmark/scenarios/networking/test_vnf_generic.py
@@ -0,0 +1,195 @@
+# Copyright (c) 2018 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 copy
+import sys
+
+import mock
+import unittest
+
+from yardstick import tests as y_tests
+from yardstick.common import utils
+
+
+with mock.patch.dict(sys.modules, y_tests.STL_MOCKS):
+ from yardstick.benchmark.scenarios.networking import vnf_generic
+
+
+TRAFFIC_PROFILE_1 = """
+schema: nsb:traffic_profile:0.1
+name: rfc2544
+description: Traffic profile to run RFC2544 latency
+traffic_profile:
+ traffic_type : RFC2544Profile
+ frame_rate : 100
+uplink_0:
+ ipv4:
+ id: 1
+ outer_l2:
+ framesize:
+ 64B: "{{get(imix, 'imix.uplink.64B', '0') }}"
+ 128B: "{{get(imix, 'imix.uplink.128B', '0') }}"
+"""
+
+TRAFFIC_PROFILE_2 = """
+{% set vports = get(extra_args, 'vports', 1) %}
+traffic_profile:
+ traffic_type : RFC2544Profile
+{% for vport in range(vports|int) %}
+uplink_{{vport}}:
+ ipv4: 192.168.0.{{vport}}
+{% endfor %}
+"""
+
+TOPOLOGY_PROFILE = """
+{% set vports = get(extra_args, 'vports', 2) %}
+nsd:nsd-catalog:
+ nsd:
+ - id: 3tg-topology
+ vld:
+{% for vport in range(0,vports,2|int) %}
+ - id: uplink_{{loop.index0}}
+ name: tg__0 to vnf__0 link {{vport + 1}}
+ vnfd-connection-point-ref:
+ - vnfd-connection-point-ref: xe{{vport}}
+ - id: downlink_{{loop.index0}}
+ name: vnf__0 to tg__0 link {{vport + 2}}
+ vnfd-connection-point-ref:
+ - vnfd-connection-point-ref: xe{{vport+1}}
+{% endfor %}
+"""
+
+class VnfGenericTestCase(unittest.TestCase):
+
+ def setUp(self):
+ scenario_cfg = {'topology': 'fake_topology',
+ 'task_path': 'fake_path',
+ 'traffic_profile': 'fake_fprofile_path'}
+ context_cfg = {}
+ topology_yaml = {'nsd:nsd-catalog': {'nsd': [mock.Mock()]}}
+
+ with mock.patch.object(utils, 'open_relative_file') as mock_open_path:
+ mock_open_path.side_effect = mock.mock_open(read_data=str(topology_yaml))
+ self.ns_testcase = vnf_generic.NetworkServiceTestCase(scenario_cfg,
+ context_cfg)
+ self.ns_testcase._get_traffic_profile = mock.Mock()
+ self.ns_testcase._get_topology = mock.Mock()
+
+ def test__fill_traffic_profile_no_args(self):
+ traffic_profile = copy.deepcopy(TRAFFIC_PROFILE_1)
+ self.ns_testcase._get_traffic_profile.return_value = traffic_profile
+
+ self.ns_testcase._fill_traffic_profile()
+ config = self.ns_testcase.traffic_profile.params
+ self.assertEqual('nsb:traffic_profile:0.1', config['schema'])
+ self.assertEqual('rfc2544', config['name'])
+ self.assertEqual('Traffic profile to run RFC2544 latency',
+ config['description'])
+ t_profile = {'traffic_type': 'RFC2544Profile',
+ 'frame_rate': 100}
+ self.assertEqual(t_profile, config['traffic_profile'])
+ uplink_0 = {
+ 'ipv4': {'id': 1,
+ 'outer_l2': {'framesize': {'128B': '0', '64B': '0'}}
+ }
+ }
+ self.assertEqual(uplink_0, config['uplink_0'])
+
+ def test__fill_traffic_profile_with_args(self):
+ traffic_profile = copy.deepcopy(TRAFFIC_PROFILE_2)
+ self.ns_testcase._get_traffic_profile.return_value = traffic_profile
+ self.ns_testcase.scenario_cfg['extra_args'] = {'vports': 3}
+
+ self.ns_testcase._fill_traffic_profile()
+ config = self.ns_testcase.traffic_profile.params
+ self.assertEqual({'ipv4': '192.168.0.0'}, config['uplink_0'])
+ self.assertEqual({'ipv4': '192.168.0.1'}, config['uplink_1'])
+ self.assertEqual({'ipv4': '192.168.0.2'}, config['uplink_2'])
+ self.assertNotIn('uplink_3', config)
+
+ def test__fill_traffic_profile_incorrect_args(self):
+ traffic_profile = copy.deepcopy(TRAFFIC_PROFILE_2)
+ self.ns_testcase._get_traffic_profile.return_value = traffic_profile
+ self.ns_testcase.scenario_cfg['extra_args'] = {'incorrect_vports': 3}
+
+ self.ns_testcase._fill_traffic_profile()
+ config = self.ns_testcase.traffic_profile.params
+ self.assertEqual({'ipv4': '192.168.0.0'}, config['uplink_0'])
+ self.assertNotIn('uplink_1', config)
+
+ def test__render_topology_with_args(self):
+ topology_profile = copy.deepcopy(TOPOLOGY_PROFILE)
+ self.ns_testcase._get_topology.return_value = topology_profile
+ self.ns_testcase.scenario_cfg['extra_args'] = {'vports': 6}
+
+ self.ns_testcase._render_topology()
+ topology = self.ns_testcase.topology
+ self.assertEqual("3tg-topology", topology['id'])
+ vld = self.ns_testcase.topology['vld']
+ self.assertEqual(len(vld), 6)
+ for index, vport in enumerate(range(0, 6, 2)):
+ self.assertEqual('uplink_{}'.format(index), vld[vport]['id'])
+ self.assertEqual('tg__0 to vnf__0 link {}'.format(vport + 1), vld[vport]['name'])
+ self.assertEqual('xe{}'.format(vport),
+ vld[vport]['vnfd-connection-point-ref'][0]
+ ['vnfd-connection-point-ref'])
+
+ self.assertEqual('downlink_{}'.format(index), vld[vport + 1]['id'])
+ self.assertEqual('vnf__0 to tg__0 link {}'.format(vport + 2), vld[vport + 1]['name'])
+ self.assertEqual('xe{}'.format(vport + 1),
+ vld[vport + 1]['vnfd-connection-point-ref'][0]
+ ['vnfd-connection-point-ref'])
+
+ def test__render_topology_incorrect_args(self):
+ topology_profile = copy.deepcopy(TOPOLOGY_PROFILE)
+ self.ns_testcase._get_topology.return_value = topology_profile
+ self.ns_testcase.scenario_cfg['extra_args'] = {'fake_vports': 5}
+
+ self.ns_testcase._render_topology()
+
+ topology = self.ns_testcase.topology
+ self.assertEqual("3tg-topology", topology['id'])
+ vld = self.ns_testcase.topology['vld']
+ self.assertEqual(len(vld), 2)
+
+ self.assertEqual('uplink_0', vld[0]['id'])
+ self.assertEqual('tg__0 to vnf__0 link 1', vld[0]['name'])
+ self.assertEqual('xe0',
+ vld[0]['vnfd-connection-point-ref'][0]['vnfd-connection-point-ref'])
+
+ self.assertEqual('downlink_0', vld[1]['id'])
+ self.assertEqual('vnf__0 to tg__0 link 2', vld[1]['name'])
+ self.assertEqual('xe1',
+ vld[1]['vnfd-connection-point-ref'][0]['vnfd-connection-point-ref'])
+
+ def test__render_topology_no_args(self):
+ topology_profile = copy.deepcopy(TOPOLOGY_PROFILE)
+ self.ns_testcase._get_topology.return_value = topology_profile
+
+ self.ns_testcase._render_topology()
+
+ topology = self.ns_testcase.topology
+ self.assertEqual("3tg-topology", topology['id'])
+ vld = self.ns_testcase.topology['vld']
+ self.assertEqual(len(vld), 2)
+
+ self.assertEqual('uplink_0', vld[0]['id'])
+ self.assertEqual('tg__0 to vnf__0 link 1', vld[0]['name'])
+ self.assertEqual('xe0',
+ vld[0]['vnfd-connection-point-ref'][0]['vnfd-connection-point-ref'])
+
+ self.assertEqual('downlink_0', vld[1]['id'])
+ self.assertEqual('vnf__0 to tg__0 link 2', vld[1]['name'])
+ self.assertEqual('xe1',
+ vld[1]['vnfd-connection-point-ref'][0]['vnfd-connection-point-ref'])
diff --git a/yardstick/tests/functional/common/fake_directory_package/README.md b/yardstick/tests/functional/common/fake_directory_package/README.md
new file mode 100644
index 000000000..689e47039
--- /dev/null
+++ b/yardstick/tests/functional/common/fake_directory_package/README.md
@@ -0,0 +1,2 @@
+# yardstick_new_plugin
+Yardstick plugin
diff --git a/yardstick/tests/functional/common/fake_directory_package/setup.py b/yardstick/tests/functional/common/fake_directory_package/setup.py
new file mode 100644
index 000000000..cf938ef4f
--- /dev/null
+++ b/yardstick/tests/functional/common/fake_directory_package/setup.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2018 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 setuptools import setup, find_packages
+
+setup(
+ name='yardstick_new_plugin_2',
+ version='1.0.0',
+ packages=find_packages(),
+ include_package_data=True,
+ url='https://www.opnfv.org',
+ entry_points={
+ 'yardstick.scenarios': [
+ 'Dummy2 = yardstick_new_plugin.benchmark.scenarios.dummy2.dummy2:'
+ 'Dummy2',
+ ]
+ },
+)
diff --git a/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/__init__.py b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/__init__.py
diff --git a/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/__init__.py b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/__init__.py
diff --git a/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/__init__.py b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/__init__.py
diff --git a/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/dummy2/__init__.py b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/dummy2/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/dummy2/__init__.py
diff --git a/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/dummy2/dummy2.py b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/dummy2/dummy2.py
new file mode 100644
index 000000000..a2211ec51
--- /dev/null
+++ b/yardstick/tests/functional/common/fake_directory_package/yardstick_new_plugin_2/benchmark/scenarios/dummy2/dummy2.py
@@ -0,0 +1,40 @@
+# Copyright (c) 2018 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 logging
+
+from yardstick.benchmark.scenarios import base
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Dummy2(base.Scenario):
+ """Execute Dummy (v2!) echo"""
+ __scenario_type__ = "Dummy2"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+ self.setup_done = False
+
+ def setup(self):
+ self.setup_done = True
+
+ def run(self, result):
+ if not self.setup_done:
+ self.setup()
+
+ result["hello"] = "yardstick"
+ LOG.info("Dummy (v2!) echo hello yardstick!")
diff --git a/yardstick/tests/functional/common/fake_pip_package/yardstick_new_plugin-1.0.0.tar.gz b/yardstick/tests/functional/common/fake_pip_package/yardstick_new_plugin-1.0.0.tar.gz
new file mode 100644
index 000000000..e5379a78a
--- /dev/null
+++ b/yardstick/tests/functional/common/fake_pip_package/yardstick_new_plugin-1.0.0.tar.gz
Binary files differ
diff --git a/yardstick/tests/functional/common/test_packages.py b/yardstick/tests/functional/common/test_packages.py
new file mode 100644
index 000000000..5dead4e55
--- /dev/null
+++ b/yardstick/tests/functional/common/test_packages.py
@@ -0,0 +1,94 @@
+# Copyright (c) 2018 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 os
+from os import path
+import re
+
+from yardstick.common import packages
+from yardstick.common import utils
+from yardstick.tests.functional import base
+
+
+class PipPackagesTestCase(base.BaseFunctionalTestCase):
+
+ TMP_FOLDER = '/tmp/pip_packages/'
+ PYTHONPATH = 'PYTHONPATH=%s' % TMP_FOLDER
+
+ def setUp(self):
+ super(PipPackagesTestCase, self).setUp()
+ privsep_helper = os.path.join(
+ os.getenv('VIRTUAL_ENV'), 'bin', 'privsep-helper')
+ self.config(
+ helper_command=' '.join(['sudo', '-EH', privsep_helper]),
+ group='yardstick_privileged')
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ utils.execute_command('sudo rm -rf %s' % self.TMP_FOLDER)
+
+ def _remove_package(self, package):
+ os.system('%s pip uninstall %s -y' % (self.PYTHONPATH, package))
+
+ def _list_packages(self):
+ pip_list_regex = re.compile(
+ r"(?P<name>[\w\.-]+) \((?P<version>[\w\d_\.\-]+),*.*\)")
+ pkg_dict = {}
+ pkgs = utils.execute_command('pip list',
+ env={'PYTHONPATH': self.TMP_FOLDER})
+ for line in pkgs:
+ match = pip_list_regex.match(line)
+ if match and match.group('name'):
+ pkg_dict[match.group('name')] = match.group('version')
+ return pkg_dict
+
+ def test_install_from_folder(self):
+ dirname = path.dirname(__file__)
+ package_dir = dirname + '/fake_directory_package'
+ package_name = 'yardstick-new-plugin-2'
+ self.addCleanup(self._remove_package, package_name)
+ self._remove_package(package_name)
+ self.assertFalse(package_name in self._list_packages())
+
+ self.assertEqual(0, packages.pip_install(package_dir, self.TMP_FOLDER))
+ self.assertTrue(package_name in self._list_packages())
+
+ def test_install_from_pip_package(self):
+ dirname = path.dirname(__file__)
+ package_path = (dirname +
+ '/fake_pip_package/yardstick_new_plugin-1.0.0.tar.gz')
+ package_name = 'yardstick-new-plugin'
+ self.addCleanup(self._remove_package, package_name)
+ self._remove_package(package_name)
+ self.assertFalse(package_name in self._list_packages())
+
+ self.assertEqual(0, packages.pip_install(package_path, self.TMP_FOLDER))
+ self.assertTrue(package_name in self._list_packages())
+
+ # NOTE(ralonsoh): an stable test plugin project is needed in OPNFV git
+ # server to execute this test.
+ # def test_install_from_url(self):
+
+ def test_pip_freeze(self):
+ # NOTE (ralonsoh): from requirements.txt file. The best way to test
+ # this function is to parse requirements.txt and test-requirements.txt
+ # and check all packages.
+ pkgs_ref = {'Babel': '2.3.4',
+ 'SQLAlchemy': '1.1.12',
+ 'influxdb': '4.1.1',
+ 'netifaces': '0.10.6',
+ 'unicodecsv': '0.14.1'}
+ pkgs = packages.pip_list()
+ for name, version in (pkgs_ref.items()):
+ self.assertEqual(version, pkgs[name])
diff --git a/yardstick/tests/unit/__init__.py b/yardstick/tests/unit/__init__.py
index a468b272b..c05f91c81 100644
--- a/yardstick/tests/unit/__init__.py
+++ b/yardstick/tests/unit/__init__.py
@@ -12,65 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from __future__ import absolute_import
+import sys
+
import mock
+from yardstick import tests
+
-STL_MOCKS = {
- 'trex_stl_lib': mock.MagicMock(),
- 'trex_stl_lib.base64': mock.MagicMock(),
- 'trex_stl_lib.binascii': mock.MagicMock(),
- 'trex_stl_lib.collections': mock.MagicMock(),
- 'trex_stl_lib.copy': mock.MagicMock(),
- 'trex_stl_lib.datetime': mock.MagicMock(),
- 'trex_stl_lib.functools': mock.MagicMock(),
- 'trex_stl_lib.imp': mock.MagicMock(),
- 'trex_stl_lib.inspect': mock.MagicMock(),
- 'trex_stl_lib.json': mock.MagicMock(),
- 'trex_stl_lib.linecache': mock.MagicMock(),
- 'trex_stl_lib.math': mock.MagicMock(),
- 'trex_stl_lib.os': mock.MagicMock(),
- 'trex_stl_lib.platform': mock.MagicMock(),
- 'trex_stl_lib.pprint': mock.MagicMock(),
- 'trex_stl_lib.random': mock.MagicMock(),
- 'trex_stl_lib.re': mock.MagicMock(),
- 'trex_stl_lib.scapy': mock.MagicMock(),
- 'trex_stl_lib.socket': mock.MagicMock(),
- 'trex_stl_lib.string': mock.MagicMock(),
- 'trex_stl_lib.struct': mock.MagicMock(),
- 'trex_stl_lib.sys': mock.MagicMock(),
- 'trex_stl_lib.threading': mock.MagicMock(),
- 'trex_stl_lib.time': mock.MagicMock(),
- 'trex_stl_lib.traceback': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_async_client': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_client': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_exceptions': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_ext': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_jsonrpc_client': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_packet_builder_interface': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_packet_builder_scapy': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_port': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_stats': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_streams': mock.MagicMock(),
- 'trex_stl_lib.trex_stl_types': mock.MagicMock(),
- 'trex_stl_lib.types': mock.MagicMock(),
- 'trex_stl_lib.utils': mock.MagicMock(),
- 'trex_stl_lib.utils.argparse': mock.MagicMock(),
- 'trex_stl_lib.utils.collections': mock.MagicMock(),
- 'trex_stl_lib.utils.common': mock.MagicMock(),
- 'trex_stl_lib.utils.json': mock.MagicMock(),
- 'trex_stl_lib.utils.os': mock.MagicMock(),
- 'trex_stl_lib.utils.parsing_opts': mock.MagicMock(),
- 'trex_stl_lib.utils.pwd': mock.MagicMock(),
- 'trex_stl_lib.utils.random': mock.MagicMock(),
- 'trex_stl_lib.utils.re': mock.MagicMock(),
- 'trex_stl_lib.utils.string': mock.MagicMock(),
- 'trex_stl_lib.utils.sys': mock.MagicMock(),
- 'trex_stl_lib.utils.text_opts': mock.MagicMock(),
- 'trex_stl_lib.utils.text_tables': mock.MagicMock(),
- 'trex_stl_lib.utils.texttable': mock.MagicMock(),
- 'trex_stl_lib.warnings': mock.MagicMock(),
- 'trex_stl_lib.yaml': mock.MagicMock(),
- 'trex_stl_lib.zlib': mock.MagicMock(),
- 'trex_stl_lib.zmq': mock.MagicMock(),
-}
+mock_stl = mock.patch.dict(sys.modules, tests.STL_MOCKS)
+mock_stl.start()
diff --git a/yardstick/tests/unit/apiserver/resources/test_env_action.py b/yardstick/tests/unit/apiserver/resources/test_env_action.py
index cf646a29c..657841669 100644
--- a/yardstick/tests/unit/apiserver/resources/test_env_action.py
+++ b/yardstick/tests/unit/apiserver/resources/test_env_action.py
@@ -33,11 +33,3 @@ class EnvTestCase(APITestCase):
time.sleep(0)
self.assertIn(u'status', resp)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/apiserver/utils/test_influx.py b/yardstick/tests/unit/apiserver/utils/test_influx.py
index 883608bb2..dce6c1cec 100644
--- a/yardstick/tests/unit/apiserver/utils/test_influx.py
+++ b/yardstick/tests/unit/apiserver/utils/test_influx.py
@@ -50,11 +50,3 @@ class QueryTestCase(unittest.TestCase):
influx.query(sql)
except Exception as e: # pylint: disable=broad-except
self.assertIsInstance(e, RuntimeError)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/base.py b/yardstick/tests/unit/base.py
new file mode 100644
index 000000000..b943efc2b
--- /dev/null
+++ b/yardstick/tests/unit/base.py
@@ -0,0 +1,23 @@
+# Copyright 2018 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 abc
+
+import six
+import unittest
+
+
+@six.add_metaclass(abc.ABCMeta)
+class BaseUnitTestCase(unittest.TestCase):
+ """Base class for unit tests"""
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
index 02a85525a..0223fd3ff 100644
--- a/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
@@ -26,14 +26,6 @@ class OvsDpdkContextTestCase(unittest.TestCase):
NODES_ovs_dpdk_SAMPLE = "nodes_ovs_dpdk_sample.yaml"
NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml"
- ATTRS = {
- 'name': 'StandaloneOvsDpdk',
- 'file': 'pod',
- 'flavor': {},
- 'servers': {},
- 'networks': {},
- }
-
NETWORKS = {
'mgmt': {'cidr': '152.16.100.10/24'},
'private_0': {
@@ -55,7 +47,17 @@ class OvsDpdkContextTestCase(unittest.TestCase):
}
def setUp(self):
+ self.attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
+ }
self.ovs_dpdk = ovs_dpdk.OvsDpdkContext()
+ self.addCleanup(self._remove_contexts)
+
+ def _remove_contexts(self):
+ if self.ovs_dpdk in self.ovs_dpdk.list:
+ self.ovs_dpdk._delete_context()
@mock.patch('yardstick.benchmark.contexts.standalone.model.Server')
@mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper')
@@ -66,9 +68,18 @@ class OvsDpdkContextTestCase(unittest.TestCase):
self.assertTrue(self.ovs_dpdk.first_run)
def test_init(self):
+ ATTRS = {
+ 'name': 'StandaloneOvsDpdk',
+ 'task_id': '1234567890',
+ 'file': 'pod',
+ 'flavor': {},
+ 'servers': {},
+ 'networks': {},
+ }
+
self.ovs_dpdk.helper.parse_pod_file = mock.Mock(
return_value=[{}, {}, {}])
- self.assertIsNone(self.ovs_dpdk.init(self.ATTRS))
+ self.assertIsNone(self.ovs_dpdk.init(ATTRS))
def test_setup_ovs(self):
with mock.patch("yardstick.ssh.SSH") as ssh:
@@ -186,12 +197,7 @@ class OvsDpdkContextTestCase(unittest.TestCase):
def test__get_server_with_dic_attr_name(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
- }
-
- self.ovs_dpdk.init(attrs)
+ self.ovs_dpdk.init(self.attrs)
attr_name = {'name': 'foo.bar'}
result = self.ovs_dpdk._get_server(attr_name)
@@ -200,14 +206,9 @@ class OvsDpdkContextTestCase(unittest.TestCase):
def test__get_server_not_found(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
- }
-
self.ovs_dpdk.helper.parse_pod_file = mock.Mock(
return_value=[{}, {}, {}])
- self.ovs_dpdk.init(attrs)
+ self.ovs_dpdk.init(self.attrs)
attr_name = 'bar.foo'
result = self.ovs_dpdk._get_server(attr_name)
@@ -216,12 +217,7 @@ class OvsDpdkContextTestCase(unittest.TestCase):
def test__get_server_mismatch(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
- }
-
- self.ovs_dpdk.init(attrs)
+ self.ovs_dpdk.init(self.attrs)
attr_name = 'bar.foo1'
result = self.ovs_dpdk._get_server(attr_name)
@@ -230,31 +226,23 @@ class OvsDpdkContextTestCase(unittest.TestCase):
def test__get_server_duplicate(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
- }
+ self.attrs['file'] = self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
- self.ovs_dpdk.init(attrs)
+ self.ovs_dpdk.init(self.attrs)
- attr_name = 'node1.foo'
+ attr_name = 'node1.foo-12345678'
with self.assertRaises(ValueError):
self.ovs_dpdk._get_server(attr_name)
def test__get_server_found(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
- }
-
- self.ovs_dpdk.init(attrs)
+ self.ovs_dpdk.init(self.attrs)
- attr_name = 'node1.foo'
+ attr_name = 'node1.foo-12345678'
result = self.ovs_dpdk._get_server(attr_name)
self.assertEqual(result['ip'], '10.229.47.137')
- self.assertEqual(result['name'], 'node1.foo')
+ self.assertEqual(result['name'], 'node1.foo-12345678')
self.assertEqual(result['user'], 'root')
self.assertEqual(result['key_filename'], '/root/.yardstick_key')
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
index f323fcd3c..f0953ef55 100644
--- a/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
@@ -29,6 +29,7 @@ class SriovContextTestCase(unittest.TestCase):
ATTRS = {
'name': 'StandaloneSriov',
+ 'task_id': '1234567890',
'file': 'pod',
'flavor': {},
'servers': {},
@@ -56,7 +57,17 @@ class SriovContextTestCase(unittest.TestCase):
}
def setUp(self):
+ self.attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
+ }
self.sriov = sriov.SriovContext()
+ self.addCleanup(self._remove_contexts)
+
+ def _remove_contexts(self):
+ if self.sriov in self.sriov.list:
+ self.sriov._delete_context()
@mock.patch('yardstick.benchmark.contexts.standalone.sriov.Libvirt')
@mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper')
@@ -105,12 +116,7 @@ class SriovContextTestCase(unittest.TestCase):
def test__get_server_with_dic_attr_name(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
- }
-
- self.sriov.init(attrs)
+ self.sriov.init(self.attrs)
attr_name = {'name': 'foo.bar'}
result = self.sriov._get_server(attr_name)
@@ -119,13 +125,8 @@ class SriovContextTestCase(unittest.TestCase):
def test__get_server_not_found(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
- }
-
self.sriov.helper.parse_pod_file = mock.Mock(return_value=[{}, {}, {}])
- self.sriov.init(attrs)
+ self.sriov.init(self.attrs)
attr_name = 'bar.foo'
result = self.sriov._get_server(attr_name)
@@ -134,12 +135,7 @@ class SriovContextTestCase(unittest.TestCase):
def test__get_server_mismatch(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
- }
-
- self.sriov.init(attrs)
+ self.sriov.init(self.attrs)
attr_name = 'bar.foo1'
result = self.sriov._get_server(attr_name)
@@ -148,25 +144,29 @@ class SriovContextTestCase(unittest.TestCase):
def test__get_server_duplicate(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
- }
+ self.attrs['file'] = self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
- self.sriov.init(attrs)
+ self.sriov.init(self.attrs)
- attr_name = 'node1.foo'
+ attr_name = 'node1.foo-12345678'
with self.assertRaises(ValueError):
self.sriov._get_server(attr_name)
def test__get_server_found(self):
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
- }
+ self.sriov.init(self.attrs)
+
+ attr_name = 'node1.foo-12345678'
+ result = self.sriov._get_server(attr_name)
+
+ self.assertEqual(result['ip'], '10.229.47.137')
+ self.assertEqual(result['name'], 'node1.foo-12345678')
+ self.assertEqual(result['user'], 'root')
+ self.assertEqual(result['key_filename'], '/root/.yardstick_key')
- self.sriov.init(attrs)
+ def test__get_server_no_task_id(self):
+ self.attrs['flags'] = {'no_setup': True}
+ self.sriov.init(self.attrs)
attr_name = 'node1.foo'
result = self.sriov._get_server(attr_name)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_base.py b/yardstick/tests/unit/benchmark/contexts/test_base.py
new file mode 100644
index 000000000..153c6a527
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/test_base.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2018 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 unittest
+
+from yardstick.benchmark.contexts import base
+
+
+class FlagsTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.flags = base.Flags()
+
+ def test___init__(self):
+ self.assertFalse(self.flags.no_setup)
+ self.assertFalse(self.flags.no_teardown)
+
+ def test___init__with_flags(self):
+ flags = base.Flags(no_setup=True)
+ self.assertTrue(flags.no_setup)
+ self.assertFalse(flags.no_teardown)
+
+ def test_parse(self):
+ self.flags.parse(no_setup=True, no_teardown="False")
+
+ self.assertTrue(self.flags.no_setup)
+ self.assertEqual(self.flags.no_teardown, "False")
+
+ def test_parse_forbidden_flags(self):
+ self.flags.parse(foo=42)
+ with self.assertRaises(AttributeError):
+ _ = self.flags.foo
diff --git a/yardstick/tests/unit/benchmark/contexts/test_dummy.py b/yardstick/tests/unit/benchmark/contexts/test_dummy.py
index 1a54035df..e393001a1 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_dummy.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_dummy.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
@@ -9,9 +7,6 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-# Unittest for yardstick.benchmark.contexts.dummy
-
-from __future__ import absolute_import
import unittest
from yardstick.benchmark.contexts import dummy
@@ -20,10 +15,55 @@ from yardstick.benchmark.contexts import dummy
class DummyContextTestCase(unittest.TestCase):
def setUp(self):
+ self.attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ }
self.test_context = dummy.DummyContext()
+ self.addCleanup(self.test_context._delete_context)
+
+ def test___init__(self):
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+ self.assertIsNone(self.test_context._name)
+ self.assertIsNone(self.test_context._task_id)
+
+ def test_init(self):
+ self.test_context.init(self.attrs)
+ self.assertEqual(self.test_context._name, 'foo')
+ self.assertEqual(self.test_context._task_id, '1234567890')
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+
+ self.assertEqual(self.test_context.name, 'foo-12345678')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test_init_flags_no_setup(self):
+ self.attrs['flags'] = {'no_setup': True, 'no_teardown': False}
+
+ self.test_context.init(self.attrs)
+
+ self.assertEqual(self.test_context._name, 'foo')
+ self.assertEqual(self.test_context._task_id, '1234567890')
+ self.assertTrue(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+
+ self.assertEqual(self.test_context.name, 'foo')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test_init_flags_no_teardown(self):
+ self.attrs['flags'] = {'no_setup': False, 'no_teardown': True}
+
+ self.test_context.init(self.attrs)
+
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertTrue(self.test_context._flags.no_teardown)
+
+ self.assertEqual(self.test_context.name, 'foo')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
def test__get_server(self):
- self.test_context.init(None)
+ self.test_context.init(self.attrs)
self.test_context.deploy()
result = self.test_context._get_server(None)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_heat.py b/yardstick/tests/unit/benchmark/contexts/test_heat.py
index 4348bb052..c54a7ab12 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_heat.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_heat.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
@@ -13,13 +11,16 @@ from collections import OrderedDict
from itertools import count
import logging
import os
-import uuid
import mock
import unittest
+from yardstick.benchmark.contexts import base
from yardstick.benchmark.contexts import heat
from yardstick.benchmark.contexts import model
+from yardstick.common import constants as consts
+from yardstick.common import exceptions as y_exc
+from yardstick import ssh
LOG = logging.getLogger(__name__)
@@ -33,10 +34,18 @@ class HeatContextTestCase(unittest.TestCase):
def setUp(self):
self.test_context = heat.HeatContext()
+ self.addCleanup(self._remove_contexts)
self.mock_context = mock.Mock(spec=heat.HeatContext())
+ def _remove_contexts(self):
+ if self.test_context in self.test_context.list:
+ self.test_context._delete_context()
+
def test___init__(self):
- self.assertIsNone(self.test_context.name)
+ self.assertIsNone(self.test_context._name)
+ self.assertIsNone(self.test_context._task_id)
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
self.assertIsNone(self.test_context.stack)
self.assertEqual(self.test_context.networks, OrderedDict())
self.assertEqual(self.test_context.servers, [])
@@ -50,8 +59,7 @@ class HeatContextTestCase(unittest.TestCase):
self.assertIsNone(self.test_context._user)
self.assertIsNone(self.test_context.template_file)
self.assertIsNone(self.test_context.heat_parameters)
- self.assertIsNotNone(self.test_context.key_uuid)
- self.assertIsNotNone(self.test_context.key_filename)
+ self.assertIsNone(self.test_context.key_filename)
@mock.patch('yardstick.benchmark.contexts.heat.PlacementGroup')
@mock.patch('yardstick.benchmark.contexts.heat.ServerGroup')
@@ -64,6 +72,7 @@ class HeatContextTestCase(unittest.TestCase):
networks = {'bar': {'cidr': '10.0.1.0/24'}}
servers = {'baz': {'floating_ip': True, 'placement': 'pgrp1'}}
attrs = {'name': 'foo',
+ 'task_id': '1234567890',
'placement_groups': pgs,
'server_groups': sgs,
'networks': networks,
@@ -71,9 +80,13 @@ class HeatContextTestCase(unittest.TestCase):
self.test_context.init(attrs)
- self.assertEqual(self.test_context.name, "foo")
- self.assertEqual(self.test_context.keypair_name, "foo-key")
- self.assertEqual(self.test_context.secgroup_name, "foo-secgroup")
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+ self.assertEqual(self.test_context._name, "foo")
+ self.assertEqual(self.test_context._task_id, '1234567890')
+ self.assertEqual(self.test_context.name, "foo-12345678")
+ self.assertEqual(self.test_context.keypair_name, "foo-12345678-key")
+ self.assertEqual(self.test_context.secgroup_name, "foo-12345678-secgroup")
mock_pg.assert_called_with('pgrp1', self.test_context,
pgs['pgrp1']['policy'])
@@ -90,40 +103,76 @@ class HeatContextTestCase(unittest.TestCase):
servers['baz'])
self.assertEqual(len(self.test_context.servers), 1)
- if os.path.exists(self.test_context.key_filename):
- try:
- os.remove(self.test_context.key_filename)
- os.remove(self.test_context.key_filename + ".pub")
- except OSError:
- LOG.exception("key_filename: %s",
- self.test_context.key_filename)
+ def test_init_no_name_or_task_id(self):
+ attrs = {}
+ self.assertRaises(KeyError, self.test_context.init, attrs)
+
+ def test_name(self):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.assertEqual(self.test_context.name, 'foo-12345678')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test_name_flags(self):
+ self.test_context._flags = base.Flags(
+ **{"no_setup": True, "no_teardown": True})
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+
+ self.assertEqual(self.test_context.name, 'foo')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test_init_no_setup_no_teardown(self):
+
+ attrs = {'name': 'foo',
+ 'task_id': '1234567890',
+ 'placement_groups': {},
+ 'server_groups': {},
+ 'networks': {},
+ 'servers': {},
+ 'flags': {
+ 'no_setup': True,
+ 'no_teardown': True,
+ },
+ }
+
+ self.test_context.init(attrs)
+ self.assertTrue(self.test_context._flags.no_setup)
+ self.assertTrue(self.test_context._flags.no_teardown)
@mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
def test__add_resources_to_template_no_servers(self, mock_template):
-
- self.test_context.keypair_name = "foo-key"
- self.test_context.secgroup_name = "foo-secgroup"
+ self.test_context._name = 'ctx'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context.keypair_name = "ctx-key"
+ self.test_context.secgroup_name = "ctx-secgroup"
self.test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
- netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'}
- self.mock_context.name = 'bar'
+ netattrs = {'cidr': '10.0.0.0/24', 'provider': None,
+ 'external_network': 'ext_net'}
+
self.test_context.networks = OrderedDict(
- {"fool-network": model.Network("fool-network", self.mock_context,
+ {"mynet": model.Network("mynet", self.test_context,
netattrs)})
self.test_context._add_resources_to_template(mock_template)
mock_template.add_keypair.assert_called_with(
- "foo-key",
- "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b")
- mock_template.add_security_group.assert_called_with("foo-secgroup")
-# mock_template.add_network.assert_called_with("bar-fool-network", 'physnet1', None)
+ "ctx-key",
+ "ctx-12345678")
+ mock_template.add_security_group.assert_called_with("ctx-secgroup")
+ mock_template.add_network.assert_called_with(
+ "ctx-12345678-mynet", 'physnet1', None, None, None, None)
mock_template.add_router.assert_called_with(
- "bar-fool-network-router",
+ "ctx-12345678-mynet-router",
netattrs["external_network"],
- "bar-fool-network-subnet")
+ "ctx-12345678-mynet-subnet")
mock_template.add_router_interface.assert_called_with(
- "bar-fool-network-router-if0",
- "bar-fool-network-router",
- "bar-fool-network-subnet")
+ "ctx-12345678-mynet-router-if0",
+ "ctx-12345678-mynet-router",
+ "ctx-12345678-mynet-subnet")
@mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
def test_attrs_get(self, *args):
@@ -148,23 +197,162 @@ class HeatContextTestCase(unittest.TestCase):
with self.assertRaises(AttributeError):
self.test_context.user = 'foo'
+ def test__create_new_stack(self):
+ template = mock.Mock()
+ self.test_context._create_new_stack(template)
+ template.create.assert_called_once()
+
+ def test__create_new_stack_stack_create_failed(self):
+ template = mock.Mock()
+ template.create.side_effect = y_exc.HeatTemplateError
+
+ self.assertRaises(y_exc.HeatTemplateError,
+ self.test_context._create_new_stack,
+ template)
+
+ def test__create_new_stack_keyboard_interrupt(self):
+ template = mock.Mock()
+ template.create.side_effect = KeyboardInterrupt
+ self.assertRaises(y_exc.StackCreationInterrupt,
+ self.test_context._create_new_stack,
+ template)
+
+ @mock.patch.object(os.path, 'exists', return_value=True)
+ @mock.patch.object(heat.HeatContext, '_add_resources_to_template')
+ @mock.patch.object(heat.HeatContext, '_create_new_stack')
+ def test_deploy_stack_creation_failed(self, mock_create,
+ mock_resources_template, mock_path_exists):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = 'foo-12345678'
+ mock_create.side_effect = y_exc.HeatTemplateError
+ self.assertRaises(y_exc.HeatTemplateError,
+ self.test_context.deploy)
+
+ mock_path_exists.assert_called_once()
+ mock_resources_template.assert_called_once()
+
+ @mock.patch.object(os.path, 'exists', return_value=False)
+ @mock.patch.object(ssh.SSH, 'gen_keys')
@mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
- def test_deploy(self, mock_template):
- self.test_context.name = 'foo'
+ def test_deploy(self, mock_template, mock_genkeys, mock_path_exists):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
self.test_context.template_file = '/bar/baz/some-heat-file'
self.test_context.heat_parameters = {'image': 'cirros'}
self.test_context.get_neutron_info = mock.MagicMock()
self.test_context.deploy()
- mock_template.assert_called_with('foo',
+ mock_template.assert_called_with('foo-12345678',
'/bar/baz/some-heat-file',
{'image': 'cirros'})
self.assertIsNotNone(self.test_context.stack)
+ key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.test_context._name_task_id])
+ mock_genkeys.assert_called_once_with(key_filename)
+ mock_path_exists.assert_called_once_with(key_filename)
+
+ @mock.patch.object(heat, 'HeatTemplate')
+ @mock.patch.object(os.path, 'exists', return_value=False)
+ @mock.patch.object(ssh.SSH, 'gen_keys')
+ @mock.patch.object(heat.HeatContext, '_retrieve_existing_stack')
+ @mock.patch.object(heat.HeatContext, '_create_new_stack')
+ def test_deploy_no_setup(self, mock_create_new_stack,
+ mock_retrieve_existing_stack, mock_genkeys, mock_path_exists,
+ *args):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context.template_file = '/bar/baz/some-heat-file'
+ self.test_context.heat_parameters = {'image': 'cirros'}
+ self.test_context.get_neutron_info = mock.MagicMock()
+ self.test_context._flags.no_setup = True
+ self.test_context.deploy()
+
+ mock_create_new_stack.assert_not_called()
+ mock_retrieve_existing_stack.assert_called_with(self.test_context.name)
+ self.assertIsNotNone(self.test_context.stack)
+ key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.test_context._name])
+ mock_genkeys.assert_called_once_with(key_filename)
+ mock_path_exists.assert_called_once_with(key_filename)
+
+ @mock.patch.object(heat, 'HeatTemplate')
+ @mock.patch.object(os.path, 'exists', return_value=False)
+ @mock.patch.object(ssh.SSH, 'gen_keys')
+ @mock.patch.object(heat.HeatContext, '_create_new_stack')
+ @mock.patch.object(heat.HeatContext, '_retrieve_existing_stack',
+ return_value=None)
+ def test_deploy_try_retrieve_context_does_not_exist(self,
+ mock_retrieve_stack, mock_create_new_stack, mock_genkeys,
+ mock_path_exists, *args):
+ self.test_context._name = 'demo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._flags.no_setup = True
+ self.test_context.template_file = '/bar/baz/some-heat-file'
+ self.test_context.get_neutron_info = mock.MagicMock()
+
+ self.test_context.deploy()
+
+ mock_retrieve_stack.assert_called_once_with(self.test_context._name)
+ mock_create_new_stack.assert_called()
+ key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.test_context._name])
+ mock_genkeys.assert_called_once_with(key_filename)
+ mock_path_exists.assert_called_once_with(key_filename)
+
+ @mock.patch.object(heat, 'HeatTemplate', return_value='heat_template')
+ @mock.patch.object(heat.HeatContext, '_add_resources_to_template')
+ @mock.patch.object(os.path, 'exists', return_value=False)
+ @mock.patch.object(ssh.SSH, 'gen_keys')
+ def test_deploy_ssh_key_before_adding_resources(self, mock_genkeys,
+ mock_path_exists, mock_add_resources, *args):
+ mock_manager = mock.Mock()
+ mock_manager.attach_mock(mock_add_resources,
+ '_add_resources_to_template')
+ mock_manager.attach_mock(mock_genkeys, 'gen_keys')
+ mock_manager.reset_mock()
+ self.test_context._name_task_id = 'demo-12345678'
+ self.test_context.get_neutron_info = mock.Mock()
+ with mock.patch.object(self.test_context, '_create_new_stack') as \
+ mock_create_stack, \
+ mock.patch.object(self.test_context, 'get_neutron_info') as \
+ mock_neutron_info:
+ self.test_context.deploy()
+
+ mock_neutron_info.assert_called_once()
+ mock_create_stack.assert_called_once()
+ key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.test_context._name_task_id])
+ mock_genkeys.assert_called_once_with(key_filename)
+ mock_path_exists.assert_called_with(key_filename)
+
+ mock_call_gen_keys = mock.call.gen_keys(key_filename)
+ mock_call_add_resources = (
+ mock.call._add_resources_to_template('heat_template'))
+ self.assertTrue(mock_manager.mock_calls.index(mock_call_gen_keys) <
+ mock_manager.mock_calls.index(mock_call_add_resources))
+
+ def test_check_for_context(self):
+ pass
+ # check that the context exists
def test_add_server_port(self):
network1 = mock.MagicMock()
network2 = mock.MagicMock()
- self.test_context.name = 'foo'
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
self.test_context.stack = mock.MagicMock()
self.test_context.networks = {
'a': network1,
@@ -173,15 +361,15 @@ class HeatContextTestCase(unittest.TestCase):
self.test_context.stack.outputs = {
u'b': u'10.20.30.45',
u'b-subnet_id': 1,
- u'foo-a-subnet-cidr': u'10.20.0.0/15',
- u'foo-a-subnet-gateway_ip': u'10.20.30.1',
+ u'foo-12345678-a-subnet-cidr': u'10.20.0.0/15',
+ u'foo-12345678-a-subnet-gateway_ip': u'10.20.30.1',
u'b-mac_address': u'00:01',
u'b-device_id': u'dev21',
u'b-network_id': u'net789',
u'd': u'40.30.20.15',
u'd-subnet_id': 2,
- u'foo-c-subnet-cidr': u'40.30.0.0/18',
- u'foo-c-subnet-gateway_ip': u'40.30.20.254',
+ u'foo-12345678-c-subnet-cidr': u'40.30.0.0/18',
+ u'foo-12345678-c-subnet-gateway_ip': u'40.30.20.254',
u'd-mac_address': u'00:10',
u'd-device_id': u'dev43',
u'd-network_id': u'net987',
@@ -192,6 +380,7 @@ class HeatContextTestCase(unittest.TestCase):
u'e-network_id': u'net987',
}
server = mock.MagicMock()
+ server.private_ip = None
server.ports = OrderedDict([
('a', [{'stack_name': 'b', 'port': 'port_a'}]),
('c', [{'stack_name': 'd', 'port': 'port_c'},
@@ -218,17 +407,41 @@ class HeatContextTestCase(unittest.TestCase):
self.assertEqual(len(server.interfaces), 3)
self.assertDictEqual(server.interfaces['port_a'], expected)
+ @mock.patch('yardstick.benchmark.contexts.heat.os')
+ @mock.patch.object(heat.HeatContext, '_delete_key_file')
@mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
- def test_undeploy(self, mock_template):
+ def test_undeploy(self, mock_template, mock_delete_key, *args):
self.test_context.stack = mock_template
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ # mock_os.path.exists.return_value = True
+ self.test_context.key_filename = 'foo/bar/foobar'
self.test_context.undeploy()
+ mock_delete_key.assert_called()
self.assertTrue(mock_template.delete.called)
@mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test_undeploy_no_teardown(self, mock_template):
+ self.test_context.stack = mock_template
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._flags.no_teardown = True
+ self.test_context.undeploy()
+
+ mock_template.delete.assert_not_called()
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
@mock.patch('yardstick.benchmark.contexts.heat.os')
def test_undeploy_key_filename(self, mock_os, mock_template):
self.test_context.stack = mock_template
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id)
mock_os.path.exists.return_value = True
+ self.test_context.key_filename = 'foo/bar/foobar'
self.assertIsNone(self.test_context.undeploy())
@mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
@@ -249,24 +462,27 @@ class HeatContextTestCase(unittest.TestCase):
baz3_server.public_ip = '127.0.0.3'
baz3_server.context.user = 'zab'
- self.test_context.name = 'bar'
+ self.test_context._name = 'bar'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
self.test_context._user = 'bot'
self.test_context.stack = mock.Mock()
self.test_context.stack.outputs = {
'private_ip': '10.0.0.1',
'public_ip': '127.0.0.1',
}
- self.test_context.key_uuid = uuid.uuid4()
self.test_context._server_map = {
'baz3': baz3_server,
'foo2': foo2_server,
}
attr_name = {
- 'name': 'foo.bar',
+ 'name': 'foo.bar-12345678',
'private_ip_attr': 'private_ip',
'public_ip_attr': 'public_ip',
}
+ self.test_context.key_uuid = 'foo-42'
result = self.test_context._get_server(attr_name)
self.assertEqual(result['user'], 'bot')
self.assertEqual(result['ip'], '127.0.0.1')
@@ -288,22 +504,26 @@ class HeatContextTestCase(unittest.TestCase):
baz3_server.public_ip = '127.0.0.3'
baz3_server.context.user = 'zab'
- self.test_context.name = 'bar'
+ self.test_context._name = 'bar'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
self.test_context._user = 'bot'
self.test_context.stack = mock.Mock()
self.test_context.stack.outputs = {
'private_ip': '10.0.0.1',
'public_ip': '127.0.0.1',
}
- self.test_context.key_uuid = uuid.uuid4()
self.test_context._server_map = {
'baz3': baz3_server,
'foo2': foo2_server,
}
attr_name = {
- 'name': 'foo.bar',
+ 'name': 'foo.bar-12345678',
}
+
+ self.test_context.key_uuid = 'foo-42'
result = self.test_context._get_server(attr_name)
self.assertEqual(result['user'], 'bot')
# no private ip attr mapping in the map results in None value in the result
@@ -327,13 +547,14 @@ class HeatContextTestCase(unittest.TestCase):
baz3_server.public_ip = None
baz3_server.context.user = 'zab'
- self.test_context.name = 'bar1'
+ self.test_context._name = 'bar1'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = 'bar1-12345678'
self.test_context.stack = mock.Mock()
self.test_context.stack.outputs = {
'private_ip': '10.0.0.1',
'public_ip': '127.0.0.1',
}
- self.test_context.key_uuid = uuid.uuid4()
self.test_context.generate_routing_table = mock.MagicMock(return_value=[])
self.test_context._server_map = {
@@ -365,19 +586,19 @@ class HeatContextTestCase(unittest.TestCase):
baz3_server.public_ip = None
baz3_server.context.user = 'zab'
- self.test_context.name = 'bar1'
+ self.test_context._name = 'bar1'
self.test_context.stack = mock.Mock()
self.test_context.stack.outputs = {
'private_ip': '10.0.0.1',
'public_ip': '127.0.0.1',
}
- self.test_context.key_uuid = uuid.uuid4()
self.test_context._server_map = {
'baz3': baz3_server,
'foo2': foo2_server,
'wow4': None,
}
+ self.test_context.key_uuid = 'foo-42'
attr_name = 'wow4'
result = self.test_context._get_server(attr_name)
self.assertIsNone(result)
@@ -398,18 +619,21 @@ class HeatContextTestCase(unittest.TestCase):
baz3_server.public_ip = None
baz3_server.context.user = 'zab'
- self.test_context.name = 'bar1'
+ self.test_context._name = 'bar1'
+ self.test_context._task_id = '1235467890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
self.test_context.stack = mock.Mock()
self.test_context.stack.outputs = {
'private_ip': '10.0.0.1',
'public_ip': '127.0.0.1',
}
- self.test_context.key_uuid = uuid.uuid4()
self.test_context._server_map = {
'baz3': baz3_server,
'foo2': foo2_server,
}
+ self.test_context.key_uuid = 'foo-42'
attr_name = {
'name': 'foo.wow4',
'private_ip_attr': 'private_ip',
@@ -434,18 +658,18 @@ class HeatContextTestCase(unittest.TestCase):
baz3_server.public_ip = None
baz3_server.context.user = 'zab'
- self.mock_context.name = 'bar1'
+ self.mock_context._name = 'bar1'
self.test_context.stack = mock.Mock()
self.mock_context.stack.outputs = {
'private_ip': '10.0.0.1',
'public_ip': '127.0.0.1',
}
- self.mock_context.key_uuid = uuid.uuid4()
self.mock_context._server_map = {
'baz3': baz3_server,
'foo2': foo2_server,
}
+ self.test_context.key_uuid = 'foo-42'
attr_name = 'foo.wow4'
result = self.test_context._get_server(attr_name)
self.assertIsNone(result)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py b/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
index e149e0d18..22153e4e8 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
@@ -10,13 +10,13 @@
import mock
import unittest
-from yardstick.benchmark.contexts.base import Context
from yardstick.benchmark.contexts import kubernetes
context_cfg = {
'type': 'Kubernetes',
'name': 'k8s',
+ 'task_id': '1234567890',
'servers': {
'host': {
'image': 'openretriever/yardstick',
@@ -40,11 +40,12 @@ class KubernetesTestCase(unittest.TestCase):
def setUp(self):
self.k8s_context = kubernetes.KubernetesContext()
+ self.addCleanup(self._remove_contexts)
self.k8s_context.init(context_cfg)
- def tearDown(self):
- # clear kubernetes contexts from global list so we don't break other tests
- Context.list = []
+ def _remove_contexts(self):
+ if self.k8s_context in self.k8s_context.list:
+ self.k8s_context._delete_context()
@mock.patch.object(kubernetes.KubernetesContext, '_delete_services')
@mock.patch.object(kubernetes.KubernetesContext, '_delete_ssh_key')
@@ -166,11 +167,3 @@ class KubernetesTestCase(unittest.TestCase):
def test_delete_services(self, mock_delete):
self.k8s_context._delete_services()
self.assertTrue(mock_delete.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/contexts/test_model.py b/yardstick/tests/unit/benchmark/contexts/test_model.py
index 28011d494..20cc00b4e 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_model.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_model.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
@@ -241,6 +239,7 @@ class ServerTestCase(unittest.TestCase):
mock_network.vnic_type = 'normal'
mock_network.subnet_stack_name = 'some-network-stack-subnet'
mock_network.provider = 'sriov'
+ mock_network.net_flags = {}
mock_network.external_network = 'ext_net'
mock_network.router = model.Router('some-router', 'some-network', self.mock_context,
'ext_net')
@@ -250,9 +249,7 @@ class ServerTestCase(unittest.TestCase):
mock_template.add_port.assert_called_with(
'some-server-some-network-port',
- mock_network.stack_name,
- mock_network.subnet_stack_name,
- mock_network.vnic_type,
+ mock_network,
sec_group_id=self.mock_context.secgroup_name,
provider=mock_network.provider,
allowed_address_pairs=mock_network.allowed_address_pairs)
@@ -513,6 +510,7 @@ class ServerTestCase(unittest.TestCase):
mock_network = mock.Mock()
mock_network.allowed_address_pairs = ["1", "2"]
mock_network.vnic_type = 'normal'
+ mock_network.net_flags = {}
mock_network.configure_mock(name='some-network', stack_name='some-network-stack',
subnet_stack_name='some-network-stack-subnet',
provider='some-provider')
@@ -522,9 +520,7 @@ class ServerTestCase(unittest.TestCase):
mock_template.add_port.assert_called_with(
'ServerFlavor-2-some-network-port',
- mock_network.stack_name,
- mock_network.subnet_stack_name,
- mock_network.vnic_type,
+ mock_network,
provider=mock_network.provider,
sec_group_id=self.mock_context.secgroup_name,
allowed_address_pairs=mock_network.allowed_address_pairs)
@@ -556,6 +552,7 @@ class ServerTestCase(unittest.TestCase):
mock_network.name = 'some-network'
mock_network.stack_name = 'some-network-stack'
mock_network.subnet_stack_name = 'some-network-stack-subnet'
+ mock_network.net_flags = {}
test_server._add_instance(mock_template, 'ServerFlavor-3',
[mock_network], 'hints')
diff --git a/yardstick/tests/unit/benchmark/contexts/test_node.py b/yardstick/tests/unit/benchmark/contexts/test_node.py
index 5329d30f4..9761f6d53 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_node.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_node.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015-2017 Huawei Technologies Co.,Ltd and others.
#
@@ -9,9 +7,6 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-# Unittest for yardstick.benchmark.contexts.node
-
-from __future__ import absolute_import
import os
import unittest
import errno
@@ -21,10 +16,6 @@ from yardstick.common import constants as consts
from yardstick.benchmark.contexts import node
-# pylint: disable=unused-argument
-# disable this for now because I keep forgetting mock patch arg ordering
-
-
class NodeContextTestCase(unittest.TestCase):
PREFIX = 'yardstick.benchmark.contexts.node'
@@ -34,7 +25,17 @@ class NodeContextTestCase(unittest.TestCase):
def setUp(self):
self.test_context = node.NodeContext()
+ self.addCleanup(self._remove_contexts)
self.os_path_join = os.path.join
+ self.attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ 'file': self._get_file_abspath(self.NODES_SAMPLE)
+ }
+
+ def _remove_contexts(self):
+ if self.test_context in self.test_context.list:
+ self.test_context._delete_context()
def _get_file_abspath(self, filename):
curr_path = os.path.dirname(os.path.abspath(__file__))
@@ -42,7 +43,7 @@ class NodeContextTestCase(unittest.TestCase):
return file_path
def test___init__(self):
- self.assertIsNone(self.test_context.name)
+ self.assertIsNone(self.test_context._name)
self.assertIsNone(self.test_context.file_path)
self.assertEqual(self.test_context.nodes, [])
self.assertEqual(self.test_context.controllers, [])
@@ -74,6 +75,7 @@ class NodeContextTestCase(unittest.TestCase):
attrs = {
'name': 'foo',
+ 'task_id': '1234567890',
'file': error_path,
}
read_mock.side_effect = IOError(errno.EBUSY, 'busy')
@@ -97,37 +99,19 @@ class NodeContextTestCase(unittest.TestCase):
self.assertEqual(str(raised.exception), str(read_mock.side_effect))
def test_read_config_file(self):
-
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SAMPLE)
- }
-
- self.test_context.init(attrs)
+ self.test_context.init(self.attrs)
self.assertIsNotNone(self.test_context.read_config_file())
def test__dispatch_script(self):
-
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SAMPLE)
- }
-
- self.test_context.init(attrs)
+ self.test_context.init(self.attrs)
self.test_context.env = {'bash': [{'script': 'dummy'}]}
self.test_context._execute_script = mock.Mock()
self.assertEqual(self.test_context._dispatch_script('bash'), None)
def test__dispatch_ansible(self):
-
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SAMPLE)
- }
-
- self.test_context.init(attrs)
+ self.test_context.init(self.attrs)
self.test_context.env = {'ansible': [{'script': 'dummy'}]}
self.test_context._do_ansible_job = mock.Mock()
@@ -136,19 +120,13 @@ class NodeContextTestCase(unittest.TestCase):
self.assertEqual(self.test_context._dispatch_ansible('ansible'), None)
@mock.patch("{}.AnsibleCommon".format(PREFIX))
- def test__do_ansible_job(self, mock_ansible):
- self.assertEqual(None, self.test_context._do_ansible_job('dummy'))
-
- def test_successful_init(self):
-
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SAMPLE)
- }
+ def test__do_ansible_job(self, *args):
+ self.assertIsNone(self.test_context._do_ansible_job('dummy'))
- self.test_context.init(attrs)
+ def test_init(self):
+ self.test_context.init(self.attrs)
- self.assertEqual(self.test_context.name, "foo")
+ self.assertEqual(self.test_context.name, "foo-12345678")
self.assertEqual(len(self.test_context.nodes), 4)
self.assertEqual(len(self.test_context.controllers), 2)
self.assertEqual(len(self.test_context.computes), 1)
@@ -156,81 +134,44 @@ class NodeContextTestCase(unittest.TestCase):
self.assertEqual(len(self.test_context.baremetals), 1)
self.assertEqual(self.test_context.baremetals[0]["name"], "node4")
- def test__get_server_with_dic_attr_name(self):
-
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SAMPLE)
- }
-
- self.test_context.init(attrs)
-
- attr_name = {'name': 'foo.bar'}
- result = self.test_context._get_server(attr_name)
+ def test__get_server_with_dict_attr_name(self):
+ self.test_context.init(self.attrs)
+ result = self.test_context._get_server({'name': 'node1.foo-12345678'})
- self.assertEqual(result, None)
+ self.assertIsNone(result, None)
def test__get_server_not_found(self):
+ self.test_context.init(self.attrs)
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SAMPLE)
- }
-
- self.test_context.init(attrs)
-
- attr_name = 'bar.foo'
- result = self.test_context._get_server(attr_name)
-
- self.assertEqual(result, None)
+ self.assertIsNone(self.test_context._get_server('bar.foo-12345678'))
def test__get_server_mismatch(self):
+ self.test_context.init(self.attrs)
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SAMPLE)
- }
-
- self.test_context.init(attrs)
-
- attr_name = 'bar.foo1'
- result = self.test_context._get_server(attr_name)
-
- self.assertEqual(result, None)
+ self.assertIsNone(self.test_context._get_server('bar.foo1'))
def test__get_server_duplicate(self):
+ self.attrs['file'] = self._get_file_abspath(
+ self.NODES_DUPLICATE_SAMPLE)
+ self.test_context.init(self.attrs)
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
- }
-
- self.test_context.init(attrs)
-
- attr_name = 'node1.foo'
with self.assertRaises(ValueError):
- self.test_context._get_server(attr_name)
+ self.test_context._get_server('node1.foo-12345678')
def test__get_server_found(self):
+ self.test_context.init(self.attrs)
- attrs = {
- 'name': 'foo',
- 'file': self._get_file_abspath(self.NODES_SAMPLE)
- }
-
- self.test_context.init(attrs)
-
- attr_name = 'node1.foo'
- result = self.test_context._get_server(attr_name)
+ result = self.test_context._get_server('node1.foo-12345678')
self.assertEqual(result['ip'], '10.229.47.137')
- self.assertEqual(result['name'], 'node1.foo')
+ self.assertEqual(result['name'], 'node1.foo-12345678')
self.assertEqual(result['user'], 'root')
self.assertEqual(result['key_filename'], '/root/.yardstick_key')
@mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
def test_deploy(self, dispatch_script_mock):
obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
obj.env = {
'type': 'script'
}
@@ -240,6 +181,7 @@ class NodeContextTestCase(unittest.TestCase):
@mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
def test_deploy_anisible(self, dispatch_ansible_mock):
obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
obj.env = {
'type': 'ansible'
}
@@ -268,6 +210,7 @@ class NodeContextTestCase(unittest.TestCase):
@mock.patch('{}.ssh.SSH.execute'.format(PREFIX))
def test_execute_remote_script(self, execute_mock, put_file_mock):
obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
obj.env = {'prefix': 'yardstick.benchmark.scenarios.compute'}
node_name_args = 'node5'
obj.nodes = [{
@@ -288,14 +231,18 @@ class NodeContextTestCase(unittest.TestCase):
def test_execute_script_local(self, local_execute_mock):
node_name = 'local'
info = {}
- node.NodeContext()._execute_script(node_name, info)
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj._execute_script(node_name, info)
self.assertTrue(local_execute_mock.called)
@mock.patch('{}.NodeContext._execute_remote_script'.format(PREFIX))
def test_execute_script_remote(self, remote_execute_mock):
node_name = 'node5'
info = {}
- node.NodeContext()._execute_script(node_name, info)
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj._execute_script(node_name, info)
self.assertTrue(remote_execute_mock.called)
def test_get_script(self):
@@ -303,13 +250,16 @@ class NodeContextTestCase(unittest.TestCase):
info_args = {
'script': script_args
}
- script, options = node.NodeContext()._get_script(info_args)
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ script, options = obj._get_script(info_args)
self.assertEqual(script_args, script)
self.assertEqual('', options)
def test_node_info(self):
node_name_args = 'node5'
obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
obj.nodes = [{'name': node_name_args, 'check': node_name_args}]
node_info = obj._get_node_info(node_name_args)
self.assertEqual(node_info.get('check'), node_name_args)
@@ -318,6 +268,7 @@ class NodeContextTestCase(unittest.TestCase):
def test_get_client(self, wait_mock):
node_name_args = 'node5'
obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
obj.nodes = [{
'name': node_name_args,
'user': 'ubuntu',
@@ -328,26 +279,38 @@ class NodeContextTestCase(unittest.TestCase):
self.assertTrue(wait_mock.called)
def test_get_server(self):
- self.test_context.name = 'vnf1'
- self.test_context.nodes = [{'name': 'my', 'value': 100}]
+ self.test_context.init(self.attrs)
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.assertEqual('foo-12345678', self.test_context.name)
+ self.assertIsNotNone(self.test_context._task_id)
- with self.assertRaises(ValueError):
- self.test_context.get_server('my.vnf2')
+ result = self.test_context.get_server('node1.foo-12345678')
- expected = {'name': 'my.vnf1', 'value': 100, 'interfaces': {}}
- result = self.test_context.get_server('my.vnf1')
- self.assertDictEqual(result, expected)
+ self.assertEqual(result['ip'], '10.229.47.137')
+ self.assertEqual(result['name'], 'node1.foo-12345678')
+ self.assertEqual(result['user'], 'root')
+ self.assertEqual(result['key_filename'], '/root/.yardstick_key')
+
+ def test_get_server_server_not_in_context(self):
+ self.test_context.init(self.attrs)
+
+ with self.assertRaises(ValueError):
+ self.test_context.get_server('my2.foo-12345678')
def test_get_context_from_server(self):
- self.test_context.name = 'vnf1'
+ self.test_context._name = 'vnf1'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
self.test_context.nodes = [{'name': 'my', 'value': 100}]
self.test_context.attrs = {'attr1': 200}
- with self.assertRaises(ValueError):
- self.test_context.get_context_from_server('my.vnf2')
-
- result = self.test_context.get_context_from_server('my.vnf1')
- self.assertIs(result, self.test_context)
+ self.assertIs(
+ self.test_context.get_context_from_server('my.vnf1-12345678'),
+ self.test_context)
# TODO: Split this into more granular tests
def test__get_network(self):
@@ -393,11 +356,3 @@ class NodeContextTestCase(unittest.TestCase):
expected = network1
result = self.test_context._get_network(attr_name)
self.assertDictEqual(result, expected)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/core/test_report.py b/yardstick/tests/unit/benchmark/core/test_report.py
index 3d9a503b6..a684ad750 100644
--- a/yardstick/tests/unit/benchmark/core/test_report.py
+++ b/yardstick/tests/unit/benchmark/core/test_report.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2017 Rajesh Kudaka.
#
diff --git a/yardstick/tests/unit/benchmark/core/test_task.py b/yardstick/tests/unit/benchmark/core/test_task.py
index ee00d8826..82a90b172 100644
--- a/yardstick/tests/unit/benchmark/core/test_task.py
+++ b/yardstick/tests/unit/benchmark/core/test_task.py
@@ -7,13 +7,22 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
+import copy
+import io
import os
+import sys
import mock
+import six
import unittest
+import uuid
+from yardstick.benchmark.contexts import dummy
from yardstick.benchmark.core import task
from yardstick.common import constants as consts
+from yardstick.common import exceptions
+from yardstick.common import task_template
+from yardstick.common import utils
class TaskTestCase(unittest.TestCase):
@@ -57,7 +66,7 @@ class TaskTestCase(unittest.TestCase):
mock_dispatcher.get = mock.MagicMock(return_value=[dispatcher1,
dispatcher2])
- self.assertEqual(None, t._do_output(output_config, {}))
+ self.assertIsNone(t._do_output(output_config, {}))
@mock.patch.object(task, 'Context')
def test_parse_networks_from_nodes(self, mock_context):
@@ -174,7 +183,6 @@ class TaskTestCase(unittest.TestCase):
'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
self.assertEqual(task_files[1], self.change_to_abspath(
'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
-
self.assertIsNone(task_args[0])
self.assertIsNone(task_args[1])
self.assertIsNone(task_args_fnames[0])
@@ -256,30 +264,37 @@ class TaskTestCase(unittest.TestCase):
actual_result = t._parse_options(options)
self.assertEqual(expected_result, actual_result)
+ def test_parse_options_no_teardown(self):
+ options = {
+ 'openstack': {
+ 'EXTERNAL_NETWORK': '$network'
+ },
+ 'nodes': ['node1', '$node'],
+ 'host': '$host',
+ 'contexts' : {'name': "my-context",
+ 'no_teardown': True}
+ }
- def test_change_server_name_host_str(self):
- scenario = {'host': 'demo'}
- suffix = '-8'
- task.change_server_name(scenario, suffix)
- self.assertEqual('demo-8', scenario['host'])
-
- def test_change_server_name_host_dict(self):
- scenario = {'host': {'name': 'demo'}}
- suffix = '-8'
- task.change_server_name(scenario, suffix)
- self.assertEqual('demo-8', scenario['host']['name'])
+ t = task.Task()
+ t.outputs = {
+ 'network': 'ext-net',
+ 'node': 'node2',
+ 'host': 'server.yardstick'
+ }
- def test_change_server_name_target_str(self):
- scenario = {'target': 'demo'}
- suffix = '-8'
- task.change_server_name(scenario, suffix)
- self.assertEqual('demo-8', scenario['target'])
+ expected_result = {
+ 'openstack': {
+ 'EXTERNAL_NETWORK': 'ext-net'
+ },
+ 'nodes': ['node1', 'node2'],
+ 'host': 'server.yardstick',
+ 'contexts': {'name': 'my-context',
+ 'no_teardown': True,
+ }
+ }
- def test_change_server_name_target_dict(self):
- scenario = {'target': {'name': 'demo'}}
- suffix = '-8'
- task.change_server_name(scenario, suffix)
- self.assertEqual('demo-8', scenario['target']['name'])
+ actual_result = t._parse_options(options)
+ self.assertEqual(expected_result, actual_result)
@mock.patch('six.moves.builtins.open', side_effect=mock.mock_open())
@mock.patch.object(task, 'utils')
@@ -299,9 +314,219 @@ class TaskTestCase(unittest.TestCase):
return os.path.join(consts.YARDSTICK_ROOT_PATH, filepath)
-def main():
- unittest.main()
+class TaskParserTestCase(unittest.TestCase):
+
+ TASK = """
+{% set value1 = value1 or 'var1' %}
+{% set value2 = value2 or 'var2' %}
+key1: {{ value1 }}
+key2:
+ - {{ value2 }}"""
+ TASK_RENDERED_1 = u"""
-if __name__ == '__main__':
- main()
+
+key1: var1
+key2:
+ - var2"""
+
+ TASK_RENDERED_2 = u"""
+
+
+key1: var3
+key2:
+ - var4"""
+
+ def setUp(self):
+ self.parser = task.TaskParser('fake/path')
+ self.scenario = {
+ 'host': 'athena.demo',
+ 'target': 'kratos.demo',
+ 'targets': [
+ 'ares.demo', 'mars.demo'
+ ],
+ 'options': {
+ 'server_name': {
+ 'host': 'jupiter.demo',
+ 'target': 'saturn.demo',
+ },
+ },
+ 'nodes': {
+ 'tg__0': 'tg_0.demo',
+ 'vnf__0': 'vnf_0.demo',
+ }
+ }
+
+ def test__change_node_names(self):
+
+ ctx_attrs = {
+ 'name': 'demo',
+ 'task_id': '1234567890',
+ 'servers': [
+ 'athena', 'kratos',
+ 'ares', 'mars',
+ 'jupiter', 'saturn',
+ 'tg_0', 'vnf_0'
+ ]
+ }
+
+ my_context = dummy.DummyContext()
+ my_context.init(ctx_attrs)
+
+ expected_scenario = {
+ 'host': 'athena.demo-12345678',
+ 'target': 'kratos.demo-12345678',
+ 'targets': [
+ 'ares.demo-12345678', 'mars.demo-12345678'
+ ],
+ 'options': {
+ 'server_name': {
+ 'host': 'jupiter.demo-12345678',
+ 'target': 'saturn.demo-12345678',
+ },
+ },
+ 'nodes': {
+ 'tg__0': 'tg_0.demo-12345678',
+ 'vnf__0': 'vnf_0.demo-12345678',
+ }
+ }
+
+ scenario = copy.deepcopy(self.scenario)
+
+ self.parser._change_node_names(scenario, [my_context])
+ self.assertEqual(scenario, expected_scenario)
+
+ def test__change_node_names_context_not_found(self):
+ scenario = copy.deepcopy(self.scenario)
+ self.assertRaises(exceptions.ScenarioConfigContextNameNotFound,
+ self.parser._change_node_names,
+ scenario, [])
+
+ def test__change_node_names_context_name_unchanged(self):
+ ctx_attrs = {
+ 'name': 'demo',
+ 'task_id': '1234567890',
+ 'flags': {
+ 'no_setup': True,
+ 'no_teardown': True
+ }
+ }
+
+ my_context = dummy.DummyContext()
+ my_context.init(ctx_attrs)
+
+ scenario = copy.deepcopy(self.scenario)
+ expected_scenario = copy.deepcopy(self.scenario)
+
+ self.parser._change_node_names(scenario, [my_context])
+ self.assertEqual(scenario, expected_scenario)
+
+ def test__parse_tasks(self):
+ task_obj = task.Task()
+ _uuid = uuid.uuid4()
+ task_obj.task_id = _uuid
+ task_files = ['/directory/task_file_name.yml']
+ mock_parser = mock.Mock()
+ mock_parser.parse_task.return_value = {'rendered': 'File content'}
+ mock_args = mock.Mock()
+ mock_args.render_only = False
+
+ tasks = task_obj._parse_tasks(mock_parser, task_files, mock_args,
+ ['arg1'], ['file_arg1'])
+ self.assertEqual(
+ [{'rendered': 'File content', 'case_name': 'task_file_name'}],
+ tasks)
+ mock_parser.parse_task.assert_called_once_with(
+ _uuid, 'arg1', 'file_arg1')
+
+ @mock.patch.object(sys, 'exit')
+ @mock.patch.object(utils, 'write_file')
+ @mock.patch.object(utils, 'makedirs')
+ def test__parse_tasks_render_only(self, mock_makedirs, mock_write_file,
+ mock_exit):
+ task_obj = task.Task()
+ _uuid = uuid.uuid4()
+ task_obj.task_id = _uuid
+ task_files = ['/directory/task_file_name.yml']
+ mock_parser = mock.Mock()
+ mock_parser.parse_task.return_value = {'rendered': 'File content'}
+ mock_args = mock.Mock()
+ mock_args.render_only = '/output_directory'
+
+ task_obj._parse_tasks(mock_parser, task_files, mock_args,
+ ['arg1'], ['file_arg1'])
+ mock_makedirs.assert_called_once_with('/output_directory')
+ mock_write_file.assert_called_once_with(
+ '/output_directory/000-task_file_name.yml', 'File content')
+ mock_exit.assert_called_once_with(0)
+
+ def test__render_task_no_args(self):
+ task_parser = task.TaskParser('task_file')
+ task_str = io.StringIO(six.text_type(self.TASK))
+ with mock.patch.object(six.moves.builtins, 'open',
+ return_value=task_str) as mock_open:
+ parsed, rendered = task_parser._render_task(None, None)
+
+ self.assertEqual(self.TASK_RENDERED_1, rendered)
+ self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
+ mock_open.assert_called_once_with('task_file')
+
+ def test__render_task_arguments(self):
+ task_parser = task.TaskParser('task_file')
+ task_str = io.StringIO(six.text_type(self.TASK))
+ with mock.patch.object(six.moves.builtins, 'open',
+ return_value=task_str) as mock_open:
+ parsed, rendered = task_parser._render_task('value1: "var1"', None)
+
+ self.assertEqual(self.TASK_RENDERED_1, rendered)
+ self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
+ mock_open.assert_called_once_with('task_file')
+
+ def test__render_task_file_arguments(self):
+ task_parser = task.TaskParser('task_file')
+ with mock.patch.object(six.moves.builtins, 'open') as mock_open:
+ mock_open.side_effect = (
+ io.StringIO(six.text_type('value2: var4')),
+ io.StringIO(six.text_type(self.TASK))
+ )
+ parsed, rendered = task_parser._render_task('value1: "var3"',
+ 'args_file')
+
+ self.assertEqual(self.TASK_RENDERED_2, rendered)
+ self.assertEqual({'key1': 'var3', 'key2': ['var4']}, parsed)
+ mock_open.assert_has_calls([mock.call('args_file'),
+ mock.call('task_file')])
+
+ def test__render_task_error_arguments(self):
+ with self.assertRaises(exceptions.TaskRenderArgumentError):
+ task.TaskParser('task_file')._render_task('value1="var3"', None)
+
+ def test__render_task_error_task_file(self):
+ task_parser = task.TaskParser('task_file')
+ with mock.patch.object(six.moves.builtins, 'open') as mock_open:
+ mock_open.side_effect = (
+ io.StringIO(six.text_type('value2: var4')),
+ IOError()
+ )
+ with self.assertRaises(exceptions.TaskReadError):
+ task_parser._render_task('value1: "var3"', 'args_file')
+
+ mock_open.assert_has_calls([mock.call('args_file'),
+ mock.call('task_file')])
+
+ def test__render_task_render_error(self):
+ task_parser = task.TaskParser('task_file')
+ with mock.patch.object(six.moves.builtins, 'open') as mock_open, \
+ mock.patch.object(task_template.TaskTemplate, 'render',
+ side_effect=TypeError) as mock_render:
+ mock_open.side_effect = (
+ io.StringIO(six.text_type('value2: var4')),
+ io.StringIO(six.text_type(self.TASK))
+ )
+ with self.assertRaises(exceptions.TaskRenderError):
+ task_parser._render_task('value1: "var3"', 'args_file')
+
+ mock_open.assert_has_calls([mock.call('args_file'),
+ mock.call('task_file')])
+ mock_render.assert_has_calls(
+ [mock.call(self.TASK, value1='var3', value2='var4')])
diff --git a/yardstick/tests/unit/benchmark/core/test_testcase.py b/yardstick/tests/unit/benchmark/core/test_testcase.py
index 1f5aad75e..119465887 100644
--- a/yardstick/tests/unit/benchmark/core/test_testcase.py
+++ b/yardstick/tests/unit/benchmark/core/test_testcase.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
@@ -35,11 +33,3 @@ class TestcaseUT(unittest.TestCase):
casename = Arg()
result = t.show(casename)
self.assertTrue(result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/runner/test_base.py b/yardstick/tests/unit/benchmark/runner/test_base.py
index 59739c54f..727207f5a 100644
--- a/yardstick/tests/unit/benchmark/runner/test_base.py
+++ b/yardstick/tests/unit/benchmark/runner/test_base.py
@@ -90,11 +90,3 @@ class RunnerTestCase(unittest.TestCase):
with self.assertRaises(NotImplementedError):
runner._run_benchmark(mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock())
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/runner/test_search.py b/yardstick/tests/unit/benchmark/runner/test_search.py
index 1bc07448d..4e5b4fe77 100644
--- a/yardstick/tests/unit/benchmark/runner/test_search.py
+++ b/yardstick/tests/unit/benchmark/runner/test_search.py
@@ -17,15 +17,8 @@ import time
import mock
import unittest
-from yardstick.tests.unit import STL_MOCKS
-
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
- from yardstick.benchmark.runners.search import SearchRunner
- from yardstick.benchmark.runners.search import SearchRunnerHelper
+from yardstick.benchmark.runners.search import SearchRunner
+from yardstick.benchmark.runners.search import SearchRunnerHelper
class TestSearchRunnerHelper(unittest.TestCase):
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py
index f0921c0f6..d5c95a086 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py
index 612b5a662..c1b3c0d72 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Juan Qiu and others
# juan_ qiu@tongji.edu.cn
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py
index 0a8e8322a..2e9f1c6bb 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py
index 9bc04ebf4..ce972779d 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py
@@ -113,7 +113,3 @@ class BaseMonitorTestCase(unittest.TestCase):
except Exception: # pylint: disable=broad-except
pass
self.assertIsNone(cls)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py
index ae74d241c..d4df02819 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huan Li and others
# lihuansse@tongji.edu.cn
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_director.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_director.py
index 72ce7b0d5..e49544e1c 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_director.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_director.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huan Li and others
# lihuansse@tongji.edu.cn
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py
index 7022ea678..5907c8b6a 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huan Li and others
# lihuansse@tongji.edu.cn
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py
index 0d61d9b15..e9c680257 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huan Li and others
# lihuansse@tongji.edu.cn
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py
index 41ce5445e..a6d2ca398 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py
index a965f7f64..2b09c0385 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huan Li and others
# lihuansse@tongji.edu.cn
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py
index 234adcb6e..324a5bda2 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huan Li and others
# lihuansse@tongji.edu.cn
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_util.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_util.py
index 548efe91b..4d97585d4 100644
--- a/yardstick/tests/unit/benchmark/scenarios/availability/test_util.py
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_util.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Kanglin Yin and others
# 14_ykl@tongji.edu.cn
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py
index b0ddfc6b4..6f66c30f9 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py
index 7b9a5ad4a..4bef589f4 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py
index 840ac7885..da6e6a22e 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py
index 51ffd2488..f24ec24ec 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
#
@@ -166,10 +164,3 @@ class CyclictestTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, c.run, result)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
index b3152d12c..9640ce000 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
@@ -193,10 +191,3 @@ class LmbenchTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, l.run, self.result)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py
index ebae9993d..8213d4490 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
#
@@ -109,11 +107,3 @@ class MEMLoadTestCase(unittest.TestCase):
with open(output) as f:
sample_output = f.read()
return sample_output
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py
index 680f6ad65..875301729 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py
index 26a26cdf7..03003d01f 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
#
@@ -157,11 +155,3 @@ class QemuMigrateTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, q.run, result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py
index 4f71fbb36..dcc0e810d 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
#
@@ -235,10 +233,3 @@ class RamspeedTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'No such type_id: 30 for \
Ramspeed scenario')
self.assertRaises(RuntimeError, r.run, self.result)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py
index 74612d7b6..643e1eae2 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
#
@@ -75,11 +73,3 @@ class SpecCPUTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, s.run, self.result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py
index c428e1fb8..74ef576b6 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
#
@@ -76,9 +74,3 @@ class SpecCPUforVMTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, s.run, self.result)
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py
index fec355b45..6339a2dcd 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
#
@@ -162,10 +160,3 @@ class UnixbenchTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, u.run, result)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py b/yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py
index bc5131806..875302da8 100644
--- a/yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py
+++ b/yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py
index bda07f723..98d967f2b 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py
@@ -55,11 +55,3 @@ class AddMemoryLoadTestCase(unittest.TestCase):
obj = AddMemoryLoad(scenario_cfg, context_cfg)
obj.run({})
self.assertTrue(mock_from_node.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py
index 25b911d5e..a61195f66 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py
@@ -24,11 +24,3 @@ class AttachVolumeTestCase(unittest.TestCase):
obj = AttachVolume(args, {})
obj.run({})
self.assertTrue(mock_attach_server_volume.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py
index 7188c29d5..a48353a4f 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py
@@ -76,11 +76,3 @@ class CheckConnectivityTestCase(unittest.TestCase):
obj.setup()
mock_ssh.SSH.execute.return_value = (0, '100', '')
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py
index f983f9c5b..a50e752fa 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py
@@ -74,11 +74,3 @@ class CheckNumaInfoTestCase(unittest.TestCase):
obj = CheckNumaInfo(scenario_cfg, {})
status = obj._check_vm2_status(info1, info2)
self.assertFalse(status)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py
index 5a40e7d8f..7a2324b3d 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py
@@ -33,10 +33,3 @@ class CheckValueTestCase(unittest.TestCase):
obj = CheckValue(scenario_cfg, {})
self.assertRaises(AssertionError, obj.run, self.result)
self.assertEqual({}, self.result)
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py
index 036ae952d..663ca5d5b 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py
@@ -27,11 +27,3 @@ class CreateFlavorTestCase(unittest.TestCase):
obj = CreateFlavor(args, {})
obj.run({})
self.assertTrue(mock_create_flavor.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py
index b26957979..639cf2906 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py
@@ -33,11 +33,3 @@ class CreateImageTestCase(unittest.TestCase):
obj.run({})
mock_create_image.assert_called_once()
mock_get_glance_client.assert_called_once()
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py
index 10e351b5e..1c3d6cebc 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py
@@ -25,11 +25,3 @@ class CreateKeypairTestCase(unittest.TestCase):
obj = create_keypair.CreateKeypair(args, {})
obj.run({})
mock_op_utils.create_keypair.assert_called_once()
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py
index e0382851f..ad4adeeb2 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py
@@ -28,11 +28,3 @@ class CreateNetworkTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
self.assertTrue(mock_create_neutron_net.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py
index 0f15058da..9a1611c3d 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py
@@ -25,11 +25,3 @@ class CreatePortTestCase(unittest.TestCase):
obj = CreatePort(args, {})
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py
index 8f3914b83..107921403 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py
@@ -28,11 +28,3 @@ class CreateRouterTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
self.assertTrue(mock_create_neutron_router.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
index c1c137cda..b55767360 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
@@ -28,11 +28,3 @@ class CreateSecGroupTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
self.assertTrue(mock_create_security_group_full.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py
index 74003b995..faee98fd1 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py
@@ -32,11 +32,3 @@ class CreateServerTestCase(unittest.TestCase):
self.assertTrue(mock_get_glance_client.called)
self.assertTrue(mock_get_neutron_client.called)
self.assertTrue(mock_create_instance_and_wait_for_active.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py
index b7f29dfe4..1536e83e0 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py
@@ -30,11 +30,3 @@ class CreateSubnetTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
self.assertTrue(mock_create_neutron_subnet.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py
index ca055db2f..4bfec3252 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py
@@ -98,11 +98,3 @@ class CreateVolumeTestCase(unittest.TestCase):
self.assertTrue(mock_image_id.called)
self.assertTrue(mock_get_glance_client.called)
self.assertTrue(mock_get_cinder_client.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py
index 4a91b8939..e345afe3c 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py
@@ -25,11 +25,3 @@ class DeleteFlavorTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_nova_client.called)
self.assertTrue(mock_delete_flavor.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py
index df2321292..be997199c 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py
@@ -25,11 +25,3 @@ class DeleteFloatingIpTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_nova_client.called)
self.assertTrue(mock_delete_floating_ip.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py
index 9edc2ff1d..eb3f9fc85 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py
@@ -27,11 +27,3 @@ class DeleteImageTestCase(unittest.TestCase):
self.assertTrue(mock_delete_image.called)
self.assertTrue(mock_image_id.called)
self.assertTrue(mock_get_glance_client.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py
index 73894a903..38cc929c0 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py
@@ -25,11 +25,3 @@ class DeleteKeypairTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_nova_client.called)
self.assertTrue(mock_delete_keypair.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py
index de3179b2d..008ed9168 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py
@@ -23,11 +23,3 @@ class DeletePortTestCase(unittest.TestCase):
obj = DeletePort(args, {})
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py
index 73cb81278..9b31566ac 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py
@@ -25,11 +25,3 @@ class DeleteRouterTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
self.assertTrue(mock_delete_neutron_router.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py
index 3cfc4ed21..e19c38d47 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py
@@ -25,11 +25,3 @@ class DeleteRouterGatewayTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
self.assertTrue(mock_remove_gateway_router.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py
index 67aff1091..6c4fdd5e3 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py
@@ -26,11 +26,3 @@ class DeleteRouterInterfaceTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_neutron_client.called)
self.assertTrue(mock_remove_interface_router.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py
index 622ead5ac..dedce2d4a 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py
@@ -25,11 +25,3 @@ class DeleteServerTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_nova_client.called)
self.assertTrue(mock_delete_instance.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py
index 9438b077a..2ea82e2a4 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py
@@ -25,11 +25,3 @@ class DeleteVolumeTestCase(unittest.TestCase):
obj.run({})
self.assertTrue(mock_get_cinder_client.called)
self.assertTrue(mock_delete_volume.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py
index 87af63a55..34fbac68c 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py
@@ -24,11 +24,3 @@ class DetachVolumeTestCase(unittest.TestCase):
obj = DetachVolume(args, {})
obj.run({})
self.assertTrue(mock_detach_volume.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py
index bf12e0a32..e9025f33f 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py
@@ -23,11 +23,3 @@ class GetFlavorTestCase(unittest.TestCase):
obj = GetFlavor(args, {})
obj.run({})
self.assertTrue(mock_get_flavor_by_name.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py
index f046c92ea..aa9f63e26 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py
@@ -41,11 +41,3 @@ class GetMigrateTargetHostTestCase(unittest.TestCase):
host = obj._get_migrate_host('host5')
self.assertTrue(mock_get_nova_client.called)
self.assertEqual(host, 'host4')
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py
index 50d5238d7..4b2132c2c 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py
@@ -101,11 +101,3 @@ class GetNumaInfoTestCase(unittest.TestCase):
obj = GetNumaInfo(scenario_cfg, {})
result = obj._get_current_host_name('1')
self.assertEqual(result, 'host5')
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py
index aebbf5416..97b81ed60 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py
@@ -40,11 +40,3 @@ class GetServerTestCase(unittest.TestCase):
obj = GetServer(scenario_cfg, {})
obj.run({})
self.assertTrue(mock_get_nova_client.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py
index 3d20d5439..04fca16aa 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py
@@ -31,11 +31,3 @@ class GetServerIpTestCase(unittest.TestCase):
obj = GetServerIp(scenario_cfg, {})
result = obj.run({})
self.assertEqual(result, {'ip': '127.0.0.1'})
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py
index 4d3745230..d6636383a 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
@@ -193,10 +191,3 @@ class IperfTestCase(unittest.TestCase):
with open(output) as f:
sample_output = f.read()
return sample_output
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_moongen_testpmd.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_moongen_testpmd.py
new file mode 100644
index 000000000..620155c7e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_moongen_testpmd.py
@@ -0,0 +1,353 @@
+#!/usr/bin/env python
+
+# Copyright 2017 Nokia
+#
+# 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.
+
+# Unittest for yardstick.benchmark.scenarios.networking.MoongenTestPMD
+
+from __future__ import absolute_import
+try:
+ from unittest import mock
+except ImportError:
+ import mock
+import unittest
+
+from yardstick.benchmark.scenarios.networking import moongen_testpmd
+
+
+@mock.patch('yardstick.benchmark.scenarios.networking.moongen_testpmd.subprocess')
+class MoongenTestPMDTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ "host": {
+ "ip": "10.229.47.137",
+ "user": "ubuntu",
+ "password": "ubuntu",
+ },
+ }
+ self.TestPMDargs = {
+ 'task_id': "1234-5678",
+ 'options': {
+ 'multistream': 1,
+ 'frame_size': 1024,
+ 'testpmd_queue': 2,
+ 'trafficgen_port1': 'ens5',
+ 'trafficgen_port2': 'ens6',
+ 'moongen_host_user': 'root',
+ 'moongen_host_passwd': 'root',
+ 'moongen_host_ip': '10.5.201.151',
+ 'moongen_dir': '/home/lua-trafficgen',
+ 'moongen_runBidirec': 'true',
+ 'Package_Loss': 0,
+ 'SearchRuntime': 60,
+ 'moongen_port1_mac': '88:cf:98:2f:4d:ed',
+ 'moongen_port2_mac': '88:cf:98:2f:4d:ee',
+ 'forward_type': 'testpmd',
+ },
+ 'sla': {
+ 'metrics': 'throughput_rx_mpps',
+ 'throughput_rx_mpps': 0.5,
+ 'action': 'monitor',
+ }
+ }
+ self.L2fwdargs = {
+ 'task_id': "1234-5678",
+ 'options': {
+ 'multistream': 1,
+ 'frame_size': 1024,
+ 'testpmd_queue': 2,
+ 'trafficgen_port1': 'ens5',
+ 'trafficgen_port2': 'ens6',
+ 'moongen_host_user': 'root',
+ 'moongen_host_passwd': 'root',
+ 'moongen_host_ip': '10.5.201.151',
+ 'moongen_dir': '/home/lua-trafficgen',
+ 'moongen_runBidirec': 'true',
+ 'Package_Loss': 0,
+ 'SearchRuntime': 60,
+ 'moongen_port1_mac': '88:cf:98:2f:4d:ed',
+ 'moongen_port2_mac': '88:cf:98:2f:4d:ee',
+ 'forward_type': 'l2fwd',
+ },
+ 'sla': {
+ 'metrics': 'throughput_rx_mpps',
+ 'throughput_rx_mpps': 0.5,
+ 'action': 'monitor',
+ }
+ }
+
+ self._mock_ssh = mock.patch(
+ 'yardstick.benchmark.scenarios.networking.moongen_testpmd.ssh')
+ self.mock_ssh = self._mock_ssh.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_ssh.stop()
+
+ def test_MoongenTestPMD_setup(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_MoongenTestPMD_teardown(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ p.teardown()
+ self.assertFalse(p.setup_done)
+
+ def test_MoongenTestPMD_l2fwd_is_forward_setup_no(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.L2fwdargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ result = p._is_forward_setup()
+ self.assertFalse(result)
+
+ def test_MoongenTestPMD_l2fwd_is_forward_setup_yes(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.L2fwdargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, 'dummy', '')
+
+ result = p._is_forward_setup()
+ self.assertTrue(result)
+
+ def test_MoongenTestPMD_testpmd_is_forward_setup_no(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, 'dummy', '')
+
+ result = p._is_forward_setup()
+ self.assertFalse(result)
+
+ def test_MoongenTestPMD_testpmd_is_forward_setup_yes(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ result = p._is_forward_setup()
+ self.assertTrue(result)
+
+ @mock.patch('time.sleep')
+ def test_MoongenTestPMD_testpmd_forward_setup_first(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, 'dummy', '')
+
+ p.forward_setup()
+ self.assertFalse(p._is_forward_setup())
+ self.assertTrue(p.forward_setup_done)
+
+ @mock.patch('time.sleep')
+ def test_MoongenTestPMD_testpmd_dpdk_setup_next(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ p.forward_setup()
+ self.assertTrue(p._is_forward_setup())
+ self.assertTrue(p.forward_setup_done)
+
+ @mock.patch('time.sleep')
+ def test_MoongenTestPMD_l2fwd_forward_setup_first(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.L2fwdargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ p.forward_setup()
+ self.assertFalse(p._is_forward_setup())
+ self.assertTrue(p.forward_setup_done)
+
+ @mock.patch('time.sleep')
+ def test_MoongenTestPMD_l2fwd_dpdk_setup_next(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.L2fwdargs, self.ctx)
+
+ # setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, 'dummy', '')
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ p.forward_setup()
+ self.assertTrue(p._is_forward_setup())
+ self.assertTrue(p.forward_setup_done)
+
+ def test_moongen_testpmd_generate_config_file(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.generate_config_file(frame_size=1, multistream=1,
+ runBidirec="True", tg_port1_vlan=1,
+ tg_port2_vlan=2, SearchRuntime=1,
+ Package_Loss=0)
+ self.assertTrue(p.CONFIG_FILE)
+
+ def test_moongen_testpmd_result_to_data_match(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ mock_subprocess.call().execute.return_value = None
+ result = ("[REPORT]Device 1->0: Tx frames: 420161490 Rx Frames: 420161490"
+ " frame loss: 0, 0.000000% Rx Mpps: 7.002708\n[REPORT] "
+ "total: Tx frames: 840321216 Rx Frames: 840321216 frame loss: "
+ "0, 0.000000% Tx Mpps: 14.005388 Rx Mpps: 14.005388\n'")
+ p.result_to_data(result=result)
+ self.assertTrue(p.TO_DATA)
+
+ def test_moongen_testpmd_result_to_data_not_match(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ mock_subprocess.call().execute.return_value = None
+ result = ("")
+ p.result_to_data(result=result)
+ self.assertTrue(p.TO_DATA)
+
+ @mock.patch('time.sleep')
+ def test_moongen_testpmd_run_ok(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+ p.setup_done = True
+ p.forward_setup_done = True
+ p.setup()
+
+ # run() specific mocks
+ p.server = self.mock_ssh.SSH.from_node()
+ mock_subprocess.call().execute.return_value = None
+ mock_subprocess.call().execute.return_value = None
+ result = ("[REPORT]Device 1->0: Tx frames: 420161490 Rx Frames: 420161490"
+ " frame loss: 0, 0.000000% Rx Mpps: 7.002708\n[REPORT] "
+ "total: Tx frames: 840321216 Rx Frames: 840321216 frame loss: "
+ "0, 0.000000% Tx Mpps: 14.005388 Rx Mpps: 14.005388\n'")
+ self.mock_ssh.SSH.from_node().execute.return_value = (
+ 0, result, '')
+
+ test_result = {}
+ p.run(test_result)
+
+ self.assertEqual(test_result['rx_mpps'], 14.005388)
+
+ def test_moongen_testpmd_run_falied_vsperf_execution(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # run() specific mocks
+ mock_subprocess.call().execute.return_value = None
+ mock_subprocess.call().execute.return_value = None
+ self.mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ result = {}
+ self.assertRaises(RuntimeError, p.run, result)
+
+ def test_moongen_testpmd_run_falied_csv_report(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # run() specific mocks
+ mock_subprocess.call().execute.return_value = None
+ mock_subprocess.call().execute.return_value = None
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ result = {}
+ self.assertRaises(RuntimeError, p.run, result)
+
+def main():
+ unittest.main()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py
index d82a00931..5907562c2 100755
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
@@ -121,10 +119,3 @@ class NetperfTestCase(unittest.TestCase):
with open(output) as f:
sample_output = f.read()
return sample_output
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py
index 8be9bb94d..956a9c078 100755
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
@@ -121,10 +119,3 @@ class NetperfNodeTestCase(unittest.TestCase):
with open(output) as f:
sample_output = f.read()
return sample_output
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py
index 1227e056e..4cdfde6b1 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd and other.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py
index 3e7a3c5ee..36e8c8a77 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
#
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py
index 7dd5351b1..b02d58437 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py
@@ -103,11 +103,3 @@ class NstatTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, n.run, result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py
index 06353249a..4adfab120 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
@@ -92,10 +90,3 @@ class PingTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, p.run, result)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py
index d2be6f576..4662c8537 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
@@ -116,10 +114,3 @@ class PingTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.side_effect = [
(0, 'host1', ''), (1, '', 'FOOBAR')]
self.assertRaises(RuntimeError, p.run, result)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py
index acd9027d3..6aea03aee 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py
@@ -665,11 +665,3 @@ class PktgenTestCase(unittest.TestCase):
expected_result["packets_received"] = 149300
expected_result["packetsize"] = 60
self.assertEqual(result, expected_result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py
index 99399abdc..976087148 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py
@@ -176,11 +176,3 @@ class PktgenDPDKLatencyTestCase(unittest.TestCase):
self.mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, p.run, result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py
index 1b12bd507..e90fb07c7 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
##############################################################################
# Copyright (c) 2017 Nokia and others.
#
@@ -192,11 +191,3 @@ class PktgenDPDKTestCase(unittest.TestCase):
mock_ssh.SSH().execute.assert_called_with(
"sudo /dpdk/destdir/bin/dpdk-procinfo -- --stats-reset > /dev/null 2>&1")
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py
index 78c0352dd..a5e5e39dc 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
@@ -68,10 +66,3 @@ class SfcTestCase(unittest.TestCase):
self.sfc.setup()
self.sfc.run(result)
self.sfc.teardown()
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
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 fb55b5ea0..ec22d6147 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
# Copyright (c) 2016-2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,27 +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.
-#
-
-# Unittest for yardstick.benchmark.scenarios.networking.test_vnf_generic
-
-from __future__ import absolute_import
+from copy import deepcopy
import os
-import errno
-import unittest
-import mock
+import sys
-from copy import deepcopy
+import mock
+import unittest
-from yardstick.tests.unit import STL_MOCKS
-from yardstick.benchmark.scenarios.networking.vnf_generic import \
- SshManager, NetworkServiceTestCase, IncorrectConfig, \
- open_relative_file
+from yardstick import tests
+from yardstick.common import utils
from yardstick.network_services.collector.subscriber import Collector
-from yardstick.network_services.vnf_generic.vnf.base import \
- GenericTrafficGen, GenericVNF
+from yardstick.network_services.traffic_profile import base
+from yardstick.network_services.vnf_generic import vnfdgen
+from yardstick.error import IncorrectConfig
+from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen
+from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
+
+
+stl_patch = mock.patch.dict(sys.modules, tests.STL_MOCKS)
+stl_patch.start()
+if stl_patch:
+ from yardstick.benchmark.scenarios.networking import vnf_generic
# pylint: disable=unused-argument
# disable this for now because I keep forgetting mock patch arg ordering
@@ -317,6 +317,7 @@ class TestNetworkServiceTestCase(unittest.TestCase):
'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
'tc': 'tc_ipv4_1Mflow_64B_packetsize',
'traffic_profile': 'ipv4_throughput_vpe.yaml',
+ 'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
'type': 'ISB',
'tc_options': {
'rfc2544': {
@@ -345,23 +346,14 @@ class TestNetworkServiceTestCase(unittest.TestCase):
},
}
- self.s = NetworkServiceTestCase(self.scenario_cfg, self.context_cfg)
+ self.s = vnf_generic.NetworkServiceTestCase(self.scenario_cfg,
+ self.context_cfg)
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
- def test_ssh_manager(self):
- with mock.patch("yardstick.ssh.SSH") as ssh:
- ssh_mock = mock.Mock(autospec=ssh.SSH)
- ssh_mock.execute = \
- mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
- ssh.from_node.return_value = ssh_mock
- for _, node_dict in self.context_cfg["nodes"].items():
- with SshManager(node_dict) as conn:
- self.assertIsNotNone(conn)
-
def test___init__(self):
assert self.topology
@@ -415,7 +407,10 @@ class TestNetworkServiceTestCase(unittest.TestCase):
'public_ip': ['1.1.1.1'],
},
}
-
+ # NOTE(ralonsoh): check the expected output. This test could be
+ # incorrect
+ # result = {'flow': {'dst_ip0': '152.16.40.2-152.16.40.254',
+ # 'src_ip0': '152.16.100.2-152.16.100.254'}}
self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
def test___get_traffic_flow_error(self):
@@ -425,16 +420,16 @@ class TestNetworkServiceTestCase(unittest.TestCase):
def test_get_vnf_imp(self):
vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]['class-name']
- with mock.patch.dict("sys.modules", STL_MOCKS):
+ with mock.patch.dict(sys.modules, tests.STL_MOCKS):
self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
- with self.assertRaises(IncorrectConfig) as raised:
- self.s.get_vnf_impl('NonExistentClass')
+ with self.assertRaises(vnf_generic.IncorrectConfig) as raised:
+ self.s.get_vnf_impl('NonExistentClass')
- exc_str = str(raised.exception)
- print(exc_str)
- self.assertIn('No implementation', exc_str)
- self.assertIn('found in', exc_str)
+ exc_str = str(raised.exception)
+ print(exc_str)
+ self.assertIn('No implementation', exc_str)
+ self.assertIn('found in', exc_str)
def test_load_vnf_models_invalid(self):
self.context_cfg["nodes"]['tg__1']['VNF model'] = \
@@ -456,39 +451,37 @@ class TestNetworkServiceTestCase(unittest.TestCase):
self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
def test_map_topology_to_infrastructure(self):
- with mock.patch("yardstick.ssh.SSH") as ssh:
- ssh_mock = mock.Mock(autospec=ssh.SSH)
- ssh_mock.execute = \
- mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
- ssh.from_node.return_value = ssh_mock
- self.s.map_topology_to_infrastructure()
+ self.s.map_topology_to_infrastructure()
nodes = self.context_cfg["nodes"]
- self.assertEqual(
- "../../vnf_descriptors/tg_rfc2544_tpl.yaml", nodes['tg__1']['VNF model'])
- self.assertEqual("../../vnf_descriptors/vpe_vnf.yaml",
+ self.assertEqual('../../vnf_descriptors/tg_rfc2544_tpl.yaml',
+ nodes['tg__1']['VNF model'])
+ self.assertEqual('../../vnf_descriptors/vpe_vnf.yaml',
nodes['vnf__1']['VNF model'])
def test_map_topology_to_infrastructure_insufficient_nodes(self):
- del self.context_cfg['nodes']['vnf__1']
- with mock.patch("yardstick.ssh.SSH") as ssh:
- ssh_mock = mock.Mock(autospec=ssh.SSH)
- ssh_mock.execute = \
- mock.Mock(return_value=(1, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
- ssh.from_node.return_value = ssh_mock
+ cfg = deepcopy(self.context_cfg)
+ del cfg['nodes']['vnf__1']
+ cfg_patch = mock.patch.object(self.s, 'context_cfg', cfg)
+ with cfg_patch:
with self.assertRaises(IncorrectConfig):
self.s.map_topology_to_infrastructure()
def test_map_topology_to_infrastructure_config_invalid(self):
- cfg = dict(self.context_cfg)
+ ssh_mock = mock.Mock()
+ ssh_mock.execute.return_value = 0, SYS_CLASS_NET + IP_ADDR_SHOW, ""
+
+ cfg = deepcopy(self.s.context_cfg)
+
+ # delete all, we don't know which will come first
del cfg['nodes']['vnf__1']['interfaces']['xe0']['local_mac']
- with mock.patch("yardstick.ssh.SSH") as ssh:
- ssh_mock = mock.Mock(autospec=ssh.SSH)
- ssh_mock.execute = \
- mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
- ssh.from_node.return_value = ssh_mock
+ del cfg['nodes']['vnf__1']['interfaces']['xe1']['local_mac']
+ del cfg['nodes']['tg__1']['interfaces']['xe0']['local_mac']
+ del cfg['nodes']['tg__1']['interfaces']['xe1']['local_mac']
+ config_patch = mock.patch.object(self.s, 'context_cfg', cfg)
+ with config_patch:
with self.assertRaises(IncorrectConfig):
self.s.map_topology_to_infrastructure()
@@ -503,10 +496,8 @@ class TestNetworkServiceTestCase(unittest.TestCase):
for interface in self.tg__1['interfaces'].values():
del interface['local_mac']
- with mock.patch(
- "yardstick.benchmark.scenarios.networking.vnf_generic.LOG"):
- with self.assertRaises(IncorrectConfig) as raised:
- self.s._resolve_topology()
+ with self.assertRaises(vnf_generic.IncorrectConfig) as raised:
+ self.s._resolve_topology()
self.assertIn('not found', str(raised.exception))
@@ -518,10 +509,8 @@ class TestNetworkServiceTestCase(unittest.TestCase):
self.s.topology["vld"][0]['vnfd-connection-point-ref'].append(
self.s.topology["vld"][0]['vnfd-connection-point-ref'][0])
- with mock.patch(
- "yardstick.benchmark.scenarios.networking.vnf_generic.LOG"):
- with self.assertRaises(IncorrectConfig) as raised:
- self.s._resolve_topology()
+ with self.assertRaises(vnf_generic.IncorrectConfig) as raised:
+ self.s._resolve_topology()
self.assertIn('wrong endpoint count', str(raised.exception))
@@ -529,10 +518,8 @@ class TestNetworkServiceTestCase(unittest.TestCase):
self.s.topology["vld"][0]['vnfd-connection-point-ref'] = \
self.s.topology["vld"][0]['vnfd-connection-point-ref'][:1]
- with mock.patch(
- "yardstick.benchmark.scenarios.networking.vnf_generic.LOG"):
- with self.assertRaises(IncorrectConfig) as raised:
- self.s._resolve_topology()
+ with self.assertRaises(vnf_generic.IncorrectConfig) as raised:
+ self.s._resolve_topology()
self.assertIn('wrong endpoint count', str(raised.exception))
@@ -578,7 +565,7 @@ class TestNetworkServiceTestCase(unittest.TestCase):
self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
self.s._fill_traffic_profile = \
mock.Mock(return_value=TRAFFIC_PROFILE)
- self.assertEqual(None, self.s.setup())
+ self.assertIsNone(self.s.setup())
def test_setup_exception(self):
with mock.patch("yardstick.ssh.SSH") as ssh:
@@ -625,15 +612,48 @@ class TestNetworkServiceTestCase(unittest.TestCase):
self.assertEqual({'imix': {'64B': 100}},
self.s._get_traffic_imix())
- def test__fill_traffic_profile(self):
- with mock.patch.dict("sys.modules", STL_MOCKS):
- self.scenario_cfg["traffic_profile"] = \
- self._get_file_abspath("ipv4_throughput_vpe.yaml")
- self.scenario_cfg["traffic_options"]["flow"] = \
- self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
- self.scenario_cfg["traffic_options"]["imix"] = \
- self._get_file_abspath("imix_voice.yaml")
- self.assertIsNotNone(self.s._fill_traffic_profile())
+ @mock.patch.object(base.TrafficProfile, 'get')
+ @mock.patch.object(vnfdgen, 'generate_vnfd')
+ def test__fill_traffic_profile(self, mock_generate, mock_tprofile_get):
+ fake_tprofile = mock.Mock()
+ fake_vnfd = mock.Mock()
+ with mock.patch.object(self.s, '_get_traffic_profile',
+ return_value=fake_tprofile) as mock_get_tp:
+ mock_generate.return_value = fake_vnfd
+ self.s._fill_traffic_profile()
+ mock_get_tp.assert_called_once()
+ mock_generate.assert_called_once_with(
+ fake_tprofile,
+ {'downlink': {},
+ 'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
+ 'flow': {'flow': {}},
+ 'imix': {'imix': {'64B': 100}},
+ 'uplink': {}}
+ )
+ mock_tprofile_get.assert_called_once_with(fake_vnfd)
+
+ @mock.patch.object(utils, 'open_relative_file')
+ def test__get_topology(self, mock_open_path):
+ self.s.scenario_cfg['topology'] = 'fake_topology'
+ self.s.scenario_cfg['task_path'] = 'fake_path'
+ mock_open_path.side_effect = mock.mock_open(read_data='fake_data')
+ self.assertEqual('fake_data', self.s._get_topology())
+ mock_open_path.assert_called_once_with('fake_topology', 'fake_path')
+
+ @mock.patch.object(vnfdgen, 'generate_vnfd')
+ def test__render_topology(self, mock_generate):
+ fake_topology = 'fake_topology'
+ mock_generate.return_value = {'nsd:nsd-catalog': {'nsd': ['fake_nsd']}}
+ with mock.patch.object(self.s, '_get_topology',
+ return_value=fake_topology) as mock_get_topology:
+ self.s._render_topology()
+ mock_get_topology.assert_called_once()
+
+ mock_generate.assert_called_once_with(
+ fake_topology,
+ {'extra_args': {'arg1': 'value1', 'arg2': 'value2'}}
+ )
+ self.assertEqual(self.s.topology, 'fake_nsd')
def test_teardown(self):
vnf = mock.Mock(autospec=GenericVNF)
@@ -658,141 +678,3 @@ class TestNetworkServiceTestCase(unittest.TestCase):
mock.Mock(return_value=True)
with self.assertRaises(RuntimeError):
self.s.teardown()
-
- SAMPLE_NETDEVS = {
- 'enp11s0': {
- 'address': '0a:de:ad:be:ef:f5',
- 'device': '0x1533',
- 'driver': 'igb',
- 'ifindex': '2',
- 'interface_name': 'enp11s0',
- 'operstate': 'down',
- 'pci_bus_id': '0000:0b:00.0',
- 'subsystem_device': '0x1533',
- 'subsystem_vendor': '0x15d9',
- 'vendor': '0x8086'
- },
- 'lan': {
- 'address': '0a:de:ad:be:ef:f4',
- 'device': '0x153a',
- 'driver': 'e1000e',
- 'ifindex': '3',
- 'interface_name': 'lan',
- 'operstate': 'up',
- 'pci_bus_id': '0000:00:19.0',
- 'subsystem_device': '0x153a',
- 'subsystem_vendor': '0x15d9',
- 'vendor': '0x8086'
- }
- }
-
- SAMPLE_VM_NETDEVS = {
- 'eth1': {
- 'address': 'fa:de:ad:be:ef:5b',
- 'device': '0x0001',
- 'driver': 'virtio_net',
- 'ifindex': '3',
- 'interface_name': 'eth1',
- 'operstate': 'down',
- 'pci_bus_id': '0000:00:04.0',
- 'vendor': '0x1af4'
- }
- }
-
- def test_parse_netdev_info(self):
- output = """\
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/ifindex:2
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/address:0a:de:ad:be:ef:f5
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/operstate:down
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/vendor:0x8086
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/device:0x1533
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_vendor:0x15d9
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_device:0x1533
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/driver:igb
-/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/pci_bus_id:0000:0b:00.0
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/ifindex:3
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/address:0a:de:ad:be:ef:f4
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/operstate:up
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/device/vendor:0x8086
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/device/device:0x153a
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_vendor:0x15d9
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_device:0x153a
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/driver:e1000e
-/sys/devices/pci0000:00/0000:00:19.0/net/lan/pci_bus_id:0000:00:19.0
-"""
- res = NetworkServiceTestCase.parse_netdev_info(output)
- assert res == self.SAMPLE_NETDEVS
-
- def test_parse_netdev_info_virtio(self):
- output = """\
-/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/ifindex:3
-/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/address:fa:de:ad:be:ef:5b
-/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/operstate:down
-/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/vendor:0x1af4
-/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/device:0x0001
-/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/driver:virtio_net
-"""
- res = NetworkServiceTestCase.parse_netdev_info(output)
- assert res == self.SAMPLE_VM_NETDEVS
-
- def test_probe_missing_values(self):
- netdevs = self.SAMPLE_NETDEVS.copy()
- network = {'local_mac': '0a:de:ad:be:ef:f5'}
- NetworkServiceTestCase._probe_missing_values(netdevs, network)
- assert network['vpci'] == '0000:0b:00.0'
-
- network = {'local_mac': '0a:de:ad:be:ef:f4'}
- NetworkServiceTestCase._probe_missing_values(netdevs, network)
- assert network['vpci'] == '0000:00:19.0'
-
- # TODO: Split this into several tests, for different IOError sub-types
- def test_open_relative_path(self):
- mock_open = mock.mock_open()
- mock_open_result = mock_open()
- mock_open_call_count = 1 # initial call to get result
-
- module_name = \
- 'yardstick.benchmark.scenarios.networking.vnf_generic.open'
-
- # test
- with mock.patch(module_name, mock_open, create=True):
- self.assertEqual(open_relative_file(
- 'foo', 'bar'), mock_open_result)
-
- mock_open_call_count += 1 # one more call expected
- self.assertEqual(mock_open.call_count, mock_open_call_count)
- self.assertIn('foo', mock_open.call_args_list[-1][0][0])
- self.assertNotIn('bar', mock_open.call_args_list[-1][0][0])
-
- def open_effect(*args, **kwargs):
- if kwargs.get('name', args[0]) == os.path.join('bar', 'foo'):
- return mock_open_result
- raise IOError(errno.ENOENT, 'not found')
-
- mock_open.side_effect = open_effect
- self.assertEqual(open_relative_file(
- 'foo', 'bar'), mock_open_result)
-
- mock_open_call_count += 2 # two more calls expected
- self.assertEqual(mock_open.call_count, mock_open_call_count)
- self.assertIn('foo', mock_open.call_args_list[-1][0][0])
- self.assertIn('bar', mock_open.call_args_list[-1][0][0])
-
- # test an IOError of type ENOENT
- mock_open.side_effect = IOError(errno.ENOENT, 'not found')
- with self.assertRaises(IOError):
- # the second call still raises
- open_relative_file('foo', 'bar')
-
- mock_open_call_count += 2 # two more calls expected
- self.assertEqual(mock_open.call_count, mock_open_call_count)
- self.assertIn('foo', mock_open.call_args_list[-1][0][0])
- self.assertIn('bar', mock_open.call_args_list[-1][0][0])
-
- # test an IOError other than ENOENT
- mock_open.side_effect = IOError(errno.EBUSY, 'busy')
- with self.assertRaises(IOError):
- open_relative_file('foo', 'bar')
-
- mock_open_call_count += 1 # one more call expected
- self.assertEqual(mock_open.call_count, mock_open_call_count)
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py
index be8ac55d0..419605b26 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
# Copyright 2016 Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -126,11 +124,3 @@ class VsperfTestCase(unittest.TestCase):
result = {}
self.assertRaises(RuntimeError, p.run, result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py
index 1923960e9..1d2278e21 100644
--- a/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py
@@ -211,11 +211,3 @@ class VsperfDPDKTestCase(unittest.TestCase):
result = {}
self.assertRaises(RuntimeError, self.scenario.run, result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py b/yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py
index ee2bbc07d..9fd5cce38 100644
--- a/yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py
+++ b/yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
#
@@ -70,10 +68,3 @@ class ParserTestCase(unittest.TestCase):
self.mock_call.return_value = 0
self.scenario.teardown()
self.assertTrue(self.scenario.teardown_done)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py b/yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py
index b98dceae7..d78506584 100644
--- a/yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
#
@@ -9,8 +7,6 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-# Unittest for yardstick.benchmark.scenarios.storage.bonnie.Bonnie
-
from __future__ import absolute_import
import unittest
@@ -65,11 +61,3 @@ class BonnieTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, b.run, self.result)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py b/yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py
index 0cffea224..f149cee69 100644
--- a/yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Ericsson AB and others.
#
@@ -63,6 +61,22 @@ class FioTestCase(unittest.TestCase):
}
args = {'options': options}
p = fio.Fio(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '/dev/vdb', '')
+ p.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_fio_job_file_no_disk__setup(self, mock_ssh):
+
+ options = {
+ 'job_file': 'job_file.ini',
+ 'directory': '/FIO_Test'
+ }
+ args = {'options': options}
+ p = fio.Fio(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
p.setup()
mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
@@ -263,11 +277,3 @@ class FioTestCase(unittest.TestCase):
with open(output) as f:
sample_output = f.read()
return sample_output
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py b/yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py
index 095674f72..c1c731b0a 100644
--- a/yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
#
@@ -99,10 +97,3 @@ class StorageCapacityTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, c.run, self.result)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py b/yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py
index 52786d7cb..5844746ab 100644
--- a/yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2016 Huawei Technologies Co.,Ltd.
#
@@ -233,10 +231,3 @@ class StorPerfTestCase(unittest.TestCase):
s = storperf.StorPerf(args, self.ctx)
self.assertRaises(AssertionError, s.teardown(), self.result)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/test_base.py b/yardstick/tests/unit/benchmark/scenarios/test_base.py
index a95e6bc86..985338532 100644
--- a/yardstick/tests/unit/benchmark/scenarios/test_base.py
+++ b/yardstick/tests/unit/benchmark/scenarios/test_base.py
@@ -13,12 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import unittest
-
from yardstick.benchmark.scenarios import base
+from yardstick.tests.unit import base as ut_base
-class ScenarioTestCase(unittest.TestCase):
+class ScenarioTestCase(ut_base.BaseUnitTestCase):
def test_get_scenario_type(self):
scenario_type = 'dummy scenario'
@@ -87,7 +86,7 @@ class ScenarioTestCase(unittest.TestCase):
str(exc.exception))
-class IterScenarioClassesTestCase(unittest.TestCase):
+class IterScenarioClassesTestCase(ut_base.BaseUnitTestCase):
def test_no_scenario_type_defined(self):
some_existing_scenario_class_names = [
diff --git a/yardstick/tests/unit/common/banned_modules/__init__.py b/yardstick/tests/unit/common/banned_modules/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/common/banned_modules/__init__.py
diff --git a/yardstick/tests/unit/common/banned_modules/banned_module.py b/yardstick/tests/unit/common/banned_modules/banned_module.py
new file mode 100644
index 000000000..f57f939d2
--- /dev/null
+++ b/yardstick/tests/unit/common/banned_modules/banned_module.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2018 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.
+
+
+class BannedClass(object):
+ pass
diff --git a/yardstick/tests/unit/common/banned_modules/importing_module.py b/yardstick/tests/unit/common/banned_modules/importing_module.py
new file mode 100644
index 000000000..fc2542f0c
--- /dev/null
+++ b/yardstick/tests/unit/common/banned_modules/importing_module.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2018 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 yardstick.common import import_tools
+from yardstick.tests.unit.common.banned_modules import banned_module
+
+
+@import_tools.decorator_banned_modules
+class ImportingClass(banned_module.BannedClass):
+ pass
diff --git a/yardstick/tests/unit/common/test_ansible_common.py b/yardstick/tests/unit/common/test_ansible_common.py
index 89ea128af..b01195fcc 100644
--- a/yardstick/tests/unit/common/test_ansible_common.py
+++ b/yardstick/tests/unit/common/test_ansible_common.py
@@ -99,7 +99,7 @@ class AnsibleNodeTestCase(unittest.TestCase):
def test_ansible_node_getattr(self):
a = ansible_common.AnsibleNode({"name": "name"})
- self.assertEqual(getattr(a, "nosuch", None), None)
+ self.assertIsNone(getattr(a, "nosuch", None))
class AnsibleNodeDictTestCase(unittest.TestCase):
@@ -145,7 +145,7 @@ class AnsibleNodeDictTestCase(unittest.TestCase):
class AnsibleCommonTestCase(unittest.TestCase):
def test_get_timeouts(self):
- self.assertAlmostEquals(ansible_common.AnsibleCommon.get_timeout(-100), 1200.0)
+ self.assertAlmostEqual(ansible_common.AnsibleCommon.get_timeout(-100), 1200.0)
def test__init__(self):
ansible_common.AnsibleCommon({})
diff --git a/yardstick/tests/unit/common/test_httpClient.py b/yardstick/tests/unit/common/test_httpClient.py
index eb09d1a52..12a8be3a0 100644
--- a/yardstick/tests/unit/common/test_httpClient.py
+++ b/yardstick/tests/unit/common/test_httpClient.py
@@ -33,11 +33,3 @@ class HttpClientTestCase(unittest.TestCase):
url = 'http://localhost:5000/hello'
httpClient.HttpClient().get(url)
mock_requests.get.assert_called_with(url)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/common/test_import_tools.py b/yardstick/tests/unit/common/test_import_tools.py
new file mode 100644
index 000000000..c8fe5fde0
--- /dev/null
+++ b/yardstick/tests/unit/common/test_import_tools.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2018 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 unittest
+
+from yardstick.common import exceptions as y_exc
+from yardstick.common import import_tools
+
+
+@import_tools.decorator_banned_modules
+class DummyClass(object):
+ pass
+
+
+class DecoratorBannedModule(unittest.TestCase):
+
+ MODULE = 'yardstick.tests.unit.common.banned_modules.banned_module'
+
+ def test_passt(self):
+ self.assertIsNotNone(DummyClass())
+
+ def test_banned_module(self):
+ import_tools.BANNED_MODULES[self.MODULE] = 'Banned module!!'
+ from yardstick.tests.unit.common.banned_modules import importing_module
+ self.addCleanup(self._remove_module)
+
+ with self.assertRaises(y_exc.YardstickBannedModuleImported) as exc:
+ importing_module.ImportingClass()
+
+ msg = ('Module "%s" cannnot be imported. Reason: "Banned module!!"'
+ % self.MODULE)
+ self.assertEqual(msg, str(exc.exception))
+
+ def _remove_module(self):
+ del import_tools.BANNED_MODULES[self.MODULE]
diff --git a/yardstick/tests/unit/common/test_openstack_utils.py b/yardstick/tests/unit/common/test_openstack_utils.py
index 8a2f5f95b..4863f05c0 100644
--- a/yardstick/tests/unit/common/test_openstack_utils.py
+++ b/yardstick/tests/unit/common/test_openstack_utils.py
@@ -54,7 +54,7 @@ class GetNetworkIdTestCase(unittest.TestCase):
output = openstack_utils.get_network_id(mock_shade_client,
'network_name')
- self.assertEqual(None, output)
+ self.assertIsNone(output)
class DeleteNeutronNetTestCase(unittest.TestCase):
diff --git a/yardstick/tests/unit/common/test_packages.py b/yardstick/tests/unit/common/test_packages.py
new file mode 100644
index 000000000..ba59a3015
--- /dev/null
+++ b/yardstick/tests/unit/common/test_packages.py
@@ -0,0 +1,88 @@
+# Copyright (c) 2018 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
+from pip import exceptions as pip_exceptions
+from pip.operations import freeze
+import unittest
+
+from yardstick.common import packages
+
+
+class PipExecuteActionTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_pip_main = mock.patch.object(packages, '_pip_main')
+ self.mock_pip_main = self._mock_pip_main.start()
+ self.mock_pip_main.return_value = 0
+ self._mock_freeze = mock.patch.object(freeze, 'freeze')
+ self.mock_freeze = self._mock_freeze.start()
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_pip_main.stop()
+ self._mock_freeze.stop()
+
+ def test_pip_execute_action(self):
+ self.assertEqual(0, packages._pip_execute_action('test_package'))
+
+ def test_remove(self):
+ self.assertEqual(0, packages._pip_execute_action('test_package',
+ action='uninstall'))
+
+ def test_install(self):
+ self.assertEqual(0, packages._pip_execute_action(
+ 'test_package', action='install', target='temp_dir'))
+
+ def test_pip_execute_action_error(self):
+ self.mock_pip_main.return_value = 1
+ self.assertEqual(1, packages._pip_execute_action('test_package'))
+
+ def test_pip_execute_action_exception(self):
+ self.mock_pip_main.side_effect = pip_exceptions.PipError
+ self.assertEqual(1, packages._pip_execute_action('test_package'))
+
+ def test_pip_list(self):
+ pkg_input = [
+ 'XStatic-Rickshaw==1.5.0.0',
+ 'xvfbwrapper==0.2.9',
+ '-e git+https://git.opnfv.org/yardstick@50773a24afc02c9652b662ecca'
+ '2fc5621ea6097a#egg=yardstick',
+ 'zope.interface==4.4.3'
+ ]
+ pkg_dict = {
+ 'XStatic-Rickshaw': '1.5.0.0',
+ 'xvfbwrapper': '0.2.9',
+ 'yardstick': '50773a24afc02c9652b662ecca2fc5621ea6097a',
+ 'zope.interface': '4.4.3'
+ }
+ self.mock_freeze.return_value = pkg_input
+
+ pkg_output = packages.pip_list()
+ for pkg_name, pkg_version in pkg_output.items():
+ self.assertEqual(pkg_dict.get(pkg_name), pkg_version)
+
+ def test_pip_list_single_package(self):
+ pkg_input = [
+ 'XStatic-Rickshaw==1.5.0.0',
+ 'xvfbwrapper==0.2.9',
+ '-e git+https://git.opnfv.org/yardstick@50773a24afc02c9652b662ecca'
+ '2fc5621ea6097a#egg=yardstick',
+ 'zope.interface==4.4.3'
+ ]
+ self.mock_freeze.return_value = pkg_input
+
+ pkg_output = packages.pip_list(pkg_name='xvfbwrapper')
+ self.assertEqual(1, len(pkg_output))
+ self.assertEqual(pkg_output.get('xvfbwrapper'), '0.2.9')
diff --git a/yardstick/tests/unit/common/test_template_format.py b/yardstick/tests/unit/common/test_template_format.py
index 44aa80333..56253efbc 100644
--- a/yardstick/tests/unit/common/test_template_format.py
+++ b/yardstick/tests/unit/common/test_template_format.py
@@ -45,10 +45,3 @@ class TemplateFormatTestCase(unittest.TestCase):
"Resources: {}\n" \
"Outputs: {}"
self.assertRaises(ValueError, template_format.parse, yaml2)
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/common/test_utils.py b/yardstick/tests/unit/common/test_utils.py
index 033bb0243..e71d0ff0f 100644
--- a/yardstick/tests/unit/common/test_utils.py
+++ b/yardstick/tests/unit/common/test_utils.py
@@ -19,6 +19,8 @@ from six.moves import configparser
import unittest
import yardstick
+from yardstick import ssh
+import yardstick.error
from yardstick.common import utils
from yardstick.common import constants
@@ -125,6 +127,63 @@ class CommonUtilTestCase(unittest.TestCase):
("=".join(item) for item in sorted(flattened_data.items())))
self.assertEqual(result, line)
+ def test_get_key_with_default_negative(self):
+ with self.assertRaises(KeyError):
+ utils.get_key_with_default({}, 'key1')
+
+ @mock.patch('yardstick.common.utils.open', create=True)
+ def test_(self, mock_open):
+ mock_open.side_effect = IOError
+
+ with self.assertRaises(IOError):
+ utils.find_relative_file('my/path', 'task/path')
+
+ self.assertEqual(mock_open.call_count, 2)
+
+ @mock.patch('yardstick.common.utils.open', create=True)
+ def test_open_relative_path(self, mock_open):
+ mock_open_result = mock_open()
+ mock_open_call_count = 1 # initial call to get result
+
+ self.assertEqual(utils.open_relative_file('foo', 'bar'), mock_open_result)
+
+ mock_open_call_count += 1 # one more call expected
+ self.assertEqual(mock_open.call_count, mock_open_call_count)
+ self.assertIn('foo', mock_open.call_args_list[-1][0][0])
+ self.assertNotIn('bar', mock_open.call_args_list[-1][0][0])
+
+ def open_effect(*args, **kwargs):
+ if kwargs.get('name', args[0]) == os.path.join('bar', 'foo'):
+ return mock_open_result
+ raise IOError(errno.ENOENT, 'not found')
+
+ mock_open.side_effect = open_effect
+ self.assertEqual(utils.open_relative_file('foo', 'bar'), mock_open_result)
+
+ mock_open_call_count += 2 # two more calls expected
+ self.assertEqual(mock_open.call_count, mock_open_call_count)
+ self.assertIn('foo', mock_open.call_args_list[-1][0][0])
+ self.assertIn('bar', mock_open.call_args_list[-1][0][0])
+
+ # test an IOError of type ENOENT
+ mock_open.side_effect = IOError(errno.ENOENT, 'not found')
+ with self.assertRaises(IOError):
+ # the second call still raises
+ utils.open_relative_file('foo', 'bar')
+
+ mock_open_call_count += 2 # two more calls expected
+ self.assertEqual(mock_open.call_count, mock_open_call_count)
+ self.assertIn('foo', mock_open.call_args_list[-1][0][0])
+ self.assertIn('bar', mock_open.call_args_list[-1][0][0])
+
+ # test an IOError other than ENOENT
+ mock_open.side_effect = IOError(errno.EBUSY, 'busy')
+ with self.assertRaises(IOError):
+ utils.open_relative_file('foo', 'bar')
+
+ mock_open_call_count += 1 # one more call expected
+ self.assertEqual(mock_open.call_count, mock_open_call_count)
+
class TestMacAddressToHex(unittest.TestCase):
@@ -930,9 +989,9 @@ class TestUtils(unittest.TestCase):
def test_error_class(self):
with self.assertRaises(RuntimeError):
- utils.ErrorClass()
+ yardstick.error.ErrorClass()
- error_instance = utils.ErrorClass(test='')
+ error_instance = yardstick.error.ErrorClass(test='')
with self.assertRaises(AttributeError):
error_instance.get_name()
@@ -1075,8 +1134,27 @@ class SafeDecodeUtf8TestCase(unittest.TestCase):
self.assertEqual('this is a byte array', out)
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
+class ReadMeminfoTestCase(unittest.TestCase):
+
+ MEMINFO = (b'MemTotal: 65860500 kB\n'
+ b'MemFree: 28690900 kB\n'
+ b'MemAvailable: 52873764 kB\n'
+ b'Active(anon): 3015676 kB\n'
+ b'HugePages_Total: 8\n'
+ b'Hugepagesize: 1048576 kB')
+ MEMINFO_DICT = {'MemTotal': '65860500',
+ 'MemFree': '28690900',
+ 'MemAvailable': '52873764',
+ 'Active(anon)': '3015676',
+ 'HugePages_Total': '8',
+ 'Hugepagesize': '1048576'}
+
+ def test_read_meminfo(self):
+ ssh_client = ssh.SSH('user', 'host')
+ with mock.patch.object(ssh_client, 'get_file_obj') as \
+ mock_get_client, \
+ mock.patch.object(six, 'BytesIO',
+ return_value=six.BytesIO(self.MEMINFO)):
+ output = utils.read_meminfo(ssh_client)
+ mock_get_client.assert_called_once_with('/proc/meminfo', mock.ANY)
+ self.assertEqual(self.MEMINFO_DICT, output)
diff --git a/yardstick/tests/unit/common/test_yaml_loader.py b/yardstick/tests/unit/common/test_yaml_loader.py
index 6c2beb422..e621dcbc5 100644
--- a/yardstick/tests/unit/common/test_yaml_loader.py
+++ b/yardstick/tests/unit/common/test_yaml_loader.py
@@ -12,7 +12,6 @@
# yardstick: this file is copied from python-heatclient and slightly modified
-from __future__ import absolute_import
import unittest
from yardstick.common import yaml_loader
@@ -23,10 +22,3 @@ class TemplateFormatTestCase(unittest.TestCase):
def test_parse_to_value_exception(self):
self.assertEqual(yaml_loader.yaml_load("string"), u"string")
-
-
-def main():
- unittest.main()
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/dispatcher/test_influxdb.py b/yardstick/tests/unit/dispatcher/test_influxdb.py
index bca94e385..c844d4bbb 100644
--- a/yardstick/tests/unit/dispatcher/test_influxdb.py
+++ b/yardstick/tests/unit/dispatcher/test_influxdb.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
#
@@ -104,11 +102,3 @@ class InfluxdbDispatcherTestCase(unittest.TestCase):
mock_time.time.return_value = 1451461248.925574
self.assertEqual(influxdb._get_nano_timestamp(results),
'1451461248925574144')
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/orchestrator/test_heat.py b/yardstick/tests/unit/orchestrator/test_heat.py
index e0a353812..aae2487aa 100644
--- a/yardstick/tests/unit/orchestrator/test_heat.py
+++ b/yardstick/tests/unit/orchestrator/test_heat.py
@@ -9,6 +9,7 @@
import tempfile
+import munch
import mock
from oslo_serialization import jsonutils
from oslo_utils import uuidutils
@@ -40,12 +41,16 @@ class HeatStackTestCase(unittest.TestCase):
self._mock_stack_delete = mock.patch.object(self.heatstack._cloud,
'delete_stack')
self.mock_stack_delete = self._mock_stack_delete.start()
+ self._mock_stack_get = mock.patch.object(self.heatstack._cloud,
+ 'get_stack')
+ self.mock_stack_get = self._mock_stack_get.start()
self.addCleanup(self._cleanup)
def _cleanup(self):
self._mock_stack_create.stop()
self._mock_stack_delete.stop()
+ self._mock_stack_get.stop()
heat._DEPLOYED_STACKS = {}
def test_create(self):
@@ -101,6 +106,88 @@ class HeatStackTestCase(unittest.TestCase):
self.assertFalse(heat._DEPLOYED_STACKS)
self.mock_stack_delete.assert_called_once_with(id, wait=True)
+ def test_get(self):
+ # make sure shade/get_stack is called with the appropriate vars
+ self.mock_stack_get.return_value = munch.Munch(
+ id="my-existing-stack-id",
+ outputs=[
+ {
+ u'output_value': u'b734d06a-dec7-...',
+ u'output_key': u'ares.demo-test-port-network_id',
+ u'description': u''
+ },
+ {u'output_value': u'b08da78c-2218-...',
+ u'output_key': u'ares.demo-test-port-subnet_id',
+ u'description': u''
+ },
+ {u'output_value': u'10.0.1.0/24',
+ u'output_key': u'demo-test-subnet-cidr',
+ u'description': u''
+ },
+ {u'output_value': u'b08da78c-2218-...',
+ u'output_key': u'demo-test-subnet',
+ u'description': u''
+ },
+ {u'output_value': u'b1a03624-aefc-...',
+ u'output_key': u'ares.demo',
+ u'description': u''
+ },
+ {u'output_value': u'266a8088-c630-...',
+ u'output_key': u'demo-secgroup',
+ u'description': u''
+ },
+ {u'output_value': u'10.0.1.5',
+ u'output_key': u'ares.demo-test-port',
+ u'description': u''
+ },
+ {u'output_value': u'10.0.1.1',
+ u'output_key': u'demo-test-subnet-gateway_ip',
+ u'description': u''
+ },
+ {u'output_value': u'',
+ u'output_key': u'ares.demo-test-port-device_id',
+ u'description': u''
+ },
+ {u'output_value': u'172.24.4.7',
+ u'output_key': u'ares.demo-fip',
+ u'description': u''
+ },
+ {u'output_value': u'fa:16:3e:6c:c3:0f',
+ u'output_key': u'ares.demo-test-port-mac_address',
+ u'description': u''}
+ ]
+ )
+ expected_outputs = {
+ 'ares.demo-test-port-network_id': 'b734d06a-dec7-...',
+ 'ares.demo-test-port-subnet_id': 'b08da78c-2218-...',
+ 'demo-test-subnet-cidr': '10.0.1.0/24',
+ 'demo-test-subnet': 'b08da78c-2218-...',
+ 'ares.demo': 'b1a03624-aefc-...',
+ 'demo-secgroup': '266a8088-c630-...',
+ 'ares.demo-test-port': '10.0.1.5',
+ 'demo-test-subnet-gateway_ip': '10.0.1.1',
+ 'ares.demo-test-port-device_id': '',
+ 'ares.demo-fip': '172.24.4.7',
+ 'ares.demo-test-port-mac_address': 'fa:16:3e:6c:c3:0f',
+ }
+
+ stack_id = "my-existing-stack-id"
+ self.heatstack.name = "my-existing-stack"
+ self.heatstack.get()
+
+ self.mock_stack_get.assert_called_once_with(self.heatstack.name)
+ self.assertEqual(expected_outputs, self.heatstack.outputs)
+ self.assertEqual(1, len(heat._DEPLOYED_STACKS))
+ self.assertEqual(self.heatstack._stack,
+ heat._DEPLOYED_STACKS[stack_id])
+
+ def test_get_invalid_name(self):
+ # No context matching this name exists
+ self.mock_stack_get.return_value = []
+ self.heatstack.name = 'not-a-stack'
+ self.heatstack.get()
+ self.assertEqual(0, len(heat._DEPLOYED_STACKS))
+
class HeatTemplateTestCase(unittest.TestCase):
@@ -160,7 +247,8 @@ class HeatTemplateTestCase(unittest.TestCase):
def test__add_resources_to_template_raw(self):
test_context = node.NodeContext()
- test_context.name = 'foo'
+ self.addCleanup(test_context._delete_context)
+ test_context._name = 'foo'
test_context.template_file = '/tmp/some-heat-file'
test_context.heat_parameters = {'image': 'cirros'}
test_context.key_filename = "/tmp/1234"
@@ -184,10 +272,18 @@ class HeatTemplateTestCase(unittest.TestCase):
heat_template.add_subnet("subnet2", "network2", "cidr2")
heat_template.add_router("router1", "gw1", "subnet1")
heat_template.add_router_interface("router_if1", "router1", "subnet1")
- heat_template.add_port("port1", "network1", "subnet1", "normal")
- heat_template.add_port("port2", "network2", "subnet2", "normal",
+ network1 = mock.MagicMock()
+ network1.stack_name = "network1"
+ network1.subnet_stack_name = "subnet1"
+ network1.vnic_type = "normal"
+ network2 = mock.MagicMock()
+ network2.stack_name = "network2"
+ network2.subnet_stack_name = "subnet2"
+ network2.vnic_type = "normal"
+ heat_template.add_port("port1", network1)
+ heat_template.add_port("port2", network2,
sec_group_id="sec_group1", provider="not-sriov")
- heat_template.add_port("port3", "network2", "subnet2", "normal",
+ heat_template.add_port("port3", network2,
sec_group_id="sec_group1", provider="sriov")
heat_template.add_floating_ip("floating_ip1", "network1", "port1",
"router_if1")
diff --git a/yardstick/tests/unit/orchestrator/test_kubernetes.py b/yardstick/tests/unit/orchestrator/test_kubernetes.py
index 33fa1dca6..f2bc5b0f4 100644
--- a/yardstick/tests/unit/orchestrator/test_kubernetes.py
+++ b/yardstick/tests/unit/orchestrator/test_kubernetes.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
##############################################################################
# Copyright (c) 2017 Intel Corporation
#
@@ -104,11 +102,3 @@ service ssh restart;while true ; do sleep 10000; done']
mock_get_pod_list.return_value.items = []
pods = k8s_template.get_rc_pods()
self.assertEqual(pods, [])
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/test_cmd/commands/test_env.py b/yardstick/tests/unit/test_cmd/commands/test_env.py
index 13c3ed44a..1156b6642 100644
--- a/yardstick/tests/unit/test_cmd/commands/test_env.py
+++ b/yardstick/tests/unit/test_cmd/commands/test_env.py
@@ -63,11 +63,3 @@ class EnvCommandTestCase(unittest.TestCase):
except Exception as e: # pylint: disable=broad-except
# NOTE(ralonsoh): try to reduce the scope of this exception.
self.assertIsInstance(e, IndexError)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/test_cmd/commands/test_testcase.py b/yardstick/tests/unit/test_cmd/commands/test_testcase.py
index 7ef157c19..f6f842e20 100644
--- a/yardstick/tests/unit/test_cmd/commands/test_testcase.py
+++ b/yardstick/tests/unit/test_cmd/commands/test_testcase.py
@@ -19,11 +19,3 @@ class TestcaseCommandsUT(unittest.TestCase):
mock_client.get.return_value = {'result': []}
TestcaseCommands().do_list({})
self.assertTrue(mock_print.called)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/yardstick/tests/unit/test_cmd/test_NSBperf.py b/yardstick/tests/unit/test_cmd/test_NSBperf.py
index 483e82a13..d64b0c551 100644
--- a/yardstick/tests/unit/test_cmd/test_NSBperf.py
+++ b/yardstick/tests/unit/test_cmd/test_NSBperf.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
# Copyright (c) 2016-2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -91,17 +89,17 @@ class TestYardstickNSCli(unittest.TestCase):
subprocess.check_output = mock.Mock(return_value=0)
args = {"vnf": "vpe",
"test": "tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml"}
- self.assertEqual(None, yardstick_ns_cli.run_test(args, test_path))
+ self.assertIsNone(yardstick_ns_cli.run_test(args, test_path))
os.chdir(cur_dir)
args = {"vnf": "vpe1"}
- self.assertEqual(None, yardstick_ns_cli.run_test(args, test_path))
+ self.assertIsNone(yardstick_ns_cli.run_test(args, test_path))
os.chdir(cur_dir)
args = {"vnf": "vpe",
"test": "tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml."}
- self.assertEqual(None, yardstick_ns_cli.run_test(args, test_path))
+ self.assertIsNone(yardstick_ns_cli.run_test(args, test_path))
os.chdir(cur_dir)
args = []
- self.assertEqual(None, yardstick_ns_cli.run_test(args, test_path))
+ self.assertIsNone(yardstick_ns_cli.run_test(args, test_path))
os.chdir(cur_dir)
def test_terminate_if_less_options(self):
diff --git a/yardstick/tests/unit/test_ssh.py b/yardstick/tests/unit/test_ssh.py
index dbaae8c37..f92290070 100644
--- a/yardstick/tests/unit/test_ssh.py
+++ b/yardstick/tests/unit/test_ssh.py
@@ -21,12 +21,13 @@ import os
import socket
import unittest
from io import StringIO
+from itertools import count
import mock
from oslo_utils import encodeutils
from yardstick import ssh
-from yardstick.ssh import SSHError
+from yardstick.ssh import SSHError, SSHTimeout
from yardstick.ssh import SSH
from yardstick.ssh import AutoConnectSSH
@@ -508,13 +509,45 @@ class SSHRunTestCase(unittest.TestCase):
class TestAutoConnectSSH(unittest.TestCase):
- def test__connect_with_wait(self):
- auto_connect_ssh = AutoConnectSSH('user1', 'host1', wait=True)
- auto_connect_ssh._get_client = mock.Mock()
- auto_connect_ssh.wait = mock_wait = mock.Mock()
+ def test__connect_loop(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1', wait=0)
+ auto_connect_ssh._get_client = mock__get_client = mock.Mock()
auto_connect_ssh._connect()
- self.assertEqual(mock_wait.call_count, 1)
+ self.assertEqual(mock__get_client.call_count, 1)
+
+ def test___init___negative(self):
+ with self.assertRaises(TypeError):
+ AutoConnectSSH('user1', 'host1', wait=['wait'])
+
+ with self.assertRaises(ValueError):
+ AutoConnectSSH('user1', 'host1', wait='wait')
+
+ @mock.patch('yardstick.ssh.time')
+ def test__connect_loop_ssh_error(self, mock_time):
+ mock_time.time.side_effect = count()
+
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1', wait=10)
+ auto_connect_ssh._get_client = mock__get_client = mock.Mock()
+ mock__get_client.side_effect = SSHError
+
+ with self.assertRaises(SSHTimeout):
+ auto_connect_ssh._connect()
+
+ self.assertEqual(mock_time.time.call_count, 12)
+
+ def test_get_file_obj(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1', wait=10)
+ auto_connect_ssh._get_client = mock__get_client = mock.Mock()
+ mock_client = mock__get_client()
+ mock_open_sftp = mock_client.open_sftp()
+ mock_sftp = mock.Mock()
+ mock_open_sftp.__enter__ = mock.Mock(return_value=mock_sftp)
+ mock_open_sftp.__exit__ = mock.Mock()
+
+ auto_connect_ssh.get_file_obj('remote/path', mock.Mock())
+
+ self.assertEqual(mock_sftp.getfo.call_count, 1)
def test__make_dict(self):
auto_connect_ssh = AutoConnectSSH('user1', 'host1')
@@ -527,7 +560,7 @@ class TestAutoConnectSSH(unittest.TestCase):
'key_filename': None,
'password': None,
'name': None,
- 'wait': True,
+ 'wait': AutoConnectSSH.DEFAULT_WAIT_TIMEOUT,
}
result = auto_connect_ssh._make_dict()
self.assertDictEqual(result, expected)
@@ -537,6 +570,13 @@ class TestAutoConnectSSH(unittest.TestCase):
self.assertEqual(auto_connect_ssh.get_class(), AutoConnectSSH)
+ def test_drop_connection(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+ self.assertFalse(auto_connect_ssh._client)
+ auto_connect_ssh._client = True
+ auto_connect_ssh.drop_connection()
+ self.assertFalse(auto_connect_ssh._client)
+
@mock.patch('yardstick.ssh.SCPClient')
def test_put(self, mock_scp_client_type):
auto_connect_ssh = AutoConnectSSH('user1', 'host1')
@@ -562,11 +602,3 @@ class TestAutoConnectSSH(unittest.TestCase):
auto_connect_ssh.put_file('a', 'b')
self.assertEqual(mock_put_sftp.call_count, 1)
-
-
-def main():
- unittest.main()
-
-
-if __name__ == '__main__':
- main()