Docker: VSPERF Results Container.
[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         self._connected = False
47
48         self._mode = str(settings.getValue('mode')).lower()
49         self._results = []
50
51     def configure(self, traffic):
52         """Set configuration values just before test execution so they
53            can be changed during runtime by test steps.
54         """
55         if not self._connected:
56             self._traffic_gen_class.connect()
57             self._connected = True
58
59         self._duration = int(settings.getValue('TRAFFICGEN_DURATION'))
60         self._lossrate = float(settings.getValue('TRAFFICGEN_LOSSRATE'))
61         self._packet_sizes = settings.getValue('TRAFFICGEN_PKT_SIZES')
62         self._results = []
63
64         # update type with detailed traffic value
65         self._type = traffic['traffic_type']
66
67     def __enter__(self):
68         """Call initialisation function.
69         """
70         pass
71
72     def __exit__(self, type_, value, traceback):
73         """Stop traffic, clean up.
74         """
75         if self._traffic_started:
76             self.stop_traffic()
77
78     def _append_results(self, result_dict, packet_size):
79         """Adds common values to traffic generator results.
80
81         :param result_dict: Dictionary containing results from trafficgen
82         :param packet_size: Packet size value.
83
84         :returns: dictionary of results with additional entries.
85         """
86
87         ret_value = result_dict
88
89         ret_value[ResultsConstants.TYPE] = self._type
90         ret_value[ResultsConstants.PACKET_SIZE] = str(packet_size)
91
92         return ret_value
93
94     def traffic_required(self):
95         """Checks selected '--mode' of traffic generator and performs
96            its specific handling.
97
98         :returns: True - in case that traffic generator should be executed
99                   False - if traffic generation is not required
100         """
101         if self._mode == 'trafficgen-off':
102             time.sleep(2)
103             self._logger.debug("All is set. Please run traffic generator manually.")
104             input(os.linesep + "Press Enter to terminate vswitchperf..." +
105                   os.linesep + os.linesep)
106             return False
107         elif self._mode == 'trafficgen-pause':
108             time.sleep(2)
109             while True:
110                 choice = input(os.linesep + 'Transmission paused, should'
111                                ' transmission be resumed? [y/n]' + os.linesep).lower()
112                 if choice in ('yes', 'y', 'ye'):
113                     return True
114                 elif choice in ('no', 'n'):
115                     self._logger.info("Traffic transmission will be skipped.")
116                     return False
117                 else:
118                     print("Please respond with 'yes', 'y', 'no' or 'n' ", end='')
119         return True
120
121     def send_traffic(self, traffic):
122         """Triggers traffic to be sent from the traffic generator.
123
124         This is a blocking function.
125
126         :param traffic: A dictionary describing the traffic to send.
127         """
128         self._logger.debug('send_traffic with %s',
129                            str(self._traffic_gen_class))
130         self.configure(traffic)
131
132     def send_traffic_async(self, traffic, dummy_function):
133         """Triggers traffic to be sent  asynchronously.
134
135         This is not a blocking function.
136
137         :param traffic: A dictionary describing the traffic to send.
138         :param function: A dictionary describing the function to call between
139              send and wait in the form:
140              function = {
141                  'function' : package.module.function,
142                  'args' : args
143              }
144              If this function requires more than one argument, all should be
145              should be passed using the args list and appropriately handled.
146          """
147         # pylint: disable=unused-argument
148         self._logger.debug('send_traffic_async with %s',
149                            str(self._traffic_gen_class))
150         self.configure(traffic)
151
152     def stop_traffic(self):
153         """Kills traffic being sent from the traffic generator.
154         """
155         self._logger.debug("stop_traffic()")
156
157     def print_results(self):
158         """IResult interface implementation.
159         """
160         counter = 0
161         for item in self._results:
162             logging.info("Record: %s", str(counter))
163             counter += 1
164             for(key, value) in list(item.items()):
165                 logging.info("         Key: " + str(key) +
166                              ", Value: " + str(value))
167
168     def get_results(self):
169         """IResult interface implementation.
170         """
171         return self._results
172
173     def validate_send_traffic(self, _dummy_result, _dummy_traffic):
174         """Verify that send traffic has succeeded
175         """
176         if self._results:
177             if 'b2b_frames' in self._results[-1]:
178                 return float(self._results[-1]['b2b_frames']) > 0
179             elif 'throughput_rx_fps' in self._results[-1]:
180                 return float(self._results[-1]['throughput_rx_fps']) > 0
181             else:
182                 return True
183         else:
184             return False
185
186     def validate_get_results(self, result):
187         """Verify that results has been returned
188         """
189         return self._results == result