diff --git a/tripleoclient/constants.py b/tripleoclient/constants.py index f2b89d56e..475199b1a 100644 --- a/tripleoclient/constants.py +++ b/tripleoclient/constants.py @@ -303,6 +303,7 @@ DEFAULT_WHOLE_DISK_IMAGE = 'overcloud-hardened-uefi-full.qcow2' FIPS_COMPLIANT_HASHES = {'sha1', 'sha224', 'sha256', 'sha384', 'sha512'} +STACK_ENV_FILE_NAME = 'tripleo-{}-environment.yaml' # Disk usage percentages to check as related to deploy backups DEPLOY_BACKUPS_USAGE_PERCENT = 50 DISK_USAGE_PERCENT = 80 diff --git a/tripleoclient/tests/test_utils.py b/tripleoclient/tests/test_utils.py index ae1f3fa3f..eb09cd74c 100644 --- a/tripleoclient/tests/test_utils.py +++ b/tripleoclient/tests/test_utils.py @@ -678,170 +678,51 @@ class TestWaitForStackUtil(TestCase): self.assertEqual(False, result) def test_check_heat_network_config(self): - stack_reg = { - 'OS::TripleO::Controller::Net::SoftwareConfig': 'val', - 'OS::TripleO::Compute::Net::SoftwareConfig': 'val', - } env_reg = { 'OS::TripleO::Controller::Net::SoftwareConfig': 'val', 'OS::TripleO::Compute::Net::SoftwareConfig': 'val', } - mock_stack = mock.MagicMock() - mock_stack.environment = mock.MagicMock() - mock_stack.environment.return_value = { - 'resource_registry': stack_reg, - } env = { 'resource_registry': env_reg } self.assertRaises(exceptions.InvalidConfiguration, - utils.check_nic_config_with_ansible, - mock_stack, env) + utils.check_nic_config_with_ansible, env) def test_check_service_vips_migrated_to_service(self): - stack_reg = { - 'OS::TripleO::Network::Ports::RedisVipPort': 'val', - 'OS::TripleO::Network::Ports::OVNDBsVipPort': 'val', - } env_reg = { 'OS::TripleO::Network::Ports::RedisVipPort': 'val', 'OS::TripleO::Network::Ports::OVNDBsVipPort': 'val', } - mock_stack = mock.MagicMock() - mock_stack.environment = mock.MagicMock() - mock_stack.environment.return_value = { - 'resource_registry': stack_reg, - } env = { 'resource_registry': env_reg } self.assertRaises(exceptions.InvalidConfiguration, utils.check_service_vips_migrated_to_service, - mock_stack, env) - - def test_check_heat_missing_network_config(self): - stack_reg = { - 'OS::TripleO::Controller::Net::SoftwareConfig': 'val', - 'OS::TripleO::Compute::Net::SoftwareConfig': 'val', - } - env_reg = { - 'OS::TripleO::Controller::Net::SoftwareConfig': 'OS::Heat::None', - } - mock_stack = mock.MagicMock() - mock_stack.environment = mock.MagicMock() - mock_stack.environment.return_value = { - 'resource_registry': stack_reg, - } - env = { - 'resource_registry': env_reg - } - - self.assertRaises(exceptions.InvalidConfiguration, - utils.check_nic_config_with_ansible, - mock_stack, env) + env) def test_check_heat_none_network_config(self): - stack_reg = { - 'OS::TripleO::Controller::Net::SoftwareConfig': 'val', - 'OS::TripleO::Compute::Net::SoftwareConfig': 'val', - } env_reg = { 'OS::TripleO::Controller::Net::SoftwareConfig': 'OS::Heat::None', 'OS::TripleO::Compute::Net::SoftwareConfig': 'OS::Heat::None', } - mock_stack = mock.MagicMock() - mock_stack.environment = mock.MagicMock() - mock_stack.environment.return_value = { - 'resource_registry': stack_reg, - } env = { 'resource_registry': env_reg, 'parameter_defaults': {'NetworkConfigWithAnsible': True} } - utils.check_nic_config_with_ansible(mock_stack, env) + utils.check_nic_config_with_ansible(env) def test_check_heat_network_config_no_ansible(self): - stack_reg = { - 'OS::TripleO::Controller::Net::SoftwareConfig': 'val', - 'OS::TripleO::Compute::Net::SoftwareConfig': 'val', - } env_reg = { 'OS::TripleO::Controller::Net::SoftwareConfig': 'val', 'OS::TripleO::Compute::Net::SoftwareConfig': 'val', } - mock_stack = mock.MagicMock() - mock_stack.environment = mock.MagicMock() - mock_stack.environment.return_value = { - 'resource_registry': stack_reg, - } env = { 'resource_registry': env_reg, 'parameter_defaults': {'NetworkConfigWithAnsible': False} } - utils.check_nic_config_with_ansible(mock_stack, env) - - def test_check_stack_network_matches_env_files(self): - stack_reg = { - 'OS::TripleO::Network': 'val', - 'OS::TripleO::Network::External': 'val', - 'OS::TripleO::Network::ExtraConfig': 'OS::Heat::None', - 'OS::TripleO::Network::InternalApi': 'val', - 'OS::TripleO::Network::Port::InternalApi': 'val', - 'OS::TripleO::Network::Management': 'val', - 'OS::TripleO::Network::Storage': 'val', - 'OS::TripleO::Network::StorageMgmt': 'val', - 'OS::TripleO::Network::Tenant': 'val' - } - env_reg = { - 'OS::TripleO::Network': 'newval', - 'OS::TripleO::Network::External': 'newval', - 'OS::TripleO::Network::ExtraConfig': 'OS::Heat::None', - 'OS::TripleO::Network::InternalApi': 'newval', - 'OS::TripleO::Network::Management': 'newval', - 'OS::TripleO::Network::Storage': 'val', - 'OS::TripleO::Network::StorageMgmt': 'val', - 'OS::TripleO::Network::Tenant': 'val' - } - mock_stack = mock.MagicMock() - mock_stack.environment = mock.MagicMock() - mock_stack.environment.return_value = { - 'resource_registry': stack_reg - } - env = { - 'resource_registry': env_reg - } - utils.check_stack_network_matches_env_files(mock_stack, env) - - def test_check_stack_network_matches_env_files_fail(self): - stack_reg = { - 'OS::TripleO::LoggingConfiguration': 'val', - 'OS::TripleO::Network': 'val', - 'OS::TripleO::Network::External': 'val', - 'OS::TripleO::Network::ExtraConfig': 'OS::Heat::None', - 'OS::TripleO::Network::InternalApi': 'val', - 'OS::TripleO::Network::Port::InternalApi': 'val', - 'OS::TripleO::Network::Management': 'val', - 'OS::TripleO::Network::Storage': 'val', - 'OS::TripleO::Network::StorageMgmt': 'val', - 'OS::TripleO::Network::Tenant': 'val' - } - env_reg = { - 'OS::TripleO::LoggingConfiguration': 'newval', - 'OS::TripleO::Network': 'newval', - 'OS::TripleO::Network::InternalApi': 'newval' - } - mock_stack = mock.MagicMock() - mock_stack.environment = mock.MagicMock() - mock_stack.environment.return_value = { - 'resource_registry': stack_reg - } - env = { - 'resource_registry': env_reg - } - with self.assertRaises(exceptions.InvalidConfiguration): - utils.check_stack_network_matches_env_files(mock_stack, env) + utils.check_nic_config_with_ansible(env) def test_check_ceph_fsid_matches_env_files(self): stack_params = { @@ -863,7 +744,8 @@ class TestWaitForStackUtil(TestCase): 'key2': 'val2', } } - utils.check_ceph_fsid_matches_env_files(mock_stack, provided_env) + utils.check_ceph_fsid_matches_env_files(mock_stack.environment(), + provided_env) def test_check_ceph_fsid_matches_env_files_fail(self): stack_params = { @@ -884,7 +766,8 @@ class TestWaitForStackUtil(TestCase): 'parameter_defaults': stack_params } with self.assertRaises(exceptions.InvalidConfiguration): - utils.check_ceph_fsid_matches_env_files(mock_stack, provided_env) + utils.check_ceph_fsid_matches_env_files(mock_stack.environment(), + provided_env) def test_check_swift_and_rgw(self): stack_reg = { @@ -902,7 +785,8 @@ class TestWaitForStackUtil(TestCase): 'resource_registry': env_reg, } - utils.check_swift_and_rgw(mock_stack, env, 'UpgradePrepare') + utils.check_swift_and_rgw(mock_stack.environment(), + env, 'UpgradePrepare') def test_check_swift_and_rgw_fail(self): stack_reg = { @@ -920,7 +804,8 @@ class TestWaitForStackUtil(TestCase): 'resource_registry': env_reg, } with self.assertRaises(exceptions.InvalidConfiguration): - utils.check_swift_and_rgw(mock_stack, env, 'UpgradePrepare') + utils.check_swift_and_rgw(mock_stack.environment(), + env, 'UpgradePrepare') @mock.patch('subprocess.check_call') @mock.patch('os.path.exists') diff --git a/tripleoclient/tests/v1/overcloud_deploy/fakes.py b/tripleoclient/tests/v1/overcloud_deploy/fakes.py index 33cd79bd1..4037bb28f 100644 --- a/tripleoclient/tests/v1/overcloud_deploy/fakes.py +++ b/tripleoclient/tests/v1/overcloud_deploy/fakes.py @@ -73,6 +73,7 @@ FAKE_STACK = { def create_to_dict_mock(**kwargs): mock_with_to_dict = mock.Mock() mock_with_to_dict.configure_mock(**kwargs) + mock_with_to_dict.environment.return_value = {} mock_with_to_dict.to_dict.return_value = kwargs return mock_with_to_dict diff --git a/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py b/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py index 0d9fbd0ea..88fd35b3d 100644 --- a/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py +++ b/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py @@ -154,7 +154,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): @mock.patch('tripleoclient.utils.copy_clouds_yaml') @mock.patch('tripleoclient.utils.get_undercloud_host_entry', autospec=True, return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') - @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files') @mock.patch('tripleoclient.utils.check_ceph_fsid_matches_env_files') @mock.patch('tripleoclient.utils.check_swift_and_rgw') @mock.patch("heatclient.common.event_utils.get_events") @@ -169,7 +168,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): mock_create_tempest_deployer_input, mock_create_parameters_env, mock_breakpoints_cleanup, - mock_events, mock_stack_network_check, + mock_events, mock_ceph_fsid, mock_swift_rgw, mock_get_undercloud_host_entry, mock_copy, mock_get_ctlplane_attrs, mock_nic_ansiblei, @@ -194,6 +193,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients = self.app.client_manager orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client mock_event = mock.Mock() mock_event.id = '1234' mock_events.return_value = [mock_events] @@ -317,7 +317,9 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): mock_tmpdir.return_value = self.tmp_dir.path clients = self.app.client_manager - + orchestration_client = clients.orchestration + orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client clients.network.api.find_attr.return_value = { "id": "network id" } @@ -372,7 +374,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): @mock.patch('tripleoclient.utils.copy_clouds_yaml') @mock.patch('tripleoclient.utils.get_undercloud_host_entry', autospec=True, return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') - @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files') @mock.patch('tripleoclient.utils.check_ceph_fsid_matches_env_files') @mock.patch('tripleoclient.utils.check_swift_and_rgw') @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @@ -394,7 +395,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): mock_create_parameters_env, mock_validate_args, mock_validate_vip_file, mock_breakpoints_cleanup, - mock_postconfig, mock_stack_network_check, + mock_postconfig, mock_ceph_fsid, mock_swift_rgw, mock_get_undercloud_host_entry, mock_copy, mock_chdir, @@ -421,7 +422,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients = self.app.client_manager orchestration_client = clients.orchestration mock_stack = fakes.create_tht_stack() - orchestration_client.stacks.get.side_effect = [None, mock_stack] + orchestration_client.stacks.get.side_effect = [mock_stack] + utils_fixture.mock_launch_heat.return_value = orchestration_client def _orch_clt_create(**kwargs): orchestration_client.stacks.get.return_value = mock_stack @@ -470,7 +472,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): @mock.patch('tripleoclient.utils.copy_clouds_yaml') @mock.patch('tripleoclient.utils.get_undercloud_host_entry', autospec=True, return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') - @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files') @mock.patch('tripleoclient.utils.check_ceph_fsid_matches_env_files') @mock.patch('tripleoclient.utils.check_swift_and_rgw') @mock.patch("heatclient.common.event_utils.get_events", autospec=True) @@ -486,7 +487,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): mock_create_tempest_deployer_input, mock_deploy_postconfig, mock_breakpoints_cleanup, - mock_events, mock_stack_network_check, + mock_events, mock_ceph_fsid, mock_swift_rgw, mock_get_undercloud_host_entry, mock_copy, mock_nic_ansible, @@ -503,13 +504,15 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): self.useFixture(fixture) utils_fixture = deployment.UtilsFixture() self.useFixture(utils_fixture) - + clients = self.app.client_manager + orchestration_client = clients.orchestration + orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client arglist = ['--templates', '/home/stack/tripleo-heat-templates'] verifylist = [ ('templates', '/home/stack/tripleo-heat-templates'), ] - clients = self.app.client_manager mock_events.return_value = [] clients.network.api.find_attr.return_value = { @@ -566,7 +569,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): autospec=True) @mock.patch('tripleoclient.utils.check_nic_config_with_ansible') @mock.patch('tripleoclient.utils.copy_clouds_yaml') - @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files') @mock.patch('tripleoclient.utils.check_ceph_fsid_matches_env_files') @mock.patch('tripleoclient.utils.check_swift_and_rgw') @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @@ -579,23 +581,21 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): '_heat_deploy', autospec=True) def test_environment_dirs(self, mock_deploy_heat, mock_create_env, mock_update_parameters, mock_post_config, - mock_stack_network_check, mock_ceph_fsid, - mock_swift_rgw, mock_copy, mock_nic_ansible, - mock_process_env, mock_rc_params, - mock_check_service_vip_migr): + mock_ceph_fsid, mock_swift_rgw, mock_copy, + mock_nic_ansible, mock_process_env, + mock_rc_params, mock_check_service_vip_migr): fixture = deployment.DeploymentWorkflowFixture() self.useFixture(fixture) utils_overcloud_fixture = deployment.UtilsOvercloudFixture() self.useFixture(utils_overcloud_fixture) utils_fixture = deployment.UtilsFixture() self.useFixture(utils_fixture) - - clients = self.app.client_manager clients = self.app.client_manager orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() - mock_update_parameters.return_value = {} + utils_fixture.mock_launch_heat.return_value = orchestration_client utils_overcloud_fixture.mock_utils_endpoint.return_value = 'foo.bar' + mock_update_parameters.return_value = {} test_env = os.path.join(self.tmp_dir.path, 'foo1.yaml') @@ -625,7 +625,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): def assertEqual(*args): self.assertEqual(*args) - def _fake_heat_deploy(self, stack, stack_name, template_path, + def _fake_heat_deploy(self, stack_name, template_path, environments, timeout, tht_root, env, run_validations, roles_file, @@ -712,12 +712,12 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): def test_try_overcloud_deploy_with_first_template_existing( self, mock_heat_deploy_func): result = self.cmd._try_overcloud_deploy_with_compat_yaml( - '/fake/path', {}, 'overcloud', ['~/overcloud-env.json'], 1, + '/fake/path', 'overcloud', ['~/overcloud-env.json'], 1, {}, False, None, None) # If it returns None it succeeded self.assertIsNone(result) mock_heat_deploy_func.assert_called_once_with( - self.cmd, {}, 'overcloud', + self.cmd, 'overcloud', '/fake/path/' + constants.OVERCLOUD_YAML_NAME, ['~/overcloud-env.json'], 1, '/fake/path', {}, False, None, deployment_options=None, env_files_tracker=None) @@ -729,7 +729,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): mock_heat_deploy_func.side_effect = Exception('error') self.assertRaises(ValueError, self.cmd._try_overcloud_deploy_with_compat_yaml, - '/fake/path', mock.ANY, mock.ANY, + '/fake/path', mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, None) @@ -741,7 +741,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): Exception('/fake/path not found') try: self.cmd._try_overcloud_deploy_with_compat_yaml( - '/fake/path', mock.ANY, mock.ANY, + '/fake/path', mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, None) except ValueError as value_error: @@ -790,7 +790,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): @mock.patch('tripleoclient.utils.copy_clouds_yaml') @mock.patch('tripleoclient.utils.get_undercloud_host_entry', autospec=True, return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') - @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files') @mock.patch('tripleoclient.utils.check_ceph_fsid_matches_env_files') @mock.patch('tripleoclient.utils.check_swift_and_rgw') @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @@ -798,7 +797,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): @mock.patch('tempfile.mkdtemp', autospec=True) @mock.patch('shutil.rmtree', autospec=True) def test_answers_file(self, mock_rmtree, mock_tmpdir, - mock_heat_deploy, mock_stack_network_check, + mock_heat_deploy, mock_ceph_fsid, mock_swift_rgw, mock_get_undercloud_host_entry, mock_copy, mock_nic_ansible, @@ -816,6 +815,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): self.useFixture(utils_oc_fixture) utils_fixture = deployment.UtilsFixture() self.useFixture(utils_fixture) + utils_fixture.mock_launch_heat.return_value = orchestration_client clients = self.app.client_manager @@ -866,17 +866,16 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): self.cmd.take_action(parsed_args) self.assertTrue(mock_heat_deploy.called) - self.assertTrue(utils_oc_fixture.mock_deploy_tht.called) # Check that Heat was called with correct parameters: call_args = mock_heat_deploy.call_args[0] - self.assertEqual(call_args[3], + self.assertEqual(call_args[2], self.tmp_dir.join( 'tripleo-heat-templates/overcloud.yaml')) - self.assertEqual(call_args[6], + self.assertEqual(call_args[5], self.tmp_dir.join('tripleo-heat-templates')) - self.assertIn('Test', call_args[7]['resource_registry']) - self.assertIn('Test2', call_args[7]['resource_registry']) + self.assertIn('Test', call_args[6]['resource_registry']) + self.assertIn('Test2', call_args[6]['resource_registry']) utils_oc_fixture.mock_deploy_tht.assert_called_with( output_dir=self.cmd.working_dir) @@ -905,7 +904,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): @mock.patch('tripleoclient.utils.copy_clouds_yaml') @mock.patch('tripleoclient.utils.get_undercloud_host_entry', autospec=True, return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') - @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files') @mock.patch('tripleoclient.utils.check_ceph_fsid_matches_env_files') @mock.patch('tripleoclient.utils.check_swift_and_rgw') @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @@ -930,7 +928,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): mock_validate_vip_file, mock_breakpoints_cleanup, mock_deploy_post_config, - mock_stack_network_check, mock_ceph_fsid, mock_swift_rgw, mock_get_undercloud_host_entry, mock_copy, mock_get_ctlplane_attrs, @@ -958,9 +955,9 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): orchestration_client = clients.orchestration mock_stack = fakes.create_tht_stack() orchestration_client.stacks.get.side_effect = [ - None, mock_stack ] + utils_fixture.mock_launch_heat.return_value = orchestration_client def _orch_clt_create(**kwargs): orchestration_client.stacks.get.return_value = mock_stack @@ -1060,6 +1057,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients.compute = mock.Mock() orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client mock_create_env.return_value = ( dict(ContainerHeatApiImage='container-heat-api-image', ContainerHeatEngineImage='container-heat-engine-image'), @@ -1093,6 +1091,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients = self.app.client_manager orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client arglist = ['--templates', '--config-download'] verifylist = [ @@ -1138,6 +1137,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients = self.app.client_manager orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client mock_create_env.return_value = ({}, []) mock_create_env.return_value = ( dict(ContainerHeatApiImage='container-heat-api-image', @@ -1184,6 +1184,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients = self.app.client_manager orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client mock_create_parameters_env.return_value = ( dict(ContainerHeatApiImage='container-heat-api-image', ContainerHeatEngineImage='container-heat-engine-image'), @@ -1233,6 +1234,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients = self.app.client_manager orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client mock_create_parameters_env.return_value = ( dict(ContainerHeatApiImage='container-heat-api-image', ContainerHeatEngineImage='container-heat-engine-image'), @@ -1281,6 +1283,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients = self.app.client_manager orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client arglist = ['--templates', '--override-ansible-cfg', 'ansible.cfg'] @@ -1324,12 +1327,11 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' '_heat_deploy', autospec=True) - @mock.patch('tripleoclient.utils.check_stack_network_matches_env_files') @mock.patch('tripleoclient.utils.check_ceph_fsid_matches_env_files') @mock.patch('tripleoclient.utils.check_swift_and_rgw') @mock.patch('heatclient.common.template_utils.deep_update', autospec=True) def test_config_download_timeout( - self, mock_hc, mock_stack_network_check, + self, mock_hc, mock_ceph_fsid, mock_swift_rgw, mock_hd, mock_get_undercloud_host_entry, mock_copy, mock_get_ctlplane_attrs, mock_nic_ansible, @@ -1347,6 +1349,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): clients = self.app.client_manager orchestration_client = clients.orchestration orchestration_client.stacks.get.return_value = fakes.create_tht_stack() + utils_fixture.mock_launch_heat.return_value = orchestration_client mock_create_parameters_env.return_value = [] arglist = ['--templates', '--overcloud-ssh-port-timeout', '42', @@ -1376,7 +1379,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): self.cmd.take_action(parsed_args) self.assertIn([ mock.call( - mock.ANY, mock.ANY, 'overcloud', mock.ANY, + mock.ANY, 'overcloud', mock.ANY, mock.ANY, 451, mock.ANY, {'parameter_defaults': { 'ContainerHeatApiImage': 'container-heat-api-image', diff --git a/tripleoclient/tests/v1/overcloud_upgrade/test_overcloud_upgrade.py b/tripleoclient/tests/v1/overcloud_upgrade/test_overcloud_upgrade.py index 3d16500be..f5ea2513f 100644 --- a/tripleoclient/tests/v1/overcloud_upgrade/test_overcloud_upgrade.py +++ b/tripleoclient/tests/v1/overcloud_upgrade/test_overcloud_upgrade.py @@ -15,7 +15,6 @@ import mock -from osc_lib import exceptions as oscexc from osc_lib.tests.utils import ParserException from tripleoclient import constants from tripleoclient import exceptions @@ -131,16 +130,6 @@ class TestOvercloudUpgradePrepare(fakes.TestOvercloudUpgradePrepare): mock_usercheck.assert_called_once() mock_overcloud_deploy.assert_called_once_with(parsed_args) - @mock.patch('tripleo_common.update.check_neutron_mechanism_drivers') - def test_upgrade_failed_wrong_driver(self, check_mech): - check_mech.return_value = 'Wrong mech' - mock_stack = mock.Mock(parameters={'DeployIdentifier': ''}) - argslist = (mock_stack, 'mock_stack', '/tmp', {}, - {}, 1, '/tmp', {}, True, False, None) - self.cmd.object_client = mock.Mock() - self.assertRaises(oscexc.CommandError, - self.cmd._heat_deploy, *argslist) - class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun): diff --git a/tripleoclient/utils.py b/tripleoclient/utils.py index f0b75369c..90928e77a 100644 --- a/tripleoclient/utils.py +++ b/tripleoclient/utils.py @@ -1059,7 +1059,7 @@ def get_rc_params(working_dir): return rc_params -def check_ceph_fsid_matches_env_files(stack, environment): +def check_ceph_fsid_matches_env_files(old_env, environment): """Check CephClusterFSID against proposed env files There have been cases where operators inadvertenly changed the @@ -1071,8 +1071,8 @@ def check_ceph_fsid_matches_env_files(stack, environment): """ env_ceph_fsid = environment.get('parameter_defaults', {}).get('CephClusterFSID', False) - stack_ceph_fsid = stack.environment().get('parameter_defaults', - {}).get('CephClusterFSID', False) + stack_ceph_fsid = old_env.get('parameter_defaults', + {}).get('CephClusterFSID', False) if bool(env_ceph_fsid) and env_ceph_fsid != stack_ceph_fsid: raise exceptions.InvalidConfiguration('The CephFSID environment value ' @@ -1086,7 +1086,7 @@ def check_ceph_fsid_matches_env_files(stack, environment): stack_ceph_fsid)) -def check_swift_and_rgw(stack, env, stage): +def check_swift_and_rgw(old_env, env, stage): """Check that Swift and RGW aren't both enabled in the overcloud When Ceph is deployed by TripleO using the default cephadm environment @@ -1108,9 +1108,9 @@ def check_swift_and_rgw(stack, env, stage): if not re.match(allowed_stage, stage) or rgw_env == 'OS::Heat::None': return - sw = stack.environment().get('resource_registry', - {}).get('OS::TripleO::Services::SwiftProxy', - 'OS::Heat::None') + sw = old_env.get('resource_registry', + {}).get('OS::TripleO::Services::SwiftProxy', + 'OS::Heat::None') # RGW is present in the env list and swift was previously deployed if sw != "OS::Heat::None": @@ -1123,22 +1123,11 @@ def check_swift_and_rgw(stack, env, stage): 'RGW)') -def check_nic_config_with_ansible(stack, environment): +def check_nic_config_with_ansible(environment): registry = environment.get('resource_registry', {}) - stack_registry = {} - is_ansible_config_stack = True - if stack: - stack_registry = stack.environment().get( - 'resource_registry', {}) - is_ansible_config_stack = stack.environment().get( - 'parameter_defaults', {}).get( - 'NetworkConfigWithAnsible', True) - is_ansible_config = environment.get( 'parameter_defaults', {}).get( - 'NetworkConfigWithAnsible', is_ansible_config_stack) - - nic_configs_in_update = set() + 'NetworkConfigWithAnsible', True) if is_ansible_config: for k, v in registry.items(): if k.endswith('Net::SoftwareConfig'): @@ -1148,23 +1137,10 @@ def check_nic_config_with_ansible(stack, environment): "Migrate to ansible jinja templates or use " "'NetworkConfigWithAnsible: false' " "in 'parameter_defaults'.") - nic_configs_in_update.add(k) - for k, v in stack_registry.items(): - if (k.endswith('Net::SoftwareConfig') and v != 'OS::Heat::None' - and k not in nic_configs_in_update): - raise exceptions.InvalidConfiguration( - "DEPRECATED: Old heat nic configs are used, " - "Migrate to ansible jinja templates or use " - "'NetworkConfigWithAnsible: false' " - "in 'parameter_defaults'.") -def check_service_vips_migrated_to_service(stack, environment): +def check_service_vips_migrated_to_service(environment): registry = environment.get('resource_registry', {}) - stack_registry = {} - if stack: - stack_registry = stack.environment().get( - 'resource_registry', {}) removed_resources = {'OS::TripleO::Network::Ports::RedisVipPort', 'OS::TripleO::Network::Ports::OVNDBsVipPort'} msg = ("Resources 'OS::TripleO::Network::Ports::RedisVipPort' and " @@ -1176,47 +1152,11 @@ def check_service_vips_migrated_to_service(stack, environment): "'ServiceNetMap' and/or 'VipSubnetMap' parameters with the desired " "network and/or subnet for the service.") for resource in removed_resources: - if resource in registry or resource in stack_registry: + if (resource in registry and + registry.get(resource) != 'OS::Heat::None'): raise exceptions.InvalidConfiguration(msg) -def check_stack_network_matches_env_files(stack, environment): - """Check stack against proposed env files to ensure non-breaking change - - Historically we have have had issues with folks forgetting the network - isolation templates in subsequent overcloud actions which have completely - broken the stack. We need to check that the networks continue to be - provided on updates and if they aren't, it's likely that the user has - failed to provide the network-isolation templates. This is a light check - to only ensure they are defined. A user can still change settings in these - networks that may break things but this will catch folks who forget - network-isolation in a subsequent update. - """ - def _get_networks(registry): - nets = set() - for k, v in registry.items(): - if (k.startswith('OS::TripleO::Network::') - and not k.startswith('OS::TripleO::Network::Port') - and v != 'OS::Heat::None'): - nets.add(k) - return nets - - stack_registry = stack.environment().get('resource_registry', {}) - env_registry = environment.get('resource_registry', {}) - - stack_nets = _get_networks(stack_registry) - env_nets = _get_networks(env_registry) - - env_diff = set(stack_nets) - set(env_nets) - if env_diff: - raise exceptions.InvalidConfiguration('Missing networks from ' - 'environment configuration. ' - 'Ensure the following networks ' - 'are properly configured in ' - 'the provided environment files ' - '[{}]'.format(env_diff)) - - def remove_known_hosts(overcloud_ip): """For a given IP address remove SSH keys from the known_hosts file""" @@ -3063,7 +3003,9 @@ def parse_ansible_inventory(inventory_file, group): return(inventory.get_hosts(pattern=group)) -def save_stack_outputs(heat, stack, working_dir): +def save_stack(stack, working_dir): + if not stack: + return outputs_dir = os.path.join(working_dir, 'outputs') makedirs(outputs_dir) for output in constants.STACK_OUTPUTS: @@ -3071,6 +3013,24 @@ def save_stack_outputs(heat, stack, working_dir): output_path = os.path.join(outputs_dir, output) with open(output_path, 'w') as f: f.write(yaml.dump(val)) + env_dir = os.path.join(working_dir, 'environment') + makedirs(env_dir) + env = stack.environment() + env_path = os.path.join( + env_dir, + constants.STACK_ENV_FILE_NAME.format(stack.stack_name)) + with open(env_path, 'w') as f: + f.write(yaml.dump(env)) + + +def get_saved_stack_env(working_dir, stack_name): + env_path = os.path.join( + working_dir, 'environment', + constants.STACK_ENV_FILE_NAME.format(stack_name)) + if not os.path.isfile(env_path): + return None + with open(env_path) as f: + return yaml.safe_load(f.read()) def get_ceph_networks(network_data_path, diff --git a/tripleoclient/v1/overcloud_deploy.py b/tripleoclient/v1/overcloud_deploy.py index ea93e18bc..8d4a57759 100644 --- a/tripleoclient/v1/overcloud_deploy.py +++ b/tripleoclient/v1/overcloud_deploy.py @@ -31,7 +31,6 @@ from keystoneauth1.exceptions.catalog import EndpointNotFound from osc_lib import exceptions as oscexc from osc_lib.i18n import _ from tripleo_common.image import kolla_builder -from tripleo_common import update from tripleo_common.utils import plan as plan_utils from tripleoclient import command @@ -127,7 +126,7 @@ class DeployOvercloud(command.Command): 'be ignored because --limit has been specified.') self.log.warning(msg) - def _heat_deploy(self, stack, stack_name, template_path, + def _heat_deploy(self, stack_name, template_path, env_files, timeout, tht_root, env, run_validations, roles_file, @@ -135,15 +134,6 @@ class DeployOvercloud(command.Command): deployment_options=None): """Verify the Baremetal nodes are available and do a stack update""" - if stack: - self.log.debug( - "Checking compatibilities of neutron drivers for {0}".format( - stack_name)) - msg = update.check_neutron_mechanism_drivers( - env, stack, None, stack_name) - if msg: - raise oscexc.CommandError(msg) - self.log.debug("Getting template contents from plan %s" % stack_name) template_files, template = template_utils.get_template_contents( @@ -161,7 +151,7 @@ class DeployOvercloud(command.Command): self.log.info("Deploying templates in the directory {0}".format( os.path.abspath(tht_root))) deployment.deploy_without_plan( - self.clients, stack, stack_name, + self.clients, stack_name, template, files, env_files_tracker, self.log, self.working_dir) @@ -209,7 +199,7 @@ class DeployOvercloud(command.Command): env, roles_data, dry_run=True)) return params - def create_env_files(self, stack, parsed_args, + def create_env_files(self, parsed_args, new_tht_root, user_tht_root): self.log.debug("Creating Environment files") # A dictionary to store resource registry types that are internal, @@ -224,18 +214,10 @@ class DeployOvercloud(command.Command): self._update_parameters( parsed_args, parameters, new_tht_root, user_tht_root) - stack_is_new = stack is None - parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE' - param_env = utils.create_parameters_env( parameters, new_tht_root, parsed_args.stack) created_env_files.extend(param_env) - if stack: - env_path = utils.create_breakpoint_cleanup_env( - new_tht_root, parsed_args.stack) - created_env_files.extend(env_path) - if parsed_args.deployed_server: created_env_files.append( os.path.join( @@ -275,7 +257,7 @@ class DeployOvercloud(command.Command): return created_env_files - def deploy_tripleo_heat_templates(self, stack, parsed_args, + def deploy_tripleo_heat_templates(self, parsed_args, new_tht_root, user_tht_root, created_env_files): """Deploy the fixed templates in TripleO Heat Templates""" @@ -320,10 +302,10 @@ class DeployOvercloud(command.Command): # warning if necessary self._check_limit_skiplist_warning(env) - if stack: + old_stack_env = utils.get_saved_stack_env( + self.working_dir, parsed_args.stack) + if old_stack_env: if not parsed_args.disable_validations: - # note(aschultz): network validation goes here before we deploy - utils.check_stack_network_matches_env_files(stack, env) ceph_deployed = env.get('resource_registry', {}).get( 'OS::TripleO::Services::CephMon', 'OS::Heat::None') ceph_external = env.get('resource_registry', {}).get( @@ -333,17 +315,17 @@ class DeployOvercloud(command.Command): # make this check and we can simply ignore it if (ceph_deployed != "OS::Heat::None" or ceph_external != "OS::Heat::None"): - utils.check_ceph_fsid_matches_env_files(stack, env) + utils.check_ceph_fsid_matches_env_files(old_stack_env, env) # upgrades: check if swift is deployed - utils.check_swift_and_rgw(stack, env, + utils.check_swift_and_rgw(old_stack_env, env, self.__class__.__name__) # check migration to new nic config with ansible - utils.check_nic_config_with_ansible(stack, env) + utils.check_nic_config_with_ansible(env) # check migration to service vips managed by servce - utils.check_service_vips_migrated_to_service(stack, env) + utils.check_service_vips_migrated_to_service(env) self._try_overcloud_deploy_with_compat_yaml( - new_tht_root, stack, + new_tht_root, parsed_args.stack, env_files, parsed_args.timeout, env, parsed_args.run_validations, @@ -371,7 +353,7 @@ class DeployOvercloud(command.Command): "user-environments/{}".format(os.path.basename(path))) utils.safe_write(reloc_path, files_dict[fullpath]) - def _try_overcloud_deploy_with_compat_yaml(self, tht_root, stack, + def _try_overcloud_deploy_with_compat_yaml(self, tht_root, stack_name, env_files, timeout, env, run_validations, @@ -380,7 +362,7 @@ class DeployOvercloud(command.Command): deployment_options=None): overcloud_yaml = os.path.join(tht_root, constants.OVERCLOUD_YAML_NAME) try: - self._heat_deploy(stack, stack_name, overcloud_yaml, + self._heat_deploy(stack_name, overcloud_yaml, env_files, timeout, tht_root, env, run_validations, @@ -1158,13 +1140,12 @@ class DeployOvercloud(command.Command): return self.heat_launcher = None - stack = None start = time.time() new_tht_root, user_tht_root = \ self.create_template_dirs(parsed_args) created_env_files = self.create_env_files( - stack, parsed_args, new_tht_root, user_tht_root) + parsed_args, new_tht_root, user_tht_root) # full_deploy means we're doing a full deployment # e.g., no --*-only args were passed @@ -1205,13 +1186,12 @@ class DeployOvercloud(command.Command): self.setup_ephemeral_heat(parsed_args) self.deploy_tripleo_heat_templates( - stack, parsed_args, new_tht_root, + parsed_args, new_tht_root, user_tht_root, created_env_files) stack = utils.get_stack( self.orchestration_client, parsed_args.stack) - utils.save_stack_outputs( - self.orchestration_client, stack, self.working_dir) + utils.save_stack(stack, self.working_dir) horizon_url = deployment.get_horizon_url( stack=stack.stack_name, diff --git a/tripleoclient/workflows/deployment.py b/tripleoclient/workflows/deployment.py index 03d95d6f9..5eb36ff9d 100644 --- a/tripleoclient/workflows/deployment.py +++ b/tripleoclient/workflows/deployment.py @@ -16,7 +16,6 @@ import os import shutil import yaml -from heatclient.common import event_utils from openstackclient import shell from tripleo_common.utils import heat as tc_heat_utils from tripleo_common.utils import overcloudrc as rc_utils @@ -44,26 +43,13 @@ def create_overcloudrc(stack_name, endpoint, admin_vip, rc_params, return os.path.abspath(rcpath) -def deploy_without_plan(clients, stack, stack_name, template, +def deploy_without_plan(clients, stack_name, template, files, env_files, log, working_dir): orchestration_client = clients.orchestration - if stack is None: - log.info("Performing Heat stack create") - action = 'CREATE' - marker = None - else: - log.info("Performing Heat stack update") - # Make sure existing parameters for stack are reused - # Find the last top-level event to use for the first marker - events = event_utils.get_events(orchestration_client, - stack_id=stack_name, - event_args={'sort_dir': 'desc', - 'limit': 1}) - marker = events[0].id if events else None - action = 'UPDATE' - + log.info("Performing Heat stack create") + marker = None set_deployment_status(stack_name, status='DEPLOYING', working_dir=working_dir) @@ -73,12 +59,7 @@ def deploy_without_plan(clients, stack, stack_name, template, 'environment_files': env_files, 'files': files} try: - if stack: - stack_args['existing'] = True - orchestration_client.stacks.update(stack.id, **stack_args) - else: - stack = orchestration_client.stacks.create(**stack_args) - + orchestration_client.stacks.create(**stack_args) print("Success.") except Exception: set_deployment_status(stack_name, @@ -87,7 +68,7 @@ def deploy_without_plan(clients, stack, stack_name, template, raise create_result = utils.wait_for_stack_ready( - orchestration_client, stack_name, marker, action) + orchestration_client, stack_name, marker) if not create_result: shell.OpenStackShell().run( ["stack", "failures", "list", '--long', stack_name]) @@ -96,10 +77,7 @@ def deploy_without_plan(clients, stack, stack_name, template, status='DEPLOY_FAILED', working_dir=working_dir ) - if stack is None: - raise exceptions.DeploymentError("Heat Stack create failed.") - else: - raise exceptions.DeploymentError("Heat Stack update failed.") + raise exceptions.DeploymentError("Heat Stack create failed.") def get_overcloud_hosts(stack, ssh_network, working_dir):