Skip to content

Commit 6a17e4e

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 (cherry picked from commit 5317526) (cherry picked from commit 8540ffc)
1 parent 3f7f01b commit 6a17e4e

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
@@ -674,7 +674,7 @@ def _do_add(self, req, image, api_pol, change):
674674
json_schema_version = change.get('json_schema_version', 10)
675675
if path_root == 'locations':
676676
api_pol.update_locations()
677-
self._do_add_locations(image, path[1], value)
677+
self._do_add_locations(image, path[1], value, req.context)
678678
else:
679679
api_pol.update_property(path_root, value)
680680
if ((hasattr(image, path_root) or
@@ -1043,7 +1043,7 @@ def _do_replace_locations(self, image, value):
10431043
raise webob.exc.HTTPBadRequest(
10441044
explanation=encodeutils.exception_to_unicode(ve))
10451045

1046-
def _do_add_locations(self, image, path_pos, value):
1046+
def _do_add_locations(self, image, path_pos, value, context):
10471047
if CONF.show_multiple_locations == False:
10481048
msg = _("It's not allowed to add locations if locations are "
10491049
"invisible.")
@@ -1059,7 +1059,7 @@ def _do_add_locations(self, image, path_pos, value):
10591059
updated_location = value
10601060
if CONF.enabled_backends:
10611061
updated_location = store_utils.get_updated_store_location(
1062-
[value])[0]
1062+
[value], context=context)[0]
10631063

10641064
pos = self._get_locations_op_pos(path_pos,
10651065
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)