Merge "Make location API compatible with multiple store"
This commit is contained in:
commit
d9f4451828
@ -33,6 +33,7 @@ from glance.api import common
|
|||||||
from glance.api import policy
|
from glance.api import policy
|
||||||
from glance.common import exception
|
from glance.common import exception
|
||||||
from glance.common import location_strategy
|
from glance.common import location_strategy
|
||||||
|
from glance.common import store_utils
|
||||||
from glance.common import timeutils
|
from glance.common import timeutils
|
||||||
from glance.common import utils
|
from glance.common import utils
|
||||||
from glance.common import wsgi
|
from glance.common import wsgi
|
||||||
@ -506,6 +507,9 @@ class ImagesController(object):
|
|||||||
raise webob.exc.HTTPConflict(explanation=msg)
|
raise webob.exc.HTTPConflict(explanation=msg)
|
||||||
|
|
||||||
val_data = self._validate_validation_data(image, value)
|
val_data = self._validate_validation_data(image, value)
|
||||||
|
# NOTE(abhishekk): get glance store based on location uri
|
||||||
|
if CONF.enabled_backends:
|
||||||
|
store_utils.update_store_in_locations(value, image.image_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# NOTE(flwang): _locations_proxy's setattr method will check if
|
# NOTE(flwang): _locations_proxy's setattr method will check if
|
||||||
@ -533,6 +537,9 @@ class ImagesController(object):
|
|||||||
raise webob.exc.HTTPConflict(explanation=msg)
|
raise webob.exc.HTTPConflict(explanation=msg)
|
||||||
|
|
||||||
val_data = self._validate_validation_data(image, [value])
|
val_data = self._validate_validation_data(image, [value])
|
||||||
|
# NOTE(abhishekk): get glance store based on location uri
|
||||||
|
if CONF.enabled_backends:
|
||||||
|
store_utils.update_store_in_locations([value], image.image_id)
|
||||||
|
|
||||||
pos = self._get_locations_op_pos(path_pos,
|
pos = self._get_locations_op_pos(path_pos,
|
||||||
len(image.locations), True)
|
len(image.locations), True)
|
||||||
|
@ -23,10 +23,38 @@ import six
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from glance.common import exception
|
from glance.common import exception
|
||||||
|
from glance.common import store_utils
|
||||||
from glance.common import utils
|
from glance.common import utils
|
||||||
from glance.tests import utils as test_utils
|
from glance.tests import utils as test_utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestStoreUtils(test_utils.BaseTestCase):
|
||||||
|
"""Test glance.common.store_utils module"""
|
||||||
|
|
||||||
|
def _test_update_store_in_location(self, metadata, store_id, expected):
|
||||||
|
locations = [{
|
||||||
|
'url': 'rbd://aaaaaaaa/images/id',
|
||||||
|
'metadata': metadata
|
||||||
|
}]
|
||||||
|
with mock.patch.object(
|
||||||
|
store_utils, '_get_store_id_from_uri') as mock_get_store_id:
|
||||||
|
mock_get_store_id.return_value = store_id
|
||||||
|
store_utils.update_store_in_locations(locations, mock.Mock())
|
||||||
|
self.assertEqual(locations[0]['metadata'].get('store'), expected)
|
||||||
|
|
||||||
|
def test_update_store_location_with_no_store(self):
|
||||||
|
self._test_update_store_in_location({}, 'rbd1', 'rbd1')
|
||||||
|
|
||||||
|
def test_update_store_location_with_different_store(self):
|
||||||
|
self._test_update_store_in_location({'store': 'rbd2'}, 'rbd1', 'rbd1')
|
||||||
|
|
||||||
|
def test_update_store_location_with_same_store(self):
|
||||||
|
self._test_update_store_in_location({'store': 'rbd1'}, 'rbd1', 'rbd1')
|
||||||
|
|
||||||
|
def test_update_store_location_with_store_none(self):
|
||||||
|
self._test_update_store_in_location({}, None, None)
|
||||||
|
|
||||||
|
|
||||||
class TestUtils(test_utils.BaseTestCase):
|
class TestUtils(test_utils.BaseTestCase):
|
||||||
"""Test routines in glance.utils"""
|
"""Test routines in glance.utils"""
|
||||||
|
|
||||||
|
@ -1784,6 +1784,112 @@ class TestImagesController(base.IsolatedUnitTest):
|
|||||||
self.assertEqual('sha512', output.os_hash_algo)
|
self.assertEqual('sha512', output.os_hash_algo)
|
||||||
self.assertEqual(MULTIHASH1, output.os_hash_value)
|
self.assertEqual(MULTIHASH1, output.os_hash_value)
|
||||||
|
|
||||||
|
@mock.patch.object(glance.quota, '_calc_required_size')
|
||||||
|
@mock.patch.object(glance.location, '_check_image_location')
|
||||||
|
@mock.patch.object(glance.location.ImageRepoProxy, '_set_acls')
|
||||||
|
@mock.patch.object(store, 'get_size_from_uri_and_backend')
|
||||||
|
@mock.patch.object(store, 'get_size_from_backend')
|
||||||
|
def test_replace_locations_identify_associated_store(
|
||||||
|
self, mock_get_size, mock_get_size_uri, mock_set_acls,
|
||||||
|
mock_check_loc, mock_calc):
|
||||||
|
mock_calc.return_value = 1
|
||||||
|
mock_get_size.return_value = 1
|
||||||
|
mock_get_size_uri.return_value = 1
|
||||||
|
self.config(show_multiple_locations=True)
|
||||||
|
self.config(enabled_backends={'fake-store': 'http'})
|
||||||
|
image_id = str(uuid.uuid4())
|
||||||
|
self.images = [
|
||||||
|
_db_fixture(image_id, owner=TENANT1,
|
||||||
|
name='1',
|
||||||
|
disk_format='raw',
|
||||||
|
container_format='bare',
|
||||||
|
status='queued',
|
||||||
|
checksum=None,
|
||||||
|
os_hash_algo=None,
|
||||||
|
os_hash_value=None),
|
||||||
|
]
|
||||||
|
self.db.image_create(None, self.images[0])
|
||||||
|
request = unit_test_utils.get_fake_request()
|
||||||
|
new_location1 = {'url': '%s/fake_location_1' % BASE_URI,
|
||||||
|
'metadata': {},
|
||||||
|
'validation_data': {'checksum': CHKSUM,
|
||||||
|
'os_hash_algo': 'sha512',
|
||||||
|
'os_hash_value': MULTIHASH1}}
|
||||||
|
new_location2 = {'url': '%s/fake_location_2' % BASE_URI,
|
||||||
|
'metadata': {},
|
||||||
|
'validation_data': {'checksum': CHKSUM,
|
||||||
|
'os_hash_algo': 'sha512',
|
||||||
|
'os_hash_value': MULTIHASH1}}
|
||||||
|
changes = [{'op': 'replace', 'path': ['locations'],
|
||||||
|
'value': [new_location1, new_location2]}]
|
||||||
|
|
||||||
|
with mock.patch.object(store_utils,
|
||||||
|
'_get_store_id_from_uri') as mock_store:
|
||||||
|
mock_store.return_value = 'fake-store'
|
||||||
|
# ensure location metadata is updated
|
||||||
|
new_location1['metadata']['store'] = 'fake-store'
|
||||||
|
new_location1['metadata']['store'] = 'fake-store'
|
||||||
|
|
||||||
|
output = self.controller.update(request, image_id, changes)
|
||||||
|
self.assertEqual(2, len(output.locations))
|
||||||
|
self.assertEqual(image_id, output.image_id)
|
||||||
|
self.assertEqual(new_location1, output.locations[0])
|
||||||
|
self.assertEqual(new_location2, output.locations[1])
|
||||||
|
self.assertEqual('active', output.status)
|
||||||
|
self.assertEqual(CHKSUM, output.checksum)
|
||||||
|
self.assertEqual('sha512', output.os_hash_algo)
|
||||||
|
self.assertEqual(MULTIHASH1, output.os_hash_value)
|
||||||
|
|
||||||
|
@mock.patch.object(glance.quota, '_calc_required_size')
|
||||||
|
@mock.patch.object(glance.location, '_check_image_location')
|
||||||
|
@mock.patch.object(glance.location.ImageRepoProxy, '_set_acls')
|
||||||
|
@mock.patch.object(store, 'get_size_from_uri_and_backend')
|
||||||
|
@mock.patch.object(store, 'get_size_from_backend')
|
||||||
|
def test_replace_locations_unknon_locations(
|
||||||
|
self, mock_get_size, mock_get_size_uri, mock_set_acls,
|
||||||
|
mock_check_loc, mock_calc):
|
||||||
|
mock_calc.return_value = 1
|
||||||
|
mock_get_size.return_value = 1
|
||||||
|
mock_get_size_uri.return_value = 1
|
||||||
|
self.config(show_multiple_locations=True)
|
||||||
|
self.config(enabled_backends={'fake-store': 'http'})
|
||||||
|
image_id = str(uuid.uuid4())
|
||||||
|
self.images = [
|
||||||
|
_db_fixture(image_id, owner=TENANT1,
|
||||||
|
name='1',
|
||||||
|
disk_format='raw',
|
||||||
|
container_format='bare',
|
||||||
|
status='queued',
|
||||||
|
checksum=None,
|
||||||
|
os_hash_algo=None,
|
||||||
|
os_hash_value=None),
|
||||||
|
]
|
||||||
|
self.db.image_create(None, self.images[0])
|
||||||
|
request = unit_test_utils.get_fake_request()
|
||||||
|
new_location1 = {'url': 'unknown://whocares',
|
||||||
|
'metadata': {},
|
||||||
|
'validation_data': {'checksum': CHKSUM,
|
||||||
|
'os_hash_algo': 'sha512',
|
||||||
|
'os_hash_value': MULTIHASH1}}
|
||||||
|
new_location2 = {'url': 'unknown://whatever',
|
||||||
|
'metadata': {'store': 'unkstore'},
|
||||||
|
'validation_data': {'checksum': CHKSUM,
|
||||||
|
'os_hash_algo': 'sha512',
|
||||||
|
'os_hash_value': MULTIHASH1}}
|
||||||
|
changes = [{'op': 'replace', 'path': ['locations'],
|
||||||
|
'value': [new_location1, new_location2]}]
|
||||||
|
|
||||||
|
output = self.controller.update(request, image_id, changes)
|
||||||
|
self.assertEqual(2, len(output.locations))
|
||||||
|
self.assertEqual(image_id, output.image_id)
|
||||||
|
self.assertEqual('active', output.status)
|
||||||
|
self.assertEqual(CHKSUM, output.checksum)
|
||||||
|
self.assertEqual('sha512', output.os_hash_algo)
|
||||||
|
self.assertEqual(MULTIHASH1, output.os_hash_value)
|
||||||
|
# ensure location metadata is same
|
||||||
|
self.assertEqual(new_location1, output.locations[0])
|
||||||
|
self.assertEqual(new_location2, output.locations[1])
|
||||||
|
|
||||||
@mock.patch.object(glance.quota, '_calc_required_size')
|
@mock.patch.object(glance.quota, '_calc_required_size')
|
||||||
@mock.patch.object(glance.location, '_check_image_location')
|
@mock.patch.object(glance.location, '_check_image_location')
|
||||||
@mock.patch.object(glance.location.ImageRepoProxy, '_set_acls')
|
@mock.patch.object(glance.location.ImageRepoProxy, '_set_acls')
|
||||||
@ -1902,6 +2008,82 @@ class TestImagesController(base.IsolatedUnitTest):
|
|||||||
self.assertEqual(new_location, output.locations[0])
|
self.assertEqual(new_location, output.locations[0])
|
||||||
self.assertEqual('active', output.status)
|
self.assertEqual('active', output.status)
|
||||||
|
|
||||||
|
@mock.patch.object(glance.quota, '_calc_required_size')
|
||||||
|
@mock.patch.object(glance.location, '_check_image_location')
|
||||||
|
@mock.patch.object(glance.location.ImageRepoProxy, '_set_acls')
|
||||||
|
@mock.patch.object(store, 'get_size_from_uri_and_backend')
|
||||||
|
@mock.patch.object(store, 'get_size_from_backend')
|
||||||
|
def test_add_location_identify_associated_store(
|
||||||
|
self, mock_get_size, mock_get_size_uri, mock_set_acls,
|
||||||
|
mock_check_loc, mock_calc):
|
||||||
|
mock_calc.return_value = 1
|
||||||
|
mock_get_size.return_value = 1
|
||||||
|
mock_get_size_uri.return_value = 1
|
||||||
|
self.config(show_multiple_locations=True)
|
||||||
|
self.config(enabled_backends={'fake-store': 'http'})
|
||||||
|
image_id = str(uuid.uuid4())
|
||||||
|
self.images = [
|
||||||
|
_db_fixture(image_id, owner=TENANT1, checksum=CHKSUM,
|
||||||
|
name='1',
|
||||||
|
disk_format='raw',
|
||||||
|
container_format='bare',
|
||||||
|
status='queued'),
|
||||||
|
]
|
||||||
|
self.db.image_create(None, self.images[0])
|
||||||
|
request = unit_test_utils.get_fake_request()
|
||||||
|
new_location = {'url': '%s/fake_location_1' % BASE_URI,
|
||||||
|
'metadata': {}}
|
||||||
|
changes = [{'op': 'add', 'path': ['locations', '-'],
|
||||||
|
'value': new_location}]
|
||||||
|
with mock.patch.object(store_utils,
|
||||||
|
'_get_store_id_from_uri') as mock_store:
|
||||||
|
mock_store.return_value = 'fake-store'
|
||||||
|
output = self.controller.update(request, image_id, changes)
|
||||||
|
|
||||||
|
self.assertEqual(image_id, output.image_id)
|
||||||
|
self.assertEqual(1, len(output.locations))
|
||||||
|
self.assertEqual('active', output.status)
|
||||||
|
# ensure location metadata is updated
|
||||||
|
new_location['metadata']['store'] = 'fake-store'
|
||||||
|
self.assertEqual(new_location, output.locations[0])
|
||||||
|
|
||||||
|
@mock.patch.object(glance.quota, '_calc_required_size')
|
||||||
|
@mock.patch.object(glance.location, '_check_image_location')
|
||||||
|
@mock.patch.object(glance.location.ImageRepoProxy, '_set_acls')
|
||||||
|
@mock.patch.object(store, 'get_size_from_uri_and_backend')
|
||||||
|
@mock.patch.object(store, 'get_size_from_backend')
|
||||||
|
def test_add_location_unknown_locations(
|
||||||
|
self, mock_get_size, mock_get_size_uri, mock_set_acls,
|
||||||
|
mock_check_loc, mock_calc):
|
||||||
|
mock_calc.return_value = 1
|
||||||
|
mock_get_size.return_value = 1
|
||||||
|
mock_get_size_uri.return_value = 1
|
||||||
|
self.config(show_multiple_locations=True)
|
||||||
|
self.config(enabled_backends={'fake-store': 'http'})
|
||||||
|
image_id = str(uuid.uuid4())
|
||||||
|
|
||||||
|
self.images = [
|
||||||
|
_db_fixture(image_id, owner=TENANT1, checksum=CHKSUM,
|
||||||
|
name='1',
|
||||||
|
disk_format='raw',
|
||||||
|
container_format='bare',
|
||||||
|
status='queued'),
|
||||||
|
]
|
||||||
|
self.db.image_create(None, self.images[0])
|
||||||
|
|
||||||
|
new_location = {'url': 'unknown://whocares', 'metadata': {}}
|
||||||
|
request = unit_test_utils.get_fake_request()
|
||||||
|
changes = [{'op': 'add', 'path': ['locations', '-'],
|
||||||
|
'value': new_location}]
|
||||||
|
|
||||||
|
output = self.controller.update(request, image_id, changes)
|
||||||
|
|
||||||
|
self.assertEqual(image_id, output.image_id)
|
||||||
|
self.assertEqual('active', output.status)
|
||||||
|
self.assertEqual(1, len(output.locations))
|
||||||
|
# ensure location metadata is same
|
||||||
|
self.assertEqual(new_location, output.locations[0])
|
||||||
|
|
||||||
@mock.patch.object(glance.quota, '_calc_required_size')
|
@mock.patch.object(glance.quota, '_calc_required_size')
|
||||||
@mock.patch.object(glance.location, '_check_image_location')
|
@mock.patch.object(glance.location, '_check_image_location')
|
||||||
@mock.patch.object(glance.location.ImageRepoProxy, '_set_acls')
|
@mock.patch.object(glance.location.ImageRepoProxy, '_set_acls')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user