teststeps: Improvements and bugfixing of teststeps
[vswitchperf.git] / core / traffic_controller.py
1 # Copyright 2015-2017 Intel Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #   http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Base class for traffic controllers
16 """
17
18 import logging
19 import os
20 import time
21
22 from core.results.results_constants import ResultsConstants
23 from conf import settings
24
25 class TrafficController(object):
26     """Base class which defines a common functionality for all traffic
27        controller classes.
28
29     Used to setup and control a traffic generator for a particular deployment
30     scenario.
31     """
32     def __init__(self, traffic_gen_class):
33         """Initialization common for all types of traffic controllers
34
35         :param traffic_gen_class: The traffic generator class to be used.
36         """
37         self._type = None
38         self._logger = logging.getLogger(__name__)
39         self._logger.debug("__init__")
40         self._traffic_gen_class = traffic_gen_class()
41         self._traffic_started = False
42         self._traffic_started_call_count = 0
43         self._duration = None
44         self._lossrate = None
45         self._packet_sizes = None
46
47         self._mode = str(settings.getValue('mode')).lower()
48         self._results = []
49
50     def configure(self, traffic):
51         """Set configuration values just before test execution so they
52            can be changed during runtime by test steps.
53         """
54         self._duration = int(settings.getValue('TRAFFICGEN_DURATION'))
55         self._lossrate = float(settings.getValue('TRAFFICGEN_LOSSRATE'))
56         self._packet_sizes = settings.getValue('TRAFFICGEN_PKT_SIZES')
57         self._results = []
58
59         # update type with detailed traffic value
60         self._type = traffic['traffic_type']
61
62     def __enter__(self):
63         """Call initialisation function.
64         """
65         self._traffic_gen_class.connect()
66
67     def __exit__(self, type_, value, traceback):
68         """Stop traffic, clean up.
69         """
70         if self._traffic_started:
71             self.stop_traffic()
72
73     def _append_results(self, result_dict, packet_size):
74         """Adds common values to traffic generator results.
75
76         :param result_dict: Dictionary containing results from trafficgen
77         :param packet_size: Packet size value.
78
79         :returns: dictionary of results with additional entries.
80         """
81
82         ret_value = result_dict
83
84         ret_value[ResultsConstants.TYPE] = self._type
85         ret_value[ResultsConstants.PACKET_SIZE] = str(packet_size)
86
87         return ret_value
88
89     def traffic_required(self):
90         """Checks selected '--mode' of traffic generator and performs
91            its specific handling.
92
93         :returns: True - in case that traffic generator should be executed
94                   False - if traffic generation is not required
95         """
96         if self._mode == 'trafficgen-off':
97             time.sleep(2)
98             self._logger.debug("All is set. Please run traffic generator manually.")
99             input(os.linesep + "Press Enter to terminate vswitchperf..." +
100                   os.linesep + os.linesep)
101             return False
102         elif self._mode == 'trafficgen-pause':
103             time.sleep(2)
104             while True:
105                 choice = input(os.linesep + 'Transmission paused, should'
106                                ' transmission be resumed? [y/n]' + os.linesep).lower()
107                 if choice in ('yes', 'y', 'ye'):
108                     return True
109                 elif choice in ('no', 'n'):
110                     self._logger.info("Traffic transmission will be skipped.")
111                     return False
112                 else:
113                     print("Please respond with 'yes', 'y', 'no' or 'n' ", end='')
114         return True
115
116     def send_traffic(self, traffic):
117         """Triggers traffic to be sent from the traffic generator.
118
119         This is a blocking function.
120
121         :param traffic: A dictionary describing the traffic to send.
122         """
123         self._logger.debug('send_traffic with ' +
124                            str(self._traffic_gen_class))
125         self.configure(traffic)
126
127     def send_traffic_async(self, traffic, dummy_function):
128         """Triggers traffic to be sent  asynchronously.
129
130         This is not a blocking function.
131
132         :param traffic: A dictionary describing the traffic to send.
133         :param function: A dictionary describing the function to call between
134              send and wait in the form:
135              function = {
136                  'function' : package.module.function,
137                  'args' : args
138              }
139              If this function requires more than one argument, all should be
140              should be passed using the args list and appropriately handled.
141          """
142         self._logger.debug('send_traffic_async with ' +
143                            str(self._traffic_gen_class))
144         self.configure(traffic)
145
146     def stop_traffic(self):
147         """Kills traffic being sent from the traffic generator.
148         """
149         self._logger.debug("stop_traffic()")
150
151     def print_results(self):
152         """IResult interface implementation.
153         """
154         counter = 0
155         for item in self._results:
156             logging.info("Record: " + str(counter))
157             counter += 1
158             for(key, value) in list(item.items()):
159                 logging.info("         Key: " + str(key) +
160                              ", Value: " + str(value))
161
162     def get_results(self):
163         """IResult interface implementation.
164         """
165         return self._results
166
167     def validate_send_traffic(self, dummy_result, dummy_traffic):
168         """Verify that send traffic has succeeded
169         """
170         if self._results:
171             if 'b2b_frames' in self._results[-1]:
172                 return float(self._results[-1]['b2b_frames']) > 0
173             elif 'throughput_rx_fps' in self._results[-1]:
174                 return float(self._results[-1]['throughput_rx_fps']) > 0
175             else:
176                 return True
177         else:
178             return False
179
180     def validate_get_results(self, result):
181         """Verify that results has been returned
182         """
183         return self._results == result