diff options
author | Jay Pipes <jaypipes@gmail.com> | 2014-03-11 17:29:37 -0400 |
---|---|---|
committer | Jay Pipes <jaypipes@gmail.com> | 2014-03-11 21:42:32 -0400 |
commit | 8babd6a99014ccaf51d955769eaec085e037cc76 (patch) | |
tree | 593832cbe2dcf4acb75ea95db2d1dd9060c2beff /nova/tests/image | |
parent | 556ab844c823dd364032d59ab1b61780243cbfd1 (diff) | |
download | nova-8babd6a99014ccaf51d955769eaec085e037cc76.tar.gz |
Ensure is_image_available handles V2 Glance API
The V2 Glance API uses warlock to validate returned models
from calls such as GET /images/{id}. The get_locations() call in
the Nova Glance image driver was using the V2 Glance API call
to GET /images/{id} (which is correct, since image locations only
exist in the V2 API), but the GlanceImageService._is_image_available()
method was checking the is_public attribute of the supplied image model.
This caused warlock to throw an exception since is_public is not
an attribute on the V2 API's returned image model in glanceclient.
This change adds some checks that can handle both the V2 and V1 returned
image models from glanceclient and a bunch of unit tests to thoroughly
exercise the is_image_available method.
Change-Id: I35b5af8331c5972bd89e1a674091fa2e3bde28a7
Closes-bug: #1291014
Diffstat (limited to 'nova/tests/image')
-rw-r--r-- | nova/tests/image/test_glance.py | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index abb69e10cf..4250566cc6 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -767,6 +767,129 @@ def _create_failing_glance_client(info): return MyGlanceStubClient() +class TestIsImageAvailable(test.NoDBTestCase): + """Tests the internal _is_image_available method on the Glance service.""" + + class ImageSpecV2(object): + visibility = None + properties = None + + class ImageSpecV1(object): + is_public = None + properties = None + + def test_auth_token_override(self): + ctx = mock.MagicMock(auth_token=True) + img = mock.MagicMock() + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + img.assert_not_called() + + def test_admin_override(self): + ctx = mock.MagicMock(auth_token=False, is_admin=True) + img = mock.MagicMock() + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + img.assert_not_called() + + def test_v2_visibility(self): + ctx = mock.MagicMock(auth_token=False, is_admin=False) + # We emulate warlock validation that throws an AttributeError + # if you try to call is_public on an image model returned by + # a call to V2 image.get(). Here, the ImageSpecV2 does not have + # an is_public attribute and MagicMock will throw an AttributeError. + img = mock.MagicMock(visibility='PUBLIC', + spec=TestIsImageAvailable.ImageSpecV2) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + + def test_v1_is_public(self): + ctx = mock.MagicMock(auth_token=False, is_admin=False) + img = mock.MagicMock(is_public=True, + spec=TestIsImageAvailable.ImageSpecV1) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + + def test_project_is_owner(self): + ctx = mock.MagicMock(auth_token=False, is_admin=False, + project_id='123') + props = { + 'owner_id': '123' + } + img = mock.MagicMock(visibility='private', properties=props, + spec=TestIsImageAvailable.ImageSpecV2) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + + ctx.reset_mock() + img = mock.MagicMock(is_public=False, properties=props, + spec=TestIsImageAvailable.ImageSpecV1) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + + def test_project_context_matches_project_prop(self): + ctx = mock.MagicMock(auth_token=False, is_admin=False, + project_id='123') + props = { + 'project_id': '123' + } + img = mock.MagicMock(visibility='private', properties=props, + spec=TestIsImageAvailable.ImageSpecV2) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + + ctx.reset_mock() + img = mock.MagicMock(is_public=False, properties=props, + spec=TestIsImageAvailable.ImageSpecV1) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + + def test_no_user_in_props(self): + ctx = mock.MagicMock(auth_token=False, is_admin=False, + project_id='123') + props = { + } + img = mock.MagicMock(visibility='private', properties=props, + spec=TestIsImageAvailable.ImageSpecV2) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertFalse(res) + + ctx.reset_mock() + img = mock.MagicMock(is_public=False, properties=props, + spec=TestIsImageAvailable.ImageSpecV1) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertFalse(res) + + def test_user_matches_context(self): + ctx = mock.MagicMock(auth_token=False, is_admin=False, + user_id='123') + props = { + 'user_id': '123' + } + img = mock.MagicMock(visibility='private', properties=props, + spec=TestIsImageAvailable.ImageSpecV2) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + + ctx.reset_mock() + img = mock.MagicMock(is_public=False, properties=props, + spec=TestIsImageAvailable.ImageSpecV1) + + res = glance.GlanceImageService._is_image_available(ctx, img) + self.assertTrue(res) + + class TestGlanceClientWrapper(test.NoDBTestCase): def setUp(self): |