From 6367d58c248dc0884ba8cfe586fd0c973b46206c Mon Sep 17 00:00:00 2001 From: James Slagle Date: Tue, 12 Nov 2019 10:59:59 -0500 Subject: [PATCH] Handle config-download in progress in tripleoclient This patch adds handling and checking of any instances of the workflow tripleo.deployment.v1.config_download_deploy already in progress for the current stack. It will prevent duplicate instances of the same workflow being started and running at the same time. It will allow for multiple instances of the workflow running at the same time as long as they are for different stacks. Change-Id: Ic8dbf28b5796ff998165b6b73b941f21c65f1dfa Closes-Bug: #1852314 (cherry picked from commit 72f5762e45284543227246c19309e147114e8c07) --- ...download-in-progress-4af02517cb5a5c0c.yaml | 6 +++ tripleoclient/exceptions.py | 11 +++++ .../tests/workflows/test_deployment.py | 41 +++++++++++++++++++ tripleoclient/workflows/deployment.py | 24 ++++++++++- 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/config-download-in-progress-4af02517cb5a5c0c.yaml diff --git a/releasenotes/notes/config-download-in-progress-4af02517cb5a5c0c.yaml b/releasenotes/notes/config-download-in-progress-4af02517cb5a5c0c.yaml new file mode 100644 index 000000000..ec39aaccc --- /dev/null +++ b/releasenotes/notes/config-download-in-progress-4af02517cb5a5c0c.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - The client (tripleoclient) now raises a new exception, + ConfigDownloadInProgress, if there is already an instance of the + tripleo.deployment.v1.config_download_deploy workflow in progress for the + current stack. diff --git a/tripleoclient/exceptions.py b/tripleoclient/exceptions.py index 2061f2730..b738b462d 100644 --- a/tripleoclient/exceptions.py +++ b/tripleoclient/exceptions.py @@ -57,6 +57,17 @@ class StackInProgress(Base): """Unable to deploy as the stack is busy""" +class ConfigDownloadInProgress(Base): + """Unable to deploy as config download already in progress""" + + msg_format = ("Config download already in progress with " + "execution id {} for stack {}") + + def __init__(self, execution_id='', stack=''): + message = self.msg_format.format(execution_id, stack) + super(ConfigDownloadInProgress, self).__init__(message) + + class RootUserExecution(Base): """Command was executed by a root user""" diff --git a/tripleoclient/tests/workflows/test_deployment.py b/tripleoclient/tests/workflows/test_deployment.py index 57b1c888f..80769cc1d 100644 --- a/tripleoclient/tests/workflows/test_deployment.py +++ b/tripleoclient/tests/workflows/test_deployment.py @@ -169,3 +169,44 @@ class TestDeploymentWorkflows(utils.TestCommand): ips = deployment.get_overcloud_hosts(stack, 'external') expected = ['4.4.4.4', '6.6.6.6', '11.11.11.11'] self.assertEqual(sorted(expected), sorted(ips)) + + def test_config_download_already_in_progress( + self): + log = mock.Mock() + stack = mock.Mock() + stack.stack_name = 'stacktest' + clients = mock.Mock() + mock_execution = mock.Mock() + mock_execution.input = '{"plan_name": "stacktest"}' + mock_return = mock.Mock(return_value=[mock_execution]) + clients.workflow_engine.executions.find = mock_return + + self.assertRaises(exceptions.ConfigDownloadInProgress, + deployment.config_download, + log, clients, stack, 'templates', 'ssh_user', + 'ssh_key', 'ssh_networks', 'output_dir', False, + 'timeout') + + @mock.patch('tripleoclient.workflows.deployment.base') + def test_config_download_already_in_progress_for_diff_stack( + self, mock_base): + log = mock.Mock() + stack = mock.Mock() + stack.stack_name = 'stacktest' + clients = mock.Mock() + mock_execution = mock.Mock() + mock_execution.input = '{"plan_name": "someotherstack"}' + mock_return = mock.Mock(return_value=[mock_execution]) + clients.workflow_engine.executions.find = mock_return + mock_exit = mock.Mock() + mock_exit.__exit__ = mock.Mock() + mock_exit.__enter__ = mock.Mock() + clients.tripleoclient.messaging_websocket = mock.Mock( + return_value=mock_exit) + mock_base.wait_for_messages = mock.Mock( + return_value=[dict(status='SUCCESS')]) + + deployment.config_download( + log, clients, stack, 'templates', 'ssh_user', + 'ssh_key', 'ssh_networks', 'output_dir', False, + 'timeout') diff --git a/tripleoclient/workflows/deployment.py b/tripleoclient/workflows/deployment.py index 9ce243211..fdeee4a53 100644 --- a/tripleoclient/workflows/deployment.py +++ b/tripleoclient/workflows/deployment.py @@ -19,6 +19,7 @@ import socket import subprocess import tempfile import time +import yaml from heatclient.common import event_utils from openstackclient import shell @@ -360,10 +361,31 @@ def config_download(log, clients, stack, templates, workflow_input.update( dict(override_ansible_cfg=override_ansible_cfg_contents)) + workflow_name = 'tripleo.deployment.v1.config_download_deploy' + + # Check to see if any existing executions for the same stack are already in + # progress. + log.info("Checking for existing executions of config_download for " + "%s" % stack.stack_name) + for execution in workflow_client.executions.find( + workflow_name=workflow_name, + state='RUNNING'): + + try: + exec_input = yaml.safe_load(execution.input) + except yaml.YAMLError as ye: + log.error("YAML error loading input for execution %s: %s" % + (execution.id, str(ye))) + raise + + if exec_input.get('plan_name', 'overcloud') == stack.stack_name: + raise exceptions.ConfigDownloadInProgress(execution.id, + stack.stack_name) + with tripleoclients.messaging_websocket() as ws: execution = base.start_workflow( workflow_client, - 'tripleo.deployment.v1.config_download_deploy', + workflow_name, workflow_input=workflow_input )