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()
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)
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,
34 CONST.__setattr__('INSTALLER_TYPE', None)
35 prepare_env.check_env_variables()
36 mock_logger_info.assert_any_call("Checking environment variables"
38 mock_logger_warn.assert_any_call("The env variable 'INSTALLER_TYPE'"
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,
45 CONST.__setattr__('INSTALLER_IP', None)
46 prepare_env.check_env_variables()
47 mock_logger_info.assert_any_call("Checking environment variables"
49 mock_logger_warn.assert_any_call(
50 "The env variable 'INSTALLER_IP' is not defined. It is recommended"
51 " to extract some information from the deployment")
53 @mock.patch('functest.ci.prepare_env.logger.info')
54 @mock.patch('functest.ci.prepare_env.logger.warning')
55 def test_check_env_variables_with_inst_ip(self, mock_logger_warn,
57 CONST.__setattr__('INSTALLER_IP', mock.Mock())
58 prepare_env.check_env_variables()
59 mock_logger_info.assert_any_call("Checking environment variables"
61 mock_logger_info.assert_any_call(test_utils.
62 SubstrMatch(" INSTALLER_IP="))
64 @mock.patch('functest.ci.prepare_env.logger.info')
65 @mock.patch('functest.ci.prepare_env.logger.warning')
66 def test_check_env_variables_missing_scenario(self, mock_logger_warn,
68 CONST.__setattr__('DEPLOY_SCENARIO', None)
69 prepare_env.check_env_variables()
70 mock_logger_info.assert_any_call("Checking environment variables"
72 mock_logger_warn.assert_any_call("The env variable"
73 " 'DEPLOY_SCENARIO' is not defined"
74 ". Setting CI_SCENARIO=undefined.")
76 @mock.patch('functest.ci.prepare_env.logger.info')
77 @mock.patch('functest.ci.prepare_env.logger.warning')
78 def test_check_env_variables_with_scenario(self, mock_logger_warn,
80 CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
81 prepare_env.check_env_variables()
82 mock_logger_info.assert_any_call("Checking environment variables"
84 mock_logger_info.assert_any_call(test_utils.
85 SubstrMatch("DEPLOY_SCENARIO="))
87 @mock.patch('functest.ci.prepare_env.logger.info')
88 @mock.patch('functest.ci.prepare_env.logger.warning')
89 def test_check_env_variables_with_ci_debug(self, mock_logger_warn,
91 CONST.__setattr__('CI_DEBUG', mock.Mock())
92 prepare_env.check_env_variables()
93 mock_logger_info.assert_any_call("Checking environment variables"
95 mock_logger_info.assert_any_call(test_utils.
96 SubstrMatch(" CI_DEBUG="))
98 @mock.patch('functest.ci.prepare_env.logger.info')
99 @mock.patch('functest.ci.prepare_env.logger.warning')
100 def test_check_env_variables_with_node(self, mock_logger_warn,
102 CONST.__setattr__('NODE_NAME', mock.Mock())
103 prepare_env.check_env_variables()
104 mock_logger_info.assert_any_call("Checking environment variables"
106 mock_logger_info.assert_any_call(test_utils.
107 SubstrMatch(" NODE_NAME="))
109 @mock.patch('functest.ci.prepare_env.logger.info')
110 @mock.patch('functest.ci.prepare_env.logger.warning')
111 def test_check_env_variables_with_build_tag(self, mock_logger_warn,
113 CONST.__setattr__('BUILD_TAG', mock.Mock())
114 prepare_env.check_env_variables()
115 mock_logger_info.assert_any_call("Checking environment variables"
118 mock_logger_info.assert_any_call(test_utils.
119 SubstrMatch(" BUILD_TAG="))
121 @mock.patch('functest.ci.prepare_env.logger.info')
122 @mock.patch('functest.ci.prepare_env.logger.warning')
123 def test_check_env_variables_with_is_ci_run(self, mock_logger_warn,
125 CONST.__setattr__('IS_CI_RUN', mock.Mock())
126 prepare_env.check_env_variables()
127 mock_logger_info.assert_any_call("Checking environment variables"
130 mock_logger_info.assert_any_call(test_utils.
131 SubstrMatch(" IS_CI_RUN="))
133 def test_get_deployment_handler_missing_const_vars(self):
134 with mock.patch('functest.ci.prepare_env.'
135 'factory.Factory.get_handler') as m:
136 CONST.__setattr__('INSTALLER_IP', None)
137 prepare_env.get_deployment_handler()
138 self.assertFalse(m.called)
140 CONST.__setattr__('INSTALLER_TYPE', None)
141 prepare_env.get_deployment_handler()
142 self.assertFalse(m.called)
144 @mock.patch('functest.ci.prepare_env.logger.debug')
145 def test_get_deployment_handler_missing_print_deploy_info(self,
147 with mock.patch('functest.ci.prepare_env.'
148 'factory.Factory.get_handler') as m, \
149 mock.patch('functest.ci.prepare_env.'
150 'ft_utils.get_parameter_from_yaml',
151 side_effect=ValueError):
152 CONST.__setattr__('INSTALLER_IP', 'test_ip')
153 CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
154 opnfv_constants.INSTALLERS = ['test_inst_type']
155 prepare_env.get_deployment_handler()
156 msg = ('Printing deployment info is not supported for '
158 mock_debug.assert_any_call(msg)
159 self.assertFalse(m.called)
161 @mock.patch('functest.ci.prepare_env.logger.debug')
162 def test_get_deployment_handler_exception(self, mock_debug):
163 with mock.patch('functest.ci.prepare_env.'
164 'factory.Factory.get_handler',
165 side_effect=Exception), \
166 mock.patch('functest.ci.prepare_env.'
167 'ft_utils.get_parameter_from_yaml'):
168 CONST.__setattr__('INSTALLER_IP', 'test_ip')
169 CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
170 opnfv_constants.INSTALLERS = ['test_inst_type']
171 prepare_env.get_deployment_handler()
172 self.assertTrue(mock_debug.called)
174 @mock.patch('functest.ci.prepare_env.logger.info')
175 @mock.patch('functest.ci.prepare_env.logger.debug')
176 def test_create_directories_missing_dir(self, mock_logger_debug,
178 with mock.patch('functest.ci.prepare_env.os.path.exists',
179 return_value=False), \
180 mock.patch('functest.ci.prepare_env.os.makedirs') \
182 prepare_env.create_directories()
183 mock_logger_info.assert_any_call("Creating needed directories...")
184 mock_method.assert_any_call(
185 CONST.__getattribute__('dir_functest_conf'))
186 mock_method.assert_any_call(
187 CONST.__getattribute__('dir_functest_data'))
188 mock_method.assert_any_call(
189 CONST.__getattribute__('dir_functest_images'))
190 mock_logger_info.assert_any_call(" %s created." %
191 CONST.__getattribute__(
192 'dir_functest_conf'))
193 mock_logger_info.assert_any_call(" %s created." %
194 CONST.__getattribute__(
195 'dir_functest_data'))
196 mock_logger_info.assert_any_call(" %s created." %
197 CONST.__getattribute__(
198 'dir_functest_images'))
200 @mock.patch('functest.ci.prepare_env.logger.info')
201 @mock.patch('functest.ci.prepare_env.logger.debug')
202 def test_create_directories_with_dir(self, mock_logger_debug,
204 with mock.patch('functest.ci.prepare_env.os.path.exists',
206 prepare_env.create_directories()
207 mock_logger_info.assert_any_call("Creating needed directories...")
208 mock_logger_debug.assert_any_call(" %s already exists." %
209 CONST.__getattribute__(
210 'dir_functest_conf'))
211 mock_logger_debug.assert_any_call(" %s already exists." %
212 CONST.__getattribute__(
213 'dir_functest_data'))
214 mock_logger_debug.assert_any_call(" %s already exists." %
215 CONST.__getattribute__(
216 'dir_functest_images'))
218 def _get_env_cred_dict(self, os_prefix=''):
219 return {'OS_USERNAME': os_prefix + 'username',
220 'OS_PASSWORD': os_prefix + 'password',
221 'OS_AUTH_URL': 'http://test_ip:test_port/v2.0',
222 'OS_TENANT_NAME': os_prefix + 'tenant_name',
223 'OS_USER_DOMAIN_NAME': os_prefix + 'user_domain_name',
224 'OS_PROJECT_DOMAIN_NAME': os_prefix + 'project_domain_name',
225 'OS_PROJECT_NAME': os_prefix + 'project_name',
226 'OS_ENDPOINT_TYPE': os_prefix + 'endpoint_type',
227 'OS_REGION_NAME': os_prefix + 'region_name'}
229 @mock.patch('functest.ci.prepare_env.logger.error')
230 @mock.patch('functest.ci.prepare_env.logger.info')
231 @mock.patch('functest.ci.prepare_env.logger.warning')
232 def test_source_rc_missing_rc_file(self, mock_logger_warn,
235 with mock.patch('functest.ci.prepare_env.os.path.isfile',
236 return_value=True), \
237 mock.patch('functest.ci.prepare_env.os.path.getsize',
239 self.assertRaises(Exception):
240 CONST.__setattr__('openstack_creds', 'test_creds')
241 prepare_env.source_rc_file()
243 def test_source_rc_missing_installer_ip(self):
244 with mock.patch('functest.ci.prepare_env.os.path.isfile',
245 return_value=False), \
246 self.assertRaises(Exception):
247 CONST.__setattr__('INSTALLER_IP', None)
248 CONST.__setattr__('openstack_creds', 'test_creds')
249 prepare_env.source_rc_file()
251 def test_source_rc_missing_installer_type(self):
252 with mock.patch('functest.ci.prepare_env.os.path.isfile',
253 return_value=False), \
254 self.assertRaises(Exception):
255 CONST.__setattr__('INSTALLER_IP', 'test_ip')
256 CONST.__setattr__('openstack_creds', 'test_creds')
257 CONST.__setattr__('INSTALLER_TYPE', 'test_type')
258 opnfv_constants.INSTALLERS = []
259 prepare_env.source_rc_file()
261 def test_source_rc_missing_os_credfile_ci_inst(self):
262 with mock.patch('functest.ci.prepare_env.os.path.isfile',
263 return_value=False), \
264 mock.patch('functest.ci.prepare_env.os.path.getsize'), \
265 mock.patch('functest.ci.prepare_env.os.path.join'), \
266 mock.patch('functest.ci.prepare_env.subprocess.Popen') \
267 as mock_subproc_popen, \
268 self.assertRaises(Exception):
269 CONST.__setattr__('openstack_creds', None)
270 CONST.__setattr__('INSTALLER_IP', 'test_ip')
271 CONST.__setattr__('INSTALLER_TYPE', 'test_type')
272 opnfv_constants.INSTALLERS = ['test_type']
274 process_mock = mock.Mock()
275 attrs = {'communicate.return_value': ('output', 'error'),
277 process_mock.configure_mock(**attrs)
278 mock_subproc_popen.return_value = process_mock
280 prepare_env.source_rc_file()
282 @mock.patch('functest.ci.prepare_env.logger.debug')
283 def test_patch_file(self, mock_logger_debug):
284 with mock.patch("__builtin__.open", mock.mock_open()), \
285 mock.patch('functest.ci.prepare_env.yaml.safe_load',
286 return_value={'test_scenario': {'tkey': 'tvalue'}}), \
287 mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
288 return_value={'tkey1': 'tvalue1'}), \
289 mock.patch('functest.ci.prepare_env.os.remove') as m, \
290 mock.patch('functest.ci.prepare_env.yaml.dump'):
291 CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
292 prepare_env.patch_file('test_file')
293 self.assertTrue(m.called)
295 @mock.patch('functest.ci.prepare_env.logger.info')
296 def test_verify_deployment_error(self, mock_logger_error):
297 mock_popen = mock.Mock()
298 attrs = {'poll.return_value': None,
299 'stdout.readline.return_value': 'ERROR'}
300 mock_popen.configure_mock(**attrs)
302 with mock.patch('functest.ci.prepare_env.print_separator') as m, \
303 mock.patch('functest.ci.prepare_env.subprocess.Popen',
304 return_value=mock_popen), \
305 self.assertRaises(Exception) as context:
306 prepare_env.verify_deployment()
307 self.assertTrue(m.called)
308 msg = "Problem while running 'check_os.sh'."
309 mock_logger_error.assert_called_once_with('ERROR')
310 self.assertTrue(msg in context)
312 def _get_rally_creds(self):
313 return {"type": "ExistingCloud",
314 "admin": {"username": 'test_user_name',
315 "password": 'test_password',
316 "tenant": 'test_tenant'}}
318 @mock.patch('functest.ci.prepare_env.os_utils.get_credentials_for_rally')
319 @mock.patch('functest.ci.prepare_env.logger.info')
320 @mock.patch('functest.ci.prepare_env.ft_utils.execute_command_raise')
321 @mock.patch('functest.ci.prepare_env.ft_utils.execute_command')
322 def test_install_rally(self, mock_exec, mock_exec_raise, mock_logger_info,
325 mock_os_utils.return_value = self._get_rally_creds()
327 prepare_env.install_rally()
329 cmd = "rally deployment destroy opnfv-rally"
330 error_msg = "Deployment %s does not exist." % \
331 CONST.__getattribute__('rally_deployment_name')
332 mock_logger_info.assert_any_call("Creating Rally environment...")
333 mock_exec.assert_any_call(cmd, error_msg=error_msg, verbose=False)
335 cmd = "rally deployment create --file=rally_conf.json --name="
336 cmd += CONST.__getattribute__('rally_deployment_name')
337 error_msg = "Problem while creating Rally deployment"
338 mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
340 cmd = "rally deployment check"
341 error_msg = ("OpenStack not responding or "
342 "faulty Rally deployment.")
343 mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
345 cmd = "rally deployment list"
346 error_msg = ("Problem while listing "
348 mock_exec.assert_any_call(cmd, error_msg=error_msg)
350 cmd = "rally plugin list | head -5"
351 error_msg = ("Problem while showing "
353 mock_exec.assert_any_call(cmd, error_msg=error_msg)
355 @mock.patch('functest.ci.prepare_env.logger.debug')
356 def test_install_tempest(self, mock_logger_debug):
357 mock_popen = mock.Mock()
358 attrs = {'poll.return_value': None,
359 'stdout.readline.return_value': '0'}
360 mock_popen.configure_mock(**attrs)
362 CONST.__setattr__('tempest_deployment_name', 'test_dep_name')
363 with mock.patch('functest.ci.prepare_env.'
364 'ft_utils.execute_command_raise',
365 side_effect=Exception), \
366 mock.patch('functest.ci.prepare_env.subprocess.Popen',
367 return_value=mock_popen), \
368 self.assertRaises(Exception):
369 prepare_env.install_tempest()
370 mock_logger_debug.assert_any_call("Tempest test_dep_name"
373 def test_create_flavor(self):
374 with mock.patch('functest.ci.prepare_env.'
375 'os_utils.get_or_create_flavor',
376 return_value=('test_', None)), \
377 self.assertRaises(Exception) as context:
378 prepare_env.create_flavor()
379 msg = 'Failed to create flavor'
380 self.assertTrue(msg in context)
382 @mock.patch('functest.ci.prepare_env.sys.exit')
383 @mock.patch('functest.ci.prepare_env.logger.error')
384 def test_check_environment_missing_file(self, mock_logger_error,
386 with mock.patch('functest.ci.prepare_env.os.path.isfile',
387 return_value=False), \
388 self.assertRaises(Exception):
389 prepare_env.check_environment()
391 @mock.patch('functest.ci.prepare_env.sys.exit')
392 @mock.patch('functest.ci.prepare_env.logger.error')
393 def test_check_environment_with_error(self, mock_logger_error,
395 with mock.patch('functest.ci.prepare_env.os.path.isfile',
396 return_value=True), \
397 mock.patch("__builtin__.open", mock.mock_open(read_data='0')), \
398 self.assertRaises(Exception):
399 prepare_env.check_environment()
401 @mock.patch('functest.ci.prepare_env.logger.info')
402 def test_check_environment_default(self, mock_logger_info):
403 with mock.patch('functest.ci.prepare_env.os.path.isfile',
405 with mock.patch("__builtin__.open", mock.mock_open(read_data='1')):
406 prepare_env.check_environment()
407 mock_logger_info.assert_any_call("Functest environment"
410 @mock.patch('functest.ci.prepare_env.print_deployment_info')
411 @mock.patch('functest.ci.prepare_env.check_environment')
412 @mock.patch('functest.ci.prepare_env.create_flavor')
413 @mock.patch('functest.ci.prepare_env.install_tempest')
414 @mock.patch('functest.ci.prepare_env.install_rally')
415 @mock.patch('functest.ci.prepare_env.verify_deployment')
416 @mock.patch('functest.ci.prepare_env.patch_config_file')
417 @mock.patch('functest.ci.prepare_env.source_rc_file')
418 @mock.patch('functest.ci.prepare_env.create_directories')
419 @mock.patch('functest.ci.prepare_env.get_deployment_handler')
420 @mock.patch('functest.ci.prepare_env.check_env_variables')
421 @mock.patch('functest.ci.prepare_env.logger.info')
422 def test_main_start(self, mock_logger_info, mock_env_var, mock_dep_handler,
423 mock_create_dir, mock_source_rc, mock_patch_config,
424 mock_verify_depl, mock_install_rally,
425 mock_install_temp, mock_create_flavor,
426 mock_check_env, mock_print_info):
427 with mock.patch("__builtin__.open", mock.mock_open()) as m:
428 args = {'action': 'start'}
429 self.assertEqual(prepare_env.main(**args), 0)
430 mock_logger_info.assert_any_call("######### Preparing Functest "
431 "environment #########\n")
432 self.assertTrue(mock_env_var.called)
433 self.assertTrue(mock_dep_handler.called)
434 self.assertTrue(mock_create_dir.called)
435 self.assertTrue(mock_source_rc.called)
436 self.assertTrue(mock_patch_config.called)
437 self.assertTrue(mock_verify_depl.called)
438 self.assertTrue(mock_install_rally.called)
439 self.assertTrue(mock_install_temp.called)
440 self.assertTrue(mock_create_flavor.called)
441 m.assert_called_once_with(
442 CONST.__getattribute__('env_active'), "w")
443 self.assertTrue(mock_check_env.called)
444 self.assertTrue(mock_print_info.called)
446 @mock.patch('functest.ci.prepare_env.check_environment')
447 def test_main_check(self, mock_check_env):
448 args = {'action': 'check'}
449 self.assertEqual(prepare_env.main(**args), 0)
450 self.assertTrue(mock_check_env.called)
452 @mock.patch('functest.ci.prepare_env.logger.error')
453 def test_main_no_arg(self, mock_logger_error):
454 args = {'action': 'not_valid'}
455 self.assertEqual(prepare_env.main(**args), -1)
456 mock_logger_error.assert_called_once_with('Argument not valid.')
459 if __name__ == "__main__":
460 logging.disable(logging.CRITICAL)
461 unittest.main(verbosity=2)