1 # Copyright (c) 2015 Intel Research and Development Ireland Ltd.
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.
20 from experimental_framework.constants import conf_file_sections as cf
21 from experimental_framework.constants import framework_parameters as fp
24 # ------------------------------------------------------
25 # List of common variables
26 # ------------------------------------------------------
30 DEPLOYMENT_UNIT = None
37 TEMPLATE_FILE_EXTENSION = None
41 PKTGEN_DPDK_DIRECTORY = None
43 PKTGEN_COREMASK = None
44 PKTGEN_MEMCHANNEL = None
45 PKTGEN_BUS_SLOT_NIC_1 = None
46 PKTGEN_BUS_SLOT_NIC_2 = None
50 INFLUXDB_DB_NAME = None
53 # ------------------------------------------------------
54 # Initialization and Input 'heat_templates/'validation
55 # ------------------------------------------------------
59 BASE_DIR = os.getcwd()
60 BASE_DIR = BASE_DIR.replace('/experimental_framework', '')
61 BASE_DIR = InputValidation.validate_directory_exist_and_format(
62 BASE_DIR, "Error 000001")
67 if len(CONF_FILE.get_variable_list(cf.CFS_PKTGEN)) > 0:
71 def init_conf_file(api=False):
74 CONF_FILE = ConfigurationFile(cf.get_sections_api())
76 CONF_FILE = ConfigurationFile(cf.get_sections())
79 def init_general_vars():
80 global TEMPLATE_FILE_EXTENSION
86 TEMPLATE_FILE_EXTENSION = '.yaml'
88 # Check Section in Configuration File
90 validate_configuration_file_section(
92 "Section " + cf.CFS_GENERAL +
93 "is not present in configuration file")
95 TEMPLATE_DIR = BASE_DIR + 'heat_templates/'
97 # Validate template name
99 validate_configuration_file_parameter(
101 cf.CFSG_TEMPLATE_NAME,
102 "Parameter " + cf.CFSG_TEMPLATE_NAME +
103 "is not present in configuration file")
105 TEMPLATE_NAME = CONF_FILE.get_variable(cf.CFS_GENERAL,
106 cf.CFSG_TEMPLATE_NAME)
107 InputValidation.validate_file_exist(
108 TEMPLATE_DIR + TEMPLATE_NAME,
109 "The provided template file does not exist")
110 RESULT_DIR = BASE_DIR + 'results/'
112 # Validate and assign Iterations
113 if cf.CFSG_ITERATIONS in CONF_FILE.get_variable_list(cf.CFS_GENERAL):
114 ITERATIONS = int(CONF_FILE.get_variable(cf.CFS_GENERAL,
122 if cf.CFSG_DEBUG in CONF_FILE.get_variable_list(cf.CFS_GENERAL) and \
123 CONF_FILE.get_variable(cf.CFS_GENERAL, cf.CFSG_DEBUG):
124 logging.basicConfig(level=logging.DEBUG)
126 logging.basicConfig(level=logging.INFO)
128 LOG = logging.getLogger()
129 log_formatter = logging.Formatter("%(asctime)s --- %(message)s")
130 file_handler = logging.FileHandler("{0}/{1}.log".format("./", "benchmark"))
131 file_handler.setFormatter(log_formatter)
132 file_handler.setLevel(logging.DEBUG)
133 LOG.addHandler(file_handler)
136 # ------------------------------------------------------
137 # InfluxDB conf variables
138 # ------------------------------------------------------
142 global INFLUXDB_DB_NAME
144 INFLUXDB_IP = CONF_FILE.get_variable(cf.CFS_INFLUXDB, cf.CFSI_IDB_IP)
145 INFLUXDB_PORT = CONF_FILE.get_variable(cf.CFS_INFLUXDB, cf.CFSI_IDB_PORT)
146 INFLUXDB_DB_NAME = CONF_FILE.get_variable(cf.CFS_INFLUXDB,
150 # ------------------------------------------------------
151 # Packet Generator conf variables
152 # ------------------------------------------------------
156 global PKTGEN_PROGRAM
157 global PKTGEN_COREMASK
158 global PKTGEN_MEMCHANNEL
159 global PKTGEN_BUS_SLOT_NIC_1
160 global PKTGEN_BUS_SLOT_NIC_2
161 global PKTGEN_DPDK_DIRECTORY
163 msg = "Section {} is not present in the configuration file".\
164 format(cf.CFS_PKTGEN)
165 InputValidation.validate_configuration_file_section(cf.CFS_PKTGEN, msg)
167 pktgen_var_list = CONF_FILE.get_variable_list(cf.CFS_PKTGEN)
168 PKTGEN = 'dpdk_pktgen' # default value
169 if cf.CFSP_PACKET_GENERATOR in pktgen_var_list:
170 msg = "Parameter {} is not present in section {}".format(
171 cf.CFSP_PACKET_GENERATOR, cf.CFS_PKTGEN)
172 InputValidation.validate_configuration_file_parameter(
173 cf.CFS_PKTGEN, cf.CFSP_PACKET_GENERATOR, msg)
174 PKTGEN = CONF_FILE.get_variable(
175 cf.CFS_PKTGEN, cf.CFSP_PACKET_GENERATOR)
177 if PKTGEN not in fp.get_supported_packet_generators():
178 raise ValueError('The specified packet generator is not supported '
181 # Check if the packet gen is dpdk_pktgen
182 if PKTGEN == cf.CFSP_PG_DPDK:
183 # Validation of DPDK pktgen directory
184 msg = "Parameter {} is not present in section {}".format(
185 cf.CFSP_DPDK_PKTGEN_DIRECTORY, cf.CFS_PKTGEN)
186 InputValidation.validate_configuration_file_parameter(
187 cf.CFS_PKTGEN, cf.CFSP_DPDK_PKTGEN_DIRECTORY, msg)
188 PKTGEN_DIR = CONF_FILE.get_variable(
189 cf.CFS_PKTGEN, cf.CFSP_DPDK_PKTGEN_DIRECTORY)
190 msg = "The directory {} does not exist.".format(PKTGEN_DIR)
191 PKTGEN_DIR = InputValidation.validate_directory_exist_and_format(
194 # Validation of the DPDK program name
195 msg = "Parameter {} is not present in section {}".format(
196 cf.CFSP_DPDK_PROGRAM_NAME, cf.CFS_PKTGEN)
197 InputValidation.validate_configuration_file_parameter(
198 cf.CFS_PKTGEN, cf.CFSP_DPDK_PROGRAM_NAME, msg)
199 PKTGEN_PROGRAM = CONF_FILE.get_variable(
200 cf.CFS_PKTGEN, cf.CFSP_DPDK_PROGRAM_NAME)
202 # Validation of the DPDK Coremask parameter
203 msg = "Parameter {} is not present in section {}".format(
204 cf.CFSP_DPDK_COREMASK, cf.CFS_PKTGEN)
205 InputValidation.validate_configuration_file_parameter(
206 cf.CFS_PKTGEN, cf.CFSP_DPDK_COREMASK, msg)
207 PKTGEN_COREMASK = CONF_FILE.get_variable(
208 cf.CFS_PKTGEN, cf.CFSP_DPDK_COREMASK)
210 # Validation of the DPDK Memory Channel parameter
211 msg = "Parameter {} is not present in section {}".format(
212 cf.CFSP_DPDK_MEMORY_CHANNEL, cf.CFS_PKTGEN)
213 InputValidation.validate_configuration_file_parameter(
214 cf.CFS_PKTGEN, cf.CFSP_DPDK_MEMORY_CHANNEL, msg)
215 PKTGEN_MEMCHANNEL = CONF_FILE.get_variable(
216 cf.CFS_PKTGEN, cf.CFSP_DPDK_MEMORY_CHANNEL)
218 # Validation of the DPDK Bus Slot 1
219 msg = "Parameter {} is not present in section {}".format(
220 cf.CFSP_DPDK_BUS_SLOT_NIC_1, cf.CFS_PKTGEN)
221 InputValidation.validate_configuration_file_parameter(
222 cf.CFS_PKTGEN, cf.CFSP_DPDK_BUS_SLOT_NIC_1, msg)
223 PKTGEN_BUS_SLOT_NIC_1 = CONF_FILE.get_variable(
224 cf.CFS_PKTGEN, cf.CFSP_DPDK_BUS_SLOT_NIC_1)
226 # Validation of the DPDK Bus Slot 2
227 msg = "Parameter {} is not present in section {}".format(
228 cf.CFSP_DPDK_BUS_SLOT_NIC_2, cf.CFS_PKTGEN)
229 InputValidation.validate_configuration_file_parameter(
230 cf.CFS_PKTGEN, cf.CFSP_DPDK_BUS_SLOT_NIC_2, msg)
231 PKTGEN_BUS_SLOT_NIC_2 = CONF_FILE.get_variable(
232 cf.CFS_PKTGEN, cf.CFSP_DPDK_BUS_SLOT_NIC_2)
234 # Validation of DPDK directory parameter
235 msg = "Parameter {} is not present in section {}".format(
236 cf.CFSP_DPDK_DPDK_DIRECTORY, cf.CFS_PKTGEN)
237 InputValidation.validate_configuration_file_parameter(
238 cf.CFS_PKTGEN, cf.CFSP_DPDK_DPDK_DIRECTORY, msg)
239 PKTGEN_DPDK_DIRECTORY = CONF_FILE.get_variable(
240 cf.CFS_PKTGEN, cf.CFSP_DPDK_DPDK_DIRECTORY)
241 msg = "Directory {} does not exist".format(
242 cf.CFSP_DPDK_DPDK_DIRECTORY)
243 PKTGEN_DPDK_DIRECTORY = InputValidation.\
244 validate_directory_exist_and_format(PKTGEN_DPDK_DIRECTORY, msg)
247 # ------------------------------------------------------
248 # Configuration file access
249 # ------------------------------------------------------
251 class ConfigurationFile:
253 Used to extract data from the configuration file
256 def __init__(self, sections, config_file='conf.cfg'):
258 Reads configuration file sections
260 :param sections: list of strings representing the sections to be
262 :param config_file: name of the configuration file (string)
265 InputValidation.validate_string(
266 config_file, "The configuration file name must be a string")
267 config_file = BASE_DIR + config_file
268 InputValidation.validate_file_exist(
269 config_file, 'The provided configuration file does not exist')
270 self.config = ConfigParser.ConfigParser()
271 self.config.read(config_file)
272 for section in sections:
274 self, section, ConfigurationFile.
275 _config_section_map(section, self.config))
278 def _config_section_map(section, config_file):
280 Returns a dictionary with the configuration values for the specific
283 :param section: section to be loaded (string)
284 :param config_file: name of the configuration file (string)
288 options = config_file.options(section)
289 for option in options:
290 dict1[option] = config_file.get(section, option)
293 def get_variable(self, section, variable_name):
295 Returns the value correspondent to a variable
297 :param section: section to be loaded (string)
298 :param variable_name: name of the variable (string)
301 message = "The variable name must be a string"
302 InputValidation.validate_string(variable_name, message)
303 if variable_name in self.get_variable_list(section):
304 sect = getattr(self, section)
305 return sect[variable_name]
307 exc_msg = 'Parameter {} is not in the {} section of the conf file'
308 exc_msg.format(variable_name, section)
309 raise ValueError(exc_msg)
311 def get_variable_list(self, section):
313 Returns the list of the available variables in a section
314 :param section: section to be loaded (string)
318 return getattr(self, section)
320 msg = 'Section {} not found in the configuration file'.\
322 raise ValueError(msg)
325 # ------------------------------------------------------
326 # Get OpenStack Credentials
327 # ------------------------------------------------------
328 def get_credentials():
330 Returns the credentials for OpenStack access from the configuration file
334 credentials[cf.CFSO_IP_CONTROLLER] = CONF_FILE.get_variable(
335 cf.CFS_OPENSTACK, cf.CFSO_IP_CONTROLLER)
336 credentials[cf.CFSO_HEAT_URL] = CONF_FILE.get_variable(
337 cf.CFS_OPENSTACK, cf.CFSO_HEAT_URL)
338 credentials[cf.CFSO_USER] = CONF_FILE.get_variable(
339 cf.CFS_OPENSTACK, cf.CFSO_USER)
340 credentials[cf.CFSO_PASSWORD] = CONF_FILE.get_variable(
341 cf.CFS_OPENSTACK, cf.CFSO_PASSWORD)
342 credentials[cf.CFSO_AUTH_URI] = CONF_FILE.get_variable(
343 cf.CFS_OPENSTACK, cf.CFSO_AUTH_URI)
344 credentials[cf.CFSO_PROJECT] = CONF_FILE.get_variable(
345 cf.CFS_OPENSTACK, cf.CFSO_PROJECT)
349 # ------------------------------------------------------
351 # ------------------------------------------------------
353 def get_heat_template_params():
355 Returns the list of deployment parameters from the configuration file
356 for the heat template
360 heat_parameters_list = CONF_FILE.get_variable_list(
361 cf.CFS_DEPLOYMENT_PARAMETERS)
362 testcase_parameters = dict()
363 for param in heat_parameters_list:
364 testcase_parameters[param] = CONF_FILE.get_variable(
365 cf.CFS_DEPLOYMENT_PARAMETERS, param)
366 return testcase_parameters
369 def get_testcase_params():
371 Returns the list of testcase parameters from the configuration file
375 testcase_parameters = dict()
376 parameters = CONF_FILE.get_variable_list(cf.CFS_TESTCASE_PARAMETERS)
377 for param in parameters:
378 testcase_parameters[param] = CONF_FILE.get_variable(
379 cf.CFS_TESTCASE_PARAMETERS, param)
380 return testcase_parameters
383 def get_file_first_line(file_name):
385 Returns the first line of a file
387 :param file_name: name of the file to be read (str)
390 message = "The name of the file must be a string"
391 InputValidation.validate_string(file_name, message)
392 message = 'The file {} does not exist'.format(file_name)
393 InputValidation.validate_file_exist(file_name, message)
394 res = open(file_name, 'r')
395 return res.readline()
398 def replace_in_file(file, text_to_search, text_to_replace):
400 Replaces a string within a file
402 :param file: name of the file (str)
403 :param text_to_search: text to be replaced
404 :param text_to_replace: new text that will replace the previous
407 message = 'The text to be replaced in the file must be a string'
408 InputValidation.validate_string(text_to_search, message)
409 message = 'The text to replace in the file must be a string'
410 InputValidation.validate_string(text_to_replace, message)
411 message = "The name of the file must be a string"
412 InputValidation.validate_string(file, message)
413 message = "The file does not exist"
414 InputValidation.validate_file_exist(file, message)
415 for line in fileinput.input(file, inplace=True):
416 print(line.replace(text_to_search, text_to_replace).rstrip())
419 # ------------------------------------------------------
421 # ------------------------------------------------------
422 def run_command(command):
423 LOG.info("Running command: " + command)
424 return os.system(command)
427 def push_data_influxdb(data):
430 db_name = INFLUXDB_DB_NAME
431 command = "curl -i -XPOST 'http://{}:{}/write?db={}' " \
432 "--data-binary {}".format(ip, port, db_name, data)
436 # ------------------------------------------------------
437 # Expose variables to other modules
438 # ------------------------------------------------------
444 def get_template_dir():
448 def get_dpdk_pktgen_vars():
449 if not (PKTGEN == 'dpdk_pktgen'):
452 ret_val[cf.CFSP_DPDK_PKTGEN_DIRECTORY] = PKTGEN_DIR
453 ret_val[cf.CFSP_DPDK_PROGRAM_NAME] = PKTGEN_PROGRAM
454 ret_val[cf.CFSP_DPDK_COREMASK] = PKTGEN_COREMASK
455 ret_val[cf.CFSP_DPDK_MEMORY_CHANNEL] = PKTGEN_MEMCHANNEL
456 ret_val[cf.CFSP_DPDK_BUS_SLOT_NIC_1] = PKTGEN_BUS_SLOT_NIC_1
457 ret_val[cf.CFSP_DPDK_BUS_SLOT_NIC_2] = PKTGEN_BUS_SLOT_NIC_2
458 ret_val[cf.CFSP_DPDK_DPDK_DIRECTORY] = PKTGEN_DPDK_DIRECTORY
462 # ------------------------------------------------------
463 # Configuration Variables from Config File
464 # ------------------------------------------------------
465 def get_deployment_configuration_variables_from_conf_file():
468 all_variables = CONF_FILE.get_variable_list(cf.CFS_EXPERIMENT_VNF)
469 for var in all_variables:
470 v = CONF_FILE.get_variable(cf.CFS_EXPERIMENT_VNF, var)
471 type = re.findall(r'@\w*', v)
472 values = re.findall(r'\"(.+?)\"', v)
473 variables[var] = values
475 types[var] = type[0][1:]
477 LOG.debug("No type has been specified for variable " + var)
481 # ------------------------------------------------------
482 # benchmarks from Config File
483 # ------------------------------------------------------
484 def get_benchmarks_from_conf_file():
485 requested_benchmarks = list()
487 CONF_FILE.get_variable(cf.CFS_GENERAL, cf.CFSG_BENCHMARKS).split(', ')
488 for benchmark in benchmarks:
489 requested_benchmarks.append(benchmark)
490 return requested_benchmarks
493 class InputValidation(object):
496 def validate_string(param, message):
497 if not isinstance(param, str):
498 raise ValueError(message)
502 def validate_integer(param, message):
503 if not isinstance(param, int):
504 raise ValueError(message)
508 def validate_dictionary(param, message):
509 if not isinstance(param, dict):
510 raise ValueError(message)
514 def validate_file_exist(file_name, message):
515 if not os.path.isfile(file_name):
516 raise ValueError(message + ' ' + file_name)
520 def validate_directory_exist_and_format(directory, message):
521 if not os.path.isdir(directory):
522 raise ValueError(message)
523 if not directory.endswith('/'):
524 return directory + '/'
528 def validate_configuration_file_parameter(section, parameter, message):
529 params = CONF_FILE.get_variable_list(section)
530 if parameter not in params:
531 raise ValueError(message)
535 def validate_configuration_file_section(section, message):
536 if section not in cf.get_sections():
537 raise ValueError(message)
541 def validate_boolean(boolean, message):
542 if isinstance(boolean, bool):
544 if isinstance(boolean, str):
545 if boolean == 'True':
547 if boolean == 'False':
549 raise ValueError(message)
552 def validate_os_credentials(credentials):
553 if not isinstance(credentials, dict):
555 'The provided openstack_credentials '
556 'variable must be in dictionary format')
558 credential_keys = ['ip_controller', 'heat_url', 'user', 'password',
559 'auth_uri', 'project']
562 for credential_key in credential_keys
563 if credential_key not in credentials.keys()
565 if len(missing) == 0:
567 msg = 'OpenStack Credentials Error! ' \
568 'The following parameters are missing: {}'.\
569 format(", ".join(missing))
570 raise ValueError(msg)