Merge "Precise self.result in pytest_suite_runner.py"
[functest.git] / functest / tests / unit / ci / test_prepare_env.py
1 #!/usr/bin/env python
2
3 # All rights reserved. This program and the accompanying materials
4 # are made available under the terms of the Apache License, Version 2.0
5 # which accompanies this distribution, and is available at
6 # http://www.apache.org/licenses/LICENSE-2.0
7
8 import logging
9 import unittest
10
11 import mock
12
13 from functest.ci import prepare_env
14 from functest.tests.unit import test_utils
15 from functest.utils.constants import CONST
16 from opnfv.utils import constants as opnfv_constants
17
18
19 class PrepareEnvTesting(unittest.TestCase):
20
21     def setUp(self):
22         self.prepare_envparser = prepare_env.PrepareEnvParser()
23
24     @mock.patch('functest.ci.prepare_env.logger.info')
25     def test_print_separator(self, mock_logger_info):
26         str = "=============================================="
27         prepare_env.print_separator()
28         mock_logger_info.assert_called_once_with(str)
29
30     @mock.patch('functest.ci.prepare_env.logger.info')
31     @mock.patch('functest.ci.prepare_env.logger.warning')
32     def test_check_env_variables_missing_inst_type(self, mock_logger_warn,
33                                                    mock_logger_info):
34         CONST.__setattr__('INSTALLER_TYPE', None)
35         prepare_env.check_env_variables()
36         mock_logger_info.assert_any_call("Checking environment variables"
37                                          "...")
38         mock_logger_warn.assert_any_call("The env variable 'INSTALLER_TYPE'"
39                                          " is not defined.")
40
41     @mock.patch('functest.ci.prepare_env.logger.info')
42     @mock.patch('functest.ci.prepare_env.logger.warning')
43     def test_check_env_variables_missing_inst_ip(self, mock_logger_warn,
44                                                  mock_logger_info):
45         CONST.__setattr__('INSTALLER_IP', None)
46         prepare_env.check_env_variables()
47         mock_logger_info.assert_any_call("Checking environment variables"
48                                          "...")
49         mock_logger_warn.assert_any_call("The env variable 'INSTALLER_IP'"
50                                          " is not defined. It is needed to"
51                                          " fetch the OpenStack credentials."
52                                          " If the credentials are not"
53                                          " provided to the container as a"
54                                          " volume, please add this env"
55                                          " variable to the 'docker run'"
56                                          " command.")
57
58     @mock.patch('functest.ci.prepare_env.logger.info')
59     @mock.patch('functest.ci.prepare_env.logger.warning')
60     def test_check_env_variables_with_inst_ip(self, mock_logger_warn,
61                                               mock_logger_info):
62         CONST.__setattr__('INSTALLER_IP', mock.Mock())
63         prepare_env.check_env_variables()
64         mock_logger_info.assert_any_call("Checking environment variables"
65                                          "...")
66         mock_logger_info.assert_any_call(test_utils.
67                                          SubstrMatch("    INSTALLER_IP="))
68
69     @mock.patch('functest.ci.prepare_env.logger.info')
70     @mock.patch('functest.ci.prepare_env.logger.warning')
71     def test_check_env_variables_missing_scenario(self, mock_logger_warn,
72                                                   mock_logger_info):
73         CONST.__setattr__('DEPLOY_SCENARIO', None)
74         prepare_env.check_env_variables()
75         mock_logger_info.assert_any_call("Checking environment variables"
76                                          "...")
77         mock_logger_warn.assert_any_call("The env variable"
78                                          " 'DEPLOY_SCENARIO' is not defined"
79                                          ". Setting CI_SCENARIO=undefined.")
80
81     @mock.patch('functest.ci.prepare_env.logger.info')
82     @mock.patch('functest.ci.prepare_env.logger.warning')
83     def test_check_env_variables_with_scenario(self, mock_logger_warn,
84                                                mock_logger_info):
85         CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
86         prepare_env.check_env_variables()
87         mock_logger_info.assert_any_call("Checking environment variables"
88                                          "...")
89         mock_logger_info.assert_any_call(test_utils.
90                                          SubstrMatch("DEPLOY_SCENARIO="))
91
92     @mock.patch('functest.ci.prepare_env.logger.info')
93     @mock.patch('functest.ci.prepare_env.logger.warning')
94     def test_check_env_variables_with_ci_debug(self, mock_logger_warn,
95                                                mock_logger_info):
96         CONST.__setattr__('CI_DEBUG', mock.Mock())
97         prepare_env.check_env_variables()
98         mock_logger_info.assert_any_call("Checking environment variables"
99                                          "...")
100         mock_logger_info.assert_any_call(test_utils.
101                                          SubstrMatch("    CI_DEBUG="))
102
103     @mock.patch('functest.ci.prepare_env.logger.info')
104     @mock.patch('functest.ci.prepare_env.logger.warning')
105     def test_check_env_variables_with_node(self, mock_logger_warn,
106                                            mock_logger_info):
107         CONST.__setattr__('NODE_NAME', mock.Mock())
108         prepare_env.check_env_variables()
109         mock_logger_info.assert_any_call("Checking environment variables"
110                                          "...")
111         mock_logger_info.assert_any_call(test_utils.
112                                          SubstrMatch("    NODE_NAME="))
113
114     @mock.patch('functest.ci.prepare_env.logger.info')
115     @mock.patch('functest.ci.prepare_env.logger.warning')
116     def test_check_env_variables_with_build_tag(self, mock_logger_warn,
117                                                 mock_logger_info):
118         CONST.__setattr__('BUILD_TAG', mock.Mock())
119         prepare_env.check_env_variables()
120         mock_logger_info.assert_any_call("Checking environment variables"
121                                          "...")
122
123         mock_logger_info.assert_any_call(test_utils.
124                                          SubstrMatch("    BUILD_TAG="))
125
126     @mock.patch('functest.ci.prepare_env.logger.info')
127     @mock.patch('functest.ci.prepare_env.logger.warning')
128     def test_check_env_variables_with_is_ci_run(self, mock_logger_warn,
129                                                 mock_logger_info):
130         CONST.__setattr__('IS_CI_RUN', mock.Mock())
131         prepare_env.check_env_variables()
132         mock_logger_info.assert_any_call("Checking environment variables"
133                                          "...")
134
135         mock_logger_info.assert_any_call(test_utils.
136                                          SubstrMatch("    IS_CI_RUN="))
137
138     def test_get_deployment_handler_missing_const_vars(self):
139         with mock.patch('functest.ci.prepare_env.'
140                         'factory.Factory.get_handler') as m:
141             CONST.__setattr__('INSTALLER_IP', None)
142             prepare_env.get_deployment_handler()
143             self.assertFalse(m.called)
144
145             CONST.__setattr__('INSTALLER_TYPE', None)
146             prepare_env.get_deployment_handler()
147             self.assertFalse(m.called)
148
149     @mock.patch('functest.ci.prepare_env.logger.debug')
150     def test_get_deployment_handler_missing_print_deploy_info(self,
151                                                               mock_debug):
152         with mock.patch('functest.ci.prepare_env.'
153                         'factory.Factory.get_handler') as m, \
154             mock.patch('functest.ci.prepare_env.'
155                        'ft_utils.get_parameter_from_yaml',
156                        side_effect=ValueError):
157             CONST.__setattr__('INSTALLER_IP', 'test_ip')
158             CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
159             opnfv_constants.INSTALLERS = ['test_inst_type']
160             prepare_env.get_deployment_handler()
161             msg = ('Printing deployment info is not supported for '
162                    'test_inst_type')
163             mock_debug.assert_any_call(msg)
164             self.assertFalse(m.called)
165
166     @mock.patch('functest.ci.prepare_env.logger.debug')
167     def test_get_deployment_handler_exception(self, mock_debug):
168         with mock.patch('functest.ci.prepare_env.'
169                         'factory.Factory.get_handler',
170                         side_effect=Exception), \
171             mock.patch('functest.ci.prepare_env.'
172                        'ft_utils.get_parameter_from_yaml'):
173             CONST.__setattr__('INSTALLER_IP', 'test_ip')
174             CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
175             opnfv_constants.INSTALLERS = ['test_inst_type']
176             prepare_env.get_deployment_handler()
177             self.assertTrue(mock_debug.called)
178
179     @mock.patch('functest.ci.prepare_env.logger.info')
180     @mock.patch('functest.ci.prepare_env.logger.debug')
181     def test_create_directories_missing_dir(self, mock_logger_debug,
182                                             mock_logger_info):
183         with mock.patch('functest.ci.prepare_env.os.path.exists',
184                         return_value=False), \
185                 mock.patch('functest.ci.prepare_env.os.makedirs') \
186                 as mock_method:
187             prepare_env.create_directories()
188             mock_logger_info.assert_any_call("Creating needed directories...")
189             mock_method.assert_any_call(
190                 CONST.__getattribute__('dir_functest_conf'))
191             mock_method.assert_any_call(
192                 CONST.__getattribute__('dir_functest_data'))
193             mock_method.assert_any_call(
194                 CONST.__getattribute__('dir_functest_images'))
195             mock_logger_info.assert_any_call("    %s created." %
196                                              CONST.__getattribute__(
197                                                  'dir_functest_conf'))
198             mock_logger_info.assert_any_call("    %s created." %
199                                              CONST.__getattribute__(
200                                                  'dir_functest_data'))
201             mock_logger_info.assert_any_call("    %s created." %
202                                              CONST.__getattribute__(
203                                                  'dir_functest_images'))
204
205     @mock.patch('functest.ci.prepare_env.logger.info')
206     @mock.patch('functest.ci.prepare_env.logger.debug')
207     def test_create_directories_with_dir(self, mock_logger_debug,
208                                          mock_logger_info):
209         with mock.patch('functest.ci.prepare_env.os.path.exists',
210                         return_value=True):
211             prepare_env.create_directories()
212             mock_logger_info.assert_any_call("Creating needed directories...")
213             mock_logger_debug.assert_any_call("   %s already exists." %
214                                               CONST.__getattribute__(
215                                                   'dir_functest_conf'))
216             mock_logger_debug.assert_any_call("   %s already exists." %
217                                               CONST.__getattribute__(
218                                                   'dir_functest_data'))
219             mock_logger_debug.assert_any_call("   %s already exists." %
220                                               CONST.__getattribute__(
221                                                   'dir_functest_images'))
222
223     def _get_env_cred_dict(self, os_prefix=''):
224         return {'OS_USERNAME': os_prefix + 'username',
225                 'OS_PASSWORD': os_prefix + 'password',
226                 'OS_AUTH_URL': 'http://test_ip:test_port/v2.0',
227                 'OS_TENANT_NAME': os_prefix + 'tenant_name',
228                 'OS_USER_DOMAIN_NAME': os_prefix + 'user_domain_name',
229                 'OS_PROJECT_DOMAIN_NAME': os_prefix + 'project_domain_name',
230                 'OS_PROJECT_NAME': os_prefix + 'project_name',
231                 'OS_ENDPOINT_TYPE': os_prefix + 'endpoint_type',
232                 'OS_REGION_NAME': os_prefix + 'region_name'}
233
234     @mock.patch('functest.ci.prepare_env.logger.error')
235     @mock.patch('functest.ci.prepare_env.logger.info')
236     @mock.patch('functest.ci.prepare_env.logger.warning')
237     def test_source_rc_missing_rc_file(self, mock_logger_warn,
238                                        mock_logger_info,
239                                        mock_logger_error):
240         with mock.patch('functest.ci.prepare_env.os.path.isfile',
241                         return_value=True), \
242                 mock.patch('functest.ci.prepare_env.os.path.getsize',
243                            return_value=0), \
244                 self.assertRaises(Exception):
245             CONST.__setattr__('openstack_creds', 'test_creds')
246             prepare_env.source_rc_file()
247
248     def test_source_rc_missing_installer_ip(self):
249         with mock.patch('functest.ci.prepare_env.os.path.isfile',
250                         return_value=False), \
251                 self.assertRaises(Exception):
252             CONST.__setattr__('INSTALLER_IP', None)
253             CONST.__setattr__('openstack_creds', 'test_creds')
254             prepare_env.source_rc_file()
255
256     def test_source_rc_missing_installer_type(self):
257         with mock.patch('functest.ci.prepare_env.os.path.isfile',
258                         return_value=False), \
259                 self.assertRaises(Exception):
260             CONST.__setattr__('INSTALLER_IP', 'test_ip')
261             CONST.__setattr__('openstack_creds', 'test_creds')
262             CONST.__setattr__('INSTALLER_TYPE', 'test_type')
263             opnfv_constants.INSTALLERS = []
264             prepare_env.source_rc_file()
265
266     def test_source_rc_missing_os_credfile_ci_inst(self):
267         with mock.patch('functest.ci.prepare_env.os.path.isfile',
268                         return_value=False), \
269                 mock.patch('functest.ci.prepare_env.os.path.getsize'), \
270                 mock.patch('functest.ci.prepare_env.os.path.join'), \
271                 mock.patch('functest.ci.prepare_env.subprocess.Popen') \
272                 as mock_subproc_popen, \
273                 self.assertRaises(Exception):
274             CONST.__setattr__('openstack_creds', 'test_creds')
275             CONST.__setattr__('INSTALLER_IP', None)
276             CONST.__setattr__('INSTALLER_TYPE', 'test_type')
277             opnfv_constants.INSTALLERS = ['test_type']
278
279             process_mock = mock.Mock()
280             attrs = {'communicate.return_value': ('output', 'error'),
281                      'return_code': 1}
282             process_mock.configure_mock(**attrs)
283             mock_subproc_popen.return_value = process_mock
284
285             prepare_env.source_rc_file()
286
287     @mock.patch('functest.ci.prepare_env.logger.debug')
288     def test_patch_file(self, mock_logger_debug):
289         with mock.patch("__builtin__.open", mock.mock_open()), \
290             mock.patch('functest.ci.prepare_env.yaml.safe_load',
291                        return_value={'test_scenario': {'tkey': 'tvalue'}}), \
292             mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
293                        return_value={'tkey1': 'tvalue1'}), \
294             mock.patch('functest.ci.prepare_env.os.remove') as m, \
295                 mock.patch('functest.ci.prepare_env.yaml.dump'):
296             CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
297             prepare_env.patch_file('test_file')
298             self.assertTrue(m.called)
299
300     @mock.patch('functest.ci.prepare_env.logger.info')
301     def test_verify_deployment_error(self, mock_logger_error):
302         mock_popen = mock.Mock()
303         attrs = {'poll.return_value': None,
304                  'stdout.readline.return_value': 'ERROR'}
305         mock_popen.configure_mock(**attrs)
306
307         with mock.patch('functest.ci.prepare_env.print_separator') as m, \
308             mock.patch('functest.ci.prepare_env.subprocess.Popen',
309                        return_value=mock_popen), \
310                 self.assertRaises(Exception) as context:
311             prepare_env.verify_deployment()
312             self.assertTrue(m.called)
313             msg = "Problem while running 'check_os.sh'."
314             mock_logger_error.assert_called_once_with('ERROR')
315             self.assertTrue(msg in context)
316
317     def _get_rally_creds(self):
318         return {"type": "ExistingCloud",
319                 "admin": {"username": 'test_user_name',
320                           "password": 'test_password',
321                           "tenant": 'test_tenant'}}
322
323     @mock.patch('functest.ci.prepare_env.os_utils.get_credentials_for_rally')
324     @mock.patch('functest.ci.prepare_env.logger.info')
325     @mock.patch('functest.ci.prepare_env.ft_utils.execute_command_raise')
326     @mock.patch('functest.ci.prepare_env.ft_utils.execute_command')
327     def test_install_rally(self, mock_exec, mock_exec_raise, mock_logger_info,
328                            mock_os_utils):
329
330         mock_os_utils.return_value = self._get_rally_creds()
331
332         prepare_env.install_rally()
333
334         cmd = "rally deployment destroy opnfv-rally"
335         error_msg = "Deployment %s does not exist." % \
336                     CONST.__getattribute__('rally_deployment_name')
337         mock_logger_info.assert_any_call("Creating Rally environment...")
338         mock_exec.assert_any_call(cmd, error_msg=error_msg, verbose=False)
339
340         cmd = "rally deployment create --file=rally_conf.json --name="
341         cmd += CONST.__getattribute__('rally_deployment_name')
342         error_msg = "Problem while creating Rally deployment"
343         mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
344
345         cmd = "rally deployment check"
346         error_msg = ("OpenStack not responding or "
347                      "faulty Rally deployment.")
348         mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
349
350         cmd = "rally deployment list"
351         error_msg = ("Problem while listing "
352                      "Rally deployment.")
353         mock_exec.assert_any_call(cmd, error_msg=error_msg)
354
355         cmd = "rally plugin list | head -5"
356         error_msg = ("Problem while showing "
357                      "Rally plugins.")
358         mock_exec.assert_any_call(cmd, error_msg=error_msg)
359
360     @mock.patch('functest.ci.prepare_env.logger.debug')
361     def test_install_tempest(self, mock_logger_debug):
362         mock_popen = mock.Mock()
363         attrs = {'poll.return_value': None,
364                  'stdout.readline.return_value': '0'}
365         mock_popen.configure_mock(**attrs)
366
367         CONST.__setattr__('tempest_deployment_name', 'test_dep_name')
368         with mock.patch('functest.ci.prepare_env.'
369                         'ft_utils.execute_command_raise',
370                         side_effect=Exception), \
371             mock.patch('functest.ci.prepare_env.subprocess.Popen',
372                        return_value=mock_popen), \
373                 self.assertRaises(Exception):
374             prepare_env.install_tempest()
375             mock_logger_debug.assert_any_call("Tempest test_dep_name"
376                                               " does not exist")
377
378     def test_create_flavor(self):
379         with mock.patch('functest.ci.prepare_env.'
380                         'os_utils.get_or_create_flavor',
381                         return_value=('test_', None)), \
382                 self.assertRaises(Exception) as context:
383             prepare_env.create_flavor()
384             msg = 'Failed to create flavor'
385             self.assertTrue(msg in context)
386
387     @mock.patch('functest.ci.prepare_env.sys.exit')
388     @mock.patch('functest.ci.prepare_env.logger.error')
389     def test_check_environment_missing_file(self, mock_logger_error,
390                                             mock_sys_exit):
391         with mock.patch('functest.ci.prepare_env.os.path.isfile',
392                         return_value=False), \
393                 self.assertRaises(Exception):
394             prepare_env.check_environment()
395
396     @mock.patch('functest.ci.prepare_env.sys.exit')
397     @mock.patch('functest.ci.prepare_env.logger.error')
398     def test_check_environment_with_error(self, mock_logger_error,
399                                           mock_sys_exit):
400         with mock.patch('functest.ci.prepare_env.os.path.isfile',
401                         return_value=True), \
402             mock.patch("__builtin__.open", mock.mock_open(read_data='0')), \
403                 self.assertRaises(Exception):
404             prepare_env.check_environment()
405
406     @mock.patch('functest.ci.prepare_env.logger.info')
407     def test_check_environment_default(self, mock_logger_info):
408         with mock.patch('functest.ci.prepare_env.os.path.isfile',
409                         return_value=True):
410             with mock.patch("__builtin__.open", mock.mock_open(read_data='1')):
411                 prepare_env.check_environment()
412                 mock_logger_info.assert_any_call("Functest environment"
413                                                  " is installed.")
414
415     @mock.patch('functest.ci.prepare_env.print_deployment_info')
416     @mock.patch('functest.ci.prepare_env.check_environment')
417     @mock.patch('functest.ci.prepare_env.create_flavor')
418     @mock.patch('functest.ci.prepare_env.install_tempest')
419     @mock.patch('functest.ci.prepare_env.install_rally')
420     @mock.patch('functest.ci.prepare_env.verify_deployment')
421     @mock.patch('functest.ci.prepare_env.patch_config_file')
422     @mock.patch('functest.ci.prepare_env.source_rc_file')
423     @mock.patch('functest.ci.prepare_env.create_directories')
424     @mock.patch('functest.ci.prepare_env.get_deployment_handler')
425     @mock.patch('functest.ci.prepare_env.check_env_variables')
426     @mock.patch('functest.ci.prepare_env.logger.info')
427     def test_main_start(self, mock_logger_info, mock_env_var, mock_dep_handler,
428                         mock_create_dir, mock_source_rc, mock_patch_config,
429                         mock_verify_depl, mock_install_rally,
430                         mock_install_temp, mock_create_flavor,
431                         mock_check_env, mock_print_info):
432         with mock.patch("__builtin__.open", mock.mock_open()) as m:
433             args = {'action': 'start'}
434             self.assertEqual(prepare_env.main(**args), 0)
435             mock_logger_info.assert_any_call("######### Preparing Functest "
436                                              "environment #########\n")
437             self.assertTrue(mock_env_var.called)
438             self.assertTrue(mock_dep_handler.called)
439             self.assertTrue(mock_create_dir.called)
440             self.assertTrue(mock_source_rc.called)
441             self.assertTrue(mock_patch_config.called)
442             self.assertTrue(mock_verify_depl.called)
443             self.assertTrue(mock_install_rally.called)
444             self.assertTrue(mock_install_temp.called)
445             self.assertTrue(mock_create_flavor.called)
446             m.assert_called_once_with(
447                 CONST.__getattribute__('env_active'), "w")
448             self.assertTrue(mock_check_env.called)
449             self.assertTrue(mock_print_info.called)
450
451     @mock.patch('functest.ci.prepare_env.check_environment')
452     def test_main_check(self, mock_check_env):
453         args = {'action': 'check'}
454         self.assertEqual(prepare_env.main(**args), 0)
455         self.assertTrue(mock_check_env.called)
456
457     @mock.patch('functest.ci.prepare_env.logger.error')
458     def test_main_no_arg(self, mock_logger_error):
459         args = {'action': 'not_valid'}
460         self.assertEqual(prepare_env.main(**args), -1)
461         mock_logger_error.assert_called_once_with('Argument not valid.')
462
463
464 if __name__ == "__main__":
465     logging.disable(logging.CRITICAL)
466     unittest.main(verbosity=2)