From d7de7ccbd68a77e07cde0e3d8bb1a0874c0be903 Mon Sep 17 00:00:00 2001 From: Abhishek Kekane Date: Wed, 19 Feb 2020 12:03:58 +0000 Subject: [PATCH] Multiple import fails if "all_stores" specified as "true" Newly added multiple import fails if user passes "all_stores" as "true" in the request. The reason is if all_stores is specified then we are getting stores using CONF.enabled_backends and unfortunately we are injecting reserved stores 'os_glance_staging_store' and 'os_glance_tasks_store' runtime. As a result import job tries to import the image in the 'os_glance_staging_store' store as well where it fails as that image is already staged in this staging store. Made a provision to exclude available reserved stores if "all_stores" is specified. Change-Id: If2616c275a969cdad5649e2cb0851275e5d0c7d2 Closes-Bug: #1863879 --- doc/source/admin/multistores.rst | 5 +++++ glance/common/utils.py | 14 +++++++++++++- glance/tests/unit/common/test_utils.py | 24 ++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/doc/source/admin/multistores.rst b/doc/source/admin/multistores.rst index 67260de538..f328762604 100644 --- a/doc/source/admin/multistores.rst +++ b/doc/source/admin/multistores.rst @@ -163,6 +163,11 @@ Currently, there are two reserved stores: import process. It replaces the use of the DEPRECATED configuration option ``[DEFAULT]/node_staging_uri``. +.. note:: + If end user wants to retrieve all the available stores using + ``CONF.enabled_backeds`` then he needs to remove reserved + stores from that list explicitly. + Configuration ~~~~~~~~~~~~~ diff --git a/glance/common/utils.py b/glance/common/utils.py index b7cf164eb3..fb0e1afc0b 100644 --- a/glance/common/utils.py +++ b/glance/common/utils.py @@ -44,6 +44,7 @@ from webob import exc from glance.common import exception from glance.common import timeutils +from glance.common import wsgi from glance.i18n import _, _LE CONF = cfg.CONF @@ -671,6 +672,17 @@ def evaluate_filter_op(value, operator, threshold): raise exception.InvalidFilterOperatorValue(msg) +def _get_available_stores(): + available_stores = CONF.enabled_backends + stores = [] + # Remove reserved stores from the available stores list + for store in available_stores: + if store not in wsgi.RESERVED_STORES: + stores.append(store) + + return stores + + def get_stores_from_request(req, body): """Processes a supplied request and extract stores from it @@ -685,7 +697,7 @@ def get_stores_from_request(req, body): msg = _("All_stores parameter can't be used with " "x-image-meta-store header or stores parameter") raise exc.HTTPBadRequest(explanation=msg) - stores = list(CONF.enabled_backends) + stores = _get_available_stores() else: try: stores = body['stores'] diff --git a/glance/tests/unit/common/test_utils.py b/glance/tests/unit/common/test_utils.py index 0dddf725b6..57f2ffc43b 100644 --- a/glance/tests/unit/common/test_utils.py +++ b/glance/tests/unit/common/test_utils.py @@ -480,6 +480,30 @@ class TestUtils(test_utils.BaseTestCase): utils.get_stores_from_request, req, body) def test_get_stores_from_request_returns_all_stores(self): + enabled_backends = { + "ceph1": "rbd", + "ceph2": "rbd" + } + reserved_stores = { + 'os_glance_staging_store': 'file', + 'os_glance_tasks_store': 'file' + } + self.config(enabled_backends=enabled_backends) + store.register_store_opts(CONF, reserved_stores=reserved_stores) + self.config(default_backend="ceph1", group="glance_store") + body = {"all_stores": True} + req = webob.Request.blank("/some_request") + mp = "glance.common.utils.glance_store.get_store_from_store_identifier" + with mock.patch(mp) as mock_get_store: + result = sorted(utils.get_stores_from_request(req, body)) + self.assertEqual(["ceph1", "ceph2"], result) + mock_get_store.assert_any_call("ceph1") + mock_get_store.assert_any_call("ceph2") + self.assertEqual(mock_get_store.call_count, 2) + self.assertNotIn('os_glance_staging_store', result) + self.assertNotIn('os_glance_tasks_store', result) + + def test_get_stores_from_request_excludes_reserved_stores(self): enabled_backends = { "ceph1": "rbd", "ceph2": "rbd"