Merge "Add Factor Testcase RX_Cache_Size"
[bottlenecks.git] / utils / infra_setup / heat / common.py
1 ##############################################################################
2 # Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 import os
11 import re
12 import ConfigParser
13 import logging
14 import fileinput
15
16 import consts.files as files
17 import consts.parameters as parameters
18
19 # ------------------------------------------------------
20 # List of common variables
21 # ------------------------------------------------------
22
23 LOG = None
24 CONF_FILE = None
25 DEPLOYMENT_UNIT = None
26 ITERATIONS = None
27
28 BASE_DIR = None
29 TEMPLATE_DIR = None
30 TEMPLATE_NAME = None
31 TEMPLATE_EXTENSION = None
32
33 # ------------------------------------------------------
34 # Initialization and Input 'heat_templates/'validation
35 # ------------------------------------------------------
36
37
38 def init(api=False):
39     global BASE_DIR
40     # BASE_DIR = os.getcwd()
41     BASE_DIR = os.path.dirname(os.path.abspath(__file__))
42     BASE_DIR = BASE_DIR.replace('/heat', '')
43     BASE_DIR = InputValidation.validate_directory_exist_and_format(
44         BASE_DIR, "Error 000001")
45
46     conf_file_init(api)
47     log_init()
48     general_vars_init(api)
49
50
51 def conf_file_init(api=False):
52     global CONF_FILE
53     if api:
54         CONF_FILE = ConfigurationFile(files.get_sections_api(),
55                                       '/tmp/bottlenecks.conf')
56     else:
57         CONF_FILE = ConfigurationFile(cf.get_sections(),
58                                       '/tmp/bottlenecks.conf')
59
60
61 def general_vars_init(api=False):
62     global TEMPLATE_EXTENSION
63     global TEMPLATE_NAME
64     global TEMPLATE_DIR
65     global ITERATIONS
66
67     TEMPLATE_EXTENSION = '.yaml'
68
69     # Check Section in Configuration File
70     InputValidation.validate_configuration_file_section(
71         files.GENERAL,
72         "Section " + files.GENERAL +
73         "is not present in configuration file")
74
75     InputValidation.validate_configuration_file_section(
76         files.OPENSTACK,
77         "Section " + files.OPENSTACK +
78         "is not present in configuration file")
79
80     TEMPLATE_DIR = '/tmp/heat_templates/'
81
82     if not api:
83         # Validate template name
84         InputValidation.validate_configuration_file_parameter(
85             files.GENERAL,
86             files.TEMPLATE_NAME,
87             "Parameter " + files.TEMPLATE_NAME +
88             "is not present in configuration file")
89         TEMPLATE_NAME = CONF_FILE.get_variable(files.GENERAL,
90                                                files.TEMPLATE_NAME)
91         InputValidation.validate_file_exist(
92             TEMPLATE_DIR + TEMPLATE_NAME,
93             "The provided template file does not exist")
94
95     # Validate and assign Iterations
96     if files.ITERATIONS in CONF_FILE.get_variable_list(files.GENERAL):
97         ITERATIONS = int(CONF_FILE.get_variable(files.GENERAL,
98                                                 files.ITERATIONS))
99     else:
100         ITERATIONS = 1
101
102
103 def log_init():
104     global LOG
105     LOG = logging.getLogger()
106     LOG.setLevel(level=logging.DEBUG)
107     log_formatter = logging.Formatter("%(asctime)s --- %(message)s")
108     file_handler = logging.FileHandler("{0}/{1}.log".format("./", "benchmark"))
109     file_handler.setFormatter(log_formatter)
110     file_handler.setLevel(logging.DEBUG)
111     LOG.addHandler(file_handler)
112
113 # ------------------------------------------------------
114 # Configuration file access
115 # ------------------------------------------------------
116
117
118 class ConfigurationFile:
119     """
120     Used to extract data from the configuration file
121     """
122
123     def __init__(self, sections, config_file='conf.cfg'):
124         """
125         Reads configuration file sections
126
127         :param sections: list of strings representing the sections to be
128                          loaded
129         :param config_file: name of the configuration file (string)
130         :return: None
131         """
132         InputValidation.validate_string(
133             config_file, "The configuration file name must be a string")
134         InputValidation.validate_file_exist(
135             config_file, 'The provided configuration file does not exist')
136         self.config = ConfigParser.ConfigParser()
137         self.config.read(config_file)
138         for section in sections:
139             setattr(
140                 self, section, ConfigurationFile.
141                 _config_section_map(section, self.config))
142
143     @staticmethod
144     def _config_section_map(section, config_file):
145         """
146         Returns a dictionary with the configuration values for the specific
147         section
148
149         :param section: section to be loaded (string)
150         :param config_file: name of the configuration file (string)
151         :return: dict
152         """
153         dict1 = dict()
154         options = config_file.options(section)
155         for option in options:
156             dict1[option] = config_file.get(section, option)
157         return dict1
158
159     def get_variable(self, section, variable_name):
160         """
161         Returns the value correspondent to a variable
162
163         :param section: section to be loaded (string)
164         :param variable_name: name of the variable (string)
165         :return: string
166         """
167         message = "The variable name must be a string"
168         InputValidation.validate_string(variable_name, message)
169         if variable_name in self.get_variable_list(section):
170             sect = getattr(self, section)
171             return sect[variable_name]
172         else:
173             exc_msg = 'Parameter {} is not in the {} section of the ' \
174                       'conf file'.format(variable_name, section)
175             raise ValueError(exc_msg)
176
177     def get_variable_list(self, section):
178         """
179         Returns the list of the available variables in a section
180         :param section: section to be loaded (string)
181         :return: list
182         """
183         try:
184             return getattr(self, section)
185         except:
186             msg = 'Section {}  not found in the configuration file'.\
187                 format(section)
188             raise ValueError(msg)
189
190 # ------------------------------------------------------
191 # Manage files
192 # ------------------------------------------------------
193
194
195 def get_heat_template_params():
196     """
197     Returns the list of deployment parameters from the configuration file
198     for the heat template
199
200     :return: dict
201     """
202     heat_parameters_list = CONF_FILE.get_variable_list(
203         files.DEPLOYMENT_PARAMETERS)
204     testcase_parameters = dict()
205     for param in heat_parameters_list:
206         testcase_parameters[param] = CONF_FILE.get_variable(
207             files.DEPLOYMENT_PARAMETERS, param)
208     return testcase_parameters
209
210
211 def get_testcase_params():
212     """
213     Returns the list of testcase parameters from the configuration file
214
215     :return: dict
216     """
217     testcase_parameters = dict()
218     parameters = CONF_FILE.get_variable_list(files.TESTCASE_PARAMETERS)
219     for param in parameters:
220         testcase_parameters[param] = CONF_FILE.get_variable(
221             files.TESTCASE_PARAMETERS, param)
222     return testcase_parameters
223
224
225 def get_file_first_line(file_name):
226     """
227     Returns the first line of a file
228
229     :param file_name: name of the file to be read (str)
230     :return: str
231     """
232     message = "name of the file must be a string"
233     InputValidation.validate_string(file_name, message)
234     message = 'file {} does not exist'.format(file_name)
235     InputValidation.validate_file_exist(file_name, message)
236     res = open(file_name, 'r')
237     return res.readline()
238
239
240 def replace_in_file(file, text_to_search, text_to_replace):
241     """
242     Replaces a string within a file
243
244     :param file: name of the file (str)
245     :param text_to_search: text to be replaced
246     :param text_to_replace: new text that will replace the previous
247     :return: None
248     """
249     message = 'text to be replaced in the file must be a string'
250     InputValidation.validate_string(text_to_search, message)
251     message = 'text to replace in the file must be a string'
252     InputValidation.validate_string(text_to_replace, message)
253     message = "name of the file must be a string"
254     InputValidation.validate_string(file, message)
255     message = "The file does not exist"
256     InputValidation.validate_file_exist(file, message)
257     for line in fileinput.input(file, inplace=True):
258         print(line.replace(text_to_search, text_to_replace).rstrip())
259
260 # ------------------------------------------------------
261 # Shell interaction
262 # ------------------------------------------------------
263
264
265 def run_command(command):
266     LOG.info("Running command: {}".format(command))
267     return os.system(command)
268
269 # ------------------------------------------------------
270 # Expose variables to other modules
271 # ------------------------------------------------------
272
273
274 def get_base_dir():
275     return BASE_DIR
276
277
278 def get_template_dir():
279     return TEMPLATE_DIR
280
281 # ------------------------------------------------------
282 # Configuration Variables from Config File
283 # ------------------------------------------------------
284
285
286 def get_deployment_configuration_variables_from_conf_file():
287     variables = dict()
288     types = dict()
289     all_variables = CONF_FILE.get_variable_list(files.EXPERIMENT_VNF)
290     for var in all_variables:
291         v = CONF_FILE.get_variable(files.EXPERIMENT_VNF, var)
292         type = re.findall(r'@\w*', v)
293         values = re.findall(r'\"(.+?)\"', v)
294         variables[var] = values
295         try:
296             types[var] = type[0][1:]
297         except IndexError:
298             LOG.debug("No type has been specified for variable " + var)
299     return variables
300
301 # ------------------------------------------------------
302 # benchmarks from Config File
303 # ------------------------------------------------------
304
305
306 def get_benchmarks_from_conf_file():
307     requested_benchmarks = list()
308     benchmarks = CONF_FILE.get_variable(
309         files.GENERAL, files.BENCHMARKS).split(', ')
310     for benchmark in benchmarks:
311         requested_benchmarks.append(benchmark)
312     return requested_benchmarks
313
314
315 class InputValidation(object):
316
317     @staticmethod
318     def validate_string(param, message):
319         if not isinstance(param, str):
320             raise ValueError(message)
321         return True
322
323     @staticmethod
324     def validate_integer(param, message):
325         if not isinstance(param, int):
326             raise ValueError(message)
327         return True
328
329     @staticmethod
330     def validate_dictionary(param, message):
331         if not isinstance(param, dict):
332             raise ValueError(message)
333         return True
334
335     @staticmethod
336     def validate_file_exist(file_name, message):
337         if not os.path.isfile(file_name):
338             raise ValueError(message + ' ' + file_name)
339         return True
340
341     @staticmethod
342     def validate_directory_exist_and_format(directory, message):
343         if not os.path.isdir(directory):
344             raise ValueError(message)
345         if not directory.endswith('/'):
346             return directory + '/'
347         return directory
348
349     @staticmethod
350     def validate_configuration_file_parameter(section, parameter, message):
351         params = CONF_FILE.get_variable_list(section)
352         if parameter not in params:
353             raise ValueError(message)
354         return True
355
356     @staticmethod
357     def validate_configuration_file_section(section, message):
358         if section not in files.get_sections():
359             raise ValueError(message)
360         return True
361
362     @staticmethod
363     def validate_boolean(boolean, message):
364         if isinstance(boolean, bool):
365             return boolean
366         if isinstance(boolean, str):
367             if boolean == 'True':
368                 return True
369             if boolean == 'False':
370                 return False
371         raise ValueError(message)
372
373     @staticmethod
374     def validate_os_credentials(credentials):
375         if not isinstance(credentials, dict):
376             raise ValueError(
377                 'The provided openstack_credentials '
378                 'variable must be in dictionary format')
379
380         credential_keys = ['user', 'password', 'ip_controller', 'heat_url',
381                            'auth_uri', 'project']
382         missing = [
383             credential_key
384             for credential_key in credential_keys
385             if credential_key not in credentials.keys()
386         ]
387         if len(missing) == 0:
388             return True
389         msg = 'OpenStack Credentials Error! ' \
390               'The following parameters are missing: {}'.\
391             format(", ".join(missing))
392         raise ValueError(msg)