Merge "NFVi Test stops after one hour even if configured context duration is longer"
authorRoss Brattain <ross.b.brattain@intel.com>
Wed, 7 Mar 2018 19:05:14 +0000 (19:05 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Wed, 7 Mar 2018 19:05:14 +0000 (19:05 +0000)
1  2 
yardstick/network_services/vnf_generic/vnf/sample_vnf.py

@@@ -1,4 -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.
  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")
@@@ -80,8 -119,6 +80,8 @@@ class DpdkVnfSetupEnvHelper(SetupEnvHel
  
      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):
          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')
              '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,
                                      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))
  
      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()
      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", {})
                                 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()
  
@@@ -609,8 -626,10 +609,10 @@@ class ScenarioHelper(object)
  
      @property
      def timeout(self):
-         return self.options.get('timeout', DEFAULT_VNF_TIMEOUT)
+         test_duration = self.scenario_cfg.get('runner', {}).get('duration',
+             self.options.get('timeout', DEFAULT_VNF_TIMEOUT))
+         test_timeout = self.options.get('timeout', DEFAULT_VNF_TIMEOUT)
+         return test_duration if test_duration > test_timeout else test_timeout
  
  class SampleVNF(GenericVNF):
      """ Class providing file-like API for generic VNF implementation """