X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=yardstick%2Fnetwork_services%2Fvnf_generic%2Fvnf%2Fsample_vnf.py;h=5eeb6c889c40d2e1ba3162ae5432dd4320848466;hb=67bd29933789e7f31c52290fdd43835e54f89eaf;hp=b5cf03477a5df485c77049f5c513d74c543488c8;hpb=f6bc49db9b164b8e8c9bba99b1d513edc2cc610f;p=yardstick.git diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py index b5cf03477..5eeb6c889 100644 --- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py +++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py @@ -22,15 +22,14 @@ import os import re import subprocess from collections import Mapping - from multiprocessing import Queue, Value, Process from six.moves import cStringIO 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.cpu import CpuSysCores from yardstick.network_services.helpers.samplevnf_helper import PortPairs from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper @@ -97,7 +96,6 @@ class SetupEnvHelper(object): CFG_CONFIG = os.path.join(REMOTE_TMP, "sample_config") CFG_SCRIPT = os.path.join(REMOTE_TMP, "sample_script") - CORES = [] DEFAULT_CONFIG_TPL_CFG = "sample.cfg" PIPELINE_COMMAND = '' VNF_TYPE = "SAMPLE" @@ -126,9 +124,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): APP_NAME = 'DpdkVnf' FIND_NET_CMD = "find /sys/class/net -lname '*{}*' -printf '%f'" - HW_DEFAULT_CORE = 3 - SW_DEFAULT_CORE = 2 - @staticmethod def _update_packet_type(ip_pipeline_cfg, traffic_options): match_str = 'pkt_type = ipv4' @@ -241,41 +236,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): 'tool_path': tool_path, } - def _get_app_cpu(self): - if self.CORES: - return self.CORES - - vnf_cfg = self.scenario_helper.vnf_cfg - sys_obj = CpuSysCores(self.ssh_helper) - self.sys_cpu = sys_obj.get_core_socket() - num_core = int(vnf_cfg["worker_threads"]) - if vnf_cfg.get("lb_config", "SW") == 'HW': - num_core += self.HW_DEFAULT_CORE - else: - num_core += self.SW_DEFAULT_CORE - app_cpu = self.sys_cpu[str(self.socket)][:num_core] - return app_cpu - - def _get_cpu_sibling_list(self, cores=None): - if cores is None: - cores = self._get_app_cpu() - sys_cmd_template = "%s/cpu%s/topology/thread_siblings_list" - awk_template = "awk -F: '{ print $1 }' < %s" - sys_path = "/sys/devices/system/cpu/" - cpu_topology = [] - try: - for core in cores: - sys_cmd = sys_cmd_template % (sys_path, core) - cpu_id = self.ssh_helper.execute(awk_template % sys_cmd)[1] - cpu_topology.extend(cpu.strip() for cpu in cpu_id.split(',')) - - return cpu_topology - except Exception: - return [] - - def _validate_cpu_cfg(self): - return self._get_cpu_sibling_list() - def setup_vnf_environment(self): self._setup_dpdk() self.bound_pci = [v['virtual-interface']["vpci"] for v in self.vnfd_helper.interfaces] @@ -323,7 +283,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): else: self.socket = 1 - cores = self._validate_cpu_cfg() # implicit ordering, presumably by DPDK port num, so pre-sort by port_num # this won't work because we don't have DPDK port numbers yet ports = sorted(self.vnfd_helper.interfaces, key=self.vnfd_helper.port_num) @@ -331,7 +290,7 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): collectd_options = self.get_collectd_options() plugins = collectd_options.get("plugins", {}) # we must set timeout to be the same as the VNF otherwise KPIs will die before VNF - return ResourceProfile(self.vnfd_helper.mgmt_interface, port_names=port_names, cores=cores, + return ResourceProfile(self.vnfd_helper.mgmt_interface, port_names=port_names, plugins=plugins, interval=collectd_options.get("interval"), timeout=self.scenario_helper.timeout) @@ -350,7 +309,7 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): if vpci == v['virtual-interface']['vpci']) # force to int intf['virtual-interface']['dpdk_port_num'] = int(dpdk_port_num) - except: + except: # pylint: disable=bare-except pass time.sleep(2) @@ -433,6 +392,10 @@ class ClientResourceHelper(ResourceHelper): self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.downlink_ports) self.all_ports = self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.all_ports) + def port_num(self, intf): + # by default return port num + return self.vnfd_helper.port_num(intf) + def get_stats(self, *args, **kwargs): try: return self.client.get_stats(*args, **kwargs) @@ -510,6 +473,11 @@ class ClientResourceHelper(ResourceHelper): self.client.clear_stats(ports=ports) def start(self, ports=None, *args, **kwargs): + # pylint: disable=keyword-arg-before-vararg + # NOTE(ralonsoh): defining keyworded arguments before variable + # positional arguments is a bug. This function definition doesn't work + # in Python 2, although it works in Python 3. Reference: + # https://www.python.org/dev/peps/pep-3102/ if ports is None: ports = self.all_ports self.client.start(ports=ports, *args, **kwargs) @@ -518,8 +486,8 @@ class ClientResourceHelper(ResourceHelper): if not self._queue.empty(): kpi = self._queue.get() self._result.update(kpi) - LOG.debug("Got KPIs from _queue for {0} {1}".format( - self.scenario_helper.name, self.RESOURCE_WORD)) + LOG.debug('Got KPIs from _queue for %s %s', + self.scenario_helper.name, self.RESOURCE_WORD) return self._result def _connect(self, client=None): @@ -708,7 +676,7 @@ class SampleVNF(GenericVNF): self.pipeline_kwargs = {} self.uplink_ports = None self.downlink_ports = None - # TODO(esm): make QueueFileWrapper invert-able so that we + # NOTE(esm): make QueueFileWrapper invert-able so that we # never have to manage the queues self.q_in = Queue() self.q_out = Queue() @@ -789,7 +757,7 @@ class SampleVNF(GenericVNF): if not self._vnf_process.is_alive(): raise RuntimeError("%s VNF process died." % self.APP_NAME) - # TODO(esm): move to QueueFileWrapper + # NOTE(esm): move to QueueFileWrapper while self.q_out.qsize() > 0: buf.append(self.q_out.get()) message = ''.join(buf) @@ -859,12 +827,12 @@ class SampleVNF(GenericVNF): self._vnf_process.terminate() # no terminate children here because we share processes with tg - def get_stats(self, *args, **kwargs): - """ - Method for checking the statistics + def get_stats(self, *args, **kwargs): # pylint: disable=unused-argument + """Method for checking the statistics - :return: - VNF statistics + This method could be overridden in children classes. + + :return: VNF statistics """ cmd = 'p {0} stats'.format(self.APP_WORD) out = self.vnf_execute(cmd) @@ -887,6 +855,11 @@ class SampleVNF(GenericVNF): LOG.debug("%s collect KPIs %s", self.APP_NAME, result) return result + def scale(self, flavor=""): + """The SampleVNF base class doesn't provide the 'scale' feature""" + raise y_exceptions.FunctionNotImplemented( + function_name='scale', class_name='SampleVNFTrafficGen') + class SampleVNFTrafficGen(GenericTrafficGen): """ Class providing file-like API for generic traffic generator """ @@ -924,18 +897,15 @@ class SampleVNFTrafficGen(GenericTrafficGen): def instantiate(self, scenario_cfg, context_cfg): self.scenario_helper.scenario_cfg = scenario_cfg - self.resource_helper.generate_cfg() self.resource_helper.setup() + # must generate_cfg after DPDK bind because we need port number + self.resource_helper.generate_cfg() LOG.info("Starting %s server...", self.APP_NAME) name = "{}-{}-{}".format(self.name, self.APP_NAME, os.getpid()) self._tg_process = Process(name=name, target=self._start_server) self._tg_process.start() - def wait_for_instantiate(self): - # overridden by subclasses - return self._wait_for_process() - def _check_status(self): raise NotImplementedError @@ -979,24 +949,6 @@ class SampleVNFTrafficGen(GenericTrafficGen): return self._traffic_process.is_alive() - def listen_traffic(self, traffic_profile): - """ Listen to traffic with the given parameters. - Method is non-blocking, returns immediately when traffic process - is running. Optional. - - :param traffic_profile: - :return: True/False - """ - pass - - def verify_traffic(self, traffic_profile): - """ Verify captured traffic after it has ended. Optional. - - :param traffic_profile: - :return: dict - """ - pass - def collect_kpi(self): # check if the tg processes have exited for proc in (self._tg_process, self._traffic_process): @@ -1023,3 +975,8 @@ class SampleVNFTrafficGen(GenericTrafficGen): self._tg_process.join(PROCESS_JOIN_TIMEOUT) self._tg_process.terminate() # no terminate children here because we share processes with vnf + + def scale(self, flavor=""): + """A traffic generator VFN doesn't provide the 'scale' feature""" + raise y_exceptions.FunctionNotImplemented( + function_name='scale', class_name='SampleVNFTrafficGen')