diff options
Diffstat (limited to 'yardstick')
22 files changed, 897 insertions, 164 deletions
diff --git a/yardstick/benchmark/contexts/base.py b/yardstick/benchmark/contexts/base.py index 0be2eee77..e362c6a3d 100644 --- a/yardstick/benchmark/contexts/base.py +++ b/yardstick/benchmark/contexts/base.py @@ -23,7 +23,7 @@ class Context(object): @abc.abstractmethod def init(self, attrs): - "Initiate context." + """Initiate context.""" @staticmethod def get_cls(context_type): @@ -56,20 +56,34 @@ class Context(object): """get server info by name from context """ + @abc.abstractmethod + def _get_network(self, attr_name): + """get network info by name from context + """ + @staticmethod def get_server(attr_name): """lookup server info by name from context attr_name: either a name for a server created by yardstick or a dict with attribute name mapping when using external heat templates """ - server = None - for context in Context.list: - server = context._get_server(attr_name) - if server is not None: - break - - if server is None: + servers = (context._get_server(attr_name) for context in Context.list) + try: + return next(s for s in servers if s) + except StopIteration: raise ValueError("context not found for server '%r'" % attr_name) - return server + @staticmethod + def get_network(attr_name): + """lookup server info by name from context + attr_name: either a name for a server created by yardstick or a dict + with attribute name mapping when using external heat templates + """ + + networks = (context._get_network(attr_name) for context in Context.list) + try: + return next(n for n in networks if n) + except StopIteration: + raise ValueError("context not found for server '%r'" % + attr_name) diff --git a/yardstick/benchmark/contexts/dummy.py b/yardstick/benchmark/contexts/dummy.py index c658d3257..8ae4b65b8 100644 --- a/yardstick/benchmark/contexts/dummy.py +++ b/yardstick/benchmark/contexts/dummy.py @@ -37,3 +37,6 @@ class DummyContext(Context): def _get_server(self, attr_name): return None + + def _get_network(self, attr_name): + return None diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py index fed8fc342..d5349eab5 100644 --- a/yardstick/benchmark/contexts/heat.py +++ b/yardstick/benchmark/contexts/heat.py @@ -25,6 +25,7 @@ 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.constants import YARDSTICK_ROOT_PATH @@ -54,9 +55,11 @@ 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.heat_timeout = None self.key_filename = ''.join( [YARDSTICK_ROOT_PATH, 'yardstick/resources/files/yardstick_key-', get_short_key_uuid(self.key_uuid)]) @@ -65,15 +68,16 @@ class HeatContext(Context): def assign_external_network(self, networks): sorted_networks = sorted(networks.items()) external_network = os.environ.get("EXTERNAL_NETWORK", "net04_ext") - have_external_network = [(name, net) - for name, net in sorted_networks if - net.get("external_network")] - # no external net defined, assign it to first network usig os.environ + + have_external_network = any(net.get("external_network") for net in networks.values()) if sorted_networks and not have_external_network: + # no external net defined, assign it to first network using os.environ sorted_networks[0][1]["external_network"] = external_network - return sorted_networks - def init(self, attrs): # pragma: no cover + self.networks = OrderedDict((name, Network(name, self, attrs)) + for name, attrs in sorted_networks) + + def init(self, attrs): """initializes itself from the supplied arguments""" self.name = attrs["name"] @@ -103,11 +107,7 @@ class HeatContext(Context): # we have to do this first, because we are injecting external_network # into the dict - sorted_networks = self.assign_external_network(attrs["networks"]) - - self.networks = OrderedDict( - (name, Network(name, self, netattrs)) for name, netattrs in - sorted_networks) + self.assign_external_network(attrs["networks"]) for name, serverattrs in sorted(attrs["servers"].items()): server = Server(name, self, serverattrs) @@ -120,7 +120,6 @@ class HeatContext(Context): with open(self.key_filename + ".pub", "w") as pubkey_file: pubkey_file.write( "%s %s\n" % (rsa_key.get_name(), rsa_key.get_base64())) - del rsa_key @property def image(self): @@ -153,9 +152,12 @@ class HeatContext(Context): template.add_network(network.stack_name, network.physical_network, network.provider, - network.segmentation_id) + network.segmentation_id, + network.port_security_enabled) template.add_subnet(network.subnet_stack_name, network.stack_name, - network.subnet_cidr) + network.subnet_cidr, + network.enable_dhcp, + network.gateway_ip) if network.router: template.add_router(network.router.stack_name, @@ -194,7 +196,7 @@ class HeatContext(Context): scheduler_hints = {} for pg in server.placement_groups: update_scheduler_hints(scheduler_hints, added_servers, pg) - # workround for openstack nova bug, check JIRA: YARDSTICK-200 + # workaround for openstack nova bug, check JIRA: YARDSTICK-200 # for details if len(availability_servers) == 2: if not scheduler_hints["different_host"]: @@ -250,6 +252,20 @@ class HeatContext(Context): list(self.networks.values()), scheduler_hints) + def get_neutron_info(self): + if not self.neutron_client: + self.neutron_client = get_neutron_client() + + networks = self.neutron_client.list_networks() + for network in self.networks.values(): + for neutron_net in networks['networks']: + if neutron_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 deploy(self): """deploys template into a stack using cloud""" print("Deploying context '%s'" % self.name) @@ -267,20 +283,16 @@ class HeatContext(Context): raise SystemExit("\nStack create interrupted") except: LOG.exception("stack failed") + # let the other failures happen, we want stack trace raise - # let the other failures happend, we want stack trace + + # TODO: use Neutron to get segementation-id + self.get_neutron_info() # copy some vital stack output into server objects for server in self.servers: if server.ports: - # TODO(hafe) can only handle one internal network for now - port = next(iter(server.ports.values())) - server.private_ip = self.stack.outputs[port["stack_name"]] - server.interfaces = {} - for network_name, port in server.ports.items(): - self.make_interface_dict(network_name, port['stack_name'], - server, - self.stack.outputs) + self.add_server_port(server) if server.floating_ip: server.public_ip = \ @@ -288,24 +300,36 @@ class HeatContext(Context): print("Context '%s' deployed" % self.name) - def make_interface_dict(self, network_name, stack_name, server, outputs): - server.interfaces[network_name] = { - "private_ip": outputs[stack_name], + def add_server_port(self, server): + # TODO(hafe) can only handle one internal network for now + port = next(iter(server.ports.values())) + server.private_ip = self.stack.outputs[port["stack_name"]] + server.interfaces = {} + for network_name, port in server.ports.items(): + server.interfaces[network_name] = self.make_interface_dict( + network_name, port['stack_name'], self.stack.outputs) + + def make_interface_dict(self, network_name, stack_name, outputs): + private_ip = outputs[stack_name] + mac_addr = outputs[stack_name + "-mac_address"] + subnet_cidr_key = "-".join([self.name, network_name, 'subnet', 'cidr']) + gateway_key = "-".join([self.name, network_name, 'subnet', 'gateway_ip']) + subnet_cidr = outputs[subnet_cidr_key] + subnet_ip = ipaddress.ip_network(subnet_cidr) + return { + "private_ip": private_ip, "subnet_id": outputs[stack_name + "-subnet_id"], - "subnet_cidr": outputs[ - "{}-{}-subnet-cidr".format(self.name, network_name)], - "netmask": str(ipaddress.ip_network( - outputs["{}-{}-subnet-cidr".format(self.name, - network_name)]).netmask), - "gateway_ip": outputs[ - "{}-{}-subnet-gateway_ip".format(self.name, network_name)], - "mac_address": outputs[stack_name + "-mac_address"], + "subnet_cidr": subnet_cidr, + "network": str(subnet_ip.network_address), + "netmask": str(subnet_ip.netmask), + "gateway_ip": outputs[gateway_key], + "mac_address": mac_addr, "device_id": outputs[stack_name + "-device_id"], "network_id": outputs[stack_name + "-network_id"], "network_name": network_name, # to match vnf_generic - "local_mac": outputs[stack_name + "-mac_address"], - "local_ip": outputs[stack_name], + "local_mac": mac_addr, + "local_ip": private_ip, "vld_id": self.networks[network_name].vld_id, } @@ -326,6 +350,19 @@ class HeatContext(Context): super(HeatContext, self).undeploy() + @staticmethod + def generate_routing_table(server): + routes = [ + { + "network": intf["network"], + "netmask": intf["netmask"], + "if": name, + "gateway": intf["gateway_ip"], + } + for name, intf in server.interfaces.items() + ] + return routes + def _get_server(self, attr_name): """lookup server info by name from context attr_name: either a name for a server created by yardstick or a dict @@ -335,7 +372,10 @@ class HeatContext(Context): 'yardstick.resources', 'files/yardstick_key-' + get_short_key_uuid(self.key_uuid)) - if isinstance(attr_name, collections.Mapping): + if not isinstance(attr_name, collections.Mapping): + server = self._server_map.get(attr_name, None) + + else: cname = attr_name["name"].split(".")[1] if cname != self.name: return None @@ -352,10 +392,6 @@ class HeatContext(Context): server = Server(attr_name["name"].split(".")[0], self, {}) server.public_ip = public_ip server.private_ip = private_ip - else: - if attr_name not in self._server_map: - return None - server = self._server_map[attr_name] if server is None: return None @@ -365,9 +401,37 @@ class HeatContext(Context): "key_filename": key_filename, "private_ip": server.private_ip, "interfaces": server.interfaces, + "routing_table": self.generate_routing_table(server), + # empty IPv6 routing table + "nd_route_tbl": [], } # Target server may only have private_ip if server.public_ip: result["ip"] = server.public_ip return result + + def _get_network(self, attr_name): + if not isinstance(attr_name, collections.Mapping): + network = self.networks.get(attr_name, None) + + else: + # Don't generalize too much Just support vld_id + vld_id = attr_name.get('vld_id') + if vld_id is None: + return None + + network = next((n for n in self.networks.values() if + getattr(n, "vld_id", None) == vld_id), None) + + if network is None: + return None + + result = { + "name": network.name, + "vld_id": network.vld_id, + "segmentation_id": network.segmentation_id, + "network_type": network.network_type, + "physical_network": network.physical_network, + } + return result diff --git a/yardstick/benchmark/contexts/kubernetes.py b/yardstick/benchmark/contexts/kubernetes.py new file mode 100644 index 000000000..a39f63137 --- /dev/null +++ b/yardstick/benchmark/contexts/kubernetes.py @@ -0,0 +1,140 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd. +# +# 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 +############################################################################## + +from __future__ import absolute_import +import logging +import time +import pkg_resources + +import paramiko + +from yardstick.benchmark.contexts.base import Context +from yardstick.orchestrator.kubernetes import KubernetesTemplate +from yardstick.common import kubernetes_utils as k8s_utils +from yardstick.common import utils + +LOG = logging.getLogger(__name__) +BITS_LENGTH = 2048 + + +class KubernetesContext(Context): + """Class that handle nodes info""" + + __context_type__ = "Kubernetes" + + def __init__(self): + self.name = '' + self.ssh_key = '' + self.key_path = '' + self.public_key_path = '' + self.template = None + + super(KubernetesContext, self).__init__() + + def init(self, attrs): + self.name = attrs.get('name', '') + + template_cfg = attrs.get('servers', {}) + self.template = KubernetesTemplate(self.name, template_cfg) + + self.ssh_key = '{}-key'.format(self.name) + + self.key_path = self._get_key_path() + self.public_key_path = '{}.pub'.format(self.key_path) + + def deploy(self): + LOG.info('Creating ssh key') + self._set_ssh_key() + + LOG.info('Launch containers') + self._create_rcs() + time.sleep(1) + self.template.get_rc_pods() + + self._wait_until_running() + + def undeploy(self): + self._delete_ssh_key() + self._delete_rcs() + self._delete_pods() + + super(KubernetesContext, self).undeploy() + + def _wait_until_running(self): + while not all(self._check_pod_status(p) for p in self.template.pods): + time.sleep(1) + + def _check_pod_status(self, pod): + status = k8s_utils.read_pod_status(pod) + LOG.debug('%s:%s', pod, status) + if status == 'Failed': + LOG.error('Pod %s status is failed', pod) + raise RuntimeError + if status != 'Running': + return False + return True + + def _create_rcs(self): + for obj in self.template.k8s_objs: + self._create_rc(obj.get_template()) + + def _create_rc(self, template): + k8s_utils.create_replication_controller(template) + + def _delete_rcs(self): + for rc in self.template.rcs: + self._delete_rc(rc) + + def _delete_rc(self, rc): + k8s_utils.delete_replication_controller(rc) + + def _delete_pods(self): + for pod in self.template.pods: + self._delete_pod(pod) + + def _delete_pod(self, pod): + k8s_utils.delete_pod(pod) + + def _get_key_path(self): + task_id = self.name.split('-')[-1] + k = 'files/yardstick_key-{}'.format(task_id) + return pkg_resources.resource_filename('yardstick.resources', k) + + def _set_ssh_key(self): + rsa_key = paramiko.RSAKey.generate(bits=BITS_LENGTH) + + LOG.info('Writing private key') + rsa_key.write_private_key_file(self.key_path) + + LOG.info('Writing public key') + key = '{} {}\n'.format(rsa_key.get_name(), rsa_key.get_base64()) + with open(self.public_key_path, 'w') as f: + f.write(key) + + LOG.info('Create configmap for ssh key') + k8s_utils.create_config_map(self.ssh_key, {'authorized_keys': key}) + + def _delete_ssh_key(self): + k8s_utils.delete_config_map(self.ssh_key) + utils.remove_file(self.key_path) + utils.remove_file(self.public_key_path) + + def _get_server(self, name): + resp = k8s_utils.get_pod_list() + hosts = ({'name': n.metadata.name, + 'ip': n.status.pod_ip, + 'user': 'root', + 'key_filename': self.key_path, + 'private_ip': n.status.pod_ip} + for n in resp.items if n.metadata.name.startswith(name)) + + return next(hosts, None) + + def _get_network(self, attr_name): + return None diff --git a/yardstick/benchmark/contexts/model.py b/yardstick/benchmark/contexts/model.py index 5077a9786..6601ecf3b 100644 --- a/yardstick/benchmark/contexts/model.py +++ b/yardstick/benchmark/contexts/model.py @@ -104,15 +104,29 @@ class Network(Object): self.stack_name = context.name + "-" + self.name self.subnet_stack_name = self.stack_name + "-subnet" self.subnet_cidr = attrs.get('cidr', '10.0.1.0/24') + self.enable_dhcp = attrs.get('enable_dhcp', 'true') self.router = None self.physical_network = attrs.get('physical_network', 'physnet1') - self.provider = attrs.get('provider', None) - self.segmentation_id = attrs.get('segmentation_id', None) + self.provider = attrs.get('provider') + self.segmentation_id = attrs.get('segmentation_id') + self.network_type = attrs.get('network_type') + self.port_security_enabled = attrs.get('port_security_enabled', True) + self.allowed_address_pairs = attrs.get('allowed_address_pairs', []) + try: + # we require 'null' or '' to disable setting gateway_ip + self.gateway_ip = attrs['gateway_ip'] + except KeyError: + # default to explicit None + self.gateway_ip = None + else: + # null is None in YAML, so we have to convert back to string + 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"]) - self.vld_id = attrs.get("vld_id", "") + self.vld_id = attrs.get("vld_id") Network.list.append(self) @@ -233,10 +247,16 @@ class Server(Object): # pragma: no cover for network in networks: port_name = server_name + "-" + network.name + "-port" self.ports[network.name] = {"stack_name": port_name} - template.add_port(port_name, network.stack_name, - network.subnet_stack_name, - sec_group_id=self.secgroup_name, - provider=network.provider) + # we can't use secgroups if port_security_enabled is False + if network.port_security_enabled: + sec_group_id = self.secgroup_name + else: + sec_group_id = None + # 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, + sec_group_id=sec_group_id, provider=network.provider, + allowed_address_pairs=network.allowed_address_pairs) port_name_list.append(port_name) if self.floating_ip: @@ -247,7 +267,7 @@ class Server(Object): # pragma: no cover external_network, port_name, network.router.stack_if_name, - self.secgroup_name) + sec_group_id) self.floating_ip_assoc["stack_name"] = \ server_name + "-fip-assoc" template.add_floating_ip_association( diff --git a/yardstick/benchmark/contexts/node.py b/yardstick/benchmark/contexts/node.py index baa1cf5d6..b3f0aca0e 100644 --- a/yardstick/benchmark/contexts/node.py +++ b/yardstick/benchmark/contexts/node.py @@ -33,6 +33,7 @@ class NodeContext(Context): self.name = None self.file_path = None self.nodes = [] + self.networks = {} self.controllers = [] self.computes = [] self.baremetals = [] @@ -77,6 +78,9 @@ class NodeContext(Context): self.env = attrs.get('env', {}) LOG.debug("Env: %r", self.env) + # add optional static network definition + self.networks.update(cfg.get("networks", {})) + def deploy(self): config_type = self.env.get('type', '') if config_type == 'ansible': @@ -141,6 +145,32 @@ class NodeContext(Context): node["name"] = attr_name return node + def _get_network(self, attr_name): + if not isinstance(attr_name, collections.Mapping): + network = self.networks.get(attr_name) + + else: + # Don't generalize too much Just support vld_id + vld_id = attr_name.get('vld_id') + if vld_id is None: + return None + + network = next((n for n in self.networks.values() if + n.get("vld_id") == vld_id), None) + + if network is None: + return None + + result = { + # name is required + "name": network["name"], + "vld_id": network.get("vld_id"), + "segmentation_id": network.get("segmentation_id"), + "network_type": network.get("network_type"), + "physical_network": network.get("physical_network"), + } + return result + def _execute_script(self, node_name, info): if node_name == 'local': self._execute_local_script(info) diff --git a/yardstick/benchmark/contexts/standalone.py b/yardstick/benchmark/contexts/standalone.py index 78eaac7ee..8614f0cac 100644 --- a/yardstick/benchmark/contexts/standalone.py +++ b/yardstick/benchmark/contexts/standalone.py @@ -36,6 +36,7 @@ class StandaloneContext(Context): self.name = None self.file_path = None self.nodes = [] + self.networks = {} self.nfvi_node = [] super(StandaloneContext, self).__init__() @@ -66,8 +67,11 @@ class StandaloneContext(Context): self.nodes.extend(cfg["nodes"]) self.nfvi_node.extend([node for node in cfg["nodes"] if node["role"] == "nfvi_node"]) + # add optional static network definition + self.networks.update(cfg.get("networks", {})) LOG.debug("Nodes: %r", self.nodes) LOG.debug("NFVi Node: %r", self.nfvi_node) + LOG.debug("Networks: %r", self.networks) def deploy(self): """don't need to deploy""" @@ -114,3 +118,31 @@ class StandaloneContext(Context): node["name"] = attr_name return node + + def _get_network(self, attr_name): + if not isinstance(attr_name, collections.Mapping): + network = self.networks.get(attr_name) + + else: + # Don't generalize too much Just support vld_id + vld_id = attr_name.get('vld_id') + if vld_id is None: + return None + try: + network = next(n for n in self.networks.values() if + n.get("vld_id") == vld_id) + except StopIteration: + return None + + if network is None: + return None + + result = { + # name is required + "name": network["name"], + "vld_id": network.get("vld_id"), + "segmentation_id": network.get("segmentation_id"), + "network_type": network.get("network_type"), + "physical_network": network.get("physical_network"), + } + return result diff --git a/yardstick/benchmark/core/task.py b/yardstick/benchmark/core/task.py index 0e85e6316..b53d6446e 100644 --- a/yardstick/benchmark/core/task.py +++ b/yardstick/benchmark/core/task.py @@ -322,6 +322,8 @@ class Task(object): # pragma: no cover if "nodes" in scenario_cfg: context_cfg["nodes"] = parse_nodes_with_context(scenario_cfg) + context_cfg["networks"] = get_networks_from_nodes( + context_cfg["nodes"]) runner = base_runner.Runner.get(runner_cfg) print("Starting runner of type '%s'" % runner_cfg["type"]) @@ -518,7 +520,7 @@ class TaskParser(object): # pragma: no cover cfg_schema)) def _check_precondition(self, cfg): - """Check if the envrionment meet the preconditon""" + """Check if the environment meet the precondition""" if "precondition" in cfg: precondition = cfg["precondition"] @@ -573,14 +575,26 @@ def _is_background_scenario(scenario): def parse_nodes_with_context(scenario_cfg): - """paras the 'nodes' fields in scenario """ + """parse the 'nodes' fields in scenario """ nodes = scenario_cfg["nodes"] - - nodes_cfg = {} - for nodename in nodes: - nodes_cfg[nodename] = Context.get_server(nodes[nodename]) - - return nodes_cfg + return {nodename: Context.get_server(node) for nodename, node in nodes.items()} + + +def get_networks_from_nodes(nodes): + """parse the 'nodes' fields in scenario """ + networks = {} + for node in nodes.values(): + if not node: + continue + for interface in node['interfaces'].values(): + vld_id = interface.get('vld_id') + # mgmt network doesn't have vld_id + if not vld_id: + continue + network = Context.get_network({"vld_id": vld_id}) + if network: + networks[network['name']] = network + return networks def runner_join(runner): diff --git a/yardstick/benchmark/core/testsuite.py b/yardstick/benchmark/core/testsuite.py new file mode 100644 index 000000000..e3940a0ba --- /dev/null +++ b/yardstick/benchmark/core/testsuite.py @@ -0,0 +1,42 @@ +############################################################################## +# Copyright (c) 2015 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 +############################################################################## + +""" Handler for yardstick command 'testcase' """ +from __future__ import absolute_import +from __future__ import print_function + +import os +import logging + +from yardstick.common import constants as consts + +LOG = logging.getLogger(__name__) + + +class Testsuite(object): + """Testcase commands. + + Set of commands to discover and display test cases. + """ + + def list_all(self, args): + """List existing test cases""" + + testsuite_list = self._get_testsuite_file_list() + + return testsuite_list + + def _get_testsuite_file_list(self): + try: + testsuite_files = sorted(os.listdir(consts.TESTSUITE_DIR)) + except OSError: + LOG.exception('Failed to list dir:\n%s\n', consts.TESTSUITE_DIR) + raise + + return testsuite_files diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py index 22de0b645..50d44c1ca 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py @@ -9,7 +9,6 @@ from __future__ import absolute_import import logging import subprocess -import traceback import yardstick.ssh as ssh from yardstick.benchmark.scenarios.availability.attacker.baseattacker import \ @@ -26,9 +25,7 @@ def _execute_shell_command(command, stdin=None): output = subprocess.check_output(command, stdin=stdin, shell=True) except Exception: exitcode = -1 - output = traceback.format_exc() - LOG.error("exec command '%s' error:\n ", command) - LOG.error(traceback.format_exc()) + LOG.error("exec command '%s' error:\n ", command, exc_info=True) return exitcode, output diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py index f7ab23dcd..cb171eafa 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py @@ -47,11 +47,11 @@ class ProcessAttacker(BaseAttacker): stdin=stdin_file) if stdout: - LOG.info("check the envrioment success!") + LOG.info("check the environment success!") return int(stdout.strip('\n')) else: LOG.error( - "the host envrioment is error, stdout:%s, stderr:%s", + "the host environment is error, stdout:%s, stderr:%s", stdout, stderr) return False diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py index a0777f94e..a9488cc30 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py @@ -11,7 +11,6 @@ from __future__ import absolute_import import os import logging import subprocess -import traceback import yardstick.ssh as ssh from yardstick.benchmark.scenarios.availability.monitor import basemonitor @@ -27,9 +26,7 @@ def _execute_shell_command(command): output = subprocess.check_output(command, shell=True) except Exception: exitcode = -1 - output = traceback.format_exc() - LOG.error("exec command '%s' error:\n ", command) - LOG.error(traceback.format_exc()) + LOG.error("exec command '%s' error:\n ", command, exc_info=True) return exitcode, output diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py index 594edeaa8..9607e3005 100644 --- a/yardstick/benchmark/scenarios/networking/vnf_generic.py +++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py @@ -164,38 +164,60 @@ class NetworkServiceTestCase(base.Scenario): for vnfd in topology["constituent-vnfd"] if vnf_id == vnfd["member-vnf-index"]), None) + @staticmethod + def get_vld_networks(networks): + return {n['vld_id']: n for n in networks.values()} + def _resolve_topology(self, context_cfg, topology): for vld in topology["vld"]: - if len(vld["vnfd-connection-point-ref"]) > 2: + try: + node_0, node_1 = vld["vnfd-connection-point-ref"] + except (TypeError, ValueError): raise IncorrectConfig("Topology file corrupted, " - "too many endpoint for connection") - - node_0, node_1 = vld["vnfd-connection-point-ref"] + "wrong number of endpoints for connection") - node0 = self._find_vnf_name_from_id(topology, - node_0["member-vnf-index-ref"]) - node1 = self._find_vnf_name_from_id(topology, - node_1["member-vnf-index-ref"]) + node_0_name = self._find_vnf_name_from_id(topology, + node_0["member-vnf-index-ref"]) + node_1_name = self._find_vnf_name_from_id(topology, + node_1["member-vnf-index-ref"]) - if0 = node_0["vnfd-connection-point-ref"] - if1 = node_1["vnfd-connection-point-ref"] + node_0_ifname = node_0["vnfd-connection-point-ref"] + node_1_ifname = node_1["vnfd-connection-point-ref"] + node_0_if = context_cfg["nodes"][node_0_name]["interfaces"][node_0_ifname] + node_1_if = context_cfg["nodes"][node_1_name]["interfaces"][node_1_ifname] try: - nodes = context_cfg["nodes"] - nodes[node0]["interfaces"][if0]["vld_id"] = vld["id"] - nodes[node1]["interfaces"][if1]["vld_id"] = vld["id"] - - nodes[node0]["interfaces"][if0]["dst_mac"] = \ - nodes[node1]["interfaces"][if1]["local_mac"] - nodes[node0]["interfaces"][if0]["dst_ip"] = \ - nodes[node1]["interfaces"][if1]["local_ip"] - - nodes[node1]["interfaces"][if1]["dst_mac"] = \ - nodes[node0]["interfaces"][if0]["local_mac"] - nodes[node1]["interfaces"][if1]["dst_ip"] = \ - nodes[node0]["interfaces"][if0]["local_ip"] + vld_networks = self.get_vld_networks(context_cfg["networks"]) + + node_0_if["vld_id"] = vld["id"] + node_1_if["vld_id"] = vld["id"] + + # set peer name + node_0_if["peer_name"] = node_1_name + node_1_if["peer_name"] = node_0_name + + # set peer interface name + node_0_if["peer_ifname"] = node_1_ifname + node_1_if["peer_ifname"] = node_0_ifname + + # just load the whole network dict + node_0_if["network"] = vld_networks.get(vld["id"], {}) + node_1_if["network"] = vld_networks.get(vld["id"], {}) + + node_0_if["dst_mac"] = node_1_if["local_mac"] + node_0_if["dst_ip"] = node_1_if["local_ip"] + + node_1_if["dst_mac"] = node_0_if["local_mac"] + node_1_if["dst_ip"] = node_0_if["local_ip"] + + # add peer interface dict, but remove circular link + # TODO: don't waste memory + node_0_copy = node_0_if.copy() + node_1_copy = node_1_if.copy() + node_0_if["peer_intf"] = node_1_copy + node_1_if["peer_intf"] = node_0_copy except KeyError: - raise IncorrectConfig("Required interface not found," + raise IncorrectConfig("Required interface not found, " "topology file corrupted") @classmethod @@ -308,21 +330,36 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ return dict(network_devices) @classmethod - def get_vnf_impl(cls, vnf_model): + def get_vnf_impl(cls, vnf_model_id): """ Find the implementing class from vnf_model["vnf"]["name"] field - :param vnf_model: dictionary containing a parsed vnfd + :param vnf_model_id: parsed vnfd model ID field :return: subclass of GenericVNF """ import_modules_from_package( "yardstick.network_services.vnf_generic.vnf") - expected_name = vnf_model['id'] - impl = (c for c in itersubclasses(GenericVNF) - if c.__name__ == expected_name) + expected_name = vnf_model_id + classes_found = [] + + def impl(): + for name, class_ in ((c.__name__, c) for c in itersubclasses(GenericVNF)): + if name == expected_name: + yield class_ + classes_found.append(name) + try: - return next(impl) + return next(impl()) except StopIteration: - raise IncorrectConfig("No implementation for %s", expected_name) + pass + + raise IncorrectConfig("No implementation for %s found in %s" % + (expected_name, classes_found)) + + @staticmethod + def update_interfaces_from_node(vnfd, node): + for intf in vnfd["vdu"][0]["external-interface"]: + node_intf = node['interfaces'][intf['name']] + intf['virtual-interface'].update(node_intf) def load_vnf_models(self, scenario_cfg, context_cfg): """ Create VNF objects based on YAML descriptors @@ -339,8 +376,11 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ scenario_cfg['task_path']) as stream: vnf_model = stream.read() vnfd = vnfdgen.generate_vnfd(vnf_model, node) - vnf_impl = self.get_vnf_impl(vnfd["vnfd:vnfd-catalog"]["vnfd"][0]) - vnf_instance = vnf_impl(vnfd["vnfd:vnfd-catalog"]["vnfd"][0]) + # TODO: here add extra context_cfg["nodes"] regardless of template + vnfd = vnfd["vnfd:vnfd-catalog"]["vnfd"][0] + self.update_interfaces_from_node(vnfd, node) + vnf_impl = self.get_vnf_impl(vnfd['id']) + vnf_instance = vnf_impl(vnfd) vnf_instance.name = node_name vnfs.append(vnf_instance) diff --git a/yardstick/cmd/NSBperf.py b/yardstick/cmd/NSBperf.py index f158d57f4..011990a3d 100755 --- a/yardstick/cmd/NSBperf.py +++ b/yardstick/cmd/NSBperf.py @@ -39,13 +39,11 @@ if not PYTHONPATH or not VIRTUAL_ENV: raise SystemExit(1) -def handler(): +def sigint_handler(*args, **kwargs): """ Capture ctrl+c and exit cli """ subprocess.call(["pkill", "-9", "yardstick"]) raise SystemExit(1) -signal.signal(signal.SIGINT, handler) - class YardstickNSCli(object): """ This class handles yardstick network serivce testing """ @@ -214,5 +212,6 @@ class YardstickNSCli(object): self.run_test(args, test_path) if __name__ == "__main__": + signal.signal(signal.SIGINT, sigint_handler) NS_CLI = YardstickNSCli() NS_CLI.main() diff --git a/yardstick/common/constants.py b/yardstick/common/constants.py index d251341fc..69485a4e4 100644 --- a/yardstick/common/constants.py +++ b/yardstick/common/constants.py @@ -26,7 +26,15 @@ except KeyError: SERVER_IP = '172.17.0.1' else: with IPDB() as ip: - SERVER_IP = ip.routes['default'].gateway + try: + SERVER_IP = ip.routes['default'].gateway + except KeyError: + # during unittests ip.routes['default'] can be invalid + SERVER_IP = '127.0.0.1' + +if not SERVER_IP: + SERVER_IP = '127.0.0.1' + # dir CONF_DIR = get_param('dir.conf', '/etc/yardstick') @@ -40,12 +48,15 @@ SAMPLE_CASE_DIR = join(REPOS_DIR, 'samples') TESTCASE_DIR = join(YARDSTICK_ROOT_PATH, 'tests/opnfv/test_cases/') TESTSUITE_DIR = join(YARDSTICK_ROOT_PATH, 'tests/opnfv/test_suites/') DOCS_DIR = join(REPOS_DIR, 'docs/testing/user/userguide/') +OPENSTACK_CONF_DIR = '/etc/openstack' # file OPENRC = get_param('file.openrc', '/etc/yardstick/openstack.creds') ETC_HOSTS = get_param('file.etc_hosts', '/etc/hosts') CONF_FILE = join(CONF_DIR, 'yardstick.conf') POD_FILE = join(CONF_DIR, 'pod.yaml') +CLOUDS_CONF = join(OPENSTACK_CONF_DIR, 'clouds.yml') +K8S_CONF_FILE = join(CONF_DIR, 'admin.conf') CONF_SAMPLE_FILE = join(CONF_SAMPLE_DIR, 'yardstick.conf.sample') FETCH_SCRIPT = get_param('file.fetch_script', 'utils/fetch_os_creds.sh') FETCH_SCRIPT = join(RELENG_DIR, FETCH_SCRIPT) @@ -76,6 +87,7 @@ GRAFANA_IMAGE = get_param('grafana.image', 'grafana/grafana') GRAFANA_TAG = get_param('grafana.tag', '3.1.1') # api +API_PORT = 5000 DOCKER_URL = 'unix://var/run/docker.sock' INSTALLERS = ['apex', 'compass', 'fuel', 'joid'] SQLITE = 'sqlite:////tmp/yardstick.db' diff --git a/yardstick/common/kubernetes_utils.py b/yardstick/common/kubernetes_utils.py new file mode 100644 index 000000000..e4c232830 --- /dev/null +++ b/yardstick/common/kubernetes_utils.py @@ -0,0 +1,137 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import logging + +from kubernetes import client +from kubernetes import config +from kubernetes.client.rest import ApiException + +from yardstick.common import constants as consts + +LOG = logging.getLogger(__name__) +LOG.setLevel(logging.DEBUG) + + +def get_core_api(): # pragma: no cover + try: + config.load_kube_config(config_file=consts.K8S_CONF_FILE) + except IOError: + LOG.exception('config file not found') + raise + + return client.CoreV1Api() + + +def create_replication_controller(template, + namespace='default', + wait=False, + **kwargs): # pragma: no cover + + core_v1_api = get_core_api() + try: + core_v1_api.create_namespaced_replication_controller(namespace, + template, + **kwargs) + except ApiException: + LOG.exception('Create replication controller failed') + raise + + +def delete_replication_controller(name, + namespace='default', + wait=False, + **kwargs): # pragma: no cover + + core_v1_api = get_core_api() + body = kwargs.get('body', client.V1DeleteOptions()) + kwargs.pop('body', None) + try: + core_v1_api.delete_namespaced_replication_controller(name, + namespace, + body, + **kwargs) + except ApiException: + LOG.exception('Delete replication controller failed') + raise + + +def delete_pod(name, + namespace='default', + wait=False, + **kwargs): # pragma: no cover + + core_v1_api = get_core_api() + body = kwargs.get('body', client.V1DeleteOptions()) + kwargs.pop('body', None) + try: + core_v1_api.delete_namespaced_pod(name, + namespace, + body, + **kwargs) + except ApiException: + LOG.exception('Delete pod failed') + raise + + +def read_pod(name, + namespace='default', + **kwargs): # pragma: no cover + core_v1_api = get_core_api() + try: + resp = core_v1_api.read_namespaced_pod(name, namespace, **kwargs) + except ApiException: + LOG.exception('Read pod failed') + raise + else: + return resp + + +def read_pod_status(name, namespace='default', **kwargs): # pragma: no cover + return read_pod(name).status.phase + + +def create_config_map(name, + data, + namespace='default', + wait=False, + **kwargs): # pragma: no cover + core_v1_api = get_core_api() + metadata = client.V1ObjectMeta(name=name) + body = client.V1ConfigMap(data=data, metadata=metadata) + try: + core_v1_api.create_namespaced_config_map(namespace, body, **kwargs) + except ApiException: + LOG.exception('Create config map failed') + raise + + +def delete_config_map(name, + namespace='default', + wait=False, + **kwargs): # pragma: no cover + core_v1_api = get_core_api() + body = kwargs.get('body', client.V1DeleteOptions()) + kwargs.pop('body', None) + try: + core_v1_api.delete_namespaced_config_map(name, + namespace, + body, + **kwargs) + except ApiException: + LOG.exception('Delete config map failed') + raise + + +def get_pod_list(namespace='default'): # pragma: no cover + core_v1_api = get_core_api() + try: + return core_v1_api.list_namespaced_pod(namespace=namespace) + except ApiException: + LOG.exception('Get pod list failed') + raise diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py index 1faba4d9e..92bb7b7d3 100644 --- a/yardstick/common/utils.py +++ b/yardstick/common/utils.py @@ -24,7 +24,10 @@ import os import subprocess import sys import collections +import socket +import random from functools import reduce +from contextlib import closing import yaml import six @@ -124,6 +127,14 @@ def makedirs(d): raise +def remove_file(path): + try: + os.remove(path) + except OSError as e: + if e.errno != errno.ENOENT: + raise + + def execute_command(cmd): exec_msg = "Executing command: '%s'" % cmd logger.debug(exec_msg) @@ -232,3 +243,34 @@ def result_handler(status, data): 'result': data } return jsonify(result) + + +def change_obj_to_dict(obj): + dic = {} + for k, v in vars(obj).items(): + try: + vars(v) + except TypeError: + dic.update({k: v}) + return dic + + +def set_dict_value(dic, keys, value): + return_dic = dic + + for key in keys.split('.'): + + return_dic.setdefault(key, {}) + if key == keys.split('.')[-1]: + return_dic[key] = value + else: + return_dic = return_dic[key] + return dic + + +def get_free_port(ip): + with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: + while True: + port = random.randint(5000, 10000) + if s.connect_ex((ip, port)) != 0: + return port diff --git a/yardstick/orchestrator/heat.py b/yardstick/orchestrator/heat.py index 7958b1cfb..57b23d393 100644 --- a/yardstick/orchestrator/heat.py +++ b/yardstick/orchestrator/heat.py @@ -231,13 +231,16 @@ name (i.e. %s).\ } def add_network(self, name, physical_network='physnet1', provider=None, - segmentation_id=None): + segmentation_id=None, port_security_enabled=True): """add to the template a Neutron Net""" log.debug("adding Neutron::Net '%s'", name) if provider is None: self.resources[name] = { 'type': 'OS::Neutron::Net', - 'properties': {'name': name} + 'properties': { + 'name': name, + 'port_security_enabled': port_security_enabled, + } } else: self.resources[name] = { @@ -245,12 +248,12 @@ name (i.e. %s).\ 'properties': { 'name': name, 'network_type': 'vlan', - 'physical_network': physical_network - } + 'physical_network': physical_network, + 'port_security_enabled': port_security_enabled, + }, } if segmentation_id: - seg_id_dit = {'segmentation_id': segmentation_id} - self.resources[name]["properties"].update(seg_id_dit) + self.resources[name]['properties']['segmentation_id'] = segmentation_id def add_server_group(self, name, policies): # pragma: no cover """add to the template a ServerGroup""" @@ -262,8 +265,9 @@ name (i.e. %s).\ 'policies': policies} } - def add_subnet(self, name, network, cidr): - """add to the template a Neutron Subnet""" + def add_subnet(self, name, network, cidr, enable_dhcp='true', gateway_ip=None): + """add to the template a Neutron Subnet + """ log.debug("adding Neutron::Subnet '%s' in network '%s', cidr '%s'", name, network, cidr) self.resources[name] = { @@ -272,9 +276,12 @@ name (i.e. %s).\ 'properties': { 'name': name, 'cidr': cidr, - 'network_id': {'get_resource': network} + 'network_id': {'get_resource': network}, + 'enable_dhcp': enable_dhcp, } } + if gateway_ip is not None: + self.resources[name]['properties']['gateway_ip'] = gateway_ip self._template['outputs'][name] = { 'description': 'subnet %s ID' % name, @@ -316,9 +323,10 @@ name (i.e. %s).\ } } - def add_port(self, name, network_name, subnet_name, sec_group_id=None, - provider=None): - """add to the template a named Neutron Port""" + def add_port(self, name, network_name, subnet_name, 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', " "secgroup:%s", name, network_name, subnet_name, sec_group_id) self.resources[name] = { @@ -341,6 +349,10 @@ name (i.e. %s).\ self.resources[name]['properties']['security_groups'] = \ [sec_group_id] + if allowed_address_pairs: + self.resources[name]['properties'][ + 'allowed_address_pairs'] = allowed_address_pairs + self._template['outputs'][name] = { 'description': 'Address for interface %s' % name, 'value': {'get_attr': [name, 'fixed_ips', 0, 'ip_address']} @@ -534,6 +546,7 @@ name (i.e. %s).\ } HEAT_WAIT_LOOP_INTERVAL = 2 + HEAT_CREATE_COMPLETE_STATUS = u'CREATE_COMPLETE' def create(self, block=True, timeout=3600): """ @@ -558,10 +571,13 @@ name (i.e. %s).\ if not block: self.outputs = stack.outputs = {} + end_time = time.time() + log.info("Created stack '%s' in %.3e secs", + self.name, end_time - start_time) return stack time_limit = start_time + timeout - for status in iter(self.status, u'CREATE_COMPLETE'): + for status in iter(self.status, self.HEAT_CREATE_COMPLETE_STATUS): log.debug("stack state %s", status) if status == u'CREATE_FAILED': stack_status_reason = heat_client.stacks.get(self.uuid).stack_status_reason @@ -574,7 +590,7 @@ name (i.e. %s).\ end_time = time.time() outputs = heat_client.stacks.get(self.uuid).outputs - log.info("Created stack '%s' in %d secs", + log.info("Created stack '%s' in %.3e secs", self.name, end_time - start_time) # keep outputs as unicode diff --git a/yardstick/orchestrator/kubernetes.py b/yardstick/orchestrator/kubernetes.py new file mode 100644 index 000000000..6d7045f58 --- /dev/null +++ b/yardstick/orchestrator/kubernetes.py @@ -0,0 +1,130 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd. +# +# 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 +############################################################################## + +from __future__ import absolute_import +from __future__ import print_function + +from yardstick.common import utils +from yardstick.common import kubernetes_utils as k8s_utils + + +class KubernetesObject(object): + + def __init__(self, name, **kwargs): + super(KubernetesObject, self).__init__() + self.name = name + self.image = kwargs.get('image', 'openretriever/yardstick') + self.command = [kwargs.get('command', '/bin/bash')] + self.args = kwargs.get('args', []) + self.ssh_key = kwargs.get('ssh_key', 'yardstick_key') + + self.volumes = [] + + self.template = { + "apiVersion": "v1", + "kind": "ReplicationController", + "metadata": { + "name": "" + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "labels": { + "app": "" + } + }, + "spec": { + "containers": [], + "volumes": [] + } + } + } + } + + self._change_value_according_name(name) + self._add_containers() + self._add_ssh_key_volume() + self._add_volumes() + + def get_template(self): + return self.template + + def _change_value_according_name(self, name): + utils.set_dict_value(self.template, 'metadata.name', name) + + utils.set_dict_value(self.template, + 'spec.template.metadata.labels.app', + name) + + def _add_containers(self): + containers = [self._add_container()] + utils.set_dict_value(self.template, + 'spec.template.spec.containers', + containers) + + def _add_container(self): + container_name = '{}-container'.format(self.name) + ssh_key_mount_path = "/root/.ssh/" + + container = { + "args": self.args, + "command": self.command, + "image": self.image, + "name": container_name, + "volumeMounts": [ + { + "mountPath": ssh_key_mount_path, + "name": self.ssh_key + } + ] + } + + return container + + def _add_volumes(self): + utils.set_dict_value(self.template, + 'spec.template.spec.volumes', + self.volumes) + + def _add_volume(self, volume): + self.volumes.append(volume) + + def _add_ssh_key_volume(self): + key_volume = { + "configMap": { + "name": self.ssh_key + }, + "name": self.ssh_key + } + self._add_volume(key_volume) + + +class KubernetesTemplate(object): + + def __init__(self, name, template_cfg): + self.name = name + self.ssh_key = '{}-key'.format(name) + + self.rcs = [self._get_rc_name(rc) for rc in template_cfg] + self.k8s_objs = [KubernetesObject(self._get_rc_name(rc), + ssh_key=self.ssh_key, + **cfg) + for rc, cfg in template_cfg.items()] + self.pods = [] + + def _get_rc_name(self, rc_name): + return '{}-{}'.format(rc_name, self.name) + + def get_rc_pods(self): + resp = k8s_utils.get_pod_list() + self.pods = [p.metadata.name for p in resp.items for s in self.rcs + if p.metadata.name.startswith(s)] + + return self.pods diff --git a/yardstick/vTC/apexlake/tests/deployment_unit_test.py b/yardstick/vTC/apexlake/tests/deployment_unit_test.py index 5a9178f53..1ff4225d6 100644 --- a/yardstick/vTC/apexlake/tests/deployment_unit_test.py +++ b/yardstick/vTC/apexlake/tests/deployment_unit_test.py @@ -130,6 +130,7 @@ class DummyDeploymentUnit(mut.DeploymentUnit): raise Exception +@mock.patch("experimental_framework.deployment_unit.time") class TestDeploymentUnit(unittest.TestCase): def setUp(self): @@ -140,7 +141,7 @@ class TestDeploymentUnit(unittest.TestCase): @mock.patch('experimental_framework.heat_manager.HeatManager', side_effect=DummyHeatManager) - def test_constructor_for_sanity(self, mock_heat_manager): + def test_constructor_for_sanity(self, mock_heat_manager, mock_time): du = mut.DeploymentUnit(dict()) self.assertTrue(isinstance(du.heat_manager, DummyHeatManager)) mock_heat_manager.assert_called_once_with(dict()) @@ -150,7 +151,7 @@ class TestDeploymentUnit(unittest.TestCase): side_effect=DummyHeatManager) @mock.patch('os.path.isfile') def test_deploy_heat_template_for_failure(self, mock_os_is_file, - mock_heat_manager): + mock_heat_manager, mock_time): mock_os_is_file.return_value = False du = mut.DeploymentUnit(dict()) template_file = '' @@ -163,7 +164,7 @@ class TestDeploymentUnit(unittest.TestCase): side_effect=DummyHeatManager) @mock.patch('os.path.isfile') def test_deploy_heat_template_for_success(self, mock_os_is_file, - mock_heat_manager): + mock_heat_manager, mock_time): mock_os_is_file.return_value = True du = mut.DeploymentUnit(dict()) template_file = '' @@ -178,7 +179,7 @@ class TestDeploymentUnit(unittest.TestCase): side_effect=DummyHeatManagerComplete) @mock.patch('os.path.isfile') def test_deploy_heat_template_2_for_success(self, mock_os_is_file, - mock_heat_manager): + mock_heat_manager, mock_time): mock_os_is_file.return_value = True du = mut.DeploymentUnit(dict()) template_file = '' @@ -196,7 +197,7 @@ class TestDeploymentUnit(unittest.TestCase): side_effect=DummyDeploymentUnit) def test_deploy_heat_template_3_for_success(self, mock_dep_unit, mock_os_is_file, - mock_heat_manager): + mock_heat_manager, mock_time): mock_os_is_file.return_value = True du = mut.DeploymentUnit(dict()) template_file = '' @@ -212,7 +213,7 @@ class TestDeploymentUnit(unittest.TestCase): side_effect=DummyHeatManagerFailed) @mock.patch('os.path.isfile') def test_deploy_heat_template_for_success_2(self, mock_os_is_file, - mock_heat_manager, mock_log): + mock_heat_manager, mock_log, mock_time): mock_os_is_file.return_value = True du = DummyDeploymentUnit(dict()) template_file = '' @@ -226,7 +227,7 @@ class TestDeploymentUnit(unittest.TestCase): side_effect=DummyHeatManagerDestroy) @mock.patch('experimental_framework.common.LOG') def test_destroy_heat_template_for_success(self, mock_log, - mock_heat_manager): + mock_heat_manager, mock_time): openstack_credentials = dict() du = mut.DeploymentUnit(openstack_credentials) du.deployed_stacks = ['stack'] @@ -238,14 +239,14 @@ class TestDeploymentUnit(unittest.TestCase): side_effect=DummyHeatManagerDestroyException) @mock.patch('experimental_framework.common.LOG') def test_destroy_heat_template_for_success_2(self, mock_log, - mock_heat_manager): + mock_heat_manager, mock_time): openstack_credentials = dict() du = mut.DeploymentUnit(openstack_credentials) du.deployed_stacks = ['stack'] stack_name = 'stack' self.assertFalse(du.destroy_heat_template(stack_name)) - def test_destroy_all_deployed_stacks_for_success(self): + def test_destroy_all_deployed_stacks_for_success(self, mock_time): du = DeploymentUnitDestroy() du.destroy_all_deployed_stacks() self.assertTrue(du.destroy_heat_template()) @@ -254,7 +255,7 @@ class TestDeploymentUnit(unittest.TestCase): side_effect=DummyHeatManagerReiteration) @mock.patch('os.path.isfile') def test_deploy_heat_template_for_success_3(self, mock_os_is_file, - mock_heat_manager): + mock_heat_manager, mock_time): mock_os_is_file.return_value = True du = mut.DeploymentUnit(dict()) template = 'template_reiteration' diff --git a/yardstick/vTC/apexlake/tests/dpdk_packet_generator_test.py b/yardstick/vTC/apexlake/tests/dpdk_packet_generator_test.py index 96ead5ef7..9fa860ab4 100644 --- a/yardstick/vTC/apexlake/tests/dpdk_packet_generator_test.py +++ b/yardstick/vTC/apexlake/tests/dpdk_packet_generator_test.py @@ -359,6 +359,7 @@ class MockRunCommand: return MockRunCommand.ret_val_finalization +@mock.patch('experimental_framework.packet_generators.dpdk_packet_generator.time') class TestDpdkPacketGenOthers(unittest.TestCase): def setUp(self): @@ -370,7 +371,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): @mock.patch('experimental_framework.packet_generators.' 'dpdk_packet_generator.DpdkPacketGenerator.' '_cores_configuration') - def test__get_core_nics_for_failure(self, mock_cores_configuration): + def test__get_core_nics_for_failure(self, mock_cores_configuration, mock_time): mock_cores_configuration.return_value = None self.assertRaises(ValueError, mut.DpdkPacketGenerator._get_core_nics, '', '') @@ -379,7 +380,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): 'dpdk_packet_generator.DpdkPacketGenerator.' '_cores_configuration') def test__get_core_nics_one_nic_for_success(self, - mock_cores_configuration): + mock_cores_configuration, mock_time): mock_cores_configuration.return_value = 'ret_val' expected = 'ret_val' output = mut.DpdkPacketGenerator._get_core_nics(1, 'coremask') @@ -390,7 +391,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): 'dpdk_packet_generator.DpdkPacketGenerator.' '_cores_configuration') def test__get_core_nics_two_nics_for_success(self, - mock_cores_configuration): + mock_cores_configuration, mock_time): mock_cores_configuration.return_value = 'ret_val' expected = 'ret_val' output = mut.DpdkPacketGenerator._get_core_nics(2, 'coremask') @@ -398,7 +399,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): mock_cores_configuration.assert_called_once_with('coremask', 1, 2, 2) @mock.patch('os.path.isfile') - def test__init_input_validation_for_success(self, mock_is_file): + def test__init_input_validation_for_success(self, mock_is_file, mock_time): mock_is_file.return_value = True pcap_file_0 = 'pcap_file_0' @@ -419,7 +420,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): variables), None) @mock.patch('os.path.isfile') - def test__init_input_validation_for_failure(self, mock_is_file): + def test__init_input_validation_for_failure(self, mock_is_file, mock_time): mock_is_file.return_value = True pcap_file_0 = 'pcap_file_0' @@ -440,7 +441,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): lua_script, pcap_directory, lua_directory, variables) @mock.patch('os.path.isfile') - def test__init_input_validation_for_failure_2(self, mock_is_file): + def test__init_input_validation_for_failure_2(self, mock_is_file, mock_time): mock_is_file.return_value = True pcap_directory = None @@ -461,7 +462,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): lua_script, pcap_directory, lua_directory, variables) @mock.patch('os.path.isfile') - def test__init_input_validation_for_failure_3(self, mock_is_file): + def test__init_input_validation_for_failure_3(self, mock_is_file, mock_time): mock_is_file.return_value = True pcap_directory = 'directory' @@ -482,7 +483,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): lua_script, pcap_directory, lua_directory, variables) @mock.patch('os.path.isfile') - def test__init_input_validation_for_failure_4(self, mock_is_file): + def test__init_input_validation_for_failure_4(self, mock_is_file, mock_time): mock_is_file.return_value = True pcap_directory = 'directory' @@ -503,7 +504,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): lua_script, pcap_directory, lua_directory, variables) @mock.patch('os.path.isfile') - def test__init_input_validation_for_failure_5(self, mock_is_file): + def test__init_input_validation_for_failure_5(self, mock_is_file, mock_time): mock_is_file.return_value = True pcap_directory = 'directory' @@ -524,7 +525,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): lua_script, pcap_directory, lua_directory, variables) @mock.patch('os.path.isfile', side_effect=[False]) - def test__init_input_validation_for_failure_6(self, mock_is_file): + def test__init_input_validation_for_failure_6(self, mock_is_file, mock_time): # mock_is_file.return_value = False pcap_directory = 'directory' @@ -545,7 +546,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): lua_script, pcap_directory, lua_directory, variables) @mock.patch('os.path.isfile', side_effect=[True, False]) - def test__init_input_validation_for_failure_7(self, mock_is_file): + def test__init_input_validation_for_failure_7(self, mock_is_file, mock_time): pcap_directory = 'directory' pcap_file_0 = 'pcap_file_0' pcap_file_1 = 'pcap_file_1' @@ -564,7 +565,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): lua_script, pcap_directory, lua_directory, variables) @mock.patch('os.path.isfile', side_effect=[True, True, False]) - def test__init_input_validation_for_failure_8(self, mock_is_file): + def test__init_input_validation_for_failure_8(self, mock_is_file, mock_time): pcap_directory = 'directory' pcap_file_0 = 'pcap_file_0' pcap_file_1 = 'pcap_file_1' @@ -583,13 +584,13 @@ class TestDpdkPacketGenOthers(unittest.TestCase): lua_script, pcap_directory, lua_directory, variables) @mock.patch('os.chdir') - def test__chdir_for_success(self, mock_os_chdir): + def test__chdir_for_success(self, mock_os_chdir, mock_time): mut.DpdkPacketGenerator._chdir('directory') mock_os_chdir.assert_called_once_with('directory') @mock.patch('experimental_framework.common.run_command', side_effect=MockRunCommand.mock_run_command) - def test__init_physical_nics_for_success(self, mock_run_command): + def test__init_physical_nics_for_success(self, mock_run_command, mock_time): dpdk_interfaces = 1 dpdk_vars = dict() @@ -608,7 +609,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): @mock.patch('experimental_framework.common.run_command', side_effect=MockRunCommand.mock_run_command) - def test__init_physical_nics_for_success_2(self, mock_run_command): + def test__init_physical_nics_for_success_2(self, mock_run_command, mock_time): dpdk_interfaces = 2 dpdk_vars = dict() @@ -626,7 +627,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): [True, True, True, True, True, True]) @mock.patch('experimental_framework.common.run_command') - def test__init_physical_nics_for_failure(self, mock_run_command): + def test__init_physical_nics_for_failure(self, mock_run_command, mock_time): dpdk_interfaces = 3 dpdk_vars = dict() self.assertRaises(ValueError, self.mut._init_physical_nics, @@ -634,7 +635,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): @mock.patch('experimental_framework.common.run_command', side_effect=MockRunCommand.mock_run_command_finalization) - def test__finalize_physical_nics_for_success(self, mock_run_command): + def test__finalize_physical_nics_for_success(self, mock_run_command, mock_time): dpdk_interfaces = 1 dpdk_vars = dict() dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] = 'dpdk_directory/' @@ -652,7 +653,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): @mock.patch('experimental_framework.common.run_command', side_effect=MockRunCommand.mock_run_command_finalization) - def test__finalize_physical_nics_for_success_2(self, mock_run_command): + def test__finalize_physical_nics_for_success_2(self, mock_run_command, mock_time): dpdk_interfaces = 2 dpdk_vars = dict() dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] = 'dpdk_directory/' @@ -668,34 +669,34 @@ class TestDpdkPacketGenOthers(unittest.TestCase): self.assertEqual(MockRunCommand.mock_run_command_finalization(), [True, True, True, True, True, True]) - def test__finalize_physical_nics_for_failure(self): + def test__finalize_physical_nics_for_failure(self, mock_time): dpdk_interfaces = 0 dpdk_vars = dict() self.assertRaises(ValueError, self.mut._finalize_physical_nics, dpdk_interfaces, dpdk_vars) - def test__cores_configuration_for_success(self): + def test__cores_configuration_for_success(self, mock_time): coremask = '1f' expected = '[2:1].0,[4:3].1' output = mut.DpdkPacketGenerator._cores_configuration(coremask, 1, 2, 2) self.assertEqual(expected, output) - def test__cores_configuration_for_success_2(self): + def test__cores_configuration_for_success_2(self, mock_time): coremask = '1f' expected = '2.0,[4:3].1' output = mut.DpdkPacketGenerator._cores_configuration(coremask, 1, 1, 2) self.assertEqual(expected, output) - def test__cores_configuration_for_success_3(self): + def test__cores_configuration_for_success_3(self, mock_time): coremask = '1f' expected = '[3:2].0,4.1' output = mut.DpdkPacketGenerator._cores_configuration(coremask, 1, 2, 1) self.assertEqual(expected, output) - def test__cores_configuration_for_failure(self): + def test__cores_configuration_for_failure(self, mock_time): coremask = '1' self.assertRaises(ValueError, mut.DpdkPacketGenerator._cores_configuration, @@ -703,7 +704,7 @@ class TestDpdkPacketGenOthers(unittest.TestCase): @mock.patch('experimental_framework.common.LOG') @mock.patch('experimental_framework.common.run_command') - def test__change_vlan_for_success(self, mock_run_command, mock_log): + def test__change_vlan_for_success(self, mock_run_command, mock_log, mock_time): mut.DpdkPacketGenerator._change_vlan('/directory/', 'pcap_file', '10') expected_param = '/directory/vlan_tag.sh /directory/pcap_file 10' mock_run_command.assert_called_with(expected_param) diff --git a/yardstick/vTC/apexlake/tests/instantiation_validation_bench_test.py b/yardstick/vTC/apexlake/tests/instantiation_validation_bench_test.py index 2bd8b7b38..69c5d745e 100644 --- a/yardstick/vTC/apexlake/tests/instantiation_validation_bench_test.py +++ b/yardstick/vTC/apexlake/tests/instantiation_validation_bench_test.py @@ -257,6 +257,7 @@ class InstantiationValidationInitTest(unittest.TestCase): self.assertEqual(dummy_os_kill('', '', True), [1, 1]) self.assertEqual(dummy_run_command('', True), [1, 1, 0, 0, 0]) + @mock.patch('experimental_framework.benchmarks.instantiation_validation_benchmark.time') @mock.patch('os.chdir') @mock.patch('experimental_framework.common.run_command', side_effect=dummy_run_command_2) @@ -265,7 +266,7 @@ class InstantiationValidationInitTest(unittest.TestCase): 'InstantiationValidationBenchmark._get_pids') @mock.patch('os.kill', side_effect=dummy_os_kill) def test__init_packet_checker_for_success(self, mock_kill, mock_pids, - mock_run_command, mock_chdir): + mock_run_command, mock_chdir, mock_time): global command_counter command_counter = [0, 0, 0, 0, 0] mock_pids.return_value = [1234, 4321] @@ -314,13 +315,14 @@ class InstantiationValidationInitTest(unittest.TestCase): self.assertEqual(dummy_replace_in_file('', '', '', True), [0, 0, 0, 1, 1, 1]) + @mock.patch('experimental_framework.benchmarks.instantiation_validation_benchmark.time') @mock.patch('experimental_framework.common.LOG') @mock.patch('experimental_framework.packet_generators.' 'dpdk_packet_generator.DpdkPacketGenerator', side_effect=DummyDpdkPacketGenerator) @mock.patch('experimental_framework.common.get_dpdk_pktgen_vars') def test_run_for_success(self, mock_common_get_vars, mock_pktgen, - mock_log): + mock_log, mock_time): rval = dict() rval[cfs.CFSP_DPDK_BUS_SLOT_NIC_2] = 'bus_2' rval[cfs.CFSP_DPDK_NAME_IF_2] = 'if_2' |