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