python utility to manage a tripleo based cloud
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1762 lines
76 KiB

  1. # Copyright 2015 Red Hat, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  4. # not use this file except in compliance with the License. You may obtain
  5. # a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. # License for the specific language governing permissions and limitations
  13. # under the License.
  14. #
  15. import fixtures
  16. import os
  17. import shutil
  18. import six
  19. import tempfile
  20. import yaml
  21. from heatclient import exc as hc_exc
  22. import mock
  23. from osc_lib import exceptions as oscexc
  24. from osc_lib.tests import utils
  25. from swiftclient.exceptions import ClientException as ObjectClientException
  26. from tripleoclient import constants
  27. from tripleoclient import exceptions
  28. from tripleoclient import plugin
  29. from tripleoclient.tests import fakes as ooofakes
  30. from tripleoclient.tests.fixture_data import deployment
  31. from tripleoclient.tests.v1.overcloud_deploy import fakes
  32. from tripleoclient.v1 import overcloud_deploy
  33. class TestDeployOvercloud(fakes.TestDeployOvercloud):
  34. def setUp(self):
  35. super(TestDeployOvercloud, self).setUp()
  36. # Get the command object to test
  37. app_args = mock.Mock()
  38. app_args.verbose_level = 1
  39. self.cmd = overcloud_deploy.DeployOvercloud(self.app, app_args)
  40. self.parameter_defaults_env_file = (
  41. tempfile.NamedTemporaryFile(mode='w', delete=False).name)
  42. self.tmp_dir = self.useFixture(fixtures.TempDir())
  43. # Mock the history command to avoid leaking files
  44. history_patcher = mock.patch('tripleoclient.utils.store_cli_param',
  45. autospec=True)
  46. history_patcher.start()
  47. self.addCleanup(history_patcher.stop)
  48. # Mock this function to avoid file creation
  49. self.real_download_missing = self.cmd._download_missing_files_from_plan
  50. self.cmd._download_missing_files_from_plan = mock.Mock()
  51. self.real_shutil = shutil.rmtree
  52. self.uuid1_value = "uuid"
  53. mock_uuid1 = mock.patch('uuid.uuid1', return_value=self.uuid1_value,
  54. autospec=True)
  55. mock_uuid1.start()
  56. self.addCleanup(mock_uuid1.stop)
  57. mock_uuid4 = mock.patch('uuid.uuid4', return_calue='uuid4',
  58. autospec=True)
  59. mock_uuid4.start()
  60. self.addCleanup(mock_uuid4.stop)
  61. # Mock time to get predicdtable DeployIdentifiers
  62. self.time_value = 12345678
  63. mock_time = mock.patch('time.time', return_value=self.time_value,
  64. autospec=True)
  65. mock_time.start()
  66. self.addCleanup(mock_time.stop)
  67. # Mock copytree to avoid creating temporary templates
  68. mock_copytree = mock.patch('shutil.copytree',
  69. autospec=True)
  70. mock_copytree.start()
  71. self.addCleanup(mock_copytree.stop)
  72. # Mock sleep to reduce time of test
  73. mock_sleep = mock.patch('time.sleep', autospec=True)
  74. mock_sleep.start()
  75. self.addCleanup(mock_sleep.stop)
  76. plan_list = mock.patch(
  77. "tripleoclient.workflows.plan_management.list_deployment_plans",
  78. autospec=True
  79. )
  80. plan_list.start()
  81. plan_list.return_value = ([
  82. "test-plan-1",
  83. "test-plan-2",
  84. ])
  85. self.addCleanup(plan_list.stop)
  86. client = self.app.client_manager.tripleoclient = plugin.ClientWrapper(
  87. instance=ooofakes.FakeInstanceData
  88. )
  89. client.messaging_websocket = \
  90. ooofakes.FakeClientWrapper().messaging_websocket
  91. get_object = client.object_store.get_object = mock.Mock()
  92. get_object.return_value = ('f1', 'content')
  93. client.object_store.put_object = mock.Mock()
  94. get_container = client.object_store.get_container = mock.MagicMock()
  95. get_container.return_value = ('container', [{'name': 'f1'}])
  96. # Mock playbook runner
  97. playbook_runner = mock.patch(
  98. 'tripleoclient.utils.run_ansible_playbook',
  99. autospec=True
  100. )
  101. playbook_runner.start()
  102. self.addCleanup(playbook_runner.stop)
  103. # Mock horizon url return
  104. horizon_url = mock.patch(
  105. 'tripleoclient.workflows.deployment.get_horizon_url',
  106. autospec=True
  107. )
  108. horizon_url.start()
  109. horizon_url.return_value = 'fake://url:12345'
  110. self.addCleanup(horizon_url.stop)
  111. def tearDown(self):
  112. super(TestDeployOvercloud, self).tearDown()
  113. os.unlink(self.parameter_defaults_env_file)
  114. self.cmd._download_missing_files_from_plan = self.real_download_missing
  115. shutil.rmtree = self.real_shutil
  116. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  117. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  118. '_get_undercloud_host_entry', autospec=True,
  119. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  120. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  121. @mock.patch("heatclient.common.event_utils.get_events")
  122. @mock.patch('tripleo_common.update.add_breakpoints_cleanup_into_env',
  123. autospec=True)
  124. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  125. '_create_parameters_env', autospec=True)
  126. @mock.patch('tripleoclient.utils.create_tempest_deployer_input',
  127. autospec=True)
  128. @mock.patch('heatclient.common.template_utils.get_template_contents',
  129. autospec=True)
  130. def test_tht_scale(self, mock_get_template_contents,
  131. mock_create_tempest_deployer_input,
  132. mock_create_parameters_env,
  133. mock_breakpoints_cleanup,
  134. mock_events, mock_stack_network_check,
  135. mock_get_undercloud_host_entry, mock_copy):
  136. fixture = deployment.DeploymentWorkflowFixture()
  137. self.useFixture(fixture)
  138. clients = self.app.client_manager
  139. orchestration_client = clients.orchestration
  140. mock_stack = fakes.create_tht_stack()
  141. orchestration_client.stacks.get.return_value = mock_stack
  142. plane_management_fixture = deployment.PlanManagementFixture()
  143. self.useFixture(plane_management_fixture)
  144. utils_fixture = deployment.UtilsFixture()
  145. self.useFixture(utils_fixture)
  146. arglist = ['--templates']
  147. verifylist = [
  148. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  149. ]
  150. clients = self.app.client_manager
  151. orchestration_client = clients.orchestration
  152. orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
  153. mock_event = mock.Mock()
  154. mock_event.id = '1234'
  155. mock_events.return_value = [mock_events]
  156. workflow_client = clients.workflow_engine
  157. workflow_client.action_executions.create.return_value = mock.MagicMock(
  158. output='{"result":[]}')
  159. object_client = clients.tripleoclient.object_store
  160. object_client.get_object = mock.Mock()
  161. mock_env = yaml.safe_dump({'environments': []})
  162. object_client.get_object.return_value = ({}, mock_env)
  163. clients.network.api.find_attr.return_value = {
  164. "id": "network id"
  165. }
  166. mock_get_template_contents.return_value = [{}, "template"]
  167. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  168. baremetal = clients.baremetal
  169. baremetal.node.list.return_value = range(10)
  170. expected_parameters = {
  171. 'CephClusterFSID': self.uuid1_value,
  172. 'CephStorageCount': 3,
  173. 'ExtraConfig': '{}',
  174. 'HypervisorNeutronPhysicalBridge': 'br-ex',
  175. 'HypervisorNeutronPublicInterface': 'nic1',
  176. 'NeutronDnsmasqOptions': 'dhcp-option-force=26,1400',
  177. 'NeutronFlatNetworks': 'datacentre',
  178. 'NeutronPublicInterface': 'nic1',
  179. 'NtpServer': '',
  180. 'SnmpdReadonlyUserPassword': 'PASSWORD',
  181. 'UpdateIdentifier': '',
  182. 'StackAction': 'UPDATE',
  183. 'DeployIdentifier': '',
  184. 'UndercloudHostsEntries': [
  185. '192.168.0.1 uc.ctlplane.localhost uc.ctlplane']
  186. }
  187. def _custom_create_params_env(_self, parameters, tht_root,
  188. container_name):
  189. for key, value in six.iteritems(parameters):
  190. self.assertEqual(value, expected_parameters[key])
  191. parameter_defaults = {"parameter_defaults": parameters}
  192. return parameter_defaults
  193. mock_create_parameters_env.side_effect = _custom_create_params_env
  194. self.cmd.take_action(parsed_args)
  195. self.assertFalse(orchestration_client.stacks.update.called)
  196. mock_get_template_contents.assert_called_with(
  197. object_request=mock.ANY,
  198. template_object=constants.OVERCLOUD_YAML_NAME)
  199. mock_create_tempest_deployer_input.assert_called_with()
  200. mock_copy.assert_called_once()
  201. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  202. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  203. '_get_undercloud_host_entry', autospec=True,
  204. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  205. @mock.patch('tripleoclient.workflows.parameters.invoke_plan_env_workflows',
  206. autospec=True)
  207. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  208. '_deploy_postconfig', autospec=True)
  209. @mock.patch('tripleo_common.update.add_breakpoints_cleanup_into_env',
  210. autospec=True)
  211. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  212. '_validate_args')
  213. @mock.patch('heatclient.common.template_utils.get_template_contents',
  214. autospec=True)
  215. @mock.patch('tempfile.mkdtemp', autospec=True)
  216. def test_tht_deploy(self, mock_tmpdir,
  217. mock_get_template_contents,
  218. mock_validate_args,
  219. mock_breakpoints_cleanup,
  220. mock_postconfig,
  221. mock_invoke_plan_env_wf,
  222. mock_get_undercloud_host_entry, mock_copy):
  223. fixture = deployment.DeploymentWorkflowFixture()
  224. self.useFixture(fixture)
  225. plane_management_fixture = deployment.PlanManagementFixture()
  226. self.useFixture(plane_management_fixture)
  227. utils_fixture = deployment.UtilsFixture()
  228. self.useFixture(utils_fixture)
  229. utils_overcloud_fixture = deployment.UtilsOvercloudFixture()
  230. self.useFixture(utils_overcloud_fixture)
  231. arglist = ['--templates', '--no-cleanup']
  232. verifylist = [
  233. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  234. ]
  235. mock_tmpdir.return_value = self.tmp_dir.path
  236. clients = self.app.client_manager
  237. orchestration_client = clients.orchestration
  238. mock_stack = fakes.create_tht_stack()
  239. orchestration_client.stacks.get.side_effect = [None, mock.Mock()]
  240. workflow_client = clients.workflow_engine
  241. workflow_client.action_executions.create.return_value = mock.MagicMock(
  242. output='{"result":[]}')
  243. object_client = clients.tripleoclient.object_store
  244. object_client.get_object = mock.Mock()
  245. mock_env = yaml.safe_dump({'environments': []})
  246. object_client.get_object.return_value = ({}, mock_env)
  247. def _orch_clt_create(**kwargs):
  248. orchestration_client.stacks.get.return_value = mock_stack
  249. orchestration_client.stacks.create.side_effect = _orch_clt_create
  250. clients.network.api.find_attr.return_value = {
  251. "id": "network id"
  252. }
  253. mock_get_template_contents.return_value = [{}, "template"]
  254. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  255. baremetal = clients.baremetal
  256. baremetal.node.list.return_value = range(10)
  257. parameters_env = {
  258. 'parameter_defaults': {
  259. 'StackAction': 'CREATE',
  260. 'UpdateIdentifier': '',
  261. 'DeployIdentifier': '',
  262. 'UndercloudHostsEntries':
  263. ['192.168.0.1 uc.ctlplane.localhost uc.ctlplane']}}
  264. self.cmd.take_action(parsed_args)
  265. self.assertFalse(orchestration_client.stacks.create.called)
  266. mock_get_template_contents.assert_called_with(
  267. object_request=mock.ANY,
  268. template_object=constants.OVERCLOUD_YAML_NAME)
  269. utils_overcloud_fixture.mock_deploy_tht.assert_called_with()
  270. mock_validate_args.assert_called_once_with(parsed_args)
  271. plane_management_fixture.mock_tarball.create_tarball.\
  272. assert_called_with(
  273. self.tmp_dir.join('tripleo-heat-templates'), mock.ANY)
  274. plane_management_fixture.mock_tarball.\
  275. tarball_extract_to_swift_container.assert_called_with(
  276. clients.tripleoclient.object_store, mock.ANY, 'overcloud')
  277. self.assertFalse(mock_invoke_plan_env_wf.called)
  278. calls = [
  279. mock.call('overcloud',
  280. 'user-environments/tripleoclient-parameters.yaml',
  281. yaml.safe_dump(parameters_env,
  282. default_flow_style=False)),
  283. mock.call('overcloud',
  284. 'user-environment.yaml',
  285. yaml.safe_dump({}, default_flow_style=False)),
  286. mock.call('overcloud',
  287. 'plan-environment.yaml',
  288. yaml.safe_dump({'environments':
  289. [{'path': 'user-environment.yaml'}]},
  290. default_flow_style=False))]
  291. object_client = clients.tripleoclient.object_store
  292. object_client.put_object.assert_has_calls(calls)
  293. tmp_param_env = self.tmp_dir.join(
  294. 'tripleo-heat-templates',
  295. 'user-environments/tripleoclient-parameters.yaml')
  296. self.assertTrue(os.path.isfile(tmp_param_env))
  297. with open(tmp_param_env, 'r') as f:
  298. env_map = yaml.safe_load(f)
  299. self.assertEqual(env_map.get('parameter_defaults'),
  300. parameters_env.get('parameter_defaults'))
  301. mock_copy.assert_called_once()
  302. @mock.patch('os.chdir')
  303. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  304. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  305. '_get_undercloud_host_entry', autospec=True,
  306. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  307. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  308. @mock.patch('shutil.rmtree', autospec=True)
  309. @mock.patch('tripleoclient.utils.get_overcloud_endpoint', autospec=True)
  310. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  311. '_deploy_postconfig', autospec=True)
  312. @mock.patch('tripleo_common.update.add_breakpoints_cleanup_into_env',
  313. autospec=True)
  314. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  315. '_validate_args')
  316. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  317. '_create_parameters_env', autospec=True)
  318. @mock.patch('tripleoclient.utils.create_tempest_deployer_input',
  319. autospec=True)
  320. @mock.patch('tripleoclient.workflows.deployment.create_overcloudrc',
  321. autospec=True)
  322. @mock.patch('heatclient.common.template_utils.get_template_contents',
  323. autospec=True)
  324. @mock.patch('tempfile.mkdtemp', autospec=True)
  325. def test_tht_deploy_with_plan_environment_file(
  326. self, mock_tmpdir, mock_get_template_contents,
  327. mock_write_overcloudrc,
  328. mock_create_tempest_deployer, mock_create_parameters_env,
  329. mock_validate_args,
  330. mock_breakpoints_cleanup,
  331. mock_postconfig, mock_shutil_rmtree,
  332. mock_invoke_plan_env_wf,
  333. mock_stack_network_check,
  334. mock_get_undercloud_host_entry, mock_copy, mock_chdir):
  335. fixture = deployment.DeploymentWorkflowFixture()
  336. self.useFixture(fixture)
  337. plane_management_fixture = deployment.PlanManagementFixture()
  338. self.useFixture(plane_management_fixture)
  339. utils_fixture = deployment.UtilsFixture()
  340. self.useFixture(utils_fixture)
  341. arglist = ['--templates', '-p', 'the-plan-environment.yaml']
  342. verifylist = [
  343. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  344. ('plan_environment_file', 'the-plan-environment.yaml')
  345. ]
  346. mock_tmpdir.return_value = "/tmp/tht"
  347. clients = self.app.client_manager
  348. orchestration_client = clients.orchestration
  349. mock_stack = fakes.create_tht_stack()
  350. orchestration_client.stacks.get.side_effect = [None, mock.Mock()]
  351. workflow_client = clients.workflow_engine
  352. workflow_client.environments.get.return_value = mock.MagicMock(
  353. variables={'environments': []})
  354. workflow_client.action_executions.create.return_value = mock.MagicMock(
  355. output='{"result":[]}')
  356. def _orch_clt_create(**kwargs):
  357. orchestration_client.stacks.get.return_value = mock_stack
  358. orchestration_client.stacks.create.side_effect = _orch_clt_create
  359. object_client = clients.tripleoclient.object_store
  360. object_client.get_object = mock.Mock()
  361. mock_env = yaml.safe_dump({'environments': []})
  362. object_client.get_object.return_value = ({}, mock_env)
  363. clients.network.api.find_attr.return_value = {
  364. "id": "network id"
  365. }
  366. mock_get_template_contents.return_value = [{}, "template"]
  367. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  368. baremetal = clients.baremetal
  369. baremetal.node.list.return_value = range(10)
  370. expected_parameters = {
  371. 'CephClusterFSID': self.uuid1_value,
  372. 'CephStorageCount': 3,
  373. 'ExtraConfig': '{}',
  374. 'HypervisorNeutronPhysicalBridge': 'br-ex',
  375. 'HypervisorNeutronPublicInterface': 'nic1',
  376. 'NeutronDnsmasqOptions': 'dhcp-option-force=26,1400',
  377. 'NeutronFlatNetworks': 'datacentre',
  378. 'NeutronNetworkType': 'gre',
  379. 'NeutronPublicInterface': 'nic1',
  380. 'NeutronTunnelTypes': 'gre',
  381. 'NtpServer': '',
  382. 'SnmpdReadonlyUserPassword': 'PASSWORD',
  383. 'UpdateIdentifier': '',
  384. 'StackAction': 'CREATE',
  385. 'DeployIdentifier': '',
  386. 'UndercloudHostsEntries': [
  387. '192.168.0.1 uc.ctlplane.localhost uc.ctlplane'
  388. ]
  389. }
  390. testcase = self
  391. def _custom_create_params_env(_self, parameters, tht_root,
  392. container_name):
  393. for key, value in six.iteritems(parameters):
  394. testcase.assertEqual(value, expected_parameters[key])
  395. parameter_defaults = {"parameter_defaults": parameters}
  396. return parameter_defaults
  397. mock_create_parameters_env.side_effect = _custom_create_params_env
  398. mock_open_context = mock.mock_open()
  399. with mock.patch('six.moves.builtins.open', mock_open_context):
  400. self.cmd.take_action(parsed_args)
  401. self.assertFalse(orchestration_client.stacks.create.called)
  402. mock_get_template_contents.assert_called_with(
  403. object_request=mock.ANY,
  404. template_object=constants.OVERCLOUD_YAML_NAME)
  405. mock_create_tempest_deployer.assert_called_with()
  406. mock_validate_args.assert_called_once_with(parsed_args)
  407. plane_management_fixture.mock_tarball.create_tarball.\
  408. assert_called_with(
  409. '/tmp/tht/tripleo-heat-templates', mock.ANY)
  410. plane_management_fixture.mock_tarball.\
  411. tarball_extract_to_swift_container.assert_called_with(
  412. clients.tripleoclient.object_store, mock.ANY, 'overcloud')
  413. workflow_client.action_executions.create.assert_called()
  414. workflow_client.executions.create.assert_called()
  415. mock_open_context.assert_has_calls(
  416. [mock.call('the-plan-environment.yaml')])
  417. clients.tripleoclient.object_store.put_object.assert_called()
  418. self.assertTrue(mock_invoke_plan_env_wf.called)
  419. mock_copy.assert_called_once()
  420. @mock.patch('os.chdir')
  421. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  422. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  423. '_get_undercloud_host_entry', autospec=True,
  424. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  425. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  426. @mock.patch('tripleoclient.workflows.parameters.'
  427. 'check_deprecated_parameters', autospec=True)
  428. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  429. '_deploy_postconfig', autospec=True)
  430. @mock.patch('tripleo_common.update.add_breakpoints_cleanup_into_env',
  431. autospec=True)
  432. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  433. '_validate_args')
  434. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  435. '_create_parameters_env', autospec=True)
  436. @mock.patch('heatclient.common.template_utils.get_template_contents',
  437. autospec=True)
  438. @mock.patch('shutil.rmtree', autospec=True)
  439. @mock.patch('tempfile.mkdtemp', autospec=True)
  440. def test_tht_deploy_skip_deploy_identifier(
  441. self, mock_tmpdir, mock_rm,
  442. mock_get_template_contents,
  443. mock_create_parameters_env, mock_validate_args,
  444. mock_breakpoints_cleanup,
  445. mock_postconfig, mock_deprecated_params, mock_stack_network_check,
  446. mock_get_undercloud_host_entry, mock_copy, mock_chdir):
  447. fixture = deployment.DeploymentWorkflowFixture()
  448. self.useFixture(fixture)
  449. plane_management_fixture = deployment.PlanManagementFixture()
  450. self.useFixture(plane_management_fixture)
  451. utils_fixture = deployment.UtilsFixture()
  452. self.useFixture(utils_fixture)
  453. utils_overcloud_fixture = deployment.UtilsOvercloudFixture()
  454. self.useFixture(utils_overcloud_fixture)
  455. arglist = ['--templates', '--skip-deploy-identifier']
  456. verifylist = [
  457. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  458. ('skip_deploy_identifier', True)
  459. ]
  460. mock_tmpdir.return_value = "/tmp/tht"
  461. clients = self.app.client_manager
  462. orchestration_client = clients.orchestration
  463. mock_stack = fakes.create_tht_stack()
  464. orchestration_client.stacks.get.side_effect = [None, mock.Mock()]
  465. workflow_client = clients.workflow_engine
  466. workflow_client.action_executions.create.return_value = mock.MagicMock(
  467. output='{"result":[]}')
  468. def _orch_clt_create(**kwargs):
  469. orchestration_client.stacks.get.return_value = mock_stack
  470. orchestration_client.stacks.create.side_effect = _orch_clt_create
  471. object_client = clients.tripleoclient.object_store
  472. object_client.get_object = mock.Mock()
  473. mock_env = yaml.safe_dump({'environments': []})
  474. object_client.get_object.return_value = ({}, mock_env)
  475. clients.network.api.find_attr.return_value = {
  476. "id": "network id"
  477. }
  478. mock_get_template_contents.return_value = [{}, "template"]
  479. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  480. baremetal = clients.baremetal
  481. baremetal.node.list.return_value = range(10)
  482. testcase = self
  483. def _custom_create_params_env(_self, parameters, tht_root,
  484. container_name):
  485. testcase.assertTrue(parameters['DeployIdentifier'] == '')
  486. parameter_defaults = {"parameter_defaults": parameters}
  487. return parameter_defaults
  488. mock_create_parameters_env.side_effect = _custom_create_params_env
  489. self.cmd.take_action(parsed_args)
  490. execution_calls = workflow_client.executions.create.call_args_list
  491. deploy_plan_call = execution_calls[1]
  492. deploy_plan_call_input = deploy_plan_call[1]['workflow_input']
  493. self.assertTrue(deploy_plan_call_input['skip_deploy_identifier'])
  494. mock_copy.assert_called_once()
  495. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  496. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  497. '_get_undercloud_host_entry', autospec=True,
  498. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  499. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  500. @mock.patch("heatclient.common.event_utils.get_events", autospec=True)
  501. @mock.patch('tripleo_common.update.add_breakpoints_cleanup_into_env',
  502. autospec=True)
  503. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  504. '_deploy_postconfig', autospec=True)
  505. @mock.patch('tripleoclient.utils.create_tempest_deployer_input',
  506. autospec=True)
  507. @mock.patch('heatclient.common.template_utils.get_template_contents',
  508. autospec=True)
  509. def test_deploy_custom_templates(self, mock_get_template_contents,
  510. mock_create_tempest_deployer_input,
  511. mock_deploy_postconfig,
  512. mock_breakpoints_cleanup,
  513. mock_events, mock_stack_network_check,
  514. mock_get_undercloud_host_entry,
  515. mock_copy):
  516. fixture = deployment.DeploymentWorkflowFixture()
  517. self.useFixture(fixture)
  518. plane_management_fixture = deployment.PlanManagementFixture()
  519. self.useFixture(plane_management_fixture)
  520. utils_fixture = deployment.UtilsFixture()
  521. self.useFixture(utils_fixture)
  522. arglist = ['--templates', '/home/stack/tripleo-heat-templates']
  523. verifylist = [
  524. ('templates', '/home/stack/tripleo-heat-templates'),
  525. ]
  526. clients = self.app.client_manager
  527. orchestration_client = clients.orchestration
  528. orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
  529. mock_events.return_value = []
  530. clients.network.api.find_attr.return_value = {
  531. "id": "network id"
  532. }
  533. mock_get_template_contents.return_value = [{}, "template"]
  534. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  535. baremetal = clients.baremetal
  536. baremetal.node.list.return_value = range(10)
  537. workflow_client = clients.workflow_engine
  538. workflow_client.action_executions.create.return_value = mock.MagicMock(
  539. output='{"result":[]}')
  540. object_client = clients.tripleoclient.object_store
  541. object_client.get_object = mock.Mock()
  542. mock_env = yaml.safe_dump({'environments': []})
  543. object_client.get_object.return_value = ({}, mock_env)
  544. with mock.patch('tempfile.mkstemp') as mkstemp:
  545. mkstemp.return_value = (os.open(self.parameter_defaults_env_file,
  546. os.O_RDWR),
  547. self.parameter_defaults_env_file)
  548. self.cmd.take_action(parsed_args)
  549. self.assertFalse(orchestration_client.stacks.update.called)
  550. mock_get_template_contents.assert_called_with(
  551. object_request=mock.ANY,
  552. template_object=constants.OVERCLOUD_YAML_NAME)
  553. mock_create_tempest_deployer_input.assert_called_with()
  554. mock_copy.assert_called_once()
  555. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  556. '_deploy_tripleo_heat_templates', autospec=True)
  557. def test_jinja2_env_path(self, mock_deploy_tht):
  558. arglist = ['--templates', '-e', 'bad_path.j2.yaml', '-e', 'other.yaml',
  559. '-e', 'bad_path2.j2.yaml']
  560. verifylist = [
  561. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  562. ('environment_files', ['bad_path.j2.yaml', 'other.yaml',
  563. 'bad_path2.j2.yaml'])
  564. ]
  565. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  566. self.assertRaises(
  567. oscexc.CommandError,
  568. self.cmd.take_action, parsed_args)
  569. self.assertFalse(mock_deploy_tht.called)
  570. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  571. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  572. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  573. '_deploy_postconfig', autospec=True)
  574. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  575. '_update_parameters', autospec=True)
  576. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  577. '_heat_deploy', autospec=True)
  578. def test_environment_dirs(self, mock_deploy_heat,
  579. mock_update_parameters, mock_post_config,
  580. mock_stack_network_check, mock_copy):
  581. fixture = deployment.DeploymentWorkflowFixture()
  582. self.useFixture(fixture)
  583. plane_management_fixture = deployment.PlanManagementFixture()
  584. self.useFixture(plane_management_fixture)
  585. utils_overcloud_fixture = deployment.UtilsOvercloudFixture()
  586. self.useFixture(utils_overcloud_fixture)
  587. clients = self.app.client_manager
  588. workflow_client = clients.workflow_engine
  589. workflow_client.action_executions.create.return_value = mock.MagicMock(
  590. output='{"result":[]}')
  591. mock_update_parameters.return_value = {}
  592. utils_overcloud_fixture.mock_utils_endpoint.return_value = 'foo.bar'
  593. test_env = os.path.join(self.tmp_dir.path, 'foo1.yaml')
  594. env_dirs = [os.path.join(os.environ.get('HOME', ''), '.tripleo',
  595. 'environments'), self.tmp_dir.path]
  596. with open(test_env, 'w') as temp_file:
  597. temp_file.write('resource_registry:\n Test: OS::Heat::None')
  598. arglist = ['--templates', '--environment-directory', self.tmp_dir.path]
  599. verifylist = [
  600. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  601. ('environment_directories', env_dirs),
  602. ]
  603. def assertEqual(*args):
  604. self.assertEqual(*args)
  605. def _fake_heat_deploy(self, stack, stack_name, template_path,
  606. parameters, environments, timeout, tht_root,
  607. env, update_plan_only, run_validations,
  608. skip_deploy_identifier, plan_env_file,
  609. deployment_options=None):
  610. assertEqual(
  611. {'parameter_defaults': {'NovaComputeLibvirtType': 'qemu'},
  612. 'resource_registry': {
  613. 'Test': 'OS::Heat::None',
  614. 'resources': {'*': {'*': {
  615. 'UpdateDeployment': {'hooks': []}}}}}}, env)
  616. mock_deploy_heat.side_effect = _fake_heat_deploy
  617. object_client = clients.tripleoclient.object_store
  618. object_client.get_object = mock.Mock()
  619. mock_env = yaml.safe_dump({'parameter_defaults':
  620. {'NovaComputeLibvirtType': 'qemu'}})
  621. object_client.get_object.return_value = ({}, mock_env)
  622. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  623. self.cmd.take_action(parsed_args)
  624. mock_copy.assert_called_once()
  625. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  626. @mock.patch('tripleoclient.utils.get_stack', autospec=True)
  627. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  628. '_deploy_postconfig', autospec=True)
  629. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  630. '_update_parameters', autospec=True)
  631. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  632. '_heat_deploy', autospec=True)
  633. def test_environment_dirs_env(self, mock_deploy_heat,
  634. mock_update_parameters, mock_post_config,
  635. mock_utils_get_stack,
  636. mock_stack_network_check):
  637. plane_management_fixture = deployment.PlanManagementFixture()
  638. self.useFixture(plane_management_fixture)
  639. utils_fixture = deployment.UtilsOvercloudFixture()
  640. self.useFixture(utils_fixture)
  641. clients = self.app.client_manager
  642. workflow_client = clients.workflow_engine
  643. workflow_client.action_executions.create.return_value = mock.MagicMock(
  644. output='{"result":[]}')
  645. mock_update_parameters.return_value = {}
  646. mock_utils_get_stack.return_value = None
  647. utils_fixture.mock_utils_endpoint.return_value = 'foo.bar'
  648. test_env = self.tmp_dir.join('foo2.yaml')
  649. with open(test_env, 'w') as temp_file:
  650. temp_file.write('resource_registry:\n Test: OS::Heat::None')
  651. arglist = ['--templates', '--update-plan-only']
  652. verifylist = [
  653. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  654. ]
  655. self.useFixture(
  656. fixtures.EnvironmentVariable('TRIPLEO_ENVIRONMENT_DIRECTORY',
  657. self.tmp_dir.path))
  658. def assertEqual(*args):
  659. self.assertEqual(*args)
  660. def _fake_heat_deploy(self, stack, stack_name, template_path,
  661. parameters, environments, timeout, tht_root,
  662. env, update_plan_only, run_validations,
  663. skip_deploy_identifier, plan_env_file,
  664. deployment_options=None):
  665. # Should be no breakpoint cleanup because utils.get_stack = None
  666. assertEqual(
  667. {'parameter_defaults': {},
  668. 'resource_registry': {'Test': u'OS::Heat::None'}}, env)
  669. mock_deploy_heat.side_effect = _fake_heat_deploy
  670. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  671. self.cmd.take_action(parsed_args)
  672. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  673. '_deploy_postconfig', autospec=True)
  674. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  675. '_update_parameters', autospec=True)
  676. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  677. '_heat_deploy', autospec=True)
  678. def test_environment_dirs_env_files_not_found(self, mock_deploy_heat,
  679. mock_update_parameters,
  680. mock_post_config):
  681. plane_management_fixture = deployment.PlanManagementFixture()
  682. self.useFixture(plane_management_fixture)
  683. utils_fixture = deployment.UtilsOvercloudFixture()
  684. self.useFixture(utils_fixture)
  685. clients = self.app.client_manager
  686. workflow_client = clients.workflow_engine
  687. workflow_client.action_executions.create.return_value = mock.MagicMock(
  688. output='{"result":[]}')
  689. mock_update_parameters.return_value = {}
  690. utils_fixture.mock_utils_endpoint.return_value = 'foo.bar'
  691. os.mkdir(self.tmp_dir.join('env'))
  692. os.mkdir(self.tmp_dir.join('common'))
  693. test_env = self.tmp_dir.join('env/foo2.yaml')
  694. with open(test_env, 'w') as temp_file:
  695. temp_file.write('resource_registry:\n '
  696. 'Test1: ../common/bar.yaml\n '
  697. 'Test2: /tmp/doesnexit.yaml')
  698. test_sub_env = self.tmp_dir.join('common/bar.yaml')
  699. with open(test_sub_env, 'w') as temp_file:
  700. temp_file.write('outputs:\n data:\n value: 1')
  701. arglist = ['--templates']
  702. verifylist = [
  703. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  704. ]
  705. self.useFixture(
  706. fixtures.EnvironmentVariable('TRIPLEO_ENVIRONMENT_DIRECTORY',
  707. self.tmp_dir.join('env')))
  708. object_client = clients.tripleoclient.object_store
  709. object_client.get_object = mock.Mock()
  710. mock_env = yaml.safe_dump({'parameter_defaults':
  711. {'NovaComputeLibvirtType': 'qemu'}})
  712. object_client.get_object.return_value = ({}, mock_env)
  713. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  714. error = self.assertRaises(hc_exc.CommandError, self.cmd.take_action,
  715. parsed_args)
  716. self.assertIn('tmp/doesnexit.yaml', str(error))
  717. @mock.patch('tripleoclient.workflows.plan_management.tarball',
  718. autospec=True)
  719. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  720. '_deploy_postconfig', autospec=True)
  721. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  722. '_update_parameters', autospec=True)
  723. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  724. '_heat_deploy', autospec=True)
  725. def test_environment_dirs_env_dir_not_found(self, mock_deploy_heat,
  726. mock_update_parameters,
  727. mock_post_config,
  728. mock_tarball):
  729. utils_fixture = deployment.UtilsOvercloudFixture()
  730. self.useFixture(utils_fixture)
  731. clients = self.app.client_manager
  732. workflow_client = clients.workflow_engine
  733. workflow_client.action_executions.create.return_value = mock.MagicMock(
  734. output='{"result":[]}')
  735. mock_update_parameters.return_value = {}
  736. utils_fixture.mock_utils_endpoint.return_value = 'foo.bar'
  737. os.mkdir(self.tmp_dir.join('env'))
  738. os.mkdir(self.tmp_dir.join('common'))
  739. arglist = ['--templates', '--environment-directory', '/tmp/notthere']
  740. verifylist = [
  741. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  742. ]
  743. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  744. error = self.assertRaises(oscexc.CommandError, self.cmd.take_action,
  745. parsed_args)
  746. self.assertIn('/tmp/notthere', str(error))
  747. @mock.patch('tripleoclient.tests.v1.overcloud_deploy.fakes.'
  748. 'FakeObjectClient.get_object', autospec=True)
  749. def test_validate_args_missing_environment_files(self, mock_obj):
  750. arglist = ['--templates',
  751. '-e', 'nonexistent.yaml']
  752. verifylist = [
  753. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  754. ('environment_files', ['nonexistent.yaml']),
  755. ]
  756. mock_obj.side_effect = ObjectClientException(mock.Mock(
  757. '/fake/path not found'))
  758. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  759. self.assertRaises(oscexc.CommandError,
  760. self.cmd._validate_args,
  761. parsed_args)
  762. @mock.patch('os.path.isfile', autospec=True)
  763. def test_validate_args_missing_rendered_files(self, mock_isfile):
  764. tht_path = '/usr/share/openstack-tripleo-heat-templates/'
  765. env_path = os.path.join(tht_path, 'noexist.yaml')
  766. arglist = ['--templates',
  767. '-e', env_path]
  768. verifylist = [
  769. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  770. ('environment_files', [env_path]),
  771. ]
  772. mock_isfile.side_effect = [False, True]
  773. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  774. self.cmd._validate_args(parsed_args)
  775. calls = [mock.call(env_path),
  776. mock.call(env_path.replace(".yaml", ".j2.yaml"))]
  777. mock_isfile.assert_has_calls(calls)
  778. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  779. '_heat_deploy', autospec=True)
  780. def test_try_overcloud_deploy_with_first_template_existing(
  781. self, mock_heat_deploy_func):
  782. result = self.cmd._try_overcloud_deploy_with_compat_yaml(
  783. '/fake/path', {}, 'overcloud', {}, ['~/overcloud-env.json'], 1,
  784. {}, False, True, False, None)
  785. # If it returns None it succeeded
  786. self.assertIsNone(result)
  787. mock_heat_deploy_func.assert_called_once_with(
  788. self.cmd, {}, 'overcloud',
  789. '/fake/path/' + constants.OVERCLOUD_YAML_NAME, {},
  790. ['~/overcloud-env.json'], 1, '/fake/path', {}, False, True, False,
  791. None, deployment_options=None)
  792. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  793. '_heat_deploy', autospec=True)
  794. def test_try_overcloud_deploy_with_no_templates_existing(
  795. self, mock_heat_deploy_func):
  796. mock_heat_deploy_func.side_effect = ObjectClientException('error')
  797. self.assertRaises(ValueError,
  798. self.cmd._try_overcloud_deploy_with_compat_yaml,
  799. '/fake/path', mock.ANY, mock.ANY, mock.ANY,
  800. mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY,
  801. mock.ANY, None)
  802. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  803. '_heat_deploy', autospec=True)
  804. def test_try_overcloud_deploy_show_missing_file(
  805. self, mock_heat_deploy_func):
  806. mock_heat_deploy_func.side_effect = \
  807. ObjectClientException('/fake/path not found')
  808. try:
  809. self.cmd._try_overcloud_deploy_with_compat_yaml(
  810. '/fake/path', mock.ANY, mock.ANY, mock.ANY,
  811. mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY,
  812. None)
  813. except ValueError as value_error:
  814. self.assertIn('/fake/path', str(value_error))
  815. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  816. '_get_undercloud_host_entry', autospec=True,
  817. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  818. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  819. '_deploy_tripleo_heat_templates', autospec=True)
  820. def test_dry_run(self, mock_create_tempest_deployer_input,
  821. mock_get_undercloud_host_entry):
  822. utils_fixture = deployment.UtilsOvercloudFixture()
  823. self.useFixture(utils_fixture)
  824. clients = self.app.client_manager
  825. orchestration_client = clients.orchestration
  826. mock_stack = fakes.create_tht_stack()
  827. orchestration_client.stacks.get.return_value = mock_stack
  828. arglist = ['--templates', '--dry-run']
  829. verifylist = [
  830. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  831. ('dry_run', True),
  832. ]
  833. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  834. self.cmd.take_action(parsed_args)
  835. self.assertFalse(utils_fixture.mock_deploy_tht.called)
  836. self.assertFalse(utils_fixture.mock_create_ocrc.called)
  837. self.assertFalse(mock_create_tempest_deployer_input.called)
  838. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  839. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  840. '_get_undercloud_host_entry', autospec=True,
  841. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  842. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  843. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  844. '_heat_deploy', autospec=True)
  845. @mock.patch('tempfile.mkdtemp', autospec=True)
  846. @mock.patch('shutil.rmtree', autospec=True)
  847. def test_answers_file(self, mock_rmtree, mock_tmpdir,
  848. mock_heat_deploy, mock_stack_network_check,
  849. mock_get_undercloud_host_entry, mock_copy):
  850. fixture = deployment.DeploymentWorkflowFixture()
  851. self.useFixture(fixture)
  852. clients = self.app.client_manager
  853. orchestration_client = clients.orchestration
  854. mock_stack = fakes.create_tht_stack()
  855. orchestration_client.stacks.get.return_value = mock_stack
  856. plane_management_fixture = deployment.PlanManagementFixture()
  857. self.useFixture(plane_management_fixture)
  858. utils_fixture = deployment.UtilsOvercloudFixture()
  859. self.useFixture(utils_fixture)
  860. clients = self.app.client_manager
  861. workflow_client = clients.workflow_engine
  862. workflow_client.action_executions.create.return_value = mock.MagicMock(
  863. output='{"result":[]}')
  864. mock_tmpdir.return_value = self.tmp_dir.path
  865. mock_rmtree.return_value = None
  866. network_client = clients.network
  867. network_client.stacks.get.return_value = None
  868. net = network_client.api.find_attr('networks', 'ctlplane')
  869. net.configure_mock(__getitem__=lambda x, y: 'testnet')
  870. test_env = self.tmp_dir.join('foo1.yaml')
  871. with open(test_env, 'w') as temp_file:
  872. temp_file.write('resource_registry:\n Test: OS::Heat::None')
  873. test_env2 = self.tmp_dir.join('foo2.yaml')
  874. with open(test_env2, 'w') as temp_file:
  875. temp_file.write('resource_registry:\n Test2: OS::Heat::None')
  876. test_answerfile = self.tmp_dir.join('answerfile')
  877. with open(test_answerfile, 'w') as answerfile:
  878. yaml.dump(
  879. {'templates':
  880. '/usr/share/openstack-tripleo-heat-templates/',
  881. 'environments': [test_env]
  882. },
  883. answerfile
  884. )
  885. arglist = ['--answers-file', test_answerfile,
  886. '--environment-file', test_env2,
  887. '--disable-password-generation']
  888. verifylist = [
  889. ('answers_file', test_answerfile),
  890. ('environment_files', [test_env2]),
  891. ('disable_password_generation', True)]
  892. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  893. object_client = clients.tripleoclient.object_store
  894. object_client.get_object = mock.Mock()
  895. mock_env = yaml.safe_dump({'parameter_defaults':
  896. {'NovaComputeLibvirtType': 'qemu'}})
  897. object_client.get_object.return_value = ({}, mock_env)
  898. self.cmd.take_action(parsed_args)
  899. self.assertTrue(mock_heat_deploy.called)
  900. self.assertTrue(utils_fixture.mock_create_ocrc.called)
  901. self.assertTrue(utils_fixture.mock_deploy_tht.called)
  902. # Check that Heat was called with correct parameters:
  903. call_args = mock_heat_deploy.call_args[0]
  904. self.assertEqual(call_args[3],
  905. self.tmp_dir.join(
  906. 'tripleo-heat-templates/overcloud.yaml'))
  907. self.assertEqual(call_args[7],
  908. self.tmp_dir.join('tripleo-heat-templates'))
  909. self.assertIn('Test', call_args[8]['resource_registry'])
  910. self.assertIn('Test2', call_args[8]['resource_registry'])
  911. utils_fixture.mock_deploy_tht.assert_called_with()
  912. mock_copy.assert_called_once()
  913. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  914. '_get_undercloud_host_entry', autospec=True,
  915. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  916. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  917. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  918. '_create_parameters_env', autospec=True)
  919. @mock.patch('tripleoclient.utils.write_overcloudrc')
  920. @mock.patch('heatclient.common.template_utils.'
  921. 'process_environment_and_files', autospec=True)
  922. @mock.patch('heatclient.common.template_utils.get_template_contents',
  923. autospec=True)
  924. def test_ntp_server_mandatory(self, mock_get_template_contents,
  925. mock_process_env,
  926. mock_write_overcloudrc,
  927. mock_create_parameters_env,
  928. mock_stack_network_check,
  929. mock_get_undercloud_host_entry):
  930. plane_management_fixture = deployment.PlanManagementFixture()
  931. self.useFixture(plane_management_fixture)
  932. clients = self.app.client_manager
  933. orchestration_client = clients.orchestration
  934. mock_stack = fakes.create_tht_stack()
  935. orchestration_client.stacks.get.return_value = mock_stack
  936. arglist = ['--templates']
  937. verifylist = [
  938. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  939. ]
  940. workflow_client = clients.workflow_engine
  941. workflow_client.action_executions.create.return_value = mock.MagicMock(
  942. output='{"result":[]}')
  943. object_client = clients.tripleoclient.object_store
  944. object_client.get_object = mock.Mock()
  945. mock_env = yaml.safe_dump({'environments': []})
  946. object_client.get_object.return_value = ({}, mock_env)
  947. def _custom_create_params_env(_self, parameters, tht_root,
  948. container_name):
  949. parameters.update({"ControllerCount": 3})
  950. parameter_defaults = {"parameter_defaults": parameters}
  951. return parameter_defaults
  952. mock_create_parameters_env.side_effect = _custom_create_params_env
  953. mock_env = fakes.create_env()
  954. mock_process_env.return_value = [{}, mock_env]
  955. mock_get_template_contents.return_value = [{}, "template"]
  956. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  957. self.assertRaises(exceptions.InvalidConfiguration,
  958. self.cmd.take_action,
  959. parsed_args)
  960. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  961. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  962. '_get_undercloud_host_entry', autospec=True,
  963. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  964. @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files')
  965. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  966. '_deploy_postconfig', autospec=True)
  967. @mock.patch('tripleo_common.update.add_breakpoints_cleanup_into_env')
  968. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  969. '_validate_args')
  970. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  971. '_create_parameters_env', autospec=True)
  972. @mock.patch('tripleoclient.utils.create_tempest_deployer_input',
  973. autospec=True)
  974. @mock.patch('heatclient.common.template_utils.'
  975. 'process_environment_and_files', autospec=True)
  976. @mock.patch('heatclient.common.template_utils.get_template_contents',
  977. autospec=True)
  978. def test_tht_deploy_with_ntp(self, mock_get_template_contents,
  979. mock_process_env,
  980. mock_create_tempest_deployer_input,
  981. mock_create_parameters_env,
  982. mock_validate_args,
  983. mock_breakpoints_cleanup,
  984. mock_deploy_post_config,
  985. mock_stack_network_check,
  986. mock_get_undercloud_host_entry, mock_copy):
  987. fixture = deployment.DeploymentWorkflowFixture()
  988. self.useFixture(fixture)
  989. plane_management_fixture = deployment.PlanManagementFixture()
  990. self.useFixture(plane_management_fixture)
  991. utils_fixture = deployment.UtilsFixture()
  992. self.useFixture(utils_fixture)
  993. arglist = ['--templates', '--ntp-server', 'ntp']
  994. verifylist = [
  995. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  996. ]
  997. clients = self.app.client_manager
  998. orchestration_client = clients.orchestration
  999. mock_stack = fakes.create_tht_stack()
  1000. orchestration_client.stacks.get.side_effect = [
  1001. None,
  1002. mock.MagicMock()
  1003. ]
  1004. def _orch_clt_create(**kwargs):
  1005. orchestration_client.stacks.get.return_value = mock_stack
  1006. orchestration_client.stacks.create.side_effect = _orch_clt_create
  1007. workflow_client = clients.workflow_engine
  1008. workflow_client.action_executions.create.return_value = mock.MagicMock(
  1009. output='{"result":[]}')
  1010. object_client = clients.tripleoclient.object_store
  1011. object_client.get_object = mock.Mock()
  1012. mock_env = yaml.safe_dump({'environments': []})
  1013. object_client.get_object.return_value = ({}, mock_env)
  1014. clients.network.api.find_attr.return_value = {
  1015. "id": "network id"
  1016. }
  1017. mock_env = fakes.create_env_with_ntp()
  1018. mock_process_env.return_value = [{}, mock_env]
  1019. mock_get_template_contents.return_value = [{}, "template"]
  1020. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1021. baremetal = clients.baremetal
  1022. baremetal.node.list.return_value = range(10)
  1023. expected_parameters = {
  1024. 'CephClusterFSID': self.uuid1_value,
  1025. 'ExtraConfig': '{}',
  1026. 'HypervisorNeutronPhysicalBridge': 'br-ex',
  1027. 'HypervisorNeutronPublicInterface': 'nic1',
  1028. 'NeutronDnsmasqOptions': 'dhcp-option-force=26,1400',
  1029. 'NeutronFlatNetworks': 'datacentre',
  1030. 'NeutronNetworkType': 'gre',
  1031. 'NeutronPublicInterface': 'nic1',
  1032. 'NeutronTunnelTypes': 'gre',
  1033. 'SnmpdReadonlyUserPassword': 'PASSWORD',
  1034. 'UpdateIdentifier': '',
  1035. 'StackAction': 'CREATE',
  1036. 'NtpServer': 'ntp',
  1037. 'DeployIdentifier': '',
  1038. 'UndercloudHostsEntries': [
  1039. '192.168.0.1 uc.ctlplane.localhost uc.ctlplane'
  1040. ]
  1041. }
  1042. def _custom_create_params_env(_self, parameters, tht_root,
  1043. container_name):
  1044. for key, value in six.iteritems(parameters):
  1045. self.assertEqual(value, expected_parameters[key])
  1046. parameter_defaults = {"parameter_defaults": parameters}
  1047. return parameter_defaults
  1048. mock_create_parameters_env.side_effect = _custom_create_params_env
  1049. self.cmd.take_action(parsed_args)
  1050. mock_get_template_contents.assert_called_with(
  1051. object_request=mock.ANY,
  1052. template_object=constants.OVERCLOUD_YAML_NAME)
  1053. mock_create_tempest_deployer_input.assert_called_with()
  1054. mock_validate_args.assert_called_once_with(parsed_args)
  1055. mock_copy.assert_called_once()
  1056. @mock.patch('tripleoclient.workflows.parameters.'
  1057. 'check_deprecated_parameters', autospec=True)
  1058. @mock.patch('tripleoclient.workflows.deployment.deploy_and_wait',
  1059. autospec=True)
  1060. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1061. '_process_and_upload_environment', autospec=True)
  1062. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1063. '_upload_missing_files', autospec=True)
  1064. @mock.patch('heatclient.common.template_utils.get_template_contents',
  1065. autospec=True)
  1066. @mock.patch('os.path.relpath', autospec=True)
  1067. @mock.patch('tripleo_common.update.add_breakpoints_cleanup_into_env',
  1068. autospec=True)
  1069. @mock.patch('tripleo_common.update.check_neutron_mechanism_drivers')
  1070. def test_heat_deploy_update_plan_only(self, check_mech,
  1071. mock_breakpoints_cleanup,
  1072. mock_relpath,
  1073. mock_get_template_contents,
  1074. mock_upload_missing_files,
  1075. mock_process_and_upload_env,
  1076. mock_deploy_and_wait,
  1077. mock_deprecated_params):
  1078. clients = self.app.client_manager
  1079. check_mech.return_value = None
  1080. orchestration_client = clients.orchestration
  1081. mock_stack = fakes.create_tht_stack()
  1082. orchestration_client.stacks.get.side_effect = [
  1083. None,
  1084. mock.MagicMock()
  1085. ]
  1086. workflow_client = clients.workflow_engine
  1087. workflow_client.action_executions.create.return_value = mock.MagicMock(
  1088. output='{"result":[]}')
  1089. object_client = clients.tripleoclient.object_store
  1090. object_client.get_object = mock.Mock()
  1091. mock_env = yaml.safe_dump({'environments': []})
  1092. object_client.get_object.return_value = ({}, mock_env)
  1093. mock_relpath.return_value = './'
  1094. mock_get_template_contents.return_value = [{}, {}]
  1095. self.cmd.clients = {}
  1096. self.cmd.object_client = object_client
  1097. self.cmd._heat_deploy(mock_stack, 'mock_stack', '/tmp', {},
  1098. {}, 1, '/tmp', {}, True, False, False, None)
  1099. self.assertFalse(mock_deploy_and_wait.called)
  1100. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  1101. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1102. '_get_undercloud_host_entry', autospec=True,
  1103. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  1104. @mock.patch('tripleoclient.workflows.deployment.create_overcloudrc',
  1105. autospec=True)
  1106. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1107. '_deploy_tripleo_heat_templates_tmpdir', autospec=True)
  1108. def test_deployed_server(self, mock_deploy_tmpdir, mock_overcloudrc,
  1109. mock_get_undercloud_host_entry, mock_copy):
  1110. fixture = deployment.DeploymentWorkflowFixture()
  1111. self.useFixture(fixture)
  1112. utils_fixture = deployment.UtilsOvercloudFixture()
  1113. self.useFixture(utils_fixture)
  1114. arglist = ['--templates', '--deployed-server', '--disable-validations']
  1115. verifylist = [
  1116. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  1117. ('deployed_server', True),
  1118. ('disable_validations', True),
  1119. ]
  1120. clients = self.app.client_manager
  1121. clients.baremetal = mock.Mock()
  1122. clients.compute = mock.Mock()
  1123. orchestration_client = clients.orchestration
  1124. orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
  1125. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1126. self.cmd.take_action(parsed_args)
  1127. self.assertTrue(mock_deploy_tmpdir.called)
  1128. self.assertNotCalled(clients.baremetal)
  1129. self.assertNotCalled(clients.compute)
  1130. self.assertTrue(utils_fixture.mock_deploy_tht.called)
  1131. mock_copy.assert_called_once()
  1132. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1133. '_deploy_tripleo_heat_templates', autospec=True)
  1134. def test_fail_overcloud_deploy_with_deployed_server_and_validations(
  1135. self, mock_deploy_tmpdir):
  1136. arglist = ['--templates', '--deployed-server']
  1137. verifylist = [
  1138. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  1139. ('deployed_server', True),
  1140. ]
  1141. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1142. self.assertRaises(oscexc.CommandError,
  1143. self.cmd.take_action,
  1144. parsed_args)
  1145. self.assertFalse(mock_deploy_tmpdir.called)
  1146. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  1147. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1148. '_get_undercloud_host_entry', autospec=True,
  1149. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  1150. @mock.patch('tripleoclient.workflows.deployment.create_overcloudrc',
  1151. autospec=True)
  1152. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1153. '_deploy_tripleo_heat_templates_tmpdir', autospec=True)
  1154. def test_config_download(
  1155. self, mock_deploy_tmpdir,
  1156. mock_overcloudrc, mock_get_undercloud_host_entry, mock_copy):
  1157. fixture = deployment.DeploymentWorkflowFixture()
  1158. self.useFixture(fixture)
  1159. utils_fixture = deployment.UtilsOvercloudFixture()
  1160. self.useFixture(utils_fixture)
  1161. clients = self.app.client_manager
  1162. orchestration_client = clients.orchestration
  1163. orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
  1164. arglist = ['--templates', '--config-download']
  1165. verifylist = [
  1166. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  1167. ('config_download', True),
  1168. ]
  1169. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1170. self.cmd.take_action(parsed_args)
  1171. self.assertTrue(mock_deploy_tmpdir.called)
  1172. self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called)
  1173. self.assertTrue(fixture.mock_config_download.called)
  1174. self.assertTrue(fixture.mock_set_deployment_status.called)
  1175. self.assertEqual(
  1176. 'deploying',
  1177. fixture.mock_set_deployment_status.call_args[-1]['status']
  1178. )
  1179. mock_copy.assert_called_once()
  1180. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  1181. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1182. '_get_undercloud_host_entry', autospec=True,
  1183. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  1184. @mock.patch('tripleoclient.workflows.deployment.create_overcloudrc',
  1185. autospec=True)
  1186. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1187. '_deploy_tripleo_heat_templates_tmpdir', autospec=True)
  1188. def test_config_download_only(
  1189. self, mock_deploy_tmpdir,
  1190. mock_overcloudrc, mock_get_undercloud_host_entry, mock_copy):
  1191. fixture = deployment.DeploymentWorkflowFixture()
  1192. self.useFixture(fixture)
  1193. utils_fixture = deployment.UtilsOvercloudFixture()
  1194. self.useFixture(utils_fixture)
  1195. clients = self.app.client_manager
  1196. orchestration_client = clients.orchestration
  1197. orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
  1198. arglist = ['--templates', '--config-download-only']
  1199. verifylist = [
  1200. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  1201. ('config_download_only', True),
  1202. ]
  1203. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1204. self.cmd.take_action(parsed_args)
  1205. self.assertFalse(mock_deploy_tmpdir.called)
  1206. self.assertFalse(fixture.mock_get_hosts_and_enable_ssh_admin.called)
  1207. self.assertTrue(fixture.mock_config_download.called)
  1208. self.assertTrue(fixture.mock_set_deployment_status.called)
  1209. self.assertEqual(
  1210. 'deploying',
  1211. fixture.mock_set_deployment_status.call_args[-1]['status'])
  1212. mock_copy.assert_called_once()
  1213. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1214. '_get_undercloud_host_entry', autospec=True,
  1215. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  1216. @mock.patch('tripleoclient.utils.create_tempest_deployer_input',
  1217. autospec=True)
  1218. @mock.patch('tripleoclient.utils.get_overcloud_endpoint', autospec=True)
  1219. @mock.patch('tripleoclient.utils.write_overcloudrc', autospec=True)
  1220. @mock.patch('tripleoclient.workflows.deployment.create_overcloudrc',
  1221. autospec=True)
  1222. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1223. '_deploy_tripleo_heat_templates_tmpdir', autospec=True)
  1224. def test_config_download_fails(
  1225. self, mock_deploy_tmpdir,
  1226. mock_overcloudrc, mock_write_overcloudrc,
  1227. mock_overcloud_endpoint,
  1228. mock_create_tempest_deployer_input,
  1229. mock_get_undercloud_host_entry):
  1230. fixture = deployment.DeploymentWorkflowFixture()
  1231. self.useFixture(fixture)
  1232. clients = self.app.client_manager
  1233. orchestration_client = clients.orchestration
  1234. orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
  1235. arglist = ['--templates', '--config-download-only']
  1236. verifylist = [
  1237. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  1238. ('config_download_only', True),
  1239. ]
  1240. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1241. fixture.mock_config_download.side_effect = \
  1242. exceptions.DeploymentError('fails')
  1243. self.assertRaises(
  1244. exceptions.DeploymentError,
  1245. self.cmd.take_action,
  1246. parsed_args)
  1247. self.assertFalse(mock_deploy_tmpdir.called)
  1248. self.assertTrue(fixture.mock_config_download.called)
  1249. self.assertTrue(fixture.mock_set_deployment_status.called)
  1250. self.assertEqual(
  1251. 'failed',
  1252. fixture.mock_set_deployment_status.call_args[-1]['status'])
  1253. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  1254. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1255. '_get_undercloud_host_entry', autospec=True,
  1256. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  1257. @mock.patch('tripleoclient.workflows.deployment.create_overcloudrc',
  1258. autospec=True)
  1259. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1260. '_deploy_tripleo_heat_templates_tmpdir', autospec=True)
  1261. def test_override_ansible_cfg(
  1262. self, mock_deploy_tmpdir,
  1263. mock_overcloudrc, mock_get_undercloud_host_entry, mock_copy):
  1264. fixture = deployment.DeploymentWorkflowFixture()
  1265. self.useFixture(fixture)
  1266. utils_fixture = deployment.UtilsOvercloudFixture()
  1267. self.useFixture(utils_fixture)
  1268. clients = self.app.client_manager
  1269. orchestration_client = clients.orchestration
  1270. orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
  1271. arglist = ['--templates',
  1272. '--override-ansible-cfg', 'ansible.cfg']
  1273. verifylist = [
  1274. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  1275. ('override_ansible_cfg', 'ansible.cfg')
  1276. ]
  1277. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1278. self.cmd.take_action(parsed_args)
  1279. self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called)
  1280. self.assertTrue(fixture.mock_config_download.called)
  1281. self.assertEqual('ansible.cfg',
  1282. fixture.mock_config_download.call_args[0][8])
  1283. mock_copy.assert_called_once()
  1284. @mock.patch('tripleoclient.utils.copy_clouds_yaml')
  1285. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1286. '_get_undercloud_host_entry', autospec=True,
  1287. return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
  1288. @mock.patch('tripleoclient.workflows.deployment.create_overcloudrc',
  1289. autospec=True)
  1290. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1291. '_deploy_tripleo_heat_templates_tmpdir', autospec=True)
  1292. def test_config_download_timeout(
  1293. self, mock_deploy_tmpdir,
  1294. mock_overcloudrc, mock_get_undercloud_host_entry, mock_copy):
  1295. fixture = deployment.DeploymentWorkflowFixture()
  1296. self.useFixture(fixture)
  1297. utils_fixture = deployment.UtilsOvercloudFixture()
  1298. self.useFixture(utils_fixture)
  1299. clients = self.app.client_manager
  1300. orchestration_client = clients.orchestration
  1301. orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
  1302. arglist = ['--templates', '--config-download-timeout', '240']
  1303. verifylist = [
  1304. ('templates', '/usr/share/openstack-tripleo-heat-templates/'),
  1305. ('config_download_timeout', 240),
  1306. ]
  1307. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1308. self.cmd.take_action(parsed_args)
  1309. fixture.mock_config_download.assert_called()
  1310. self.assertEqual(240*60, fixture.mock_config_download.call_args[0][9])
  1311. mock_copy.assert_called_once()
  1312. def test_download_missing_files_from_plan(self):
  1313. # Restore the real function so we don't accidentally call the mock
  1314. self.cmd._download_missing_files_from_plan = self.real_download_missing
  1315. # Set up the client mocks
  1316. self.cmd._setup_clients(mock.Mock())
  1317. dirname = '/tmp/tht-missing'
  1318. mock_open = mock.mock_open()
  1319. mock_makedirs = mock.Mock()
  1320. builtin_mod = six.moves.builtins.__name__
  1321. with mock.patch('os.makedirs', mock_makedirs):
  1322. with mock.patch('%s.open' % builtin_mod, mock_open):
  1323. self.cmd._download_missing_files_from_plan(dirname,
  1324. 'overcast')
  1325. mock_makedirs.assert_called_with(dirname)
  1326. mock_open.assert_called()
  1327. def test_validate_args_deprecated(self):
  1328. arglist = ['--control-scale', '3', '--control-flavor', 'control']
  1329. verifylist = [
  1330. ('control_scale', 3),
  1331. ('control_flavor', 'control'),
  1332. ]
  1333. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1334. self.assertRaises(oscexc.CommandError,
  1335. self.cmd.take_action,
  1336. parsed_args)
  1337. @mock.patch('tripleoclient.workflows.baremetal.undeploy_roles',
  1338. autospec=True)
  1339. @mock.patch('tripleoclient.workflows.baremetal.deploy_roles',
  1340. autospec=True)
  1341. @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
  1342. '_write_user_environment', autospec=True)
  1343. def test_provision_baremetal(self, mock_write, mock_deploy_roles,
  1344. mock_undeploy_roles):
  1345. mock_write.return_value = (
  1346. '/tmp/tht/user-environments/baremetal-deployed.yaml',
  1347. 'overcloud/user-environments/baremetal-deployed.yaml'
  1348. )
  1349. mock_deploy_roles.return_value = {
  1350. 'parameter_defaults': {'foo': 'bar'}
  1351. }
  1352. bm_deploy_path = self.tmp_dir.join('bm_deploy.yaml')
  1353. deploy_data = [
  1354. {'name': 'Compute', 'count': 10},
  1355. {'name': 'Controller', 'count': 3},
  1356. ]
  1357. with open(bm_deploy_path, 'w') as temp_file:
  1358. yaml.safe_dump(deploy_data, temp_file)
  1359. ssh_key_path = self.tmp_dir.join('id_rsa.pub')
  1360. with open(ssh_key_path, 'w') as temp_file:
  1361. temp_file.write('sekrit')
  1362. arglist = [
  1363. '--baremetal-deployment', bm_deploy_path,
  1364. '--overcloud-ssh-key', ssh_key_path
  1365. ]
  1366. verifylist = [
  1367. ('baremetal_deployment', bm_deploy_path),
  1368. ('overcloud_ssh_key', ssh_key_path),
  1369. ]
  1370. parsed_args = self.check_parser(self.cmd, arglist, verifylist)
  1371. tht_root = '/tmp/tht'
  1372. result = self.cmd._provision_baremetal(parsed_args, tht_root)
  1373. self.cmd._unprovision_baremetal(parsed_args)
  1374. self.assertEqual(
  1375. ['/tmp/tht/user-environments/baremetal-deployed.yaml'],
  1376. result
  1377. )
  1378. mock_deploy_roles.assert_called_once_with(
  1379. self.app.client_manager,
  1380. plan='overcloud',
  1381. roles=deploy_data,
  1382. ssh_keys=['sekrit'],
  1383. ssh_user_name='heat-admin'
  1384. )
  1385. mock_undeploy_roles.assert_called_once_with(
  1386. self.app.client_manager,
  1387. plan='overcloud',
  1388. roles=deploy_data
  1389. )
  1390. mock_write.assert_called_once_with(
  1391. self.cmd,
  1392. {'parameter_defaults': {'foo': 'bar'}},
  1393. 'baremetal-deployed.yaml',
  1394. '/tmp/tht',
  1395. 'overcloud'
  1396. )
  1397. @mock.patch('subprocess.Popen', autospec=True)
  1398. def test__get_undercloud_host_entry(self, mock_popen):
  1399. mock_process = mock.Mock()
  1400. mock_process.communicate.return_value = (
  1401. 'fd12::1 uc.ctlplane.localdomain uc.ctlplane', '')
  1402. mock_process.returncode = 0
  1403. mock_popen.return_value = mock_process
  1404. expected = ('fd12::1 uc.ctlplane.localdomain uc.ctlplane')
  1405. self.assertEqual(expected, self.cmd._get_undercloud_host_entry())
  1406. class TestArgumentValidation(fakes.TestDeployOvercloud):
  1407. def setUp(self):
  1408. super(TestArgumentValidation, self).setUp()
  1409. def is_dir(arg):
  1410. if arg == '/tmp/real_dir':
  1411. return True
  1412. else:
  1413. return False
  1414. patcher = mock.patch('os.path.isdir')
  1415. mock_isdir = patcher.start()
  1416. mock_isdir.side_effect = is_dir
  1417. self.addCleanup(patcher.stop)
  1418. app_args = mock.Mock()
  1419. app_args.verbose_level = 1
  1420. self.validate = overcloud_deploy.DeployOvercloud(
  1421. self.app, app_args)._validate_args_environment_directory
  1422. def test_validate_env_dir(self):
  1423. self.assertIsNone(self.validate(['/tmp/real_dir']))
  1424. def test_validate_env_dir_empty(self):
  1425. self.assertIsNone(self.validate([]))
  1426. def test_validate_env_dir_not_a_real_directory(self):
  1427. self.assertRaises(oscexc.CommandError,
  1428. self.validate,
  1429. ['/tmp/not_a_real_dir'])
  1430. def test_validate_env_dir_ignore_default_not_existing(self):
  1431. full_path = os.path.expanduser(constants.DEFAULT_ENV_DIRECTORY)
  1432. self.assertIsNone(self.validate([full_path]))
  1433. class TestGetDeploymentStatus(utils.TestCommand):
  1434. def setUp(self):
  1435. super(TestGetDeploymentStatus, self).setUp()
  1436. self.cmd = overcloud_deploy.GetDeploymentStatus(self.app, None)
  1437. self.app.client_manager = mock.Mock()
  1438. clients = self.clients = self.app.client_manager
  1439. tc = clients.tripleoclient = ooofakes.FakeClientWrapper()
  1440. tc.create_mistral_context = plugin.ClientWrapper(
  1441. instance=ooofakes.FakeInstanceData
  1442. ).create_mistral_context
  1443. obj = tc.object_store = mock.Mock()
  1444. obj.put_object = mock.Mock()
  1445. @mock.patch(
  1446. 'tripleo_common.actions.deployment.DeploymentStatusAction.run',
  1447. autospec=True
  1448. )
  1449. def test_get_deployment_status(self, mock_get_deployment_status):
  1450. parsed_args = self.check_parser(self.cmd, [], [])
  1451. self.cmd.app.stdout = six.StringIO()
  1452. status = dict(
  1453. cd_status='SUCCESS',
  1454. stack_status='SUCCESS',
  1455. deployment_status='SUCCESS',
  1456. ansible_status='SUCCESS',
  1457. status_update='SUCCESS'
  1458. )
  1459. mock_get_deployment_status.return_value = status
  1460. self.cmd.take_action(parsed_args)
  1461. expected = (
  1462. '+-----------+-------------------+\n'
  1463. '| Plan Name | Deployment Status |\n'
  1464. '+-----------+-------------------+\n'
  1465. '| overcloud | SUCCESS |\n'
  1466. '+-----------+-------------------+\n')
  1467. self.assertEqual(expected, self.cmd.app.stdout.getvalue())
  1468. class TestGetDeploymentFailures(utils.TestCommand):
  1469. def setUp(self):
  1470. super(TestGetDeploymentFailures, self).setUp()
  1471. self.cmd = overcloud_deploy.GetDeploymentFailures(self.app, None)
  1472. self.app.client_manager = mock.Mock()
  1473. self.clients = self.app.client_manager
  1474. @mock.patch(
  1475. 'tripleoclient.workflows.deployment.get_deployment_failures',
  1476. autospec=True)
  1477. def test_plan_get_deployment_status(self, mock_get_deployment_failures):
  1478. parsed_args = self.check_parser(self.cmd, [], [])
  1479. self.cmd.app.stdout = six.StringIO()
  1480. failures = {
  1481. 'host0': [
  1482. ['Task1', dict(key1=1, key2=2, key3=3)],
  1483. ['Task2', dict(key4=4, key5=5, key3=5)]
  1484. ],
  1485. 'host1': [
  1486. ['Task1', dict(key1=1, key2=2, key3=['a', 'b', 'c'])]
  1487. ],
  1488. }
  1489. mock_get_deployment_failures.return_value = failures
  1490. self.cmd.take_action(parsed_args)
  1491. expected = (
  1492. '|-> Failures for host: host0\n'
  1493. '|--> Task: Task1\n'
  1494. '|---> key1: 1\n'
  1495. '|---> key2: 2\n'
  1496. '|---> key3: 3\n'
  1497. '|--> Task: Task2\n'
  1498. '|---> key3: 5\n'
  1499. '|---> key4: 4\n'
  1500. '|---> key5: 5\n'
  1501. '\n'
  1502. '|-> Failures for host: host1\n'
  1503. '|--> Task: Task1\n'
  1504. '|---> key1: 1\n'
  1505. '|---> key2: 2\n'
  1506. '|---> key3: [\n'
  1507. ' "a",\n'
  1508. ' "b",\n'
  1509. ' "c"\n'
  1510. ']\n\n')
  1511. self.assertEqual(expected, self.cmd.app.stdout.getvalue())