fd3785b990508c498f3ce5e02acc9b4ccc3e604f
[functest.git] / functest / opnfv_tests / openstack / tempest / conf_utils.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2015 All rights reserved
4 # 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 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 import ConfigParser
11 import logging
12 import os
13 import pkg_resources
14 import shutil
15 import subprocess
16
17 import yaml
18
19 from functest.utils.constants import CONST
20 import functest.utils.functest_utils as ft_utils
21 import functest.utils.openstack_utils as os_utils
22
23
24 IMAGE_ID_ALT = None
25 FLAVOR_ID_ALT = None
26 GLANCE_IMAGE_PATH = os.path.join(
27     CONST.__getattribute__('dir_functest_images'),
28     CONST.__getattribute__('openstack_image_file_name'))
29 TEMPEST_RESULTS_DIR = os.path.join(CONST.__getattribute__('dir_results'),
30                                    'tempest')
31 TEMPEST_CUSTOM = pkg_resources.resource_filename(
32     'functest', 'opnfv_tests/openstack/tempest/custom_tests/test_list.txt')
33 TEMPEST_BLACKLIST = pkg_resources.resource_filename(
34     'functest', 'opnfv_tests/openstack/tempest/custom_tests/blacklist.txt')
35 TEMPEST_DEFCORE = pkg_resources.resource_filename(
36     'functest',
37     'opnfv_tests/openstack/tempest/custom_tests/defcore_req.txt')
38 TEMPEST_RAW_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_raw_list.txt')
39 TEMPEST_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_list.txt')
40 REFSTACK_RESULTS_DIR = os.path.join(CONST.__getattribute__('dir_results'),
41                                     'refstack')
42 TEMPEST_CONF_YAML = pkg_resources.resource_filename(
43     'functest', 'opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml')
44
45 CI_INSTALLER_TYPE = CONST.__getattribute__('INSTALLER_TYPE')
46 CI_INSTALLER_IP = CONST.__getattribute__('INSTALLER_IP')
47
48 """ logging configuration """
49 logger = logging.getLogger(__name__)
50
51
52 def create_tempest_resources(use_custom_images=False,
53                              use_custom_flavors=False):
54
55     logger.debug("Creating private network for Tempest suite")
56     network_dic = os_utils.create_shared_network_full(
57         CONST.__getattribute__('tempest_private_net_name'),
58         CONST.__getattribute__('tempest_private_subnet_name'),
59         CONST.__getattribute__('tempest_router_name'),
60         CONST.__getattribute__('tempest_private_subnet_cidr'))
61     if network_dic is None:
62         raise Exception('Failed to create private network')
63
64     image_id = ""
65     image_id_alt = ""
66     flavor_id = ""
67     flavor_id_alt = ""
68
69     if (CONST.__getattribute__('tempest_use_custom_images') or
70        use_custom_images):
71         # adding alternative image should be trivial should we need it
72         logger.debug("Creating image for Tempest suite")
73         _, image_id = os_utils.get_or_create_image(
74             CONST.__getattribute__('openstack_image_name'),
75             GLANCE_IMAGE_PATH,
76             CONST.__getattribute__('openstack_image_disk_format'))
77         if image_id is None:
78             raise Exception('Failed to create image')
79
80     if use_custom_images:
81         logger.debug("Creating 2nd image for Tempest suite")
82         _, image_id_alt = os_utils.get_or_create_image(
83             CONST.__getattribute__('openstack_image_name_alt'),
84             GLANCE_IMAGE_PATH,
85             CONST.__getattribute__('openstack_image_disk_format'))
86         if image_id_alt is None:
87             raise Exception('Failed to create image')
88
89     if (CONST.__getattribute__('tempest_use_custom_flavors') or
90        use_custom_flavors):
91         # adding alternative flavor should be trivial should we need it
92         logger.debug("Creating flavor for Tempest suite")
93         _, flavor_id = os_utils.get_or_create_flavor(
94             CONST.__getattribute__('openstack_flavor_name'),
95             CONST.__getattribute__('openstack_flavor_ram'),
96             CONST.__getattribute__('openstack_flavor_disk'),
97             CONST.__getattribute__('openstack_flavor_vcpus'))
98         if flavor_id is None:
99             raise Exception('Failed to create flavor')
100
101     if use_custom_flavors:
102         logger.debug("Creating 2nd flavor for tempest_defcore")
103         _, flavor_id_alt = os_utils.get_or_create_flavor(
104             CONST.__getattribute__('openstack_flavor_name_alt'),
105             CONST.__getattribute__('openstack_flavor_ram'),
106             CONST.__getattribute__('openstack_flavor_disk'),
107             CONST.__getattribute__('openstack_flavor_vcpus'))
108         if flavor_id_alt is None:
109             raise Exception('Failed to create flavor')
110
111     img_flavor_dict = {}
112     img_flavor_dict['image_id'] = image_id
113     img_flavor_dict['image_id_alt'] = image_id_alt
114     img_flavor_dict['flavor_id'] = flavor_id
115     img_flavor_dict['flavor_id_alt'] = flavor_id_alt
116
117     return img_flavor_dict
118
119
120 def get_verifier_id():
121     """
122     Returns verifer id for current Tempest
123     """
124     cmd = ("rally verify list-verifiers | awk '/" +
125            CONST.__getattribute__('tempest_deployment_name') +
126            "/ {print $2}'")
127     p = subprocess.Popen(cmd, shell=True,
128                          stdout=subprocess.PIPE,
129                          stderr=subprocess.STDOUT)
130     deployment_uuid = p.stdout.readline().rstrip()
131     if deployment_uuid == "":
132         logger.error("Tempest verifier not found.")
133         raise Exception('Error with command:%s' % cmd)
134     return deployment_uuid
135
136
137 def get_verifier_deployment_id():
138     """
139     Returns deployment id for active Rally deployment
140     """
141     cmd = ("rally deployment list | awk '/" +
142            CONST.__getattribute__('rally_deployment_name') +
143            "/ {print $2}'")
144     p = subprocess.Popen(cmd, shell=True,
145                          stdout=subprocess.PIPE,
146                          stderr=subprocess.STDOUT)
147     deployment_uuid = p.stdout.readline().rstrip()
148     if deployment_uuid == "":
149         logger.error("Rally deployment not found.")
150         raise Exception('Error with command:%s' % cmd)
151     return deployment_uuid
152
153
154 def get_verifier_repo_dir(verifier_id):
155     """
156     Returns installed verfier repo directory for Tempest
157     """
158     if not verifier_id:
159         verifier_id = get_verifier_id()
160
161     return os.path.join(CONST.__getattribute__('dir_rally_inst'),
162                         'verification',
163                         'verifier-{}'.format(verifier_id),
164                         'repo')
165
166
167 def get_verifier_deployment_dir(verifier_id, deployment_id):
168     """
169     Returns Rally deployment directory for current verifier
170     """
171     if not verifier_id:
172         verifier_id = get_verifier_id()
173
174     if not deployment_id:
175         deployment_id = get_verifier_deployment_id()
176
177     return os.path.join(CONST.__getattribute__('dir_rally_inst'),
178                         'verification',
179                         'verifier-{}'.format(verifier_id),
180                         'for-deployment-{}'.format(deployment_id))
181
182
183 def get_repo_tag(repo):
184     """
185     Returns last tag of current branch
186     """
187     cmd = ("git -C {0} describe --abbrev=0 HEAD".format(repo))
188     p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
189     tag = p.stdout.readline().rstrip()
190
191     return str(tag)
192
193
194 def backup_tempest_config(conf_file):
195     """
196     Copy config file to tempest results directory
197     """
198     if not os.path.exists(TEMPEST_RESULTS_DIR):
199         os.makedirs(TEMPEST_RESULTS_DIR)
200
201     shutil.copyfile(conf_file,
202                     os.path.join(TEMPEST_RESULTS_DIR, 'tempest.conf'))
203
204
205 def configure_tempest(deployment_dir, IMAGE_ID=None, FLAVOR_ID=None,
206                       MODE=None):
207     """
208     Calls rally verify and updates the generated tempest.conf with
209     given parameters
210     """
211     conf_file = configure_verifier(deployment_dir)
212     configure_tempest_update_params(conf_file,
213                                     IMAGE_ID, FLAVOR_ID)
214
215
216 def configure_tempest_defcore(deployment_dir, img_flavor_dict):
217     """
218     Add/update needed parameters into tempest.conf file
219     """
220     conf_file = configure_verifier(deployment_dir)
221     configure_tempest_update_params(conf_file,
222                                     img_flavor_dict.get("image_id"),
223                                     img_flavor_dict.get("flavor_id"))
224
225     logger.debug("Updating selected tempest.conf parameters for defcore...")
226     config = ConfigParser.RawConfigParser()
227     config.read(conf_file)
228     config.set('DEFAULT', 'log_file', '{}/tempest.log'.format(deployment_dir))
229     config.set('oslo_concurrency', 'lock_path',
230                '{}/lock_files'.format(deployment_dir))
231     config.set('scenario', 'img_dir', '{}'.format(deployment_dir))
232     config.set('scenario', 'img_file', 'tempest-image')
233     config.set('compute', 'image_ref', img_flavor_dict.get("image_id"))
234     config.set('compute', 'image_ref_alt',
235                img_flavor_dict['image_id_alt'])
236     config.set('compute', 'flavor_ref', img_flavor_dict.get("flavor_id"))
237     config.set('compute', 'flavor_ref_alt',
238                img_flavor_dict['flavor_id_alt'])
239
240     with open(conf_file, 'wb') as config_file:
241         config.write(config_file)
242
243     confpath = pkg_resources.resource_filename(
244         'functest',
245         'opnfv_tests/openstack/refstack_client/refstack_tempest.conf')
246     shutil.copyfile(conf_file, confpath)
247
248
249 def configure_tempest_update_params(tempest_conf_file,
250                                     IMAGE_ID=None, FLAVOR_ID=None):
251     """
252     Add/update needed parameters into tempest.conf file
253     """
254     logger.debug("Updating selected tempest.conf parameters...")
255     config = ConfigParser.RawConfigParser()
256     config.read(tempest_conf_file)
257     config.set(
258         'compute',
259         'fixed_network_name',
260         CONST.__getattribute__('tempest_private_net_name'))
261     config.set('compute', 'volume_device_name',
262                CONST.__getattribute__('tempest_volume_device_name'))
263     if CONST.__getattribute__('tempest_use_custom_images'):
264         if IMAGE_ID is not None:
265             config.set('compute', 'image_ref', IMAGE_ID)
266         if IMAGE_ID_ALT is not None:
267             config.set('compute', 'image_ref_alt', IMAGE_ID_ALT)
268     if CONST.__getattribute__('tempest_use_custom_flavors'):
269         if FLAVOR_ID is not None:
270             config.set('compute', 'flavor_ref', FLAVOR_ID)
271         if FLAVOR_ID_ALT is not None:
272             config.set('compute', 'flavor_ref_alt', FLAVOR_ID_ALT)
273     config.set('identity', 'region', 'RegionOne')
274     if os_utils.is_keystone_v3():
275         auth_version = 'v3'
276     else:
277         auth_version = 'v2'
278     config.set('identity', 'auth_version', auth_version)
279     config.set(
280         'validation', 'ssh_timeout',
281         CONST.__getattribute__('tempest_validation_ssh_timeout'))
282     config.set('object-storage', 'operator_role',
283                CONST.__getattribute__('tempest_object_storage_operator_role'))
284
285     if CONST.__getattribute__('OS_ENDPOINT_TYPE') is not None:
286         sections = config.sections()
287         if os_utils.is_keystone_v3():
288             config.set('identity', 'v3_endpoint_type',
289                        CONST.__getattribute__('OS_ENDPOINT_TYPE'))
290             if 'identity-feature-enabled' not in sections:
291                 config.add_section('identity-feature-enabled')
292                 config.set('identity-feature-enabled', 'api_v2', False)
293                 config.set('identity-feature-enabled', 'api_v2_admin', False)
294         services_list = ['compute',
295                          'volume',
296                          'image',
297                          'network',
298                          'data-processing',
299                          'object-storage',
300                          'orchestration']
301         for service in services_list:
302             if service not in sections:
303                 config.add_section(service)
304             config.set(service, 'endpoint_type',
305                        CONST.__getattribute__('OS_ENDPOINT_TYPE'))
306
307     logger.debug('Add/Update required params defined in tempest_conf.yaml '
308                  'into tempest.conf file')
309     with open(TEMPEST_CONF_YAML) as f:
310         conf_yaml = yaml.safe_load(f)
311     if conf_yaml:
312         sections = config.sections()
313         for section in conf_yaml:
314             if section not in sections:
315                 config.add_section(section)
316             sub_conf = conf_yaml.get(section)
317             for key, value in sub_conf.items():
318                 config.set(section, key, value)
319
320     with open(tempest_conf_file, 'wb') as config_file:
321         config.write(config_file)
322
323     backup_tempest_config(tempest_conf_file)
324
325
326 def configure_verifier(deployment_dir):
327     """
328     Execute rally verify configure-verifier, which generates tempest.conf
329     """
330     tempest_conf_file = os.path.join(deployment_dir, "tempest.conf")
331     if os.path.isfile(tempest_conf_file):
332         logger.debug("Verifier is already configured.")
333         logger.debug("Reconfiguring the current verifier...")
334         cmd = "rally verify configure-verifier --reconfigure"
335     else:
336         logger.info("Configuring the verifier...")
337         cmd = "rally verify configure-verifier"
338     ft_utils.execute_command(cmd)
339
340     logger.debug("Looking for tempest.conf file...")
341     if not os.path.isfile(tempest_conf_file):
342         logger.error("Tempest configuration file %s NOT found."
343                      % tempest_conf_file)
344         raise Exception("Tempest configuration file %s NOT found."
345                         % tempest_conf_file)
346     else:
347         return tempest_conf_file