Browse Source

Merge "Refactor deploy validations for ephemeral heat"

changes/27/839727/11
Zuul 1 month ago committed by Gerrit Code Review
parent
commit
b640b16428
  1. 1
      tripleoclient/constants.py
  2. 141
      tripleoclient/tests/test_utils.py
  3. 1
      tripleoclient/tests/v1/overcloud_deploy/fakes.py
  4. 70
      tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py
  5. 11
      tripleoclient/tests/v1/overcloud_upgrade/test_overcloud_upgrade.py
  6. 105
      tripleoclient/utils.py
  7. 59
      tripleoclient/v1/overcloud_deploy.py
  8. 34
      tripleoclient/workflows/deployment.py

1
tripleoclient/constants.py

@ -299,6 +299,7 @@ KIND_TEMPLATES = {'roles': WD_DEFAULT_ROLES_FILE_NAME,
'baremetal': WD_DEFAULT_BAREMETAL_FILE_NAME,
'vips': WD_DEFAULT_VIP_FILE_NAME}
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

141
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,10 +766,10 @@ 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_ceph_ansible(self):
res_reg = {
'resource_registry': {
'OS::Tripleo::Services::CephMon': '/path/to/ceph-ansible.yml',
@ -900,7 +782,6 @@ class TestWaitForStackUtil(TestCase):
'UpgradeConverge')
def test_check_ceph_ansible_fail(self):
res_reg = {
'resource_registry': {
'OS::Tripleo::Services::CephMon': '/path/to/ceph-ansible.yml',
@ -927,7 +808,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 = {
@ -945,7 +827,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')

1
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

70
tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py

@ -161,7 +161,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.utils.check_ceph_ansible')
@ -177,7 +176,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_ceph_ansible,
mock_get_undercloud_host_entry, mock_copy,
@ -203,6 +202,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]
@ -325,7 +325,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"
}
@ -380,7 +382,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.utils.check_ceph_ansible')
@ -401,7 +402,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_ceph_ansible,
mock_get_undercloud_host_entry, mock_copy,
mock_chdir,
@ -429,7 +430,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
@ -478,7 +480,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.utils.check_ceph_ansible')
@ -495,7 +496,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_ceph_ansible,
mock_get_undercloud_host_entry,
@ -513,13 +514,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 = {
@ -576,7 +579,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.utils.check_ceph_ansible')
@ -590,7 +592,7 @@ 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_ceph_fsid,
mock_swift_rgw, mock_ceph_ansible,
mock_copy, mock_nic_ansible,
mock_process_env, mock_rc_params,
@ -601,13 +603,12 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
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')
@ -637,7 +638,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,
@ -724,12 +725,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)
@ -741,7 +742,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_heat_deploy_func.side_effect = oscexc.CommandError('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)
@ -753,7 +754,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
oscexc.CommandError('/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:
@ -802,7 +803,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.utils.check_ceph_ansible')
@ -811,7 +811,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_ceph_ansible,
mock_get_undercloud_host_entry,
@ -832,6 +832,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
@ -884,17 +885,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)
@ -923,7 +923,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.utils.check_ceph_ansible')
@ -947,7 +946,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_ceph_ansible,
mock_get_undercloud_host_entry, mock_copy,
@ -976,9 +974,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
@ -1078,6 +1076,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'),
@ -1111,6 +1110,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 = [
@ -1156,6 +1156,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',
@ -1202,6 +1203,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'),
@ -1251,6 +1253,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'),
@ -1299,6 +1302,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']
@ -1342,13 +1346,12 @@ 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('tripleoclient.utils.check_ceph_ansible')
@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_ceph_ansible,
mock_hd, mock_get_undercloud_host_entry, mock_copy,
mock_get_ctlplane_attrs, mock_nic_ansible,
@ -1366,6 +1369,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',
@ -1395,7 +1399,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',

11
tripleoclient/tests/v1/overcloud_upgrade/test_overcloud_upgrade.py

@ -15,7 +15,6 @@
from unittest import mock
from osc_lib import exceptions as oscexc
from osc_lib.tests.utils import ParserException
from tripleoclient import constants
from tripleoclient import exceptions
@ -128,16 +127,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):

105
tripleoclient/utils.py

@ -1077,7 +1077,7 @@ def check_ceph_ansible(resource_registry, stage):
'file.')
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
@ -1089,8 +1089,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 '
@ -1104,7 +1104,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
@ -1126,9 +1126,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":
@ -1141,22 +1141,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'):
@ -1166,23 +1155,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 "
@ -1194,7 +1170,7 @@ 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) and
if (resource in registry and
registry.get(resource) != 'OS::Heat::None'):
raise exceptions.InvalidConfiguration(msg)
@ -1213,43 +1189,6 @@ def check_neutron_resources(environment):
raise exceptions.InvalidConfiguration(msg.format(rsrc, rsrc_type))
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"""
@ -3239,7 +3178,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:
@ -3247,6 +3188,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,

59
tripleoclient/v1/overcloud_deploy.py

@ -29,7 +29,6 @@ import yaml
from heatclient.common import template_utils
from osc_lib import exceptions as oscexc
from osc_lib.i18n import _
from tripleo_common import update
from tripleo_common.utils import plan as plan_utils
from tripleoclient import command
@ -204,7 +203,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,
@ -212,15 +211,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(
@ -238,7 +228,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)
@ -261,7 +251,7 @@ class DeployOvercloud(command.Command):
base_path=new_tht_root)
return new_tht_root, tht_root
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,
@ -277,18 +267,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(
@ -328,7 +310,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"""
@ -373,10 +355,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(
@ -386,21 +368,22 @@ 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(env)
# check migration to service vips managed by servce
utils.check_service_vips_migrated_to_service(env)
# check if ceph-ansible env is present
utils.check_ceph_ansible(env.get('resource_registry', {}),
self.__class__.__name__)
# check migration to new nic config with ansible
utils.check_nic_config_with_ansible(stack, env)
# check migration to service vips managed by servce
utils.check_service_vips_migrated_to_service(stack, env)
utils.check_neutron_resources(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,
@ -410,7 +393,7 @@ class DeployOvercloud(command.Command):
self._unprovision_baremetal(parsed_args)
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,
@ -419,7 +402,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,
@ -1096,13 +1079,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
@ -1143,13 +1125,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,

34
tripleoclient/workflows/deployment.py

@ -17,7 +17,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):

Loading…
Cancel
Save