diff --git a/releasenotes/notes/mistral-swift-tempurl-action-ce4946a0b76db53c.yaml b/releasenotes/notes/mistral-swift-tempurl-action-ce4946a0b76db53c.yaml new file mode 100644 index 000000000..47ee57c85 --- /dev/null +++ b/releasenotes/notes/mistral-swift-tempurl-action-ce4946a0b76db53c.yaml @@ -0,0 +1,6 @@ +--- +features: + - A new Mistral action has been added to create signed temporary URLs. It + also sets the required metadata with a random key if not yet existing. + This can be used on overcloud nodes to pull and push objects, for example + to distribute Swift rings across all nodes. diff --git a/setup.cfg b/setup.cfg index 494374ec6..cb4dcf2ad 100644 --- a/setup.cfg +++ b/setup.cfg @@ -85,6 +85,7 @@ mistral.actions = tripleo.plan.list = tripleo_common.actions.plan:ListPlansAction tripleo.role.list = tripleo_common.actions.plan:ListRolesAction tripleo.scale.delete_node = tripleo_common.actions.scale:ScaleDownAction + tripleo.swift.tempurl = tripleo_common.actions.swifthelper:SwiftTempUrlAction tripleo.templates.process = tripleo_common.actions.templates:ProcessTemplatesAction tripleo.templates.upload_default = tripleo_common.actions.templates:UploadTemplatesAction tripleo.validations.get_pubkey = tripleo_common.actions.validations:GetPubkeyAction diff --git a/tripleo_common/actions/swifthelper.py b/tripleo_common/actions/swifthelper.py new file mode 100644 index 000000000..39dd39030 --- /dev/null +++ b/tripleo_common/actions/swifthelper.py @@ -0,0 +1,49 @@ +# Copyright 2016 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import uuid + +from six.moves import urllib +from swiftclient import exceptions as swiftexceptions +from swiftclient.utils import generate_temp_url +from tripleo_common.actions import base + + +class SwiftTempUrlAction(base.TripleOAction): + + def __init__(self, container, obj, method='GET', valid='86400'): + super(SwiftTempUrlAction, self).__init__() + self.container = container + self.obj = obj + self.method = method + self.valid = valid + + def run(self): + swift_client = self.get_object_client() + + try: + cont_stat = swift_client.head_container(self.container) + except swiftexceptions.ClientException: + cont_stat = {} + + key = cont_stat.get('x-container-meta-temp-url-key') + if not key: + key = str(uuid.uuid4()) + cont_stat = swift_client.put_container( + self.container, {'X-Container-Meta-Temp-Url-Key': key}) + parsed = urllib.parse.urlparse(swift_client.url) + path = "%s/%s/%s" % (parsed.path, self.container, self.obj) + temp_path = generate_temp_url(path, self.valid, key, self.method) + return "%s://%s%s" % (parsed.scheme, parsed.netloc, temp_path) diff --git a/tripleo_common/tests/actions/test_swifthelper.py b/tripleo_common/tests/actions/test_swifthelper.py new file mode 100644 index 000000000..5dc4c8594 --- /dev/null +++ b/tripleo_common/tests/actions/test_swifthelper.py @@ -0,0 +1,58 @@ +# Copyright 2016 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +import mock + +from tripleo_common.actions import swifthelper +from tripleo_common.tests import base + + +class SwiftTempUrlActionTest(base.TestCase): + @mock.patch('time.time') + @mock.patch('uuid.uuid4') + @mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client') + @mock.patch('mistral.context.ctx') + def _test_get_tempurl(self, secret, mock_ctx, mock_get_object_client, + mock_uuid, mock_time): + mock_ctx.return_value = mock.MagicMock() + + url = "http://swift:8080/v1/AUTH_test" + swiftclient = mock.MagicMock(url=url) + headers = {} + if secret: + headers['x-container-meta-temp-url-key'] = secret + swiftclient.head_container.return_value = headers + mock_get_object_client.return_value = swiftclient + + mock_uuid.return_value = '1-2-3-4' + mock_time.return_value = 1500000000 + + action = swifthelper.SwiftTempUrlAction("container", "obj") + tempurl = action.run() + + expected = "%s/container/obj?temp_url_sig=%s&temp_url_expires=%d" % ( + url, "ea8fdc57e2b2b1fbb7210bddd40029a7c8d5e2ed", 1500086400) + self.assertEqual(expected, tempurl) + + if not secret: + swiftclient.put_container.assert_called_with( + 'container', {'X-Container-Meta-Temp-Url-Key': '1-2-3-4'}) + + def test_get_tempurl(self): + # temp-url-key already set on the container + self._test_get_tempurl('1-2-3-4') + + def test_get_tempurl_no_key(self): + # temp-url-key not yet set + self._test_get_tempurl(None) diff --git a/workbooks/deployment.yaml b/workbooks/deployment.yaml index 816eba3fe..1f0d1d234 100644 --- a/workbooks/deployment.yaml +++ b/workbooks/deployment.yaml @@ -128,7 +128,7 @@ workflows: get_heat_stack: action: heat.stacks_get stack_id=<% $.container %> - on-error: deploy + on-error: check_container on-success: - set_stack_in_progress: <% "_IN_PROGRESS" in task(get_heat_stack).result.stack_status %> - deploy: <% not "_IN_PROGRESS" in task(get_heat_stack).result.stack_status %> @@ -139,6 +139,46 @@ workflows: status: FAILED message: The Heat stack is busy. + check_container: + action: swift.head_container container=<% $.container %> + on-success: get_tempurl + on-error: create_container + + create_container: + action: tripleo.plan.create_container container="<% $.container %>-swift-rings" + on-success: get_tempurl + + get_tempurl: + action: tripleo.swift.tempurl + on-success: set_get_tempurl + input: + container: "<% $.container %>-swift-rings" + obj: "swift-rings.tar.gz" + + set_get_tempurl: + action: tripleo.parameters.update + input: + parameters: + SwiftRingGetTempurl: <% task(get_tempurl).result %> + container: <% $.container %> + on-success: put_tempurl + + put_tempurl: + action: tripleo.swift.tempurl + on-success: set_put_tempurl + input: + container: "<% $.container %>-swift-rings" + obj: "swift-rings.tar.gz" + method: "PUT" + + set_put_tempurl: + action: tripleo.parameters.update + input: + parameters: + SwiftRingPutTempurl: <% task(put_tempurl).result %> + container: <% $.container %> + on-success: deploy + deploy: action: tripleo.deployment.deploy timeout=<% $.timeout %> container=<% $.container %> on-success: send_message