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(
51 "The env variable 'INSTALLER_IP' is not defined. It is recommended"
52 " to extract some information from the deployment")
54 @mock.patch('functest.ci.prepare_env.logger.info')
55 @mock.patch('functest.ci.prepare_env.logger.warning')
56 def test_check_env_variables_with_inst_ip(self, mock_logger_warn,
58 CONST.__setattr__('INSTALLER_IP', mock.Mock())
59 prepare_env.check_env_variables()
60 mock_logger_info.assert_any_call("Checking environment variables"
62 mock_logger_info.assert_any_call(test_utils.
63 SubstrMatch(" INSTALLER_IP="))
65 @mock.patch('functest.ci.prepare_env.logger.info')
66 @mock.patch('functest.ci.prepare_env.logger.warning')
67 def test_check_env_variables_missing_scenario(self, mock_logger_warn,
69 CONST.__setattr__('DEPLOY_SCENARIO', None)
70 prepare_env.check_env_variables()
71 mock_logger_info.assert_any_call("Checking environment variables"
73 mock_logger_warn.assert_any_call("The env variable"
74 " 'DEPLOY_SCENARIO' is not defined"
75 ". Setting CI_SCENARIO=undefined.")
77 @mock.patch('functest.ci.prepare_env.logger.info')
78 @mock.patch('functest.ci.prepare_env.logger.warning')
79 def test_check_env_variables_with_scenario(self, mock_logger_warn,
81 CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
82 prepare_env.check_env_variables()
83 mock_logger_info.assert_any_call("Checking environment variables"
85 mock_logger_info.assert_any_call(test_utils.
86 SubstrMatch("DEPLOY_SCENARIO="))
88 @mock.patch('functest.ci.prepare_env.logger.info')
89 @mock.patch('functest.ci.prepare_env.logger.warning')
90 def test_check_env_variables_with_ci_debug(self, mock_logger_warn,
92 CONST.__setattr__('CI_DEBUG', mock.Mock())
93 prepare_env.check_env_variables()
94 mock_logger_info.assert_any_call("Checking environment variables"
96 mock_logger_info.assert_any_call(test_utils.
97 SubstrMatch(" CI_DEBUG="))
99 @mock.patch('functest.ci.prepare_env.logger.info')
100 @mock.patch('functest.ci.prepare_env.logger.warning')
101 def test_check_env_variables_with_node(self, mock_logger_warn,
103 CONST.__setattr__('NODE_NAME', mock.Mock())
104 prepare_env.check_env_variables()
105 mock_logger_info.assert_any_call("Checking environment variables"
107 mock_logger_info.assert_any_call(test_utils.
108 SubstrMatch(" NODE_NAME="))
110 @mock.patch('functest.ci.prepare_env.logger.info')
111 @mock.patch('functest.ci.prepare_env.logger.warning')
112 def test_check_env_variables_with_build_tag(self, mock_logger_warn,
114 CONST.__setattr__('BUILD_TAG', mock.Mock())
115 prepare_env.check_env_variables()
116 mock_logger_info.assert_any_call("Checking environment variables"
119 mock_logger_info.assert_any_call(test_utils.
120 SubstrMatch(" BUILD_TAG="))
122 @mock.patch('functest.ci.prepare_env.logger.info')
123 @mock.patch('functest.ci.prepare_env.logger.warning')
124 def test_check_env_variables_with_is_ci_run(self, mock_logger_warn,
126 CONST.__setattr__('IS_CI_RUN', mock.Mock())
127 prepare_env.check_env_variables()
128 mock_logger_info.assert_any_call("Checking environment variables"
131 mock_logger_info.assert_any_call(test_utils.
132 SubstrMatch(" IS_CI_RUN="))
134 def test_get_deployment_handler_missing_const_vars(self):
135 with mock.patch('functest.ci.prepare_env.'
136 'factory.Factory.get_handler') as m:
137 CONST.__setattr__('INSTALLER_IP', None)
138 prepare_env.get_deployment_handler()
139 self.assertFalse(m.called)
141 CONST.__setattr__('INSTALLER_TYPE', None)
142 prepare_env.get_deployment_handler()
143 self.assertFalse(m.called)
145 @mock.patch('functest.ci.prepare_env.logger.debug')
146 def test_get_deployment_handler_missing_print_deploy_info(self,
148 with mock.patch('functest.ci.prepare_env.'
149 'factory.Factory.get_handler') as m, \
150 mock.patch('functest.ci.prepare_env.'
151 'ft_utils.get_parameter_from_yaml',
152 side_effect=ValueError):
153 CONST.__setattr__('INSTALLER_IP', 'test_ip')
154 CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
155 opnfv_constants.INSTALLERS = ['test_inst_type']
156 prepare_env.get_deployment_handler()
157 msg = ('Printing deployment info is not supported for '
159 mock_debug.assert_any_call(msg)
160 self.assertFalse(m.called)
162 @mock.patch('functest.ci.prepare_env.logger.debug')
163 def test_get_deployment_handler_exception(self, mock_debug):
164 with mock.patch('functest.ci.prepare_env.'
165 'factory.Factory.get_handler',
166 side_effect=Exception), \
167 mock.patch('functest.ci.prepare_env.'
168 'ft_utils.get_parameter_from_yaml'):
169 CONST.__setattr__('INSTALLER_IP', 'test_ip')
170 CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
171 opnfv_constants.INSTALLERS = ['test_inst_type']
172 prepare_env.get_deployment_handler()
173 self.assertTrue(mock_debug.called)
175 @mock.patch('functest.ci.prepare_env.logger.info')
176 @mock.patch('functest.ci.prepare_env.logger.debug')
177 def test_create_directories_missing_dir(self, mock_logger_debug,
179 with mock.patch('functest.ci.prepare_env.os.path.exists',
180 return_value=False), \
181 mock.patch('functest.ci.prepare_env.os.makedirs') \
183 prepare_env.create_directories()
184 mock_logger_info.assert_any_call("Creating needed directories...")
185 mock_method.assert_any_call(
186 CONST.__getattribute__('dir_functest_conf'))
187 mock_method.assert_any_call(
188 CONST.__getattribute__('dir_functest_data'))
189 mock_method.assert_any_call(
190 CONST.__getattribute__('dir_functest_images'))
191 mock_logger_info.assert_any_call(" %s created." %
192 CONST.__getattribute__(
193 'dir_functest_conf'))
194 mock_logger_info.assert_any_call(" %s created." %
195 CONST.__getattribute__(
196 'dir_functest_data'))
197 mock_logger_info.assert_any_call(" %s created." %
198 CONST.__getattribute__(
199 'dir_functest_images'))
201 @mock.patch('functest.ci.prepare_env.logger.info')
202 @mock.patch('functest.ci.prepare_env.logger.debug')
203 def test_create_directories_with_dir(self, mock_logger_debug,
205 with mock.patch('functest.ci.prepare_env.os.path.exists',
207 prepare_env.create_directories()
208 mock_logger_info.assert_any_call("Creating needed directories...")
209 mock_logger_debug.assert_any_call(" %s already exists." %
210 CONST.__getattribute__(
211 'dir_functest_conf'))
212 mock_logger_debug.assert_any_call(" %s already exists." %
213 CONST.__getattribute__(
214 'dir_functest_data'))
215 mock_logger_debug.assert_any_call(" %s already exists." %
216 CONST.__getattribute__(
217 'dir_functest_images'))
219 def _get_env_cred_dict(self, os_prefix=''):
220 return {'OS_USERNAME': os_prefix + 'username',
221 'OS_PASSWORD': os_prefix + 'password',
222 'OS_AUTH_URL': 'http://test_ip:test_port/v2.0',
223 'OS_TENANT_NAME': os_prefix + 'tenant_name',
224 'OS_USER_DOMAIN_NAME': os_prefix + 'user_domain_name',
225 'OS_PROJECT_DOMAIN_NAME': os_prefix + 'project_domain_name',
226 'OS_PROJECT_NAME': os_prefix + 'project_name',
227 'OS_ENDPOINT_TYPE': os_prefix + 'endpoint_type',
228 'OS_REGION_NAME': os_prefix + 'region_name'}
230 @mock.patch('functest.ci.prepare_env.logger.error')
231 @mock.patch('functest.ci.prepare_env.logger.info')
232 @mock.patch('functest.ci.prepare_env.logger.warning')
233 def test_source_rc_missing_rc_file(self, mock_logger_warn,
236 with mock.patch('functest.ci.prepare_env.os.path.isfile',
237 return_value=True), \
238 mock.patch('functest.ci.prepare_env.os.path.getsize',
240 self.assertRaises(Exception):
241 CONST.__setattr__('openstack_creds', 'test_creds')
242 prepare_env.source_rc_file()
244 def test_source_rc_missing_installer_ip(self):
245 with mock.patch('functest.ci.prepare_env.os.path.isfile',
246 return_value=False), \
247 self.assertRaises(Exception):
248 CONST.__setattr__('INSTALLER_IP', None)
249 CONST.__setattr__('openstack_creds', 'test_creds')
250 prepare_env.source_rc_file()
252 def test_source_rc_missing_installer_type(self):
253 with mock.patch('functest.ci.prepare_env.os.path.isfile',
254 return_value=False), \
255 self.assertRaises(Exception):
256 CONST.__setattr__('INSTALLER_IP', 'test_ip')
257 CONST.__setattr__('openstack_creds', 'test_creds')
258 CONST.__setattr__('INSTALLER_TYPE', 'test_type')
259 opnfv_constants.INSTALLERS = []
260 prepare_env.source_rc_file()
262 def test_source_rc_missing_os_credfile_ci_inst(self):
263 with mock.patch('functest.ci.prepare_env.os.path.isfile',
264 return_value=False), \
265 mock.patch('functest.ci.prepare_env.os.path.getsize'), \
266 mock.patch('functest.ci.prepare_env.os.path.join'), \
267 mock.patch('functest.ci.prepare_env.subprocess.Popen') \
268 as mock_subproc_popen, \
269 self.assertRaises(Exception):
270 CONST.__setattr__('openstack_creds', None)
271 CONST.__setattr__('INSTALLER_IP', 'test_ip')
272 CONST.__setattr__('INSTALLER_TYPE', 'test_type')
273 opnfv_constants.INSTALLERS = ['test_type']
275 process_mock = mock.Mock()
276 attrs = {'communicate.return_value': ('output', 'error'),
278 process_mock.configure_mock(**attrs)
279 mock_subproc_popen.return_value = process_mock
281 prepare_env.source_rc_file()
283 @mock.patch('functest.ci.prepare_env.logger.debug')
284 def test_patch_file(self, mock_logger_debug):
285 with mock.patch("__builtin__.open", mock.mock_open()), \
286 mock.patch('functest.ci.prepare_env.yaml.safe_load',
287 return_value={'test_scenario': {'tkey': 'tvalue'}}), \
288 mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
289 return_value={'tkey1': 'tvalue1'}), \
290 mock.patch('functest.ci.prepare_env.os.remove') as m, \
291 mock.patch('functest.ci.prepare_env.yaml.dump'):
292 CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
293 prepare_env.patch_file('test_file')
294 self.assertTrue(m.called)
296 @mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
297 return_value={'tkey1': 'tvalue1'})
298 @mock.patch('functest.ci.prepare_env.yaml.safe_load',
299 return_value={'test_scenario': {'tkey': 'tvalue'}})
300 @mock.patch('functest.ci.prepare_env.update_db_url')
301 def test_update_db_url(self, mock_db_url, mock_safe_load,
302 mock_get_functest_yaml):
303 CONST.__setattr__('DEPLOY_SCENARIO', 'default_scenario')
304 with mock.patch("__builtin__.open", mock.mock_open()), \
305 mock.patch('functest.ci.prepare_env.yaml.dump'), \
306 mock.patch.dict('functest.ci.prepare_env.os.environ',
307 {'TEST_DB_URL': self.db_url_env},
309 prepare_env.update_config_file()
310 self.assertTrue(mock_db_url.called)
312 def test_verify_deployment(self):
313 with mock.patch('functest.ci.check_deployment.CheckDeployment') \
314 as mock_check_deployment:
315 prepare_env.verify_deployment()
316 self.assertTrue(mock_check_deployment.called)
318 def test_verify_deployment_error(self):
319 with mock.patch('functest.ci.prepare_env.'
320 'check_deployment.CheckDeployment',
321 return_value=('test_', None)), \
322 self.assertRaises(Exception):
323 prepare_env.verify_deployment()
325 def _get_rally_creds(self):
326 return {"type": "ExistingCloud",
327 "admin": {"username": 'test_user_name',
328 "password": 'test_password',
329 "tenant": 'test_tenant'}}
331 @mock.patch('functest.ci.prepare_env.os_utils.get_credentials_for_rally')
332 @mock.patch('functest.ci.prepare_env.logger.info')
333 @mock.patch('functest.ci.prepare_env.ft_utils.execute_command_raise')
334 @mock.patch('functest.ci.prepare_env.ft_utils.execute_command')
335 def test_install_rally(self, mock_exec, mock_exec_raise, mock_logger_info,
338 mock_os_utils.return_value = self._get_rally_creds()
340 prepare_env.install_rally()
342 cmd = "rally deployment destroy opnfv-rally"
343 error_msg = "Deployment %s does not exist." % \
344 CONST.__getattribute__('rally_deployment_name')
345 mock_logger_info.assert_any_call("Creating Rally environment...")
346 mock_exec.assert_any_call(cmd, error_msg=error_msg, verbose=False)
348 cmd = "rally deployment create --file=rally_conf.json --name="
349 cmd += CONST.__getattribute__('rally_deployment_name')
350 error_msg = "Problem while creating Rally deployment"
351 mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
353 cmd = "rally deployment check"
354 error_msg = ("OpenStack not responding or "
355 "faulty Rally deployment.")
356 mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
358 cmd = "rally deployment list"
359 error_msg = ("Problem while listing "
361 mock_exec.assert_any_call(cmd, error_msg=error_msg)
363 cmd = "rally plugin list | head -5"
364 error_msg = ("Problem while showing "
366 mock_exec.assert_any_call(cmd, error_msg=error_msg)
368 @mock.patch('functest.ci.prepare_env.logger.debug')
369 def test_install_tempest(self, mock_logger_debug):
370 mock_popen = mock.Mock()
371 attrs = {'poll.return_value': None,
372 'stdout.readline.return_value': '0'}
373 mock_popen.configure_mock(**attrs)
375 CONST.__setattr__('tempest_deployment_name', 'test_dep_name')
376 with mock.patch('functest.ci.prepare_env.'
377 'ft_utils.execute_command_raise',
378 side_effect=Exception), \
379 mock.patch('functest.ci.prepare_env.subprocess.Popen',
380 return_value=mock_popen), \
381 self.assertRaises(Exception):
382 prepare_env.install_tempest()
383 mock_logger_debug.assert_any_call("Tempest test_dep_name"
386 def test_create_flavor(self):
387 with mock.patch('functest.ci.prepare_env.'
388 'os_utils.get_or_create_flavor',
389 return_value=('test_', None)), \
390 self.assertRaises(Exception) as context:
391 prepare_env.create_flavor()
392 msg = 'Failed to create flavor'
393 self.assertTrue(msg in context)
395 @mock.patch('functest.ci.prepare_env.sys.exit')
396 @mock.patch('functest.ci.prepare_env.logger.error')
397 def test_check_environment_missing_file(self, mock_logger_error,
399 with mock.patch('functest.ci.prepare_env.os.path.isfile',
400 return_value=False), \
401 self.assertRaises(Exception):
402 prepare_env.check_environment()
404 @mock.patch('functest.ci.prepare_env.sys.exit')
405 @mock.patch('functest.ci.prepare_env.logger.error')
406 def test_check_environment_with_error(self, mock_logger_error,
408 with mock.patch('functest.ci.prepare_env.os.path.isfile',
409 return_value=True), \
410 mock.patch("__builtin__.open", mock.mock_open(read_data='0')), \
411 self.assertRaises(Exception):
412 prepare_env.check_environment()
414 @mock.patch('functest.ci.prepare_env.logger.info')
415 def test_check_environment_default(self, mock_logger_info):
416 with mock.patch('functest.ci.prepare_env.os.path.isfile',
418 with mock.patch("__builtin__.open", mock.mock_open(read_data='1')):
419 prepare_env.check_environment()
420 mock_logger_info.assert_any_call("Functest environment"
423 @mock.patch('functest.ci.prepare_env.check_environment')
424 @mock.patch('functest.ci.prepare_env.create_flavor')
425 @mock.patch('functest.ci.prepare_env.install_tempest')
426 @mock.patch('functest.ci.prepare_env.install_rally')
427 @mock.patch('functest.ci.prepare_env.verify_deployment')
428 @mock.patch('functest.ci.prepare_env.update_config_file')
429 @mock.patch('functest.ci.prepare_env.source_rc_file')
430 @mock.patch('functest.ci.prepare_env.create_directories')
431 @mock.patch('functest.ci.prepare_env.check_env_variables')
432 @mock.patch('functest.ci.prepare_env.logger.info')
433 def test_main_start(self, mock_logger_info, mock_env_var,
434 mock_create_dir, mock_source_rc, mock_update_config,
435 mock_verify_depl, mock_install_rally,
436 mock_install_temp, mock_create_flavor,
438 with mock.patch("__builtin__.open", mock.mock_open()) as m:
439 args = {'action': 'start'}
440 self.assertEqual(prepare_env.prepare_env(**args), 0)
441 mock_logger_info.assert_any_call("######### Preparing Functest "
442 "environment #########\n")
443 self.assertTrue(mock_env_var.called)
444 self.assertTrue(mock_create_dir.called)
445 self.assertTrue(mock_source_rc.called)
446 self.assertTrue(mock_update_config.called)
447 self.assertTrue(mock_verify_depl.called)
448 self.assertTrue(mock_install_rally.called)
449 self.assertTrue(mock_install_temp.called)
450 self.assertTrue(mock_create_flavor.called)
451 m.assert_called_once_with(
452 CONST.__getattribute__('env_active'), "w")
453 self.assertTrue(mock_check_env.called)
455 @mock.patch('functest.ci.prepare_env.check_environment')
456 def test_main_check(self, mock_check_env):
457 args = {'action': 'check'}
458 self.assertEqual(prepare_env.prepare_env(**args), 0)
459 self.assertTrue(mock_check_env.called)
461 @mock.patch('functest.ci.prepare_env.logger.error')
462 def test_main_no_arg(self, mock_logger_error):
463 args = {'action': 'not_valid'}
464 self.assertEqual(prepare_env.prepare_env(**args), -1)
465 mock_logger_error.assert_called_once_with('Argument not valid.')
468 if __name__ == "__main__":
469 logging.disable(logging.CRITICAL)
470 unittest.main(verbosity=2)