1 # Copyright (c) 2016-2017 Intel Corporation
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 from __future__ import absolute_import
16 from __future__ import print_function
23 # ixload uses its own py2. So importing jsonutils fails. So adding below
24 # workaround to support call from yardstick
26 from oslo_serialization import jsonutils
28 import json as jsonutils
31 class ErrorClass(object):
33 def __init__(self, *args, **kwargs):
34 if 'test' not in kwargs:
37 def __getattr__(self, item):
42 from IxLoad import IxLoad, StatCollectorUtils
45 StatCollectorUtils = ErrorClass
47 LOG = logging.getLogger(__name__)
48 CSV_FILEPATH_NAME = 'IxL_statResults.csv'
53 'L2-3 Stats for Client Ports.csv',
54 'L2-3 Stats for Server Ports.csv',
55 'IxLoad Detailed Report.html',
56 'IxLoad Detailed Report.pdf'
60 ["HTTP Client", "TCP Connections Established", "kSum"],
61 ["HTTP Client", "TCP Connection Requests Failed", "kSum"],
62 ["HTTP Client", "HTTP Simulated Users", "kSum"],
63 ["HTTP Client", "HTTP Concurrent Connections", "kSum"],
64 ["HTTP Client", "HTTP Connections", "kSum"],
65 ["HTTP Client", "HTTP Transactions", "kSum"],
66 ["HTTP Client", "HTTP Connection Attempts", "kSum"]
70 ["HTTP Server", "TCP Connections Established", "kSum"],
71 ["HTTP Server", "TCP Connection Requests Failed", "kSum"]
75 INCOMING_STAT_RECORD_TEMPLATE = """
76 =====================================
77 INCOMING STAT RECORD >>> %s
81 =====================================
84 INCOMING_STAT_INTERVAL_TEMPLATE = """
85 =====================================
86 Incoming stats: Time interval: %s
87 Incoming stats: Time interval: %s
88 =====================================
92 def validate_non_string_sequence(value, default=None, raise_exc=None):
93 if isinstance(value, collections.Sequence) and not isinstance(value, str):
100 def join_non_strings(separator, *non_strings):
102 non_strings = validate_non_string_sequence(non_strings[0], raise_exc=RuntimeError)
103 except (IndexError, RuntimeError):
105 return str(separator).join(str(non_string) for non_string in non_strings)
108 class IXLOADHttpTest(object):
110 def __init__(self, test_input):
112 self.stat_utils = None
113 self.remote_server = None
114 self.config_file = None
115 self.results_on_windows = None
116 self.result_dir = None
119 self.ports_to_reassign = None
120 self.test_input = jsonutils.loads(test_input)
121 self.parse_run_test()
124 def format_ports_for_reassignment(ports):
125 formatted = [join_non_strings(';', p) for p in ports if len(p) == 3]
126 LOG.debug('for client ports:%s', os.linesep.join(formatted))
129 def reassign_ports(self, test, repository, ports_to_reassign):
130 LOG.debug('ReassignPorts: %s %s', test, repository)
132 chassis_chain = repository.cget('chassisChain')
133 LOG.debug('chassischain: %s', chassis_chain)
134 client_ports = ports_to_reassign[0::2]
135 server_ports = ports_to_reassign[1::2]
137 client_ports = self.format_ports_for_reassignment(client_ports)
138 LOG.debug('Reassigning client ports: %s', client_ports)
139 server_ports = self.format_ports_for_reassignment(server_ports)
140 LOG.debug('Reassigning server ports: %s', server_ports)
141 ports_to_set = client_ports + server_ports
144 LOG.debug('Reassigning ports: %s', ports_to_set)
145 test.setPorts(ports_to_set)
147 LOG.error('Error: Could not remap port assignment for: %s',
149 self.ix_load.delete(repository)
150 self.ix_load.disconnect()
154 def stat_collector(*args):
155 LOG.debug(INCOMING_STAT_RECORD_TEMPLATE, args, len(args), args[0], args[1])
158 def IxL_StatCollectorCommand(*args):
160 timestamp = args[1][1]
161 LOG.debug(INCOMING_STAT_INTERVAL_TEMPLATE, timestamp, stats)
164 def set_results_dir(test_controller, results_on_windows):
166 If the folder doesn't exists on the Windows Client PC,
167 IxLoad will automatically create it.
170 test_controller.setResultDir(results_on_windows)
172 LOG.error('Error creating results dir on Win: %s',
176 def load_config_file(self, config_file):
178 LOG.debug(config_file)
179 repository = self.ix_load.new("ixRepository", name=config_file)
182 LOG.error('Error: IxLoad config file not found: %s', config_file)
185 def start_http_test(self):
186 self.ix_load = IxLoad()
188 LOG.debug('--- ixLoad obj: %s', self.ix_load)
190 self.ix_load.connect(self.remote_server)
194 log_tag = "IxLoad-api"
196 logger = self.ix_load.new("ixLogger", log_tag, 1)
197 log_engine = logger.getEngine()
198 log_engine.setLevels(self.ix_load.ixLogger.kLevelDebug,
199 self.ix_load.ixLogger.kLevelInfo)
200 log_engine.setFile(log_name, 2, 256, 1)
202 # Initialize stat collection utilities
203 self.stat_utils = StatCollectorUtils()
205 test_controller = self.ix_load.new("ixTestController", outputDir=1)
207 repository = self.load_config_file(self.config_file)
209 # Get the first test on the testList
210 test_name = repository.testList[0].cget("name")
211 test = repository.testList.getItem(test_name)
213 self.set_results_dir(test_controller, self.results_on_windows)
215 test.config(statsRequired=1, enableResetPorts=1, csvInterval=2,
216 enableForceOwnership=True)
218 # ---- Remap ports ----
220 self.reassign_ports(test, repository, self.ports_to_reassign)
222 LOG.exception("Exception occurred during reassign_ports")
224 # -----------------------------------------------------------------------
225 # Set up stat Collection
226 # -----------------------------------------------------------------------
227 test_server_handle = test_controller.getTestServerHandle()
228 self.stat_utils.Initialize(test_server_handle)
230 # Clear any stats that may have been registered previously
231 self.stat_utils.ClearStats()
233 # Define the stats we would like to collect
234 self.stat_utils.AddStat(caption="Watch_Stat_1",
235 statSourceType="HTTP Client",
236 statName="TCP Connections Established",
237 aggregationType="kSum",
240 self.stat_utils.AddStat(caption="Watch_Stat_2",
241 statSourceType="HTTP Client",
242 statName="TCP Connection Requests Failed",
243 aggregationType="kSum",
246 self.stat_utils.AddStat(caption="Watch_Stat_3",
247 statSourceType="HTTP Server",
248 statName="TCP Connections Established",
249 aggregationType="kSum",
252 self.stat_utils.AddStat(caption="Watch_Stat_4",
253 statSourceType="HTTP Server",
254 statName="TCP Connection Requests Failed",
255 aggregationType="kSum",
258 self.stat_utils.StartCollector(self.IxL_StatCollectorCommand)
260 test_controller.run(test)
261 self.ix_load.waitForTestFinish()
263 test_controller.releaseConfigWaitFinish()
265 # Stop the collector (running in the tcl event loop)
266 self.stat_utils.StopCollector()
269 test_controller.generateReport(detailedReport=1, format="PDF;HTML")
270 test_controller.releaseConfigWaitFinish()
272 self.ix_load.delete(test)
273 self.ix_load.delete(test_controller)
274 self.ix_load.delete(logger)
275 self.ix_load.delete(log_engine)
277 LOG.debug('Retrieving CSV stats from Windows Client PC ...')
278 for stat_file in STATS_TO_GET:
279 enhanced_stat_file = stat_file.replace('-', '')
280 enhanced_stat_file = enhanced_stat_file.replace(' ', '_')
281 enhanced_stat_file = enhanced_stat_file.replace('__', '_')
283 LOG.debug('Getting csv stat file: %s', stat_file)
284 src_file = os.path.join(self.results_on_windows, stat_file)
285 dst_file = os.path.join(self.result_dir, '_'.join(['ixLoad', enhanced_stat_file]))
286 self.ix_load.retrieveFileCopy(src_file, dst_file)
288 self.ix_load.disconnect()
290 def parse_run_test(self):
291 self.remote_server = self.test_input["remote_server"]
292 LOG.debug("remote tcl server: %s", self.remote_server)
294 self.config_file = self.test_input["ixload_cfg"]
295 LOG.debug("ixload config: %s", self.remote_server)
297 self.results_on_windows = 'C:/Results'
298 self.result_dir = self.test_input["result_dir"]
299 self.chassis = self.test_input["ixia_chassis"]
300 LOG.debug("remote ixia chassis: %s", self.chassis)
302 self.card = self.test_input["IXIA"]["card"]
303 self.ports_to_reassign = [
304 [self.chassis, self.card, port] for port in
305 self.test_input["IXIA"]["ports"]
308 LOG.debug("Ports to be reassigned: %s", self.ports_to_reassign)
312 # Get the args from cmdline and parse and run the test
313 test_input = "".join(args[1:])
315 ixload_obj = IXLOADHttpTest(test_input)
316 ixload_obj.start_http_test()
318 if __name__ == '__main__':
319 LOG.info("Start http_ixload test")