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.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.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.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.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.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.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.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.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.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.INSTALLER_IP = None
144 prepare_env.get_deployment_handler()
145 self.assertFalse(m.called)
147 CONST.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.INSTALLER_IP = 'test_ip'
160 CONST.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.INSTALLER_IP = 'test_ip'
176 CONST.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(CONST.dir_functest_conf)
192 mock_method.assert_any_call(CONST.dir_functest_data)
193 mock_logger_info.assert_any_call(" %s created." %
194 CONST.dir_functest_conf)
195 mock_logger_info.assert_any_call(" %s created." %
196 CONST.dir_functest_data)
198 @mock.patch('functest.ci.prepare_env.logger.info')
199 @mock.patch('functest.ci.prepare_env.logger.debug')
200 def test_create_directories_with_dir(self, mock_logger_debug,
202 with mock.patch('functest.ci.prepare_env.os.path.exists',
204 prepare_env.create_directories()
205 mock_logger_info.assert_any_call("Creating needed directories...")
206 mock_logger_debug.assert_any_call(" %s already exists." %
207 CONST.dir_functest_conf)
208 mock_logger_debug.assert_any_call(" %s already exists." %
209 CONST.dir_functest_data)
211 def _get_env_cred_dict(self, os_prefix=''):
212 return {'OS_USERNAME': os_prefix + 'username',
213 'OS_PASSWORD': os_prefix + 'password',
214 'OS_AUTH_URL': 'http://test_ip:test_port/v2.0',
215 'OS_TENANT_NAME': os_prefix + 'tenant_name',
216 'OS_USER_DOMAIN_NAME': os_prefix + 'user_domain_name',
217 'OS_PROJECT_DOMAIN_NAME': os_prefix + 'project_domain_name',
218 'OS_PROJECT_NAME': os_prefix + 'project_name',
219 'OS_ENDPOINT_TYPE': os_prefix + 'endpoint_type',
220 'OS_REGION_NAME': os_prefix + 'region_name'}
222 @mock.patch('functest.ci.prepare_env.logger.error')
223 @mock.patch('functest.ci.prepare_env.logger.info')
224 @mock.patch('functest.ci.prepare_env.logger.warning')
225 def test_source_rc_missing_rc_file(self, mock_logger_warn,
228 with mock.patch('functest.ci.prepare_env.os.path.isfile',
229 return_value=True), \
230 mock.patch('functest.ci.prepare_env.os.path.getsize',
232 self.assertRaises(Exception):
233 CONST.openstack_creds = 'test_creds'
234 prepare_env.source_rc_file()
236 def test_source_rc_missing_installer_ip(self):
237 with mock.patch('functest.ci.prepare_env.os.path.isfile',
238 return_value=False), \
239 self.assertRaises(Exception):
240 CONST.INSTALLER_IP = None
241 CONST.openstack_creds = 'test_creds'
242 prepare_env.source_rc_file()
244 def test_source_rc_missing_installer_type(self):
245 with mock.patch('functest.ci.prepare_env.os.path.isfile',
246 return_value=False), \
247 self.assertRaises(Exception):
248 CONST.INSTALLER_IP = 'test_ip'
249 CONST.openstack_creds = 'test_creds'
250 CONST.INSTALLER_TYPE = 'test_type'
251 opnfv_constants.INSTALLERS = []
252 prepare_env.source_rc_file()
254 def test_source_rc_missing_os_credfile_ci_inst(self):
255 with mock.patch('functest.ci.prepare_env.os.path.isfile',
256 return_value=False), \
257 mock.patch('functest.ci.prepare_env.os.path.getsize'), \
258 mock.patch('functest.ci.prepare_env.os.path.join'), \
259 mock.patch('functest.ci.prepare_env.subprocess.Popen') \
260 as mock_subproc_popen, \
261 self.assertRaises(Exception):
262 CONST.openstack_creds = 'test_creds'
263 CONST.INSTALLER_IP = None
264 CONST.INSTALLER_TYPE = 'test_type'
265 opnfv_constants.INSTALLERS = ['test_type']
267 process_mock = mock.Mock()
268 attrs = {'communicate.return_value': ('output', 'error'),
270 process_mock.configure_mock(**attrs)
271 mock_subproc_popen.return_value = process_mock
273 prepare_env.source_rc_file()
275 @mock.patch('functest.ci.prepare_env.logger.debug')
276 def test_patch_file(self, mock_logger_debug):
277 with mock.patch("__builtin__.open", mock.mock_open()), \
278 mock.patch('functest.ci.prepare_env.yaml.safe_load',
279 return_value={'test_scenario': {'tkey': 'tvalue'}}), \
280 mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
281 return_value={'tkey1': 'tvalue1'}), \
282 mock.patch('functest.ci.prepare_env.os.remove') as m, \
283 mock.patch('functest.ci.prepare_env.yaml.dump'):
284 CONST.DEPLOY_SCENARIO = 'test_scenario'
285 prepare_env.patch_file('test_file')
286 self.assertTrue(m.called)
288 @mock.patch('functest.ci.prepare_env.logger.info')
289 def test_verify_deployment_error(self, mock_logger_error):
290 mock_popen = mock.Mock()
291 attrs = {'poll.return_value': None,
292 'stdout.readline.return_value': 'ERROR'}
293 mock_popen.configure_mock(**attrs)
295 with mock.patch('functest.ci.prepare_env.print_separator') as m, \
296 mock.patch('functest.ci.prepare_env.subprocess.Popen',
297 return_value=mock_popen), \
298 self.assertRaises(Exception) as context:
299 prepare_env.verify_deployment()
300 self.assertTrue(m.called)
301 msg = "Problem while running 'check_os.sh'."
302 mock_logger_error.assert_called_once_with('ERROR')
303 self.assertTrue(msg in context)
305 def _get_rally_creds(self):
306 return {"type": "ExistingCloud",
307 "admin": {"username": 'test_user_name',
308 "password": 'test_password',
309 "tenant": 'test_tenant'}}
311 @mock.patch('functest.ci.prepare_env.os_utils.get_credentials_for_rally')
312 @mock.patch('functest.ci.prepare_env.logger.info')
313 @mock.patch('functest.ci.prepare_env.ft_utils.execute_command_raise')
314 @mock.patch('functest.ci.prepare_env.ft_utils.execute_command')
315 def test_install_rally(self, mock_exec, mock_exec_raise, mock_logger_info,
318 mock_os_utils.return_value = self._get_rally_creds()
320 prepare_env.install_rally()
322 cmd = "rally deployment destroy opnfv-rally"
323 error_msg = "Deployment %s does not exist." % \
324 CONST.rally_deployment_name
325 mock_logger_info.assert_any_call("Creating Rally environment...")
326 mock_exec.assert_any_call(cmd, error_msg=error_msg, verbose=False)
328 cmd = "rally deployment create --file=rally_conf.json --name="
329 cmd += CONST.rally_deployment_name
330 error_msg = "Problem while creating Rally deployment"
331 mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
333 cmd = "rally deployment check"
334 error_msg = ("OpenStack not responding or "
335 "faulty Rally deployment.")
336 mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
338 cmd = "rally deployment list"
339 error_msg = ("Problem while listing "
341 mock_exec.assert_any_call(cmd, error_msg=error_msg)
343 cmd = "rally plugin list | head -5"
344 error_msg = ("Problem while showing "
346 mock_exec.assert_any_call(cmd, error_msg=error_msg)
348 @mock.patch('functest.ci.prepare_env.logger.debug')
349 def test_install_tempest(self, mock_logger_debug):
350 mock_popen = mock.Mock()
351 attrs = {'poll.return_value': None,
352 'stdout.readline.return_value': '0'}
353 mock_popen.configure_mock(**attrs)
355 CONST.tempest_deployment_name = 'test_dep_name'
356 with mock.patch('functest.ci.prepare_env.'
357 'ft_utils.execute_command_raise',
358 side_effect=Exception), \
359 mock.patch('functest.ci.prepare_env.subprocess.Popen',
360 return_value=mock_popen), \
361 self.assertRaises(Exception):
362 prepare_env.install_tempest()
363 mock_logger_debug.assert_any_call("Tempest test_dep_name"
366 def test_create_flavor(self):
367 with mock.patch('functest.ci.prepare_env.'
368 'os_utils.get_or_create_flavor',
369 return_value=('test_', None)), \
370 self.assertRaises(Exception) as context:
371 prepare_env.create_flavor()
372 msg = 'Failed to create flavor'
373 self.assertTrue(msg in context)
375 @mock.patch('functest.ci.prepare_env.sys.exit')
376 @mock.patch('functest.ci.prepare_env.logger.error')
377 def test_check_environment_missing_file(self, mock_logger_error,
379 with mock.patch('functest.ci.prepare_env.os.path.isfile',
380 return_value=False), \
381 self.assertRaises(Exception):
382 prepare_env.check_environment()
384 @mock.patch('functest.ci.prepare_env.sys.exit')
385 @mock.patch('functest.ci.prepare_env.logger.error')
386 def test_check_environment_with_error(self, mock_logger_error,
388 with mock.patch('functest.ci.prepare_env.os.path.isfile',
389 return_value=True), \
390 mock.patch("__builtin__.open", mock.mock_open(read_data='0')), \
391 self.assertRaises(Exception):
392 prepare_env.check_environment()
394 @mock.patch('functest.ci.prepare_env.logger.info')
395 def test_check_environment_default(self, mock_logger_info):
396 with mock.patch('functest.ci.prepare_env.os.path.isfile',
398 with mock.patch("__builtin__.open", mock.mock_open(read_data='1')):
399 prepare_env.check_environment()
400 mock_logger_info.assert_any_call("Functest environment"
403 @mock.patch('functest.ci.prepare_env.print_deployment_info')
404 @mock.patch('functest.ci.prepare_env.check_environment')
405 @mock.patch('functest.ci.prepare_env.create_flavor')
406 @mock.patch('functest.ci.prepare_env.install_tempest')
407 @mock.patch('functest.ci.prepare_env.install_rally')
408 @mock.patch('functest.ci.prepare_env.verify_deployment')
409 @mock.patch('functest.ci.prepare_env.patch_config_file')
410 @mock.patch('functest.ci.prepare_env.source_rc_file')
411 @mock.patch('functest.ci.prepare_env.create_directories')
412 @mock.patch('functest.ci.prepare_env.get_deployment_handler')
413 @mock.patch('functest.ci.prepare_env.check_env_variables')
414 @mock.patch('functest.ci.prepare_env.logger.info')
415 def test_main_start(self, mock_logger_info, mock_env_var, mock_dep_handler,
416 mock_create_dir, mock_source_rc, mock_patch_config,
417 mock_verify_depl, mock_install_rally,
418 mock_install_temp, mock_create_flavor,
419 mock_check_env, mock_print_info):
420 with mock.patch("__builtin__.open", mock.mock_open()) as m:
421 args = {'action': 'start'}
422 self.assertEqual(prepare_env.main(**args), 0)
423 mock_logger_info.assert_any_call("######### Preparing Functest "
424 "environment #########\n")
425 self.assertTrue(mock_env_var.called)
426 self.assertTrue(mock_dep_handler.called)
427 self.assertTrue(mock_create_dir.called)
428 self.assertTrue(mock_source_rc.called)
429 self.assertTrue(mock_patch_config.called)
430 self.assertTrue(mock_verify_depl.called)
431 self.assertTrue(mock_install_rally.called)
432 self.assertTrue(mock_install_temp.called)
433 self.assertTrue(mock_create_flavor.called)
434 m.assert_called_once_with(CONST.env_active, "w")
435 self.assertTrue(mock_check_env.called)
436 self.assertTrue(mock_print_info.called)
438 @mock.patch('functest.ci.prepare_env.check_environment')
439 def test_main_check(self, mock_check_env):
440 args = {'action': 'check'}
441 self.assertEqual(prepare_env.main(**args), 0)
442 self.assertTrue(mock_check_env.called)
444 @mock.patch('functest.ci.prepare_env.logger.error')
445 def test_main_no_arg(self, mock_logger_error):
446 args = {'action': 'not_valid'}
447 self.assertEqual(prepare_env.main(**args), -1)
448 mock_logger_error.assert_called_once_with('Argument not valid.')
451 if __name__ == "__main__":
452 unittest.main(verbosity=2)