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):
22 self.prepare_envparser = prepare_env.PrepareEnvParser()
23 self.db_url_env = 'http://foo/testdb'
25 @mock.patch('functest.ci.prepare_env.logger.info')
26 def test_print_separator(self, mock_logger_info):
27 str = "=============================================="
28 prepare_env.print_separator()
29 mock_logger_info.assert_called_once_with(str)
31 @mock.patch('functest.ci.prepare_env.logger.info')
32 @mock.patch('functest.ci.prepare_env.logger.warning')
33 def test_check_env_variables_missing_inst_type(self, mock_logger_warn,
35 CONST.__setattr__('INSTALLER_TYPE', None)
36 prepare_env.check_env_variables()
37 mock_logger_info.assert_any_call("Checking environment variables"
39 mock_logger_warn.assert_any_call("The env variable 'INSTALLER_TYPE'"
42 @mock.patch('functest.ci.prepare_env.logger.info')
43 @mock.patch('functest.ci.prepare_env.logger.warning')
44 def test_check_env_variables_missing_inst_ip(self, mock_logger_warn,
46 CONST.__setattr__('INSTALLER_IP', None)
47 prepare_env.check_env_variables()
48 mock_logger_info.assert_any_call("Checking environment variables"
50 mock_logger_warn.assert_any_call("The env variable 'INSTALLER_IP'"
51 " is not defined. It is needed to"
52 " fetch the OpenStack credentials."
53 " If the credentials are not"
54 " provided to the container as a"
55 " volume, please add this env"
56 " variable to the 'docker run'"
59 @mock.patch('functest.ci.prepare_env.logger.info')
60 @mock.patch('functest.ci.prepare_env.logger.warning')
61 def test_check_env_variables_with_inst_ip(self, mock_logger_warn,
63 CONST.__setattr__('INSTALLER_IP', mock.Mock())
64 prepare_env.check_env_variables()
65 mock_logger_info.assert_any_call("Checking environment variables"
67 mock_logger_info.assert_any_call(test_utils.
68 SubstrMatch(" INSTALLER_IP="))
70 @mock.patch('functest.ci.prepare_env.logger.info')
71 @mock.patch('functest.ci.prepare_env.logger.warning')
72 def test_check_env_variables_missing_scenario(self, mock_logger_warn,
74 CONST.__setattr__('DEPLOY_SCENARIO', None)
75 prepare_env.check_env_variables()
76 mock_logger_info.assert_any_call("Checking environment variables"
78 mock_logger_warn.assert_any_call("The env variable"
79 " 'DEPLOY_SCENARIO' is not defined"
80 ". Setting CI_SCENARIO=undefined.")
82 @mock.patch('functest.ci.prepare_env.logger.info')
83 @mock.patch('functest.ci.prepare_env.logger.warning')
84 def test_check_env_variables_with_scenario(self, mock_logger_warn,
86 CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
87 prepare_env.check_env_variables()
88 mock_logger_info.assert_any_call("Checking environment variables"
90 mock_logger_info.assert_any_call(test_utils.
91 SubstrMatch("DEPLOY_SCENARIO="))
93 @mock.patch('functest.ci.prepare_env.logger.info')
94 @mock.patch('functest.ci.prepare_env.logger.warning')
95 def test_check_env_variables_with_ci_debug(self, mock_logger_warn,
97 CONST.__setattr__('CI_DEBUG', mock.Mock())
98 prepare_env.check_env_variables()
99 mock_logger_info.assert_any_call("Checking environment variables"
101 mock_logger_info.assert_any_call(test_utils.
102 SubstrMatch(" CI_DEBUG="))
104 @mock.patch('functest.ci.prepare_env.logger.info')
105 @mock.patch('functest.ci.prepare_env.logger.warning')
106 def test_check_env_variables_with_node(self, mock_logger_warn,
108 CONST.__setattr__('NODE_NAME', mock.Mock())
109 prepare_env.check_env_variables()
110 mock_logger_info.assert_any_call("Checking environment variables"
112 mock_logger_info.assert_any_call(test_utils.
113 SubstrMatch(" NODE_NAME="))
115 @mock.patch('functest.ci.prepare_env.logger.info')
116 @mock.patch('functest.ci.prepare_env.logger.warning')
117 def test_check_env_variables_with_build_tag(self, mock_logger_warn,
119 CONST.__setattr__('BUILD_TAG', mock.Mock())
120 prepare_env.check_env_variables()
121 mock_logger_info.assert_any_call("Checking environment variables"
124 mock_logger_info.assert_any_call(test_utils.
125 SubstrMatch(" BUILD_TAG="))
127 @mock.patch('functest.ci.prepare_env.logger.info')
128 @mock.patch('functest.ci.prepare_env.logger.warning')
129 def test_check_env_variables_with_is_ci_run(self, mock_logger_warn,
131 CONST.__setattr__('IS_CI_RUN', mock.Mock())
132 prepare_env.check_env_variables()
133 mock_logger_info.assert_any_call("Checking environment variables"
136 mock_logger_info.assert_any_call(test_utils.
137 SubstrMatch(" IS_CI_RUN="))
139 def test_get_deployment_handler_missing_const_vars(self):
140 with mock.patch('functest.ci.prepare_env.'
141 'factory.Factory.get_handler') as m:
142 CONST.__setattr__('INSTALLER_IP', None)
143 prepare_env.get_deployment_handler()
144 self.assertFalse(m.called)
146 CONST.__setattr__('INSTALLER_TYPE', None)
147 prepare_env.get_deployment_handler()
148 self.assertFalse(m.called)
150 @mock.patch('functest.ci.prepare_env.logger.debug')
151 def test_get_deployment_handler_missing_print_deploy_info(self,
153 with mock.patch('functest.ci.prepare_env.'
154 'factory.Factory.get_handler') as m, \
155 mock.patch('functest.ci.prepare_env.'
156 'ft_utils.get_parameter_from_yaml',
157 side_effect=ValueError):
158 CONST.__setattr__('INSTALLER_IP', 'test_ip')
159 CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
160 opnfv_constants.INSTALLERS = ['test_inst_type']
161 prepare_env.get_deployment_handler()
162 msg = ('Printing deployment info is not supported for '
164 mock_debug.assert_any_call(msg)
165 self.assertFalse(m.called)
167 @mock.patch('functest.ci.prepare_env.logger.debug')
168 def test_get_deployment_handler_exception(self, mock_debug):
169 with mock.patch('functest.ci.prepare_env.'
170 'factory.Factory.get_handler',
171 side_effect=Exception), \
172 mock.patch('functest.ci.prepare_env.'
173 'ft_utils.get_parameter_from_yaml'):
174 CONST.__setattr__('INSTALLER_IP', 'test_ip')
175 CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
176 opnfv_constants.INSTALLERS = ['test_inst_type']
177 prepare_env.get_deployment_handler()
178 self.assertTrue(mock_debug.called)
180 @mock.patch('functest.ci.prepare_env.logger.info')
181 @mock.patch('functest.ci.prepare_env.logger.debug')
182 def test_create_directories_missing_dir(self, mock_logger_debug,
184 with mock.patch('functest.ci.prepare_env.os.path.exists',
185 return_value=False), \
186 mock.patch('functest.ci.prepare_env.os.makedirs') \
188 prepare_env.create_directories()
189 mock_logger_info.assert_any_call("Creating needed directories...")
190 mock_method.assert_any_call(
191 CONST.__getattribute__('dir_functest_conf'))
192 mock_method.assert_any_call(
193 CONST.__getattribute__('dir_functest_data'))
194 mock_method.assert_any_call(
195 CONST.__getattribute__('dir_functest_images'))
196 mock_logger_info.assert_any_call(" %s created." %
197 CONST.__getattribute__(
198 'dir_functest_conf'))
199 mock_logger_info.assert_any_call(" %s created." %
200 CONST.__getattribute__(
201 'dir_functest_data'))
202 mock_logger_info.assert_any_call(" %s created." %
203 CONST.__getattribute__(
204 'dir_functest_images'))
206 @mock.patch('functest.ci.prepare_env.logger.info')
207 @mock.patch('functest.ci.prepare_env.logger.debug')
208 def test_create_directories_with_dir(self, mock_logger_debug,
210 with mock.patch('functest.ci.prepare_env.os.path.exists',
212 prepare_env.create_directories()
213 mock_logger_info.assert_any_call("Creating needed directories...")
214 mock_logger_debug.assert_any_call(" %s already exists." %
215 CONST.__getattribute__(
216 'dir_functest_conf'))
217 mock_logger_debug.assert_any_call(" %s already exists." %
218 CONST.__getattribute__(
219 'dir_functest_data'))
220 mock_logger_debug.assert_any_call(" %s already exists." %
221 CONST.__getattribute__(
222 'dir_functest_images'))
224 def _get_env_cred_dict(self, os_prefix=''):
225 return {'OS_USERNAME': os_prefix + 'username',
226 'OS_PASSWORD': os_prefix + 'password',
227 'OS_AUTH_URL': 'http://test_ip:test_port/v2.0',
228 'OS_TENANT_NAME': os_prefix + 'tenant_name',
229 'OS_USER_DOMAIN_NAME': os_prefix + 'user_domain_name',
230 'OS_PROJECT_DOMAIN_NAME': os_prefix + 'project_domain_name',
231 'OS_PROJECT_NAME': os_prefix + 'project_name',
232 'OS_ENDPOINT_TYPE': os_prefix + 'endpoint_type',
233 'OS_REGION_NAME': os_prefix + 'region_name'}
235 @mock.patch('functest.ci.prepare_env.logger.error')
236 @mock.patch('functest.ci.prepare_env.logger.info')
237 @mock.patch('functest.ci.prepare_env.logger.warning')
238 def test_source_rc_missing_rc_file(self, mock_logger_warn,
241 with mock.patch('functest.ci.prepare_env.os.path.isfile',
242 return_value=True), \
243 mock.patch('functest.ci.prepare_env.os.path.getsize',
245 self.assertRaises(Exception):
246 CONST.__setattr__('openstack_creds', 'test_creds')
247 prepare_env.source_rc_file()
249 def test_source_rc_missing_installer_ip(self):
250 with mock.patch('functest.ci.prepare_env.os.path.isfile',
251 return_value=False), \
252 self.assertRaises(Exception):
253 CONST.__setattr__('INSTALLER_IP', None)
254 CONST.__setattr__('openstack_creds', 'test_creds')
255 prepare_env.source_rc_file()
257 def test_source_rc_missing_installer_type(self):
258 with mock.patch('functest.ci.prepare_env.os.path.isfile',
259 return_value=False), \
260 self.assertRaises(Exception):
261 CONST.__setattr__('INSTALLER_IP', 'test_ip')
262 CONST.__setattr__('openstack_creds', 'test_creds')
263 CONST.__setattr__('INSTALLER_TYPE', 'test_type')
264 opnfv_constants.INSTALLERS = []
265 prepare_env.source_rc_file()
267 def test_source_rc_missing_os_credfile_ci_inst(self):
268 with mock.patch('functest.ci.prepare_env.os.path.isfile',
269 return_value=False), \
270 mock.patch('functest.ci.prepare_env.os.path.getsize'), \
271 mock.patch('functest.ci.prepare_env.os.path.join'), \
272 mock.patch('functest.ci.prepare_env.subprocess.Popen') \
273 as mock_subproc_popen, \
274 self.assertRaises(Exception):
275 CONST.__setattr__('openstack_creds', 'test_creds')
276 CONST.__setattr__('INSTALLER_IP', None)
277 CONST.__setattr__('INSTALLER_TYPE', 'test_type')
278 opnfv_constants.INSTALLERS = ['test_type']
280 process_mock = mock.Mock()
281 attrs = {'communicate.return_value': ('output', 'error'),
283 process_mock.configure_mock(**attrs)
284 mock_subproc_popen.return_value = process_mock
286 prepare_env.source_rc_file()
288 @mock.patch('functest.ci.prepare_env.logger.debug')
289 def test_patch_file(self, mock_logger_debug):
290 with mock.patch("__builtin__.open", mock.mock_open()), \
291 mock.patch('functest.ci.prepare_env.yaml.safe_load',
292 return_value={'test_scenario': {'tkey': 'tvalue'}}), \
293 mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
294 return_value={'tkey1': 'tvalue1'}), \
295 mock.patch('functest.ci.prepare_env.os.remove') as m, \
296 mock.patch('functest.ci.prepare_env.yaml.dump'):
297 CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
298 prepare_env.patch_file('test_file')
299 self.assertTrue(m.called)
301 @mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
302 return_value={'tkey1': 'tvalue1'})
303 @mock.patch('functest.ci.prepare_env.yaml.safe_load',
304 return_value={'test_scenario': {'tkey': 'tvalue'}})
305 @mock.patch('functest.ci.prepare_env.update_db_url')
306 def test_update_db_url(self, mock_db_url, mock_safe_load,
307 mock_get_functest_yaml):
308 CONST.__setattr__('DEPLOY_SCENARIO', 'default_scenario')
309 with mock.patch("__builtin__.open", mock.mock_open()), \
310 mock.patch('functest.ci.prepare_env.yaml.dump'), \
311 mock.patch.dict('functest.ci.prepare_env.os.environ',
312 {'TEST_DB_URL': self.db_url_env},
314 prepare_env.update_config_file()
315 self.assertTrue(mock_db_url.called)
317 @mock.patch('functest.ci.prepare_env.logger.info')
318 def test_verify_deployment_error(self, mock_logger_error):
319 mock_popen = mock.Mock()
320 attrs = {'poll.return_value': None,
321 'stdout.readline.return_value': 'ERROR'}
322 mock_popen.configure_mock(**attrs)
324 with mock.patch('functest.ci.prepare_env.print_separator') as m, \
325 mock.patch('functest.ci.prepare_env.subprocess.Popen',
326 return_value=mock_popen), \
327 self.assertRaises(Exception) as context:
328 prepare_env.verify_deployment()
329 self.assertTrue(m.called)
330 msg = "Problem while running 'check_os.sh'."
331 mock_logger_error.assert_called_once_with('ERROR')
332 self.assertTrue(msg in context)
334 def _get_rally_creds(self):
335 return {"type": "ExistingCloud",
336 "admin": {"username": 'test_user_name',
337 "password": 'test_password',
338 "tenant": 'test_tenant'}}
340 @mock.patch('functest.ci.prepare_env.os_utils.get_credentials_for_rally')
341 @mock.patch('functest.ci.prepare_env.logger.info')
342 @mock.patch('functest.ci.prepare_env.ft_utils.execute_command_raise')
343 @mock.patch('functest.ci.prepare_env.ft_utils.execute_command')
344 def test_install_rally(self, mock_exec, mock_exec_raise, mock_logger_info,
347 mock_os_utils.return_value = self._get_rally_creds()
349 prepare_env.install_rally()
351 cmd = "rally deployment destroy opnfv-rally"
352 error_msg = "Deployment %s does not exist." % \
353 CONST.__getattribute__('rally_deployment_name')
354 mock_logger_info.assert_any_call("Creating Rally environment...")
355 mock_exec.assert_any_call(cmd, error_msg=error_msg, verbose=False)
357 cmd = "rally deployment create --file=rally_conf.json --name="
358 cmd += CONST.__getattribute__('rally_deployment_name')
359 error_msg = "Problem while creating Rally deployment"
360 mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
362 cmd = "rally deployment check"
363 error_msg = ("OpenStack not responding or "
364 "faulty Rally deployment.")
365 mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
367 cmd = "rally deployment list"
368 error_msg = ("Problem while listing "
370 mock_exec.assert_any_call(cmd, error_msg=error_msg)
372 cmd = "rally plugin list | head -5"
373 error_msg = ("Problem while showing "
375 mock_exec.assert_any_call(cmd, error_msg=error_msg)
377 @mock.patch('functest.ci.prepare_env.logger.debug')
378 def test_install_tempest(self, mock_logger_debug):
379 mock_popen = mock.Mock()
380 attrs = {'poll.return_value': None,
381 'stdout.readline.return_value': '0'}
382 mock_popen.configure_mock(**attrs)
384 CONST.__setattr__('tempest_deployment_name', 'test_dep_name')
385 with mock.patch('functest.ci.prepare_env.'
386 'ft_utils.execute_command_raise',
387 side_effect=Exception), \
388 mock.patch('functest.ci.prepare_env.subprocess.Popen',
389 return_value=mock_popen), \
390 self.assertRaises(Exception):
391 prepare_env.install_tempest()
392 mock_logger_debug.assert_any_call("Tempest test_dep_name"
395 def test_create_flavor(self):
396 with mock.patch('functest.ci.prepare_env.'
397 'os_utils.get_or_create_flavor',
398 return_value=('test_', None)), \
399 self.assertRaises(Exception) as context:
400 prepare_env.create_flavor()
401 msg = 'Failed to create flavor'
402 self.assertTrue(msg in context)
404 @mock.patch('functest.ci.prepare_env.sys.exit')
405 @mock.patch('functest.ci.prepare_env.logger.error')
406 def test_check_environment_missing_file(self, mock_logger_error,
408 with mock.patch('functest.ci.prepare_env.os.path.isfile',
409 return_value=False), \
410 self.assertRaises(Exception):
411 prepare_env.check_environment()
413 @mock.patch('functest.ci.prepare_env.sys.exit')
414 @mock.patch('functest.ci.prepare_env.logger.error')
415 def test_check_environment_with_error(self, mock_logger_error,
417 with mock.patch('functest.ci.prepare_env.os.path.isfile',
418 return_value=True), \
419 mock.patch("__builtin__.open", mock.mock_open(read_data='0')), \
420 self.assertRaises(Exception):
421 prepare_env.check_environment()
423 @mock.patch('functest.ci.prepare_env.logger.info')
424 def test_check_environment_default(self, mock_logger_info):
425 with mock.patch('functest.ci.prepare_env.os.path.isfile',
427 with mock.patch("__builtin__.open", mock.mock_open(read_data='1')):
428 prepare_env.check_environment()
429 mock_logger_info.assert_any_call("Functest environment"
432 @mock.patch('functest.ci.prepare_env.print_deployment_info')
433 @mock.patch('functest.ci.prepare_env.check_environment')
434 @mock.patch('functest.ci.prepare_env.create_flavor')
435 @mock.patch('functest.ci.prepare_env.install_tempest')
436 @mock.patch('functest.ci.prepare_env.install_rally')
437 @mock.patch('functest.ci.prepare_env.verify_deployment')
438 @mock.patch('functest.ci.prepare_env.update_config_file')
439 @mock.patch('functest.ci.prepare_env.source_rc_file')
440 @mock.patch('functest.ci.prepare_env.create_directories')
441 @mock.patch('functest.ci.prepare_env.get_deployment_handler')
442 @mock.patch('functest.ci.prepare_env.check_env_variables')
443 @mock.patch('functest.ci.prepare_env.logger.info')
444 def test_main_start(self, mock_logger_info, mock_env_var, mock_dep_handler,
445 mock_create_dir, mock_source_rc, mock_update_config,
446 mock_verify_depl, mock_install_rally,
447 mock_install_temp, mock_create_flavor,
448 mock_check_env, mock_print_info):
449 with mock.patch("__builtin__.open", mock.mock_open()) as m:
450 args = {'action': 'start'}
451 self.assertEqual(prepare_env.main(**args), 0)
452 mock_logger_info.assert_any_call("######### Preparing Functest "
453 "environment #########\n")
454 self.assertTrue(mock_env_var.called)
455 self.assertTrue(mock_dep_handler.called)
456 self.assertTrue(mock_create_dir.called)
457 self.assertTrue(mock_source_rc.called)
458 self.assertTrue(mock_update_config.called)
459 self.assertTrue(mock_verify_depl.called)
460 self.assertTrue(mock_install_rally.called)
461 self.assertTrue(mock_install_temp.called)
462 self.assertTrue(mock_create_flavor.called)
463 m.assert_called_once_with(
464 CONST.__getattribute__('env_active'), "w")
465 self.assertTrue(mock_check_env.called)
466 self.assertTrue(mock_print_info.called)
468 @mock.patch('functest.ci.prepare_env.check_environment')
469 def test_main_check(self, mock_check_env):
470 args = {'action': 'check'}
471 self.assertEqual(prepare_env.main(**args), 0)
472 self.assertTrue(mock_check_env.called)
474 @mock.patch('functest.ci.prepare_env.logger.error')
475 def test_main_no_arg(self, mock_logger_error):
476 args = {'action': 'not_valid'}
477 self.assertEqual(prepare_env.main(**args), -1)
478 mock_logger_error.assert_called_once_with('Argument not valid.')
481 if __name__ == "__main__":
482 logging.disable(logging.CRITICAL)
483 unittest.main(verbosity=2)