Support using ephemeral Heat

This patch begins to add support for using the ephemeral Heat process
to the overcloud deploy command.

The functionality is enabled with the newly added --heat-type cli arg,
which can be used to select the heat type to be used by the deployment
playbooks and modules.  The options are:

installed: current behavior using Heat installed on the undercloud
pod: ephemeral Heat podman pod (heat-api/engine)
container: ephemeral Heat podman container (heat-all)
native: ephemeral Heat native heat-all process

The default is "installed" initially to preserve the existing
functionality.

Signed-off-by: James Slagle <jslagle@redhat.com>
Implements: blueprint ephemeral-heat-overcloud
Change-Id: I8fb6ca088b1052488ff4f9ada4d3ab29c0be4735
This commit is contained in:
James Slagle 2021-04-20 09:37:05 -04:00
parent 7a1c4e2b0b
commit e8f53ae778
8 changed files with 319 additions and 191 deletions

View File

@ -0,0 +1,7 @@
---
features:
- |
A new cli argument, --heat-type is added to openstack overcloud deploy.
Available options are "installed", "pod", "container", and "native". The
default is "installed". The argument specifies the type of Heat process to
use for the deployment.

View File

@ -54,6 +54,7 @@ DEFAULT_HEAT_ENGINE_CONTAINER = ('{}/{}/openstack-heat-engine:{}'.format(
USER_PARAMETERS = 'user-environments/tripleoclient-parameters.yaml' USER_PARAMETERS = 'user-environments/tripleoclient-parameters.yaml'
PASSWORDS_ENV_FORMAT = '{}-passwords.yaml'
# This directory may contain additional environments to use during deploy # This directory may contain additional environments to use during deploy
DEFAULT_ENV_DIRECTORY = os.path.join(os.environ.get('HOME', '~/'), DEFAULT_ENV_DIRECTORY = os.path.join(os.environ.get('HOME', '~/'),

View File

@ -125,6 +125,7 @@ class HeatBaseLauncher(object):
user='heat', user='heat',
heat_dir='/var/log/heat-launcher', heat_dir='/var/log/heat-launcher',
use_tmp_dir=True, use_tmp_dir=True,
use_root=False,
rm_heat=False, rm_heat=False,
skip_heat_pull=False): skip_heat_pull=False):
self.api_port = api_port self.api_port = api_port
@ -197,11 +198,12 @@ class HeatBaseLauncher(object):
self._write_fake_keystone_token(self.api_port, self.token_file) self._write_fake_keystone_token(self.api_port, self.token_file)
self._write_heat_config() self._write_heat_config()
self._write_api_paste_config() self._write_api_paste_config()
uid = int(self.get_heat_uid()) if use_root:
gid = int(self.get_heat_gid()) uid = int(self.get_heat_uid())
os.chown(self.install_dir, uid, gid) gid = int(self.get_heat_gid())
os.chown(self.config_file, uid, gid) os.chown(self.install_dir, uid, gid)
os.chown(self.paste_file, uid, gid) os.chown(self.config_file, uid, gid)
os.chown(self.paste_file, uid, gid)
def _write_heat_config(self): def _write_heat_config(self):
# TODO(ksambor) It will be nice to have possibilities to configure heat # TODO(ksambor) It will be nice to have possibilities to configure heat

View File

@ -259,10 +259,11 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'_validate_args') '_validate_args')
@mock.patch('heatclient.common.template_utils.get_template_contents', @mock.patch('heatclient.common.template_utils.get_template_contents',
autospec=True) autospec=True)
@mock.patch('os.chmod', autospec=True)
@mock.patch('os.chdir', autospec=True) @mock.patch('os.chdir', autospec=True)
@mock.patch('tempfile.mkdtemp', autospec=True) @mock.patch('tempfile.mkdtemp', autospec=True)
@mock.patch('tripleoclient.utils.makedirs') @mock.patch('tripleoclient.utils.makedirs')
def test_tht_deploy(self, mock_md, mock_tmpdir, mock_cd, def test_tht_deploy(self, mock_md, mock_tmpdir, mock_cd, mock_chmod,
mock_get_template_contents, mock_validate_args, mock_get_template_contents, mock_validate_args,
mock_breakpoints_cleanup, mock_postconfig, mock_breakpoints_cleanup, mock_postconfig,
mock_invoke_plan_env_wf, mock_invoke_plan_env_wf,
@ -505,8 +506,10 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_copy.assert_called_once() mock_copy.assert_called_once()
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates', autospec=True) 'create_params_and_env_files', autospec=True)
def test_jinja2_env_path(self, mock_deploy_tht): @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'deploy_tripleo_heat_templates', autospec=True)
def test_jinja2_env_path(self, mock_deploy_tht, mock_create_env):
arglist = ['--templates', '-e', 'bad_path.j2.yaml', '-e', 'other.yaml', arglist = ['--templates', '-e', 'bad_path.j2.yaml', '-e', 'other.yaml',
'-e', 'bad_path2.j2.yaml'] '-e', 'bad_path2.j2.yaml']
@ -533,9 +536,11 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'_deploy_postconfig', autospec=True) '_deploy_postconfig', autospec=True)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_update_parameters', autospec=True) '_update_parameters', autospec=True)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'create_params_and_env_files', autospec=True)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_heat_deploy', autospec=True) '_heat_deploy', autospec=True)
def test_environment_dirs(self, mock_deploy_heat, def test_environment_dirs(self, mock_deploy_heat, mock_create_env,
mock_update_parameters, mock_post_config, mock_update_parameters, mock_post_config,
mock_stack_network_check, mock_ceph_fsid, mock_stack_network_check, mock_ceph_fsid,
mock_copy, mock_nic_ansible, mock_copy, mock_nic_ansible,
@ -593,6 +598,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_rc_params.return_value = {'password': 'password', mock_rc_params.return_value = {'password': 'password',
'region': 'region1'} 'region': 'region1'}
mock_deploy_heat.side_effect = _fake_heat_deploy mock_deploy_heat.side_effect = _fake_heat_deploy
mock_create_env.return_value = ({}, [])
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
mock_copy.assert_called_once() mock_copy.assert_called_once()
@ -700,8 +706,10 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'_get_undercloud_host_entry', autospec=True, '_get_undercloud_host_entry', autospec=True,
return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates', autospec=True) 'create_params_and_env_files', autospec=True)
def test_dry_run(self, mock_create_tempest_deployer_input, @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'deploy_tripleo_heat_templates', autospec=True)
def test_dry_run(self, mock_deploy, mock_create_env,
mock_get_undercloud_host_entry): mock_get_undercloud_host_entry):
utils_fixture = deployment.UtilsOvercloudFixture() utils_fixture = deployment.UtilsOvercloudFixture()
self.useFixture(utils_fixture) self.useFixture(utils_fixture)
@ -715,10 +723,11 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
('dry_run', True), ('dry_run', True),
] ]
mock_create_env.return_value = ({}, [])
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
self.assertFalse(utils_fixture.mock_deploy_tht.called) self.assertFalse(utils_fixture.mock_deploy_tht.called)
self.assertFalse(mock_create_tempest_deployer_input.called) self.assertFalse(mock_deploy.called)
@mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service') @mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service')
@mock.patch('tripleoclient.utils.get_rc_params', autospec=True) @mock.patch('tripleoclient.utils.get_rc_params', autospec=True)
@ -1017,8 +1026,10 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'_get_undercloud_host_entry', autospec=True, '_get_undercloud_host_entry', autospec=True,
return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates_tmpdir', autospec=True) 'create_params_and_env_files', autospec=True)
def test_deployed_server(self, mock_deploy_tmpdir, @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'deploy_tripleo_heat_templates', autospec=True)
def test_deployed_server(self, mock_deploy, mock_create_env,
mock_get_undercloud_host_entry, mock_get_undercloud_host_entry,
mock_copy, mock_rc_params): mock_copy, mock_rc_params):
fixture = deployment.DeploymentWorkflowFixture() fixture = deployment.DeploymentWorkflowFixture()
@ -1039,9 +1050,10 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
clients.compute = mock.Mock() clients.compute = mock.Mock()
orchestration_client = clients.orchestration orchestration_client = clients.orchestration
orchestration_client.stacks.get.return_value = fakes.create_tht_stack() orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
mock_create_env.return_value = ({}, [])
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
self.assertTrue(mock_deploy_tmpdir.called) self.assertTrue(mock_deploy.called)
self.assertNotCalled(clients.baremetal) self.assertNotCalled(clients.baremetal)
self.assertNotCalled(clients.compute) self.assertNotCalled(clients.compute)
self.assertTrue(utils_fixture.mock_deploy_tht.called) self.assertTrue(utils_fixture.mock_deploy_tht.called)
@ -1053,9 +1065,11 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'_get_undercloud_host_entry', autospec=True, '_get_undercloud_host_entry', autospec=True,
return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates_tmpdir', autospec=True) 'create_params_and_env_files', autospec=True)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'deploy_tripleo_heat_templates', autospec=True)
def test_config_download( def test_config_download(
self, mock_deploy_tmpdir, self, mock_deploy, mock_create_env,
mock_get_undercloud_host_entry, mock_get_undercloud_host_entry,
mock_copy, mock_rc_params): mock_copy, mock_rc_params):
fixture = deployment.DeploymentWorkflowFixture() fixture = deployment.DeploymentWorkflowFixture()
@ -1074,8 +1088,9 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
mock_rc_params.return_value = {'password': 'password', mock_rc_params.return_value = {'password': 'password',
'region': 'region1'} 'region': 'region1'}
mock_create_env.return_value = ({}, [])
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
self.assertTrue(mock_deploy_tmpdir.called) self.assertTrue(mock_deploy.called)
self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called) self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called)
self.assertTrue(fixture.mock_config_download.called) self.assertTrue(fixture.mock_config_download.called)
self.assertTrue(fixture.mock_set_deployment_status.called) self.assertTrue(fixture.mock_set_deployment_status.called)
@ -1091,9 +1106,11 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'_get_undercloud_host_entry', autospec=True, '_get_undercloud_host_entry', autospec=True,
return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates_tmpdir', autospec=True) 'create_params_and_env_files', autospec=True)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'deploy_tripleo_heat_templates', autospec=True)
def test_config_download_setup_only( def test_config_download_setup_only(
self, mock_deploy_tmpdir, self, mock_deploy, mock_create_env,
mock_get_undercloud_host_entry, mock_get_undercloud_host_entry,
mock_copy, mock_rc_params): mock_copy, mock_rc_params):
fixture = deployment.DeploymentWorkflowFixture() fixture = deployment.DeploymentWorkflowFixture()
@ -1103,6 +1120,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
clients = self.app.client_manager clients = self.app.client_manager
orchestration_client = clients.orchestration orchestration_client = clients.orchestration
orchestration_client.stacks.get.return_value = fakes.create_tht_stack() orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
mock_create_env.return_value = ({}, [])
arglist = ['--templates', '--config-download', '--setup-only'] arglist = ['--templates', '--config-download', '--setup-only']
verifylist = [ verifylist = [
@ -1114,7 +1132,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_rc_params.return_value = {'password': 'password', mock_rc_params.return_value = {'password': 'password',
'region': 'region1'} 'region': 'region1'}
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
self.assertTrue(mock_deploy_tmpdir.called)
self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called) self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called)
self.assertTrue(fixture.mock_config_download.called) self.assertTrue(fixture.mock_config_download.called)
self.assertTrue(fixture.mock_set_deployment_status.called) self.assertTrue(fixture.mock_set_deployment_status.called)
@ -1124,17 +1141,20 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
) )
mock_copy.assert_called_once() mock_copy.assert_called_once()
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'create_params_and_env_files', autospec=True)
@mock.patch('tripleoclient.utils.get_rc_params', autospec=True) @mock.patch('tripleoclient.utils.get_rc_params', autospec=True)
@mock.patch('tripleoclient.utils.copy_clouds_yaml') @mock.patch('tripleoclient.utils.copy_clouds_yaml')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_get_undercloud_host_entry', autospec=True, '_get_undercloud_host_entry', autospec=True,
return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates_tmpdir', autospec=True) 'deploy_tripleo_heat_templates', autospec=True)
def test_config_download_only( def test_config_download_only(
self, mock_deploy_tmpdir, self, mock_deploy,
mock_get_undercloud_host_entry, mock_get_undercloud_host_entry,
mock_copy, mock_rc_params): mock_copy, mock_rc_params,
mock_create_parameters_env):
fixture = deployment.DeploymentWorkflowFixture() fixture = deployment.DeploymentWorkflowFixture()
self.useFixture(fixture) self.useFixture(fixture)
utils_fixture = deployment.UtilsOvercloudFixture() utils_fixture = deployment.UtilsOvercloudFixture()
@ -1142,6 +1162,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
clients = self.app.client_manager clients = self.app.client_manager
orchestration_client = clients.orchestration orchestration_client = clients.orchestration
orchestration_client.stacks.get.return_value = fakes.create_tht_stack() orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
mock_create_parameters_env.return_value = (mock.Mock(), mock.Mock())
arglist = ['--templates', '--config-download-only'] arglist = ['--templates', '--config-download-only']
verifylist = [ verifylist = [
@ -1153,7 +1174,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'region': 'region1'} 'region': 'region1'}
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
self.assertFalse(mock_deploy_tmpdir.called) self.assertFalse(mock_deploy.called)
self.assertFalse(fixture.mock_get_hosts_and_enable_ssh_admin.called) self.assertFalse(fixture.mock_get_hosts_and_enable_ssh_admin.called)
self.assertTrue(fixture.mock_config_download.called) self.assertTrue(fixture.mock_config_download.called)
self.assertTrue(fixture.mock_set_deployment_status.called) self.assertTrue(fixture.mock_set_deployment_status.called)
@ -1162,6 +1183,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
fixture.mock_set_deployment_status.call_args[-1]['status']) fixture.mock_set_deployment_status.call_args[-1]['status'])
mock_copy.assert_called_once() mock_copy.assert_called_once()
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'create_params_and_env_files', autospec=True)
@mock.patch('tripleoclient.utils.get_rc_params', autospec=True) @mock.patch('tripleoclient.utils.get_rc_params', autospec=True)
@mock.patch('tripleoclient.utils.copy_clouds_yaml') @mock.patch('tripleoclient.utils.copy_clouds_yaml')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
@ -1171,18 +1194,20 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
autospec=True) autospec=True)
@mock.patch('tripleoclient.utils.get_overcloud_endpoint', autospec=True) @mock.patch('tripleoclient.utils.get_overcloud_endpoint', autospec=True)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates_tmpdir', autospec=True) 'deploy_tripleo_heat_templates', autospec=True)
def test_config_download_fails( def test_config_download_fails(
self, mock_deploy_tmpdir, self, mock_deploy,
mock_overcloud_endpoint, mock_overcloud_endpoint,
mock_create_tempest_deployer_input, mock_create_tempest_deployer_input,
mock_get_undercloud_host_entry, mock_get_undercloud_host_entry,
mock_copy, mock_rc_params): mock_copy, mock_rc_params,
mock_create_parameters_env):
fixture = deployment.DeploymentWorkflowFixture() fixture = deployment.DeploymentWorkflowFixture()
self.useFixture(fixture) self.useFixture(fixture)
clients = self.app.client_manager clients = self.app.client_manager
orchestration_client = clients.orchestration orchestration_client = clients.orchestration
orchestration_client.stacks.get.return_value = fakes.create_tht_stack() orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
mock_create_parameters_env.return_value = (mock.Mock(), mock.Mock())
arglist = ['--templates', '--config-download-only'] arglist = ['--templates', '--config-download-only']
verifylist = [ verifylist = [
@ -1199,7 +1224,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
exceptions.DeploymentError, exceptions.DeploymentError,
self.cmd.take_action, self.cmd.take_action,
parsed_args) parsed_args)
self.assertFalse(mock_deploy_tmpdir.called) self.assertFalse(mock_deploy.called)
self.assertTrue(fixture.mock_config_download.called) self.assertTrue(fixture.mock_config_download.called)
self.assertTrue(fixture.mock_set_deployment_status.called) self.assertTrue(fixture.mock_set_deployment_status.called)
self.assertEqual( self.assertEqual(
@ -1212,9 +1237,11 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'_get_undercloud_host_entry', autospec=True, '_get_undercloud_host_entry', autospec=True,
return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates_tmpdir', autospec=True) 'create_params_and_env_files', autospec=True)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'deploy_tripleo_heat_templates', autospec=True)
def test_override_ansible_cfg( def test_override_ansible_cfg(
self, mock_deploy_tmpdir, self, mock_deploy, mock_create_env,
mock_get_undercloud_host_entry, mock_get_undercloud_host_entry,
mock_copy, mock_rc_params): mock_copy, mock_rc_params):
fixture = deployment.DeploymentWorkflowFixture() fixture = deployment.DeploymentWorkflowFixture()
@ -1235,11 +1262,14 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_rc_params.return_value = {'password': 'password', mock_rc_params.return_value = {'password': 'password',
'region': 'region1'} 'region': 'region1'}
mock_create_env.return_value = ({}, [])
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called) self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called)
self.assertTrue(fixture.mock_config_download.called) self.assertTrue(fixture.mock_config_download.called)
mock_copy.assert_called_once() mock_copy.assert_called_once()
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'create_params_and_env_files', autospec=True)
@mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service') @mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service')
@mock.patch('tripleo_common.utils.plan.default_image_params', @mock.patch('tripleo_common.utils.plan.default_image_params',
autospec=True) autospec=True)
@ -1273,7 +1303,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_process_env, mock_roles_data, mock_process_env, mock_roles_data,
mock_container_prepare, mock_generate_password, mock_container_prepare, mock_generate_password,
mock_rc_params, mock_default_image_params, mock_rc_params, mock_default_image_params,
mock_check_service_vip_migr): mock_check_service_vip_migr,
mock_create_parameters_env):
fixture = deployment.DeploymentWorkflowFixture() fixture = deployment.DeploymentWorkflowFixture()
self.useFixture(fixture) self.useFixture(fixture)
utils_fixture = deployment.UtilsOvercloudFixture() utils_fixture = deployment.UtilsOvercloudFixture()
@ -1281,6 +1312,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
clients = self.app.client_manager clients = self.app.client_manager
orchestration_client = clients.orchestration orchestration_client = clients.orchestration
orchestration_client.stacks.get.return_value = fakes.create_tht_stack() orchestration_client.stacks.get.return_value = fakes.create_tht_stack()
mock_create_parameters_env.return_value = ({}, [])
arglist = ['--templates', '--overcloud-ssh-port-timeout', '42', arglist = ['--templates', '--overcloud-ssh-port-timeout', '42',
'--timeout', '451'] '--timeout', '451']
@ -1294,18 +1326,13 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_rc_params.return_value = {'password': 'password', mock_rc_params.return_value = {'password': 'password',
'region': 'region1'} 'region': 'region1'}
# assuming heat deploy consumed a 3m out of total 451m timeout # assuming heat deploy consumed a 3m out of total 451m timeout
with mock.patch('time.time', side_effect=[0, 1585820346, with mock.patch('time.time', side_effect=[1585820346,
0, 12345678, 0, 12345678, 0, 0,
1585820526]): 1585820526]):
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
self.assertIn( self.assertIn(
[mock.call(mock.ANY, mock.ANY, 'overcloud', mock.ANY, [mock.call(mock.ANY, mock.ANY, 'overcloud', mock.ANY,
{'StackAction': 'UPDATE', {'StackAction': 'UPDATE'}, mock.ANY,
'DeployIdentifier': 12345678,
'RootStackName': 'overcloud',
'UndercloudHostsEntries':
['192.168.0.1 uc.ctlplane.localhost uc.ctlplane'],
'CtlplaneNetworkAttributes': {}}, mock.ANY,
451, mock.ANY, mock.ANY, False, None, 451, mock.ANY, mock.ANY, False, None,
deployment_options={}, env_files_tracker=mock.ANY)], deployment_options={}, env_files_tracker=mock.ANY)],
mock_hd.mock_calls) mock_hd.mock_calls)
@ -1333,9 +1360,11 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'_get_undercloud_host_entry', autospec=True, '_get_undercloud_host_entry', autospec=True,
return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane') return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_tripleo_heat_templates_tmpdir', autospec=True) 'create_params_and_env_files', autospec=True)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'deploy_tripleo_heat_templates', autospec=True)
def test_config_download_only_timeout( def test_config_download_only_timeout(
self, mock_deploy_tmpdir, self, mock_deploy, mock_create_env,
mock_get_undercloud_host_entry, mock_update, mock_get_undercloud_host_entry, mock_update,
mock_copyi, mock_rc_params, mock_cd_dir): mock_copyi, mock_rc_params, mock_cd_dir):
utils_fixture = deployment.UtilsOvercloudFixture() utils_fixture = deployment.UtilsOvercloudFixture()
@ -1362,6 +1391,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_rc_params.return_value = {'password': 'password', mock_rc_params.return_value = {'password': 'password',
'region': 'region1'} 'region': 'region1'}
mock_create_env.return_value = ({}, [])
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
playbook = os.path.join(os.environ.get( playbook = os.path.join(os.environ.get(
'HOME'), self.cmd.working_dir, 'HOME'), self.cmd.working_dir,

View File

@ -52,7 +52,6 @@ from heatclient.common import template_utils
from heatclient.common import utils as heat_utils from heatclient.common import utils as heat_utils
from heatclient.exc import HTTPNotFound from heatclient.exc import HTTPNotFound
from osc_lib import exceptions as oscexc from osc_lib import exceptions as oscexc
from osc_lib import utils as osc_lib_utils
from osc_lib.i18n import _ from osc_lib.i18n import _
from oslo_concurrency import processutils from oslo_concurrency import processutils
from six.moves import configparser from six.moves import configparser
@ -71,6 +70,14 @@ from tripleoclient import constants
from tripleoclient import exceptions from tripleoclient import exceptions
from tripleoclient import heat_launcher from tripleoclient import heat_launcher
try:
# TODO(slagle): the try/except can be removed once tripleo_common is
# released with
# https://review.opendev.org/c/openstack/tripleo-common/+/787819
from tripleo_common.utils import heat as tc_heat_utils
except ImportError:
tc_heat_utils = None
LOG = logging.getLogger(__name__ + ".utils") LOG = logging.getLogger(__name__ + ".utils")
_local_orchestration_client = None _local_orchestration_client = None
@ -2566,6 +2573,11 @@ def write_user_environment(env_map, abs_env_path, tht_root,
def launch_heat(launcher=None, restore_db=False): def launch_heat(launcher=None, restore_db=False):
if not tc_heat_utils:
msg = "tripleo-common too old to use ephemeral Heat"
LOG.error(msg)
raise Exception(msg)
global _local_orchestration_client global _local_orchestration_client
global _heat_pid global _heat_pid
@ -2589,7 +2601,7 @@ def launch_heat(launcher=None, restore_db=False):
heat_api_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) heat_api_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
test_heat_api_port(heat_api_socket, launcher.host, int(launcher.api_port)) test_heat_api_port(heat_api_socket, launcher.host, int(launcher.api_port))
_local_orchestration_client = local_orchestration_client( _local_orchestration_client = tc_heat_utils.local_orchestration_client(
launcher.host, launcher.api_port) launcher.host, launcher.api_port)
return _local_orchestration_client return _local_orchestration_client
@ -2609,41 +2621,6 @@ def get_heat_launcher(heat_type, *args, **kwargs):
return heat_launcher.HeatPodLauncher(*args, **kwargs) return heat_launcher.HeatPodLauncher(*args, **kwargs)
def local_orchestration_client(host="127.0.0.1", api_port=8006):
"""Returns a local orchestration service client"""
API_VERSIONS = {
'1': 'heatclient.v1.client.Client',
}
heat_client = osc_lib_utils.get_client_class(
'tripleoclient',
'1',
API_VERSIONS)
LOG.debug('Instantiating local_orchestration client for '
'host %s, port %s: %s',
host, api_port, heat_client)
endpoint = 'http://%s:%s/v1/admin' % (host, api_port)
client = heat_client(
endpoint=endpoint,
username='admin',
password='fake',
region_name='regionOne',
token='fake',
)
for v in ('OS_USER_DOMAIN_NAME',
'OS_PROJECT_DOMAIN_NAME',
'OS_PROJECT_NAME'):
os.environ.pop(v, None)
os.environ['OS_AUTH_TYPE'] = "none"
os.environ['OS_ENDPOINT'] = endpoint
return client
def kill_heat(launcher, backup_db=True): def kill_heat(launcher, backup_db=True):
global _heat_pid global _heat_pid
if _heat_pid: if _heat_pid:

View File

@ -77,59 +77,44 @@ class DeployOvercloud(command.Command):
answers['environments'].extend(args.environment_files) answers['environments'].extend(args.environment_files)
args.environment_files = answers['environments'] args.environment_files = answers['environments']
def _update_parameters(self, args, stack, tht_root, user_tht_root): def _update_parameters(self, args, parameters,
parameters = {} tht_root, user_tht_root):
stack_is_new = stack is None
parameters['RootStackName'] = args.stack parameters['RootStackName'] = args.stack
if not args.skip_deploy_identifier: if not args.skip_deploy_identifier:
parameters['DeployIdentifier'] = int(time.time()) parameters['DeployIdentifier'] = int(time.time())
else: else:
parameters['DeployIdentifier'] = '' parameters['DeployIdentifier'] = ''
parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE' if args.heat_type != 'installed':
heat = None
else:
heat = self.orchestration_client
# We need the processed env for the image parameters atm # Check for existing passwords file
env_files = [] password_params_path = os.path.join(
env_files.append( self.working_dir,
os.path.join(tht_root, constants.DEFAULT_RESOURCE_REGISTRY)) constants.PASSWORDS_ENV_FORMAT.format(args.stack))
if args.environment_directories: if os.path.exists(password_params_path):
env_files.extend(utils.load_environment_directories( with open(password_params_path, 'r') as f:
args.environment_directories)) passwords_env = yaml.safe_load(f.read())
if args.environment_files: else:
env_files.extend(args.environment_files) passwords_env = None
_, env = utils.process_multiple_environments(
env_files, tht_root, user_tht_root,
cleanup=(not args.no_cleanup))
default_image_params = plan_utils.default_image_params()
image_params = {}
if not args.disable_container_prepare:
image_params = kolla_builder.container_images_prepare_multi(
env, roles.get_roles_data(args.roles_file,
tht_root), dry_run=True)
if image_params:
default_image_params.update(image_params)
parameters.update(default_image_params)
password_params = plan_utils.generate_passwords( password_params = plan_utils.generate_passwords(
None, self.orchestration_client, None, heat, args.stack, passwords_env=passwords_env)
args.stack)
# Save generated passwords file
with open(password_params_path, 'w') as f:
f.write(yaml.safe_dump(dict(parameter_defaults=password_params)))
os.chmod(password_params_path, 0o600)
parameters.update(password_params) parameters.update(password_params)
param_args = ( param_args = (
('NtpServer', 'ntp_server'), ('NtpServer', 'ntp_server'),
('NovaComputeLibvirtType', 'libvirt_type'),
) )
if stack_is_new:
new_stack_args = (
('NovaComputeLibvirtType', 'libvirt_type'),
)
param_args = param_args + new_stack_args
# Update parameters from commandline # Update parameters from commandline
for param, arg in param_args: for param, arg in param_args:
if getattr(args, arg, None) is not None: if getattr(args, arg, None) is not None:
@ -245,7 +230,7 @@ class DeployOvercloud(command.Command):
template, files, env_files_tracker, template, files, env_files_tracker,
self.log, self.working_dir) self.log, self.working_dir)
def _deploy_tripleo_heat_templates_tmpdir(self, stack, parsed_args): def create_template_dirs(self, parsed_args):
tht_root = os.path.abspath(parsed_args.templates) tht_root = os.path.abspath(parsed_args.templates)
new_tht_root = "%s/tripleo-heat-templates" % self.working_dir new_tht_root = "%s/tripleo-heat-templates" % self.working_dir
self.log.debug("Creating working templates tree in %s" self.log.debug("Creating working templates tree in %s"
@ -257,38 +242,61 @@ class DeployOvercloud(command.Command):
parsed_args.roles_file, parsed_args.roles_file,
parsed_args.networks_file, parsed_args.networks_file,
new_tht_root) new_tht_root)
self._deploy_tripleo_heat_templates(stack, parsed_args, return new_tht_root, tht_root
new_tht_root, tht_root)
def _deploy_tripleo_heat_templates(self, stack, parsed_args,
tht_root, user_tht_root):
"""Deploy the fixed templates in TripleO Heat Templates"""
self.log.info("Processing templates in the directory {0}".format(
os.path.abspath(tht_root)))
def create_params_and_env_files(self, new_tht_root, user_tht_root,
parsed_args):
self.log.debug("Creating Environment files") self.log.debug("Creating Environment files")
created_env_files = [] created_env_files = []
created_env_files.append( created_env_files.append(
os.path.join(tht_root, constants.DEFAULT_RESOURCE_REGISTRY)) os.path.join(new_tht_root, constants.DEFAULT_RESOURCE_REGISTRY))
created_env_files.extend(
self._provision_baremetal(parsed_args, tht_root))
if parsed_args.environment_directories: if parsed_args.environment_directories:
created_env_files.extend(utils.load_environment_directories( created_env_files.extend(utils.load_environment_directories(
parsed_args.environment_directories)) parsed_args.environment_directories))
created_env_files.extend(
self._provision_baremetal(parsed_args, new_tht_root))
_, env = utils.process_multiple_environments(
created_env_files, new_tht_root, user_tht_root,
cleanup=(not parsed_args.no_cleanup))
default_image_params = plan_utils.default_image_params()
image_params = {}
if not parsed_args.disable_container_prepare:
image_params = kolla_builder.container_images_prepare_multi(
env, roles.get_roles_data(parsed_args.roles_file,
new_tht_root), dry_run=True)
parameters = {} parameters = {}
parameters.update(self._update_parameters( if image_params:
parsed_args, stack, tht_root, user_tht_root)) default_image_params.update(image_params)
parameters.update(default_image_params)
self._update_parameters(
parsed_args, parameters, new_tht_root, user_tht_root)
return parameters, created_env_files
def deploy_tripleo_heat_templates(self, stack, parsed_args,
new_tht_root, user_tht_root,
parameters, created_env_files):
"""Deploy the fixed templates in TripleO Heat Templates"""
self.log.info("Processing templates in the directory {0}".format(
os.path.abspath(new_tht_root)))
stack_is_new = stack is None
parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE'
param_env = utils.create_parameters_env( param_env = utils.create_parameters_env(
parameters, tht_root, parsed_args.stack) parameters, new_tht_root, parsed_args.stack)
created_env_files.extend(param_env) created_env_files.extend(param_env)
if parsed_args.deployed_server: if parsed_args.deployed_server:
created_env_files.append( created_env_files.append(
os.path.join(tht_root, constants.DEPLOYED_SERVER_ENVIRONMENT)) os.path.join(
new_tht_root,
constants.DEPLOYED_SERVER_ENVIRONMENT))
if parsed_args.environment_files: if parsed_args.environment_files:
created_env_files.extend(parsed_args.environment_files) created_env_files.extend(parsed_args.environment_files)
@ -300,22 +308,22 @@ class DeployOvercloud(command.Command):
if stack: if stack:
env_path = utils.create_breakpoint_cleanup_env( env_path = utils.create_breakpoint_cleanup_env(
tht_root, parsed_args.stack) new_tht_root, parsed_args.stack)
created_env_files.extend(env_path) created_env_files.extend(env_path)
self.log.debug("Processing environment files %s" % created_env_files) self.log.debug("Processing environment files %s" % created_env_files)
env_files_tracker = [] env_files_tracker = []
env_files, env = utils.process_multiple_environments( env_files, env = utils.process_multiple_environments(
created_env_files, tht_root, user_tht_root, created_env_files, new_tht_root, user_tht_root,
env_files_tracker=env_files_tracker, env_files_tracker=env_files_tracker,
cleanup=(not parsed_args.no_cleanup)) cleanup=(not parsed_args.no_cleanup))
# Invokes the workflows specified in plan environment file # Invokes the workflows specified in plan environment file
if parsed_args.plan_environment_file: if parsed_args.plan_environment_file:
output_path = utils.build_user_env_path( output_path = utils.build_user_env_path(
'derived_parameters.yaml', tht_root) 'derived_parameters.yaml', new_tht_root)
workflow_params.build_derived_params_environment( workflow_params.build_derived_params_environment(
self.clients, parsed_args.stack, tht_root, env_files, self.clients, parsed_args.stack, new_tht_root, env_files,
env_files_tracker, parsed_args.roles_file, env_files_tracker, parsed_args.roles_file,
parsed_args.plan_environment_file, parsed_args.plan_environment_file,
output_path, utils.playbook_verbosity(self=self)) output_path, utils.playbook_verbosity(self=self))
@ -323,12 +331,12 @@ class DeployOvercloud(command.Command):
created_env_files.append(output_path) created_env_files.append(output_path)
env_files_tracker = [] env_files_tracker = []
env_files, env = utils.process_multiple_environments( env_files, env = utils.process_multiple_environments(
created_env_files, tht_root, user_tht_root, created_env_files, new_tht_root, user_tht_root,
env_files_tracker=env_files_tracker, env_files_tracker=env_files_tracker,
cleanup=(not parsed_args.no_cleanup)) cleanup=(not parsed_args.no_cleanup))
# Copy the env_files to tmp folder for archiving # Copy the env_files to tmp folder for archiving
self._copy_env_files(env_files, tht_root) self._copy_env_files(env_files, new_tht_root)
if parsed_args.limit: if parsed_args.limit:
# check if skip list is defined while using --limit and throw a # check if skip list is defined while using --limit and throw a
@ -365,7 +373,7 @@ class DeployOvercloud(command.Command):
'(with HA).') '(with HA).')
self._try_overcloud_deploy_with_compat_yaml( self._try_overcloud_deploy_with_compat_yaml(
tht_root, stack, new_tht_root, stack,
parsed_args.stack, parameters, env_files, parsed_args.stack, parameters, env_files,
parsed_args.timeout, env, parsed_args.timeout, env,
parsed_args.run_validations, parsed_args.run_validations,
@ -911,6 +919,35 @@ class DeployOvercloud(command.Command):
'input, output, and generated files will be stored.\n' 'input, output, and generated files will be stored.\n'
'Defaults to "$HOME/overcloud-deploy/<stack>"') 'Defaults to "$HOME/overcloud-deploy/<stack>"')
) )
parser.add_argument(
'--heat-type',
action='store',
default='installed',
choices=['system', 'pod', 'container', 'native'],
help=_('The type of Heat process to use to execute '
'the deployment.\n'
'installed (Default): Use the system installed '
'Heat.\n'
'pod: Use an ephemeral Heat pod.\n'
'container: Use an ephemeral Heat container.\n'
'native: Use an ephemeral Heat process.')
)
parser.add_argument(
'--rm-heat',
action='store_true',
default=False,
help=_('If specified and --heat-type is container or pod '
'any existing container or pod of a previous '
'ephemeral Heat process will be deleted first. '
'Ignored if --heat-type is native.')
)
parser.add_argument(
'--skip-heat-pull',
action='store_true',
default=False,
help=_('When --heat-type is pod or container, assume '
'the container image has already been pulled ')
)
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
@ -950,21 +987,64 @@ class DeployOvercloud(command.Command):
parsed_args.environment_files) parsed_args.environment_files)
self._update_args_from_answers_file(parsed_args) self._update_args_from_answers_file(parsed_args)
stack = utils.get_stack(self.orchestration_client, parsed_args.stack)
stack_create = stack is None
if stack_create:
self.log.info("No stack found, will be doing a stack create")
else:
self.log.info("Stack found, will be doing a stack update")
if parsed_args.dry_run: if parsed_args.dry_run:
self.log.info("Validation Finished") self.log.info("Validation Finished")
return return
self.heat_launcher = None
stack = None
stack_create = None
start = time.time() start = time.time()
if not parsed_args.config_download_only: new_tht_root, user_tht_root = \
self._deploy_tripleo_heat_templates_tmpdir(stack, parsed_args) self.create_template_dirs(parsed_args)
parameters, created_env_files = \
self.create_params_and_env_files(
new_tht_root, user_tht_root, parsed_args)
if parsed_args.heat_type != 'installed':
self.log.info("Using tripleo-deploy with "
"ephemeral heat-all for stack operation")
api_container_image = parameters['ContainerHeatApiImage']
engine_container_image = \
parameters['ContainerHeatEngineImage']
self.heat_launcher = utils.get_heat_launcher(
parsed_args.heat_type,
api_container_image=api_container_image,
engine_container_image=engine_container_image,
heat_dir=os.path.join(self.working_dir,
'heat-launcher'),
use_tmp_dir=False,
rm_heat=parsed_args.rm_heat,
skip_heat_pull=parsed_args.skip_heat_pull)
self.orchestration_client = \
utils.launch_heat(self.heat_launcher)
self.clients.orchestration = self.orchestration_client
try:
if parsed_args.heat_type == 'installed':
stack = utils.get_stack(self.orchestration_client,
parsed_args.stack)
stack_create = stack is None
if stack_create:
self.log.info("No stack found, "
"will be doing a stack create")
else:
self.log.info("Stack found, "
"will be doing a stack update")
if not (parsed_args.config_download_only or
parsed_args.setup_only):
self.deploy_tripleo_heat_templates(
stack, parsed_args, new_tht_root, user_tht_root,
parameters, created_env_files)
except Exception:
if parsed_args.heat_type != 'installed' and self.heat_launcher:
self.log.info("Stopping ephemeral heat.")
utils.kill_heat(self.heat_launcher)
utils.rm_heat(self.heat_launcher)
raise
# Get a new copy of the stack after stack update/create. If it was # Get a new copy of the stack after stack update/create. If it was
# a create then the previous stack object would be None. # a create then the previous stack object would be None.
@ -980,7 +1060,8 @@ class DeployOvercloud(command.Command):
stack.get() stack.get()
overcloud_endpoint = utils.get_overcloud_endpoint(stack) overcloud_endpoint = utils.get_overcloud_endpoint(stack)
horizon_url = deployment.get_horizon_url( horizon_url = deployment.get_horizon_url(
stack=stack.stack_name) stack=stack.stack_name,
heat_type=parsed_args.heat_type)
rc_params = utils.get_rc_params( rc_params = utils.get_rc_params(
self.orchestration_client, self.orchestration_client,
parsed_args.stack) parsed_args.stack)
@ -993,6 +1074,9 @@ class DeployOvercloud(command.Command):
stack, rc_params, parsed_args.no_proxy, stack, rc_params, parsed_args.no_proxy,
self.working_dir) self.working_dir)
config_download_dir = parsed_args.output_dir or \
os.path.join(self.working_dir, "config-download")
if parsed_args.config_download or parsed_args.setup_only: if parsed_args.config_download or parsed_args.setup_only:
self.log.info("Deploying overcloud configuration") self.log.info("Deploying overcloud configuration")
deployment.set_deployment_status( deployment.set_deployment_status(
@ -1009,7 +1093,8 @@ class DeployOvercloud(command.Command):
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
self.get_key_pair(parsed_args), self.get_key_pair(parsed_args),
parsed_args.overcloud_ssh_port_timeout, parsed_args.overcloud_ssh_port_timeout,
verbosity=utils.playbook_verbosity(self=self) verbosity=utils.playbook_verbosity(self=self),
heat_type=parsed_args.heat_type
) )
if parsed_args.config_download_timeout: if parsed_args.config_download_timeout:
@ -1026,8 +1111,6 @@ class DeployOvercloud(command.Command):
deployment_options['ansible_python_interpreter'] = \ deployment_options['ansible_python_interpreter'] = \
parsed_args.deployment_python_interpreter parsed_args.deployment_python_interpreter
config_download_dir = parsed_args.output_dir or \
os.path.join(self.working_dir, "config-download")
deployment.make_config_download_dir(config_download_dir, deployment.make_config_download_dir(config_download_dir,
parsed_args.stack) parsed_args.stack)
@ -1082,7 +1165,8 @@ class DeployOvercloud(command.Command):
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
self.get_key_pair(parsed_args), self.get_key_pair(parsed_args),
parsed_args.overcloud_ssh_port_timeout, parsed_args.overcloud_ssh_port_timeout,
verbosity=utils.playbook_verbosity(self=self) verbosity=utils.playbook_verbosity(self=self),
heat_type=parsed_args.heat_type
) )
deployment.set_deployment_status( deployment.set_deployment_status(
@ -1117,6 +1201,11 @@ class DeployOvercloud(command.Command):
rcpath, old_rcpath)) rcpath, old_rcpath))
print("Overcloud Deployed {0}".format(deploy_message)) print("Overcloud Deployed {0}".format(deploy_message))
if parsed_args.heat_type != 'installed':
self.log.info("Stopping ephemeral heat.")
utils.kill_heat(self.heat_launcher)
utils.rm_heat(self.heat_launcher)
if parsed_args.output_dir: if parsed_args.output_dir:
ansible_dir = config_download_dir ansible_dir = config_download_dir
else: else:

View File

@ -477,7 +477,8 @@ class Deploy(command.Command):
self.heat_launch = heat_launcher.HeatNativeLauncher( self.heat_launch = heat_launcher.HeatNativeLauncher(
parsed_args.heat_api_port, parsed_args.heat_api_port,
parsed_args.heat_container_image, parsed_args.heat_container_image,
parsed_args.heat_user) parsed_args.heat_user,
use_root=True)
# NOTE(dprince): we launch heat with fork exec because # NOTE(dprince): we launch heat with fork exec because
# we don't want it to inherit our args. Launching heat # we don't want it to inherit our args. Launching heat

View File

@ -28,6 +28,13 @@ from tripleoclient.constants import DEFAULT_WORK_DIR
from tripleoclient import exceptions from tripleoclient import exceptions
from tripleoclient import utils from tripleoclient import utils
try:
# TODO(slagle): the try/except can be removed once tripleo_common is
# released with
# https://review.opendev.org/c/openstack/tripleo-common/+/787819
from tripleo_common.utils import heat as tc_heat_utils
except ImportError:
tc_heat_utils = None
_WORKFLOW_TIMEOUT = 360 # 6 * 60 seconds _WORKFLOW_TIMEOUT = 360 # 6 * 60 seconds
@ -136,7 +143,7 @@ def get_overcloud_hosts(stack, ssh_network):
def get_hosts_and_enable_ssh_admin(stack, overcloud_ssh_network, def get_hosts_and_enable_ssh_admin(stack, overcloud_ssh_network,
overcloud_ssh_user, overcloud_ssh_key, overcloud_ssh_user, overcloud_ssh_key,
overcloud_ssh_port_timeout, overcloud_ssh_port_timeout,
verbosity=0): verbosity=0, heat_type='installed'):
"""Enable ssh admin access. """Enable ssh admin access.
Get a list of hosts from a given stack and enable admin ssh across all of Get a list of hosts from a given stack and enable admin ssh across all of
@ -169,7 +176,8 @@ def get_hosts_and_enable_ssh_admin(stack, overcloud_ssh_network,
overcloud_ssh_user, overcloud_ssh_user,
overcloud_ssh_key, overcloud_ssh_key,
overcloud_ssh_port_timeout, overcloud_ssh_port_timeout,
verbosity=verbosity verbosity=verbosity,
heat_type=heat_type
) )
else: else:
raise exceptions.DeploymentError( raise exceptions.DeploymentError(
@ -181,7 +189,7 @@ def get_hosts_and_enable_ssh_admin(stack, overcloud_ssh_network,
def enable_ssh_admin(stack, hosts, ssh_user, ssh_key, timeout, def enable_ssh_admin(stack, hosts, ssh_user, ssh_key, timeout,
verbosity=0): verbosity=0, heat_type='installed'):
"""Run enable ssh admin access playbook. """Run enable ssh admin access playbook.
:param stack: Stack data. :param stack: Stack data.
@ -213,22 +221,28 @@ def enable_ssh_admin(stack, hosts, ssh_user, ssh_key, timeout,
ssh_key ssh_key
) )
) )
with utils.TempDirs() as tmp: try:
utils.run_ansible_playbook( if heat_type != 'installed' and tc_heat_utils.heatclient:
playbook='cli-enable-ssh-admin.yaml', tc_heat_utils.heatclient.save_environment()
inventory=','.join(hosts), with utils.TempDirs() as tmp:
workdir=tmp, utils.run_ansible_playbook(
playbook_dir=ANSIBLE_TRIPLEO_PLAYBOOKS, playbook='cli-enable-ssh-admin.yaml',
key=ssh_key, inventory=','.join(hosts),
ssh_user=ssh_user, workdir=tmp,
verbosity=verbosity, playbook_dir=ANSIBLE_TRIPLEO_PLAYBOOKS,
extra_vars={ key=ssh_key,
"ssh_user": ssh_user, ssh_user=ssh_user,
"ssh_servers": hosts, verbosity=verbosity,
'tripleo_cloud_name': stack.stack_name extra_vars={
}, "ssh_user": ssh_user,
ansible_timeout=timeout "ssh_servers": hosts,
) 'tripleo_cloud_name': stack.stack_name
},
ansible_timeout=timeout
)
finally:
if heat_type != 'installed' and tc_heat_utils.heatclient:
tc_heat_utils.heatclient.restore_environment()
print("Enabling ssh admin - COMPLETE.") print("Enabling ssh admin - COMPLETE.")
@ -467,7 +481,8 @@ def config_download(log, clients, stack, ssh_network='ctlplane',
repo.git.commit("--amend", "--no-edit") repo.git.commit("--amend", "--no-edit")
def get_horizon_url(stack, verbosity=0): def get_horizon_url(stack, verbosity=0,
heat_type='installed'):
"""Return horizon URL string. """Return horizon URL string.
:params stack: Stack name :params stack: Stack name
@ -475,22 +490,28 @@ def get_horizon_url(stack, verbosity=0):
:returns: string :returns: string
""" """
with utils.TempDirs() as tmp: try:
horizon_tmp_file = os.path.join(tmp, 'horizon_url') if heat_type != 'installed' and tc_heat_utils.heatclient:
utils.run_ansible_playbook( tc_heat_utils.heatclient.save_environment()
playbook='cli-undercloud-get-horizon-url.yaml', with utils.TempDirs() as tmp:
inventory='localhost,', horizon_tmp_file = os.path.join(tmp, 'horizon_url')
workdir=tmp, utils.run_ansible_playbook(
playbook_dir=ANSIBLE_TRIPLEO_PLAYBOOKS, playbook='cli-undercloud-get-horizon-url.yaml',
verbosity=verbosity, inventory='localhost,',
extra_vars={ workdir=tmp,
'stack_name': stack, playbook_dir=ANSIBLE_TRIPLEO_PLAYBOOKS,
'horizon_url_output_file': horizon_tmp_file verbosity=verbosity,
} extra_vars={
) 'stack_name': stack,
'horizon_url_output_file': horizon_tmp_file
}
)
with open(horizon_tmp_file) as f: with open(horizon_tmp_file) as f:
return f.read().strip() return f.read().strip()
finally:
if heat_type != 'installed' and tc_heat_utils.heatclient:
tc_heat_utils.heatclient.restore_environment()
def get_deployment_status(clients, stack_name, working_dir): def get_deployment_status(clients, stack_name, working_dir):