Move _get_locations to module level plus tests

Moves the nova.image.glance.GlanceImageService._get_locations object
method into module level scope (the self argument was unused) and
adds full unit tests for the nova.image.glance._get_location() function.

Change-Id: Ib386330b70abe1e0353f1fafa3e68bc3e7a2d1b1
Partial-bug: #1293938
This commit is contained in:
Jay Pipes 2014-04-07 00:30:21 -04:00
parent de9f5feba4
commit 9048078fcc
2 changed files with 82 additions and 20 deletions

View File

@ -277,25 +277,6 @@ class GlanceImageService(object):
base_image_meta = _translate_from_glance(image)
return base_image_meta
def _get_locations(self, context, image_id):
"""Returns the direct url representing the backend storage location,
or None if this attribute is not shown by Glance.
"""
try:
client = GlanceClientWrapper()
image_meta = client.call(context, 2, 'get', image_id)
except Exception:
_reraise_translated_image_exception(image_id)
if not _is_image_available(context, image_meta):
raise exception.ImageNotFound(image_id=image_id)
locations = getattr(image_meta, 'locations', [])
du = getattr(image_meta, 'direct_url', None)
if du:
locations.append({'url': du, 'metadata': {}})
return locations
def _get_transfer_module(self, scheme):
try:
return self._download_handlers[scheme]
@ -309,7 +290,7 @@ class GlanceImageService(object):
def download(self, context, image_id, data=None, dst_path=None):
"""Calls out to Glance for data and writes data."""
if CONF.allowed_direct_url_schemes and dst_path is not None:
locations = self._get_locations(context, image_id)
locations = _get_locations(self._client, context, image_id)
for entry in locations:
loc_url = entry['url']
loc_meta = entry['metadata']
@ -395,6 +376,25 @@ class GlanceImageService(object):
return True
def _get_locations(client, context, image_id):
"""Returns the direct url representing the backend storage location,
or None if this attribute is not shown by Glance.
"""
try:
image_meta = client.call(context, 2, 'get', image_id)
except Exception:
_reraise_translated_image_exception(image_id)
if not _is_image_available(context, image_meta):
raise exception.ImageNotFound(image_id=image_id)
locations = getattr(image_meta, 'locations', [])
du = getattr(image_meta, 'direct_url', None)
if du:
locations.append({'url': du, 'metadata': {}})
return locations
def _extract_query_params(params):
_params = {}
accepted_params = ('filters', 'marker', 'limit',

View File

@ -466,6 +466,68 @@ def _create_failing_glance_client(info):
return MyGlanceStubClient()
class TestGetLocations(test.NoDBTestCase):
"""Tests the internal _get_locations function."""
class ImageSpecV2(object):
visibility = None
properties = None
locations = None
direct_url = None
@mock.patch('nova.image.glance._is_image_available')
def test_success_has_locations(self, avail_mock):
avail_mock.return_value = True
locations = [
mock.sentinel.loc1
]
image_meta = mock.MagicMock(locations=locations,
spec=TestGetLocations.ImageSpecV2)
client_mock = mock.MagicMock()
client_mock.call.return_value = image_meta
locs = glance._get_locations(client_mock, mock.sentinel.ctx,
mock.sentinel.image_id)
client_mock.call.assert_called_once_with(mock.sentinel.ctx,
2, 'get',
mock.sentinel.image_id)
self.assertEqual(locations, locs)
avail_mock.assert_called_once_with(mock.sentinel.ctx, image_meta)
@mock.patch('nova.image.glance._is_image_available')
def test_success_direct_uri_added_to_locations(self, avail_mock):
avail_mock.return_value = True
locations = [
mock.sentinel.loc1
]
image_meta = mock.MagicMock(locations=locations,
spec=TestGetLocations.ImageSpecV2,
direct_uri=mock.sentinel.duri)
client_mock = mock.MagicMock()
client_mock.call.return_value = image_meta
locs = glance._get_locations(client_mock, mock.sentinel.ctx,
mock.sentinel.image_id)
client_mock.call.assert_called_once_with(mock.sentinel.ctx,
2, 'get',
mock.sentinel.image_id)
expected = locations
expected.append({"url": mock.sentinel.duri, "metadata": {}})
self.assertEqual(expected, locs)
@mock.patch('nova.image.glance._reraise_translated_image_exception')
@mock.patch('nova.image.glance._is_image_available')
def test_get_locations_not_found(self, avail_mock, reraise_mock):
raised = exception.ImageNotFound(image_id=123)
reraise_mock.side_effect = raised
client_mock = mock.MagicMock()
client_mock.call.side_effect = glanceclient.exc.NotFound
self.assertRaises(exception.ImageNotFound, glance._get_locations,
client_mock, mock.sentinel.ctx,
mock.sentinel.image_id)
class TestIsImageAvailable(test.NoDBTestCase):
"""Tests the internal _is_image_available function."""