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 5a331780b..826831ce2 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 @@ -368,10 +369,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 )