integration: Support of integration testcases
[vswitchperf.git] / testcases / testcase.py
index d470d95..0effce7 100644 (file)
 
 import csv
 import os
+import time
 import logging
 import subprocess
 import copy
-import time
 from collections import OrderedDict
 
-from core.results.results_constants import ResultsConstants
 import core.component_factory as component_factory
 from core.loader import Loader
+from core.results.results_constants import ResultsConstants
 from tools import tasks
 from tools import hugepages
-from tools.report import report
-from conf import settings as S
 from tools.pkt_gen.trafficgen.trafficgenhelper import TRAFFIC_DEFAULTS
+from conf import settings as S
 from conf import get_test_param
 
 class TestCase(object):
@@ -46,24 +45,44 @@ class TestCase(object):
         :param results_dir: Where the csv formatted results are written.
         """
         self._hugepages_mounted = False
+        self._traffic_ctl = None
+        self._vnf_ctl = None
+        self._vswitch_ctl = None
+        self._collector = None
+        self._loadgen = None
+        self._output_file = None
+        self._tc_results = None
 
         # set test parameters; CLI options take precedence to testcase settings
         self._logger = logging.getLogger(__name__)
         self.name = cfg['Name']
         self.desc = cfg.get('Description', 'No description given.')
+        self.test = cfg.get('TestSteps', None)
 
-        bidirectional = cfg.get('biDirectional', False)
+        bidirectional = cfg.get('biDirectional', TRAFFIC_DEFAULTS['bidir'])
         bidirectional = get_test_param('bidirectional', bidirectional)
 
-        traffic_type = cfg.get('Traffic Type', 'rfc2544')
+        traffic_type = cfg.get('Traffic Type', TRAFFIC_DEFAULTS['traffic_type'])
         traffic_type = get_test_param('traffic_type', traffic_type)
 
-        framerate = cfg.get('iLoad', 100)
+        framerate = cfg.get('iLoad', TRAFFIC_DEFAULTS['frame_rate'])
         framerate = get_test_param('iload', framerate)
 
         self.deployment = cfg['Deployment']
         self._frame_mod = cfg.get('Frame Modification', None)
 
+        self._tunnel_type = None
+        self._tunnel_operation = None
+
+        if self.deployment == 'op2p':
+            self._tunnel_operation = cfg['Tunnel Operation']
+
+            if 'Tunnel Type' in cfg:
+                self._tunnel_type = cfg['Tunnel Type']
+                self._tunnel_type = get_test_param('tunnel_type',
+                                                   self._tunnel_type)
+
+
         # identify guest loopback method, so it can be added into reports
         self.guest_loopback = []
         if self.deployment in ['pvp', 'pvvp']:
@@ -78,11 +97,11 @@ class TestCase(object):
 
         # read configuration of streams; CLI parameter takes precedence to
         # testcase definition
-        multistream = cfg.get('MultiStream', 0)
+        multistream = cfg.get('MultiStream', TRAFFIC_DEFAULTS['multistream'])
         multistream = get_test_param('multistream', multistream)
-        stream_type = cfg.get('Stream Type', 'L4')
+        stream_type = cfg.get('Stream Type', TRAFFIC_DEFAULTS['stream_type'])
         stream_type = get_test_param('stream_type', stream_type)
-        pre_installed_flows = cfg.get('Pre-installed Flows', 'No')
+        pre_installed_flows = cfg.get('Pre-installed Flows', TRAFFIC_DEFAULTS['pre_installed_flows'])
         pre_installed_flows = get_test_param('pre-installed_flows', pre_installed_flows)
 
         # check if test requires background load and which generator it uses
@@ -100,8 +119,9 @@ class TestCase(object):
         # set traffic details, so they can be passed to vswitch and traffic ctls
         self._traffic = copy.deepcopy(TRAFFIC_DEFAULTS)
         self._traffic.update({'traffic_type': traffic_type,
-                              'flow_type': cfg.get('Flow Type', 'port'),
+                              'flow_type': cfg.get('Flow Type', TRAFFIC_DEFAULTS['flow_type']),
                               'bidir': bidirectional,
+                              'tunnel_type': self._tunnel_type,
                               'multistream': int(multistream),
                               'stream_type': stream_type,
                               'pre_installed_flows' : pre_installed_flows,
@@ -117,10 +137,8 @@ class TestCase(object):
         # Packet Forwarding mode
         self._vswitch_none = 'none' == S.getValue('VSWITCH').strip().lower()
 
-    def run(self):
-        """Run the test
-
-        All setup and teardown through controllers is included.
+    def run_initialize(self):
+        """ Prepare test execution environment
         """
         self._logger.debug(self.name)
 
@@ -130,36 +148,86 @@ class TestCase(object):
         # copy sources of l2 forwarding tools into VM shared dir if needed
         self._copy_fwd_tools_for_guest()
 
+        if self.deployment == "op2p":
+            self._traffic['l2'].update({'srcmac':
+                                        S.getValue('TRAFFICGEN_PORT1_MAC'),
+                                        'dstmac':
+                                        S.getValue('TRAFFICGEN_PORT2_MAC')})
+
+            self._traffic['l3'].update({'srcip':
+                                        S.getValue('TRAFFICGEN_PORT1_IP'),
+                                        'dstip':
+                                        S.getValue('TRAFFICGEN_PORT2_IP')})
+
+            if self._tunnel_operation == "decapsulation":
+                self._traffic['l2'] = S.getValue(self._tunnel_type.upper() + '_FRAME_L2')
+                self._traffic['l3'] = S.getValue(self._tunnel_type.upper() + '_FRAME_L3')
+                self._traffic['l4'] = S.getValue(self._tunnel_type.upper() + '_FRAME_L4')
+
+
         self._logger.debug("Controllers:")
         loader = Loader()
-        traffic_ctl = component_factory.create_traffic(
+        self._traffic_ctl = component_factory.create_traffic(
             self._traffic['traffic_type'],
             loader.get_trafficgen_class())
-        vnf_ctl = component_factory.create_vnf(
+
+        self._vnf_ctl = component_factory.create_vnf(
             self.deployment,
             loader.get_vnf_class())
 
         if self._vswitch_none:
-            vswitch_ctl = component_factory.create_pktfwd(
+            self._vswitch_ctl = component_factory.create_pktfwd(
                 loader.get_pktfwd_class())
         else:
-            vswitch_ctl = component_factory.create_vswitch(
+            self._vswitch_ctl = component_factory.create_vswitch(
                 self.deployment,
                 loader.get_vswitch_class(),
-                self._traffic)
+                self._traffic,
+                self._tunnel_operation)
 
-        collector = component_factory.create_collector(
+        self._collector = component_factory.create_collector(
             loader.get_collector_class(),
             self._results_dir, self.name)
-        loadgen = component_factory.create_loadgen(
+        self._loadgen = component_factory.create_loadgen(
             self._loadgen,
             self._load_cfg)
 
+        self._output_file = os.path.join(self._results_dir, "result_" + self.name +
+                                         "_" + self.deployment + ".csv")
+
         self._logger.debug("Setup:")
-        with vswitch_ctl, loadgen:
-            with vnf_ctl, collector:
+
+    def run_finalize(self):
+        """ Tear down test execution environment and record test results
+        """
+        # umount hugepages if mounted
+        self._umount_hugepages()
+
+    def run_report(self):
+        """ Report test results
+        """
+        self._logger.debug("self._collector Results:")
+        self._collector.print_results()
+
+        if S.getValue('mode') != 'trafficgen-off':
+            self._logger.debug("Traffic Results:")
+            self._traffic_ctl.print_results()
+
+            self._tc_results = self._append_results(self._traffic_ctl.get_results())
+            TestCase._write_result_to_file(self._tc_results, self._output_file)
+
+    def run(self):
+        """Run the test
+
+        All setup and teardown through controllers is included.
+        """
+        # prepare test execution environment
+        self.run_initialize()
+
+        with self._vswitch_ctl, self._loadgen:
+            with self._vnf_ctl, self._collector:
                 if not self._vswitch_none:
-                    self._add_flows(vswitch_ctl)
+                    self._add_flows()
 
                 # run traffic generator if requested, otherwise wait for manual termination
                 if S.getValue('mode') == 'trafficgen-off':
@@ -167,30 +235,28 @@ class TestCase(object):
                     self._logger.debug("All is set. Please run traffic generator manually.")
                     input(os.linesep + "Press Enter to terminate vswitchperf..." + os.linesep + os.linesep)
                 else:
-                    with traffic_ctl:
-                        traffic_ctl.send_traffic(self._traffic)
+                    if S.getValue('mode') == 'trafficgen-pause':
+                        time.sleep(2)
+                        true_vals = ('yes', 'y', 'ye', None)
+                        while True:
+                            choice = input(os.linesep + 'Transmission paused, should'
+                                           ' transmission be resumed? ' + os.linesep).lower()
+                            if not choice or choice not in true_vals:
+                                print('Please respond with \'yes\' or \'y\' ', end='')
+                            else:
+                                break
+                    with self._traffic_ctl:
+                        self._traffic_ctl.send_traffic(self._traffic)
 
                     # dump vswitch flows before they are affected by VNF termination
                     if not self._vswitch_none:
-                        vswitch_ctl.dump_vswitch_flows()
+                        self._vswitch_ctl.dump_vswitch_flows()
 
-        # umount hugepages if mounted
-        self._umount_hugepages()
-
-        self._logger.debug("Collector Results:")
-        collector.print_results()
-
-        if S.getValue('mode') != 'trafficgen-off':
-            self._logger.debug("Traffic Results:")
-            traffic_ctl.print_results()
-
-            output_file = os.path.join(self._results_dir, "result_" + self.name +
-                                       "_" + self.deployment + ".csv")
+        # tear down test execution environment and log results
+        self.run_finalize()
 
-            tc_results = self._append_results(traffic_ctl.get_results())
-            TestCase._write_result_to_file(tc_results, output_file)
-
-            report.generate(output_file, tc_results, collector.get_results())
+        # report test results
+        self.run_report()
 
     def _append_results(self, results):
         """
@@ -211,7 +277,8 @@ class TestCase(object):
                 item[ResultsConstants.SCAL_PRE_INSTALLED_FLOWS] = self._traffic['pre_installed_flows']
             if len(self.guest_loopback):
                 item[ResultsConstants.GUEST_LOOPBACK] = ' '.join(self.guest_loopback)
-
+            if self._tunnel_type:
+                item[ResultsConstants.TUNNEL_TYPE] = self._tunnel_type
         return results
 
     def _copy_fwd_tools_for_guest(self):
@@ -222,9 +289,13 @@ class TestCase(object):
         while counter < self.deployment.count('v'):
             guest_dir = S.getValue('GUEST_SHARE_DIR')[counter]
 
-            # create shared dir if it doesn't exist
-            if not os.path.exists(guest_dir):
-                os.makedirs(guest_dir)
+            # remove shared dir if it exists to avoid issues with file consistency
+            if os.path.exists(guest_dir):
+                tasks.run_task(['rm', '-f', '-r', guest_dir], self._logger,
+                               'Removing content of shared directory...', True)
+
+            # directory to share files between host and guest
+            os.makedirs(guest_dir)
 
             # copy sources into shared dir only if neccessary
             if 'testpmd' in self.guest_loopback or 'l2fwd' in self.guest_loopback:
@@ -288,7 +359,6 @@ class TestCase(object):
             for result in results:
                 writer.writerow(result)
 
-
     @staticmethod
     def _get_unique_keys(list_of_dicts):
         """Gets unique key values as ordered list of strings in given dicts
@@ -304,13 +374,10 @@ class TestCase(object):
 
         return list(result.keys())
 
-
-    def _add_flows(self, vswitch_ctl):
+    def _add_flows(self):
         """Add flows to the vswitch
-
-        :param vswitch_ctl vswitch controller
         """
-        vswitch = vswitch_ctl.get_vswitch()
+        vswitch = self._vswitch_ctl.get_vswitch()
         # TODO BOM 15-08-07 the frame mod code assumes that the
         # physical ports are ports 1 & 2. The actual numbers
         # need to be retrived from the vSwitch and the metadata value