Skip to content

Commit 5317526

Browse files
committed
Fix LP#2054575
This patch contains a squash of two commits: COMMIT 1: Make location URL compatible with cinder backend While adding location to an image, cinder sends location url as `cinder://volume_id` for single as well as multistore which is incompatible with glance multistore and store throws InvalidLoctation error. Modifying the location url to be compatible with multistore as `cinder://store_id/volume_id` to avoid Invalid Location error. Related-Bug: #2054575 Change-Id: I5f791c58ae857f6c553276dd9808799c3db3aa4f COMMIT 2: Fix: optimized upload volume in Cinder store When Glance is configured to use Cinder store and we upload volume to Glance in the optimized path, it fails with InvalidLocation error. This happens because Cinder is not aware about the store in which we will create the image and supplies the old format URL i.e. cinder://<vol-id> whereas Glance expects new location format i.e. cinder://<store-id>/<vol-id>. Glance has code to update the format from old location format to new location format but it isn't triggered in case of old location APIs. This patch adds the context to the update store ID request which calls the Cinder store to provide the updated location, hence fixing the optimized path for upload volume to image. Closes-Bug: #2054575 Change-Id: Idd1cb8982b40b85a17821596f76dfa10207f6381 The commits are squashed together to make backport easier. Change-Id: I9ecdfe08b63c00446dc3e24195e3b8e59b82f55c
1 parent aec654f commit 5317526

File tree

4 files changed

+45
-10
lines changed

4 files changed

+45
-10
lines changed

glance/api/v2/images.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ def _do_add(self, req, image, api_pol, change):
673673
json_schema_version = change.get('json_schema_version', 10)
674674
if path_root == 'locations':
675675
api_pol.update_locations()
676-
self._do_add_locations(image, path[1], value)
676+
self._do_add_locations(image, path[1], value, req.context)
677677
else:
678678
api_pol.update_property(path_root, value)
679679
if ((hasattr(image, path_root) or
@@ -1042,7 +1042,7 @@ def _do_replace_locations(self, image, value):
10421042
raise webob.exc.HTTPBadRequest(
10431043
explanation=encodeutils.exception_to_unicode(ve))
10441044

1045-
def _do_add_locations(self, image, path_pos, value):
1045+
def _do_add_locations(self, image, path_pos, value, context):
10461046
if CONF.show_multiple_locations == False:
10471047
msg = _("It's not allowed to add locations if locations are "
10481048
"invisible.")
@@ -1058,7 +1058,7 @@ def _do_add_locations(self, image, path_pos, value):
10581058
updated_location = value
10591059
if CONF.enabled_backends:
10601060
updated_location = store_utils.get_updated_store_location(
1061-
[value])[0]
1061+
[value], context=context)[0]
10621062

10631063
pos = self._get_locations_op_pos(path_pos,
10641064
len(image.locations), True)

glance/common/store_utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,12 @@ def _update_cinder_location_and_store_id(context, loc):
238238
"due to unknown issues."), uri)
239239

240240

241-
def get_updated_store_location(locations):
241+
def get_updated_store_location(locations, context=None):
242242
for loc in locations:
243+
if loc['url'].startswith("cinder://") and context:
244+
_update_cinder_location_and_store_id(context, loc)
245+
continue
246+
243247
store_id = _get_store_id_from_uri(loc['url'])
244248
if store_id:
245249
loc['metadata']['store'] = store_id

glance/tests/unit/common/test_utils.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ class TestCinderStoreUtils(base.MultiStoreClearingUnitTest):
102102
new_callable=mock.PropertyMock)
103103
def _test_update_cinder_store_in_location(self, mock_url_prefix,
104104
mock_associate_store,
105-
is_valid=True):
105+
is_valid=True,
106+
modify_source_url=False):
106107
volume_id = 'db457a25-8f16-4b2c-a644-eae8d17fe224'
107108
store_id = 'fast-cinder'
108109
expected = 'fast-cinder'
@@ -117,7 +118,11 @@ def _test_update_cinder_store_in_location(self, mock_url_prefix,
117118
}]
118119
mock_url_prefix.return_value = 'cinder://%s' % store_id
119120
image.locations = locations
120-
store_utils.update_store_in_locations(context, image, image_repo)
121+
if modify_source_url:
122+
updated_location = store_utils.get_updated_store_location(
123+
locations, context=context)
124+
else:
125+
store_utils.update_store_in_locations(context, image, image_repo)
121126

122127
if is_valid:
123128
# This is the case where we found an image that has an
@@ -129,10 +134,18 @@ def _test_update_cinder_store_in_location(self, mock_url_prefix,
129134
# format i.e. this is the case when store is valid and location
130135
# url, metadata are updated and image_repo.save is called
131136
expected_url = mock_url_prefix.return_value + '/' + volume_id
132-
self.assertEqual(expected_url, image.locations[0].get('url'))
133-
self.assertEqual(expected, image.locations[0]['metadata'].get(
134-
'store'))
135-
self.assertEqual(1, image_repo.save.call_count)
137+
if modify_source_url:
138+
# This is the case where location url is modified to be
139+
# compatible with multistore as below,
140+
# `cinder://store_id/volume_id` to avoid InvalidLocation error
141+
self.assertEqual(expected_url, updated_location[0].get('url'))
142+
self.assertEqual(expected,
143+
updated_location[0]['metadata'].get('store'))
144+
else:
145+
self.assertEqual(expected_url, image.locations[0].get('url'))
146+
self.assertEqual(expected, image.locations[0]['metadata'].get(
147+
'store'))
148+
self.assertEqual(1, image_repo.save.call_count)
136149
else:
137150
# Here, we've got an image backed by a volume which does
138151
# not have a corresponding store specifying the volume_type.
@@ -151,6 +164,15 @@ def test_update_cinder_store_location_valid_type(self):
151164
def test_update_cinder_store_location_invalid_type(self):
152165
self._test_update_cinder_store_in_location(is_valid=False)
153166

167+
def test_get_updated_cinder_store_location(self):
168+
"""
169+
Test if location url is modified to be compatible
170+
with multistore.
171+
"""
172+
173+
self._test_update_cinder_store_in_location(
174+
modify_source_url=True)
175+
154176

155177
class TestUtils(test_utils.BaseTestCase):
156178
"""Test routines in glance.utils"""
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
fixes:
3+
- |
4+
`Bug #2054575 <https://bugs.launchpad.net/glance/+bug/2054575>`_:
5+
Fixed the issue when cinder uploads a volume to glance in the
6+
optimized path and glance rejects the request with invalid location.
7+
Now we convert the old location format sent by cinder into the new
8+
location format supported by multi store, hence allowing volumes to
9+
be uploaded in an optimized way.

0 commit comments

Comments
 (0)