Ephemeral Heat: Add a --refresh option to external update run

In order to support ephemeral Heat, the external update run command
should rely on the already downloaded config-download playbooks as
generated by update prepare. There is no Heat instance available to
re-download the playbooks automatically.

To support the old behavior with a system installed Heat, a --refresh
option is added which will refresh the config-download playbooks.

We can not have an option to refresh the playbooks automatically with
ephemeral Heat, because the command would need to inherit from
DeployCommand and require environment files so that we can use the
ContainerImagePrepare value to get the ephemeral Heat container images,
as well as the ephemeral Heat setup and tear down code. As this would be
a much larger refactor to the CLI, we avoid it.

The correct fix for the case where the stack may have been modified out
of order is to require another run of update prepare which will
regenerate the playbooks.

Change-Id: Ib01d920112f5e84190fbcd9470dd7bac269b3987
Signed-off-by: James Slagle <jslagle@redhat.com>
(cherry picked from commit 76c9590636)
This commit is contained in:
James Slagle 2021-05-21 12:18:31 -04:00
parent 4ed3d8b4c9
commit 234a41b7dd
3 changed files with 111 additions and 33 deletions

View File

@ -13,7 +13,9 @@
# under the License.
#
import fixtures
import mock
import os
from tripleoclient.tests import fakes as ooofakes
from tripleoclient.tests.v1.overcloud_external_update import fakes
@ -89,3 +91,37 @@ class TestOvercloudExternalUpdateRun(fakes.TestOvercloudExternalUpdateRun):
]
self.check_parser(self.cmd, argslist, verifylist)
@mock.patch('tripleoclient.workflows.deployment.config_download')
@mock.patch('tripleoclient.utils.get_default_working_dir', autospec=True)
@mock.patch('tripleoclient.workflows.deployment.snapshot_dir',
autospec=True)
@mock.patch('tripleoclient.utils.run_ansible_playbook', autospec=True)
@mock.patch('tripleoclient.utils.get_key')
def test_update_with_refresh(
self, mock_get_key,
mock_run_ansible_playbook,
mock_snapshot_dir,
mock_get_default_working_dir,
mock_config_download):
argslist = ['--yes', '--refresh']
verifylist = [
('refresh', True)
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
argslist = ['--yes']
verifylist = [
('refresh', False)
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
mock_get_key.return_value = '/test/key'
work_dir = self.useFixture(fixtures.TempDir())
mock_get_default_working_dir.return_value = work_dir.path
ansible_dir = os.path.join(work_dir.path, 'config-download',
'overcloud')
self.cmd.take_action(parsed_args)
mock_get_key.assert_called_once_with('overcloud')
mock_snapshot_dir.assert_called_once_with(ansible_dir)
mock_run_ansible_playbook.assert_called()
mock_config_download.assert_not_called()

View File

@ -13,6 +13,8 @@
# under the License.
#
import os
from oslo_config import cfg
from oslo_log import log as logging
@ -114,6 +116,11 @@ class ExternalUpdateRun(command.Command):
help=_('The number of Ansible forks to use for the'
' config-download ansible-playbook command.')
)
parser.add_argument(
'--refresh',
action='store_true',
help=_('Refresh the config-download playbooks')
)
return parser
@ -128,35 +135,60 @@ class ExternalUpdateRun(command.Command):
constants.UPDATE_PROMPT, self.log)):
raise OvercloudUpdateNotConfirmed(constants.UPDATE_NO)
_, ansible_dir = self.get_ansible_key_and_dir(
no_workflow=True,
stack=parsed_args.stack,
orchestration=self.app.client_manager.orchestration
)
deployment.config_download(
log=self.log,
clients=self.app.client_manager,
stack=oooutils.get_stack(
self.app.client_manager.orchestration,
parsed_args.stack
),
output_dir=ansible_dir,
verbosity=oooutils.playbook_verbosity(self=self),
ansible_playbook_name=constants.EXTERNAL_UPDATE_PLAYBOOKS,
extra_vars=oooutils.parse_extra_vars(
extra_var_strings=parsed_args.extra_vars
),
inventory_path=oooutils.get_tripleo_ansible_inventory(
parsed_args.static_inventory,
parsed_args.ssh_user,
parsed_args.stack,
return_inventory_file_path=True
),
tags=parsed_args.tags,
skip_tags=parsed_args.skip_tags,
limit_hosts=oooutils.playbook_limit_parse(
limit_nodes=parsed_args.limit
),
forks=parsed_args.ansible_forks
)
if parsed_args.refresh:
_, ansible_dir = self.get_ansible_key_and_dir(
no_workflow=True,
stack=parsed_args.stack,
orchestration=self.app.client_manager.orchestration
)
deployment.config_download(
log=self.log,
clients=self.app.client_manager,
stack=oooutils.get_stack(
self.app.client_manager.orchestration,
parsed_args.stack
),
output_dir=ansible_dir,
verbosity=oooutils.playbook_verbosity(self=self),
ansible_playbook_name=constants.EXTERNAL_UPDATE_PLAYBOOKS,
extra_vars=oooutils.parse_extra_vars(
extra_var_strings=parsed_args.extra_vars
),
inventory_path=oooutils.get_tripleo_ansible_inventory(
parsed_args.static_inventory,
parsed_args.ssh_user,
parsed_args.stack,
return_inventory_file_path=True
),
tags=parsed_args.tags,
skip_tags=parsed_args.skip_tags,
limit_hosts=oooutils.playbook_limit_parse(
limit_nodes=parsed_args.limit
),
forks=parsed_args.ansible_forks
)
else:
working_dir = oooutils.get_default_working_dir(parsed_args.stack)
config_download_dir = os.path.join(working_dir, 'config-download')
ansible_dir = os.path.join(config_download_dir, parsed_args.stack)
inventory_path = os.path.join(ansible_dir,
'tripleo-ansible-inventory.yaml')
key = oooutils.get_key(parsed_args.stack)
playbooks = [os.path.join(ansible_dir, p)
for p in constants.EXTERNAL_UPDATE_PLAYBOOKS]
oooutils.run_ansible_playbook(
playbook=playbooks,
inventory=inventory_path,
workdir=config_download_dir,
tags=parsed_args.tags,
skip_tags=parsed_args.skip_tags,
limit_hosts=oooutils.playbook_limit_parse(
limit_nodes=parsed_args.limit
),
forks=parsed_args.ansible_forks,
key=key,
reproduce_command=True
)
deployment.snapshot_dir(ansible_dir)
self.log.info("Completed Overcloud External Update Run.")

View File

@ -469,9 +469,19 @@ def config_download(log, clients, stack, ssh_network='ctlplane',
print_msg=(verbosity == 0)
)
if os.path.exists(stack_work_dir):
snapshot_dir(stack_work_dir)
def snapshot_dir(directory):
"""Git snapshot a directory
:params directory: Directory to snapshot
:type directory: string
:returns: None
"""
if os.path.exists(directory):
# Object to the git repository
repo = git.Repo(stack_work_dir)
repo = git.Repo(directory)
# Configure git user.name and user.email
git_config_user = "mistral"