From 29692ee4f57a8ad961bd227b13583149906eec55 Mon Sep 17 00:00:00 2001 From: Rabi Mishra Date: Fri, 18 Dec 2015 08:54:31 +0530 Subject: [PATCH] Use custom find functions for image lookup Use get interface and custom find functions to look for images by id/name. Find interface is now implemented in the client plugin itslef, as glanceclient v2 does not support it. Once it's implemented in galnceclient v2, we can leverage images.find interface directly. This also leverges openstack.common.apicient.exceptions. Change-Id: Ibf85495b9d5533c759c4e63284806f11e6e45413 --- .../rackspace/resources/auto_scale.py | 2 +- .../rackspace/tests/test_auto_scale.py | 3 +- .../tests/test_rackspace_cloud_server.py | 8 +- heat/engine/clients/os/glance.py | 73 ++++++------- heat/engine/resources/aws/ec2/instance.py | 3 +- .../resources/openstack/cinder/volume.py | 3 +- .../engine/resources/openstack/nova/server.py | 6 +- .../resources/openstack/sahara/cluster.py | 3 +- .../resources/openstack/sahara/image.py | 3 +- heat/tests/aws/test_instance.py | 37 +++---- heat/tests/aws/test_instance_network.py | 5 +- heat/tests/clients/test_clients.py | 25 ++++- heat/tests/clients/test_glance_client.py | 103 +++++------------- heat/tests/db/test_sqlalchemy_api.py | 5 +- .../tests/engine/service/test_stack_create.py | 2 +- heat/tests/engine/tools.py | 5 +- heat/tests/openstack/cinder/test_volume.py | 5 +- heat/tests/openstack/nova/fakes.py | 1 + heat/tests/openstack/nova/test_server.py | 49 +++++---- heat/tests/openstack/sahara/test_cluster.py | 3 +- heat/tests/openstack/sahara/test_image.py | 3 +- heat/tests/test_nokey.py | 5 +- heat/tests/test_server_tags.py | 5 +- heat/tests/test_validate.py | 18 +-- 24 files changed, 175 insertions(+), 200 deletions(-) diff --git a/contrib/rackspace/rackspace/resources/auto_scale.py b/contrib/rackspace/rackspace/resources/auto_scale.py index 068500fc80..3230f01be5 100644 --- a/contrib/rackspace/rackspace/resources/auto_scale.py +++ b/contrib/rackspace/rackspace/resources/auto_scale.py @@ -309,7 +309,7 @@ class Group(resource.Resource): user_data = server_args.get(self.LAUNCH_CONFIG_ARGS_SERVER_USER_DATA) cdrive = (server_args.get(self.LAUNCH_CONFIG_ARGS_SERVER_CDRIVE) or bool(user_data is not None and len(user_data.strip()))) - image_id = self.client_plugin('glance').get_image_id( + image_id = self.client_plugin('glance').find_image_by_name_or_id( server_args[self.LAUNCH_CONFIG_ARGS_SERVER_IMAGE_REF]) flavor_id = self.client_plugin('nova').find_flavor_by_name_or_id( server_args[self.LAUNCH_CONFIG_ARGS_SERVER_FLAVOR_REF]) diff --git a/contrib/rackspace/rackspace/tests/test_auto_scale.py b/contrib/rackspace/rackspace/tests/test_auto_scale.py index 2104fe5fed..bd8343c7b8 100644 --- a/contrib/rackspace/rackspace/tests/test_auto_scale.py +++ b/contrib/rackspace/rackspace/tests/test_auto_scale.py @@ -215,7 +215,8 @@ class ScalingGroupTest(common.HeatTestCase): self.patchobject(auto_scale.Group, 'auto_scale', return_value=self.fake_auto_scale) # mock nova and glance client methods to satisfy contraints - mock_im = self.patchobject(glance.GlanceClientPlugin, 'get_image_id') + mock_im = self.patchobject(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') mock_im.return_value = 'image-ref' mock_fl = self.patchobject(nova.NovaClientPlugin, 'find_flavor_by_name_or_id') diff --git a/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py b/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py index 6bdfe4fdde..54a0136839 100644 --- a/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py +++ b/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py @@ -76,15 +76,15 @@ class CloudServersTest(common.HeatTestCase): resource._register_class("OS::Nova::Server", cloud_server.CloudServer) - def _mock_get_image_id_success(self, imageId): + def _mock_find_image_by_name_or_id_success(self, imageId): self.mock_get_image = mock.Mock() self.ctx.clients.client_plugin( - 'glance').get_image_id = self.mock_get_image + 'glance').find_image_by_name_or_id = self.mock_get_image self.mock_get_image.return_value = imageId def _stub_server_validate(self, server, imageId_input, image_id): # stub glance image validate - self._mock_get_image_id_success(image_id) + self._mock_find_image_by_name_or_id_success(image_id) def _setup_test_stack(self, stack_name): t = template_format.parse(wp_template) @@ -472,7 +472,7 @@ class CloudServersTest(common.HeatTestCase): mock_servers_create = mock.Mock(return_value=return_server) self.fc.servers.create = mock_servers_create image_id = mock.ANY - self._mock_get_image_id_success(image_id) + self._mock_find_image_by_name_or_id_success(image_id) self.m.StubOutWithMock(self.fc.servers, 'get') self.fc.servers.get(return_server.id).MultipleTimes( ).AndReturn(return_server) diff --git a/heat/engine/clients/os/glance.py b/heat/engine/clients/os/glance.py index 498ccb4c87..d993d51d95 100644 --- a/heat/engine/clients/os/glance.py +++ b/heat/engine/clients/os/glance.py @@ -13,10 +13,8 @@ from glanceclient import client as gc from glanceclient import exc -from oslo_utils import uuidutils +from glanceclient.openstack.common.apiclient import exceptions -from heat.common import exception -from heat.common.i18n import _ from heat.engine.clients import client_plugin from heat.engine import constraints @@ -25,7 +23,7 @@ CLIENT_NAME = 'glance' class GlanceClientPlugin(client_plugin.ClientPlugin): - exceptions_module = exc + exceptions_module = [exceptions, exc] service_types = [IMAGE] = ['image'] @@ -49,57 +47,50 @@ class GlanceClientPlugin(client_plugin.ClientPlugin): return gc.Client('1', endpoint, **args) + def _find_with_attr(self, entity, **kwargs): + """Find a item for entity with attributes matching ``**kwargs``.""" + matches = list(self._findall_with_attr(entity, **kwargs)) + num_matches = len(matches) + if num_matches == 0: + msg = ("No %(name)s matching %(args)s.") % { + 'name': entity, + 'args': kwargs + } + raise exceptions.NotFound(msg) + elif num_matches > 1: + raise exceptions.NoUniqueMatch() + else: + return matches[0] + + def _findall_with_attr(self, entity, **kwargs): + """Find all items for entity with attributes matching ``**kwargs``.""" + func = getattr(self.client(), entity) + filters = {'filters': kwargs} + return func.list(**filters) + def is_not_found(self, ex): - return isinstance(ex, exc.HTTPNotFound) + return isinstance(ex, (exceptions.NotFound, exc.HTTPNotFound)) def is_over_limit(self, ex): return isinstance(ex, exc.HTTPOverLimit) def is_conflict(self, ex): - return isinstance(ex, exc.HTTPConflict) + return isinstance(ex, (exceptions.Conflict, exc.Conflict)) - def get_image_id(self, image_identifier): + def find_image_by_name_or_id(self, image_identifier): """Return the ID for the specified image name or identifier. :param image_identifier: image name or a UUID-like identifier :returns: the id of the requested :image_identifier: - :raises: exception.EntityNotFound, - exception.PhysicalResourceNameAmbiguity - """ - if uuidutils.is_uuid_like(image_identifier): - try: - image_id = self.client().images.get(image_identifier).id - except exc.HTTPNotFound: - image_id = self.get_image_id_by_name(image_identifier) - else: - image_id = self.get_image_id_by_name(image_identifier) - return image_id - - def get_image_id_by_name(self, image_identifier): - """Return the ID for the specified image name. - - :param image_identifier: image name - :returns: the id of the requested :image_identifier: - :raises: exception.EntityNotFound, - exception.PhysicalResourceNameAmbiguity """ try: - filters = {'name': image_identifier} - image_list = list(self.client().images.list(filters=filters)) - except exc.ClientException as ex: - raise exception.Error( - _("Error retrieving image list from glance: %s") % ex) - num_matches = len(image_list) - if num_matches == 0: - raise exception.EntityNotFound(entity='Image', - name=image_identifier) - elif num_matches > 1: - raise exception.PhysicalResourceNameAmbiguity( - name=image_identifier) - else: - return image_list[0].id + return self.client().images.get(image_identifier).id + except exc.HTTPNotFound: + return self._find_with_attr('images', name=image_identifier).id class ImageConstraint(constraints.BaseCustomConstraint): + expected_exceptions = (exceptions.NotFound, exceptions.NoUniqueMatch) + resource_client_name = CLIENT_NAME - resource_getter_name = 'get_image_id' + resource_getter_name = 'find_image_by_name_or_id' diff --git a/heat/engine/resources/aws/ec2/instance.py b/heat/engine/resources/aws/ec2/instance.py index 4e9d78193a..2d28d151e1 100644 --- a/heat/engine/resources/aws/ec2/instance.py +++ b/heat/engine/resources/aws/ec2/instance.py @@ -510,7 +510,8 @@ class Instance(resource.Resource, sh.SchedulerHintsMixin): image_name = self.properties[self.IMAGE_ID] - image_id = self.client_plugin('glance').get_image_id(image_name) + image_id = self.client_plugin( + 'glance').find_image_by_name_or_id(image_name) flavor_id = self.client_plugin().find_flavor_by_name_or_id(flavor) diff --git a/heat/engine/resources/openstack/cinder/volume.py b/heat/engine/resources/openstack/cinder/volume.py index c261bc4e0c..1f9d2fca47 100644 --- a/heat/engine/resources/openstack/cinder/volume.py +++ b/heat/engine/resources/openstack/cinder/volume.py @@ -260,7 +260,8 @@ class CinderVolume(vb.BaseVolume, sh.SchedulerHintsMixin): arguments[self.CINDER_SCHEDULER_HINTS] = scheduler_hints if self.properties[self.IMAGE]: - arguments['imageRef'] = self.client_plugin('glance').get_image_id( + arguments['imageRef'] = self.client_plugin( + 'glance').find_image_by_name_or_id( self.properties[self.IMAGE]) elif self.properties[self.IMAGE_REF]: arguments['imageRef'] = self.properties[self.IMAGE_REF] diff --git a/heat/engine/resources/openstack/nova/server.py b/heat/engine/resources/openstack/nova/server.py index 9bc75d08a3..23a792a418 100644 --- a/heat/engine/resources/openstack/nova/server.py +++ b/heat/engine/resources/openstack/nova/server.py @@ -733,7 +733,8 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin, image = self.properties[self.IMAGE] if image: - image = self.client_plugin('glance').get_image_id(image) + image = self.client_plugin( + 'glance').find_image_by_name_or_id(image) flavor_id = self.client_plugin().find_flavor_by_name_or_id(flavor) @@ -989,7 +990,8 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin, prop_diff.get(self.IMAGE_UPDATE_POLICY) or self.properties[self.IMAGE_UPDATE_POLICY]) image = prop_diff[self.IMAGE] - image_id = self.client_plugin('glance').get_image_id(image) + image_id = self.client_plugin( + 'glance').find_image_by_name_or_id(image) preserve_ephemeral = ( image_update_policy == 'REBUILD_PRESERVE_EPHEMERAL') password = (prop_diff.get(self.ADMIN_PASS) or diff --git a/heat/engine/resources/openstack/sahara/cluster.py b/heat/engine/resources/openstack/sahara/cluster.py index cafd7e40df..c2bf7ec460 100644 --- a/heat/engine/resources/openstack/sahara/cluster.py +++ b/heat/engine/resources/openstack/sahara/cluster.py @@ -196,7 +196,8 @@ class SaharaCluster(resource.Resource): image_id = (self.properties[self.IMAGE_ID] or self.properties[self.IMAGE]) if image_id: - image_id = self.client_plugin('glance').get_image_id(image_id) + image_id = self.client_plugin( + 'glance').find_image_by_name_or_id(image_id) # check that image is provided in case when # cluster template is missing one diff --git a/heat/engine/resources/openstack/sahara/image.py b/heat/engine/resources/openstack/sahara/image.py index bdc75b2dfe..fb1da0abb5 100644 --- a/heat/engine/resources/openstack/sahara/image.py +++ b/heat/engine/resources/openstack/sahara/image.py @@ -71,7 +71,8 @@ class SaharaImageRegistry(resource.Resource): entity = 'images' def handle_create(self): - self.resource_id_set(self.client_plugin('glance').get_image_id( + self.resource_id_set(self.client_plugin( + 'glance').find_image_by_name_or_id( self.properties[self.IMAGE])) self.client().images.update_image( diff --git a/heat/tests/aws/test_instance.py b/heat/tests/aws/test_instance.py index 6a160d602a..e742f5ab9a 100644 --- a/heat/tests/aws/test_instance.py +++ b/heat/tests/aws/test_instance.py @@ -14,7 +14,6 @@ import copy import uuid -from glanceclient import exc as glance_exceptions import mock import mox from neutronclient.v2_0 import client as neutronclient @@ -96,13 +95,16 @@ class InstancesTest(common.HeatTestCase): return (tmpl, stack) def _mock_get_image_id_success(self, imageId_input, imageId): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( imageId_input).MultipleTimes().AndReturn(imageId) def _mock_get_image_id_fail(self, image_id, exp): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id(image_id).AndRaise(exp) + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( + image_id).AndRaise(exp) def _get_test_template(self, stack_name, image_id=None, volumes=False): (tmpl, stack) = self._setup_test_stack(stack_name) @@ -407,8 +409,7 @@ class InstancesTest(common.HeatTestCase): resource_defns['WebServer'], stack) self._mock_get_image_id_fail('Slackware', - exception.EntityNotFound( - entity='Image', name='Slackware')) + glance.exceptions.NotFound()) self.stub_VolumeConstraint_validate() self.stub_FlavorConstraint_validate() self.stub_KeypairConstraint_validate() @@ -419,9 +420,8 @@ class InstancesTest(common.HeatTestCase): error = self.assertRaises(exception.ResourceFailure, create) self.assertEqual( "StackValidationFailed: resources.instance_create_image_err: " - "Property error: " - "WebServer.Properties.ImageId: Error validating value " - "'Slackware': The Image (Slackware) could not be found.", + "Property error: WebServer.Properties.ImageId: " + "Error validating value 'Slackware': Not Found (HTTP 404)", six.text_type(error)) self.m.VerifyAll() @@ -438,8 +438,7 @@ class InstancesTest(common.HeatTestCase): resource_defns['WebServer'], stack) self._mock_get_image_id_fail('CentOS 5.2', - exception.PhysicalResourceNameAmbiguity( - name='CentOS 5.2')) + glance.exceptions.NoUniqueMatch()) self.stub_KeypairConstraint_validate() self.stub_SnapshotConstraint_validate() @@ -450,10 +449,9 @@ class InstancesTest(common.HeatTestCase): create = scheduler.TaskRunner(instance.create) error = self.assertRaises(exception.ResourceFailure, create) self.assertEqual( - 'StackValidationFailed: resources.instance_create_image_err: ' - 'Property error: ' - 'WebServer.Properties.ImageId: Multiple physical ' - 'resources were found with name (CentOS 5.2).', + "StackValidationFailed: resources.instance_create_image_err: " + "Property error: WebServer.Properties.ImageId: " + "Error validating value 'CentOS 5.2': ", six.text_type(error)) self.m.VerifyAll() @@ -468,7 +466,7 @@ class InstancesTest(common.HeatTestCase): instance = instances.Instance('instance_create_image_err', resource_defns['WebServer'], stack) - self._mock_get_image_id_fail('1', glance_exceptions.NotFound(404)) + self._mock_get_image_id_fail('1', glance.exceptions.NotFound()) self.stub_VolumeConstraint_validate() self.stub_FlavorConstraint_validate() @@ -479,8 +477,9 @@ class InstancesTest(common.HeatTestCase): create = scheduler.TaskRunner(instance.create) error = self.assertRaises(exception.ResourceFailure, create) self.assertEqual( - 'StackValidationFailed: resources.instance_create_image_err: ' - 'Property error: WebServer.Properties.ImageId: 404 (HTTP 404)', + "StackValidationFailed: resources.instance_create_image_err: " + "Property error: WebServer.Properties.ImageId: " + "Error validating value '1': Not Found (HTTP 404)", six.text_type(error)) self.m.VerifyAll() diff --git a/heat/tests/aws/test_instance_network.py b/heat/tests/aws/test_instance_network.py index 331f6252d0..d71b198351 100644 --- a/heat/tests/aws/test_instance_network.py +++ b/heat/tests/aws/test_instance_network.py @@ -155,8 +155,9 @@ class instancesTest(common.HeatTestCase): self.fc = fakes_nova.FakeClient() def _mock_get_image_id_success(self, imageId_input, imageId): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( imageId_input).MultipleTimes().AndReturn(imageId) def _test_instance_create_delete(self, vm_status='ACTIVE', diff --git a/heat/tests/clients/test_clients.py b/heat/tests/clients/test_clients.py index 175a6e5b21..9174569b7b 100644 --- a/heat/tests/clients/test_clients.py +++ b/heat/tests/clients/test_clients.py @@ -15,6 +15,7 @@ from ceilometerclient import exc as ceil_exc from ceilometerclient.openstack.common.apiclient import exceptions as c_a_exc from cinderclient import exceptions as cinder_exc from glanceclient import exc as glance_exc +from glanceclient.openstack.common.apiclient import exceptions as g_a_exc from heatclient import client as heatclient from heatclient import exc as heat_exc from keystoneclient.auth.identity import v3 @@ -501,13 +502,21 @@ class TestIsNotFound(common.HeatTestCase): exception=lambda: cinder_exc.ClientException( code=409, message='conflict'), )), - ('glance_not_found', dict( + ('glance_not_found_1', dict( is_not_found=True, is_over_limit=False, is_client_exception=True, is_conflict=False, plugin='glance', - exception=lambda: glance_exc.HTTPNotFound(details='gone'), + exception=lambda: g_a_exc.NotFound(), + )), + ('glance_not_found_2', dict( + is_not_found=True, + is_over_limit=False, + is_client_exception=True, + is_conflict=False, + plugin='glance', + exception=lambda: glance_exc.HTTPNotFound(), )), ('glance_exception', dict( is_not_found=False, @@ -525,13 +534,21 @@ class TestIsNotFound(common.HeatTestCase): plugin='glance', exception=lambda: glance_exc.HTTPOverLimit(details='over'), )), - ('glance_conflict', dict( + ('glance_conflict_1', dict( is_not_found=False, is_over_limit=False, is_client_exception=True, is_conflict=True, plugin='glance', - exception=lambda: glance_exc.HTTPConflict(), + exception=lambda: g_a_exc.Conflict(), + )), + ('glance_conflict_1', dict( + is_not_found=False, + is_over_limit=False, + is_client_exception=True, + is_conflict=True, + plugin='glance', + exception=lambda: glance_exc.Conflict(), )), ('heat_not_found', dict( is_not_found=True, diff --git a/heat/tests/clients/test_glance_client.py b/heat/tests/clients/test_glance_client.py index c8db6e2e9c..964a0f94cf 100644 --- a/heat/tests/clients/test_glance_client.py +++ b/heat/tests/clients/test_glance_client.py @@ -13,11 +13,10 @@ import uuid -from glanceclient import exc as glance_exceptions +from glanceclient import exc +from glanceclient.openstack.common.apiclient import exceptions import mock -import six -from heat.common import exception from heat.engine.clients.os import glance from heat.tests import common from heat.tests import utils @@ -35,78 +34,31 @@ class GlanceUtilsTests(common.HeatTestCase): self.glance_plugin._client = self.glance_client self.my_image = mock.MagicMock() - def test_get_image_id(self): - """Tests the get_image_id function.""" + def test_find_image_by_name_or_id(self): + """Tests the find_image_by_name_or_id function.""" img_id = str(uuid.uuid4()) img_name = 'myfakeimage' self.my_image.id = img_id self.my_image.name = img_name - self.glance_client.images.get.return_value = self.my_image - self.glance_client.images.list.side_effect = ([self.my_image], []) - self.assertEqual(img_id, self.glance_plugin.get_image_id(img_id)) - self.assertEqual(img_id, self.glance_plugin.get_image_id(img_name)) - self.assertRaises(exception.EntityNotFound, - self.glance_plugin.get_image_id, 'noimage') - - calls = [mock.call(filters={'name': img_name}), - mock.call(filters={'name': 'noimage'})] - self.glance_client.images.get.assert_called_once_with(img_id) - self.glance_client.images.list.assert_has_calls(calls) - - def test_get_image_id_by_name_in_uuid(self): - """Tests the get_image_id function by name in uuid.""" - img_id = str(uuid.uuid4()) - img_name = str(uuid.uuid4()) - self.my_image.id = img_id - self.my_image.name = img_name self.glance_client.images.get.side_effect = [ - glance_exceptions.HTTPNotFound()] - self.glance_client.images.list.return_value = [self.my_image] - - self.assertEqual(img_id, self.glance_plugin.get_image_id(img_name)) - self.glance_client.images.get.assert_called_once_with(img_name) - self.glance_client.images.list.assert_called_once_with( - filters={'name': img_name}) - - def test_get_image_id_glance_exception(self): - """Test get_image_id when glance raises an exception.""" - # Simulate HTTP exception - img_name = str(uuid.uuid4()) + self.my_image, + exc.HTTPNotFound(), + exc.HTTPNotFound(), + exc.HTTPNotFound()] self.glance_client.images.list.side_effect = [ - glance_exceptions.ClientException("Error")] - - expected_error = "Error retrieving image list from glance: Error" - e = self.assertRaises(exception.Error, - self.glance_plugin.get_image_id_by_name, - img_name) - self.assertEqual(expected_error, six.text_type(e)) - self.glance_client.images.list.assert_called_once_with( - filters={'name': img_name}) - - def test_get_image_id_not_found(self): - """Tests the get_image_id function while image is not found.""" - img_name = str(uuid.uuid4()) - self.glance_client.images.get.side_effect = [ - glance_exceptions.HTTPNotFound()] - self.glance_client.images.list.return_value = [] - - self.assertRaises(exception.EntityNotFound, - self.glance_plugin.get_image_id, img_name) - self.glance_client.images.get.assert_called_once_with(img_name) - self.glance_client.images.list.assert_called_once_with( - filters={'name': img_name}) - - def test_get_image_id_name_ambiguity(self): - """Tests the get_image_id function while name ambiguity .""" - img_name = 'ambiguity_name' - self.my_image.name = img_name - - self.glance_client.images.list.return_value = [self.my_image, - self.my_image] - self.assertRaises(exception.PhysicalResourceNameAmbiguity, - self.glance_plugin.get_image_id, img_name) - self.glance_client.images.list.assert_called_once_with( - filters={'name': img_name}) + [self.my_image], + [], + [self.my_image, self.my_image]] + self.assertEqual(img_id, + self.glance_plugin.find_image_by_name_or_id(img_id)) + self.assertEqual(img_id, + self.glance_plugin.find_image_by_name_or_id(img_name)) + self.assertRaises(exceptions.NotFound, + self.glance_plugin.find_image_by_name_or_id, + 'noimage') + self.assertRaises(exceptions.NoUniqueMatch, + self.glance_plugin.find_image_by_name_or_id, + 'myfakeimage') class ImageConstraintTest(common.HeatTestCase): @@ -114,16 +66,15 @@ class ImageConstraintTest(common.HeatTestCase): def setUp(self): super(ImageConstraintTest, self).setUp() self.ctx = utils.dummy_context() - self.mock_get_image = mock.Mock() + self.mock_find_image = mock.Mock() self.ctx.clients.client_plugin( - 'glance').get_image_id = self.mock_get_image + 'glance').find_image_by_name_or_id = self.mock_find_image self.constraint = glance.ImageConstraint() def test_validation(self): - self.mock_get_image.return_value = "id1" + self.mock_find_image.side_effect = ["id1", + exceptions.NotFound(), + exceptions.NoUniqueMatch()] self.assertTrue(self.constraint.validate("foo", self.ctx)) - - def test_validation_error(self): - self.mock_get_image.side_effect = exception.EntityNotFound( - entity='Image', name='bar') self.assertFalse(self.constraint.validate("bar", self.ctx)) + self.assertFalse(self.constraint.validate("baz", self.ctx)) diff --git a/heat/tests/db/test_sqlalchemy_api.py b/heat/tests/db/test_sqlalchemy_api.py index 643d688644..ea85497f2e 100644 --- a/heat/tests/db/test_sqlalchemy_api.py +++ b/heat/tests/db/test_sqlalchemy_api.py @@ -95,8 +95,9 @@ class SqlAlchemyTest(common.HeatTestCase): super(SqlAlchemyTest, self).tearDown() def _mock_get_image_id_success(self, imageId_input, imageId): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( imageId_input).MultipleTimes().AndReturn(imageId) def _setup_test_stack(self, stack_name, stack_id=None, owner_id=None, diff --git a/heat/tests/engine/service/test_stack_create.py b/heat/tests/engine/service/test_stack_create.py index 0137b765b0..78374c623c 100644 --- a/heat/tests/engine/service/test_stack_create.py +++ b/heat/tests/engine/service/test_stack_create.py @@ -274,7 +274,7 @@ class StackCreateTest(common.HeatTestCase): fc = fakes_nova.FakeClient() self.patchobject(nova.NovaClientPlugin, '_create', return_value=fc) - self.patchobject(glance.GlanceClientPlugin, 'get_image_id', + self.patchobject(glance.GlanceClientPlugin, 'find_image_by_name_or_id', return_value=744) resource = stk['WebServer'] diff --git a/heat/tests/engine/tools.py b/heat/tests/engine/tools.py index d2ffeeb1d6..0968255c98 100644 --- a/heat/tests/engine/tools.py +++ b/heat/tests/engine/tools.py @@ -175,8 +175,9 @@ def setup_keystone_mocks(mocks, stack): def setup_mock_for_image_constraint(mocks, imageId_input, imageId_output=744): - mocks.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + mocks.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( imageId_input).MultipleTimes().AndReturn(imageId_output) diff --git a/heat/tests/openstack/cinder/test_volume.py b/heat/tests/openstack/cinder/test_volume.py index 18ef5d6232..0435c1df96 100644 --- a/heat/tests/openstack/cinder/test_volume.py +++ b/heat/tests/openstack/cinder/test_volume.py @@ -151,8 +151,9 @@ class CinderVolumeTest(vt_base.BaseVolumeTest): image_id = '46988116-6703-4623-9dbc-2bc6d284021b' cinder.CinderClientPlugin._create().AndReturn( self.cinder_fc) - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( image_id).MultipleTimes().AndReturn(image_id) self.cinder_fc.volumes.create( diff --git a/heat/tests/openstack/nova/fakes.py b/heat/tests/openstack/nova/fakes.py index 6bb45bed71..bbd76ed08c 100644 --- a/heat/tests/openstack/nova/fakes.py +++ b/heat/tests/openstack/nova/fakes.py @@ -408,6 +408,7 @@ class FakeHTTPClient(base_client.HTTPClient): return (200, {'image': self.get_images_detail()[1]['images'][0]}) get_images_456 = get_images_1 + get_images_image_name = get_images_1 # # Keypairs diff --git a/heat/tests/openstack/nova/test_server.py b/heat/tests/openstack/nova/test_server.py index f1d400c801..e80b52eb6d 100644 --- a/heat/tests/openstack/nova/test_server.py +++ b/heat/tests/openstack/nova/test_server.py @@ -282,13 +282,16 @@ class ServersTest(common.HeatTestCase): return fake_interface(port, mac, ip) def _mock_get_image_id_success(self, imageId_input, imageId): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( imageId_input).MultipleTimes().AndReturn(imageId) def _mock_get_image_id_fail(self, image_id, exp): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id(image_id).AndRaise(exp) + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( + image_id).AndRaise(exp) def _mock_get_keypair_success(self, keypair_input, keypair): self.m.StubOutWithMock(nova.NovaClientPlugin, 'get_keypair') @@ -466,9 +469,7 @@ class ServersTest(common.HeatTestCase): resource_defns['WebServer'], stack) self._mock_get_image_id_fail('Slackware', - exception.EntityNotFound( - entity='Image', - name='Slackware')) + glance.exceptions.NotFound()) self.stub_FlavorConstraint_validate() self.stub_KeypairConstraint_validate() self.m.ReplayAll() @@ -478,7 +479,7 @@ class ServersTest(common.HeatTestCase): self.assertEqual( "StackValidationFailed: resources.WebServer: Property error: " "WebServer.Properties.image: Error validating value 'Slackware': " - "The Image (Slackware) could not be found.", + "Not Found (HTTP 404)", six.text_type(error)) self.m.VerifyAll() @@ -494,8 +495,7 @@ class ServersTest(common.HeatTestCase): resource_defns['WebServer'], stack) self._mock_get_image_id_fail('CentOS 5.2', - exception.PhysicalResourceNameAmbiguity( - name='CentOS 5.2')) + glance.exceptions.NoUniqueMatch()) self.stub_FlavorConstraint_validate() self.stub_KeypairConstraint_validate() self.m.ReplayAll() @@ -503,9 +503,9 @@ class ServersTest(common.HeatTestCase): create = scheduler.TaskRunner(server.create) error = self.assertRaises(exception.ResourceFailure, create) self.assertEqual( - 'StackValidationFailed: resources.WebServer: Property error: ' - 'WebServer.Properties.image: Multiple physical ' - 'resources were found with name (CentOS 5.2).', + "StackValidationFailed: resources.WebServer: Property error: " + "WebServer.Properties.image: " + "Error validating value 'CentOS 5.2': ", six.text_type(error)) self.m.VerifyAll() @@ -521,8 +521,7 @@ class ServersTest(common.HeatTestCase): resource_defns['WebServer'], stack) self._mock_get_image_id_fail('1', - exception.EntityNotFound( - entity='Image', name='1')) + glance.exceptions.NotFound()) self.stub_KeypairConstraint_validate() self.stub_FlavorConstraint_validate() self.m.ReplayAll() @@ -532,7 +531,7 @@ class ServersTest(common.HeatTestCase): self.assertEqual( "StackValidationFailed: resources.WebServer: Property error: " "WebServer.Properties.image: Error validating value '1': " - "The Image (1) could not be found.", + "Not Found (HTTP 404)", six.text_type(error)) self.m.VerifyAll() @@ -3661,7 +3660,7 @@ class ServersTest(common.HeatTestCase): self.m.StubOutWithMock(glance.ImageConstraint, "validate") # verify that validate gets invoked exactly once for update - ex = exception.EntityNotFound(entity='Image', name='Update Image') + ex = glance.exceptions.NotFound() glance.ImageConstraint.validate('Update Image', mox.IgnoreArg()).AndRaise(ex) self.m.ReplayAll() @@ -3674,8 +3673,7 @@ class ServersTest(common.HeatTestCase): err = self.assertRaises(exception.ResourceFailure, updater) self.assertEqual('StackValidationFailed: resources.my_server: ' 'Property error: ' - 'WebServer.Properties.image: The Image ' - '(Update Image) could not be found.', + 'WebServer.Properties.image: Not Found (HTTP 404)', six.text_type(err)) self.m.VerifyAll() @@ -3769,10 +3767,11 @@ class ServersTest(common.HeatTestCase): self.m.StubOutWithMock(self.fc.servers, 'get') self.fc.servers.get(return_server.id).AndReturn(return_server) - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( 'F17-x86_64-gold').MultipleTimes().AndReturn(744) - glance.GlanceClientPlugin.get_image_id( + glance.GlanceClientPlugin.find_image_by_name_or_id( 'CentOS 5.2').MultipleTimes().AndReturn(1) self.patchobject(neutron.NeutronClientPlugin, 'resolve_network', @@ -3817,7 +3816,8 @@ class ServersTest(common.HeatTestCase): mock_plugin = self.patchobject(nova.NovaClientPlugin, '_create') mock_plugin.return_value = self.fc - get_image = self.patchobject(glance.GlanceClientPlugin, 'get_image_id') + get_image = self.patchobject(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') get_image.return_value = 744 return_server = self.fc.servers.list()[1] @@ -3862,7 +3862,8 @@ class ServersTest(common.HeatTestCase): mock_plugin = self.patchobject(nova.NovaClientPlugin, '_create') mock_plugin.return_value = self.fc - get_image = self.patchobject(glance.GlanceClientPlugin, 'get_image_id') + get_image = self.patchobject(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') get_image.return_value = 744 return_server = self.fc.servers.list()[1] diff --git a/heat/tests/openstack/sahara/test_cluster.py b/heat/tests/openstack/sahara/test_cluster.py index 0b8a6cdcf3..3a21c702fc 100644 --- a/heat/tests/openstack/sahara/test_cluster.py +++ b/heat/tests/openstack/sahara/test_cluster.py @@ -63,7 +63,8 @@ class SaharaClusterTest(common.HeatTestCase): super(SaharaClusterTest, self).setUp() self.patchobject(sc.constraints.CustomConstraint, '_is_valid' ).return_value = True - self.patchobject(glance.GlanceClientPlugin, 'get_image_id' + self.patchobject(glance.GlanceClientPlugin, + 'find_image_by_name_or_id' ).return_value = 'some_image_id' self.patchobject(neutron.NeutronClientPlugin, '_create') self.patchobject(neutron.NeutronClientPlugin, 'find_neutron_resource' diff --git a/heat/tests/openstack/sahara/test_image.py b/heat/tests/openstack/sahara/test_image.py index e9a86b7aff..945b0a1c0d 100644 --- a/heat/tests/openstack/sahara/test_image.py +++ b/heat/tests/openstack/sahara/test_image.py @@ -47,7 +47,8 @@ class SaharaImageTest(common.HeatTestCase): self.client = mock.Mock() self.patchobject(image.SaharaImageRegistry, 'client', return_value=self.client) - self.patchobject(glance.GlanceClientPlugin, 'get_image_id', + self.patchobject(glance.GlanceClientPlugin, + 'find_image_by_name_or_id', return_value='12345') def _create_resource(self, name, snippet, stack): diff --git a/heat/tests/test_nokey.py b/heat/tests/test_nokey.py index 4eaa70d8b3..5402947150 100644 --- a/heat/tests/test_nokey.py +++ b/heat/tests/test_nokey.py @@ -60,8 +60,9 @@ class nokeyTest(common.HeatTestCase): self.m.StubOutWithMock(nova.NovaClientPlugin, '_create') nova.NovaClientPlugin._create().AndReturn(self.fc) - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( 'CentOS 5.2').MultipleTimes().AndReturn(1) # need to resolve the template functions diff --git a/heat/tests/test_server_tags.py b/heat/tests/test_server_tags.py index 85ad48232f..5d22f343c3 100644 --- a/heat/tests/test_server_tags.py +++ b/heat/tests/test_server_tags.py @@ -58,8 +58,9 @@ class ServerTagsTest(common.HeatTestCase): self.fc = fakes_nova.FakeClient() def _mock_get_image_id_success(self, imageId_input, imageId): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( imageId_input).MultipleTimes().AndReturn(imageId) def _setup_test_instance(self, intags=None, nova_tags=None): diff --git a/heat/tests/test_validate.py b/heat/tests/test_validate.py index 152ebfeb51..14d04ab41e 100644 --- a/heat/tests/test_validate.py +++ b/heat/tests/test_validate.py @@ -11,7 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -from glanceclient import exc as glance_exceptions import mock from oslo_messaging.rpc import dispatcher import six @@ -915,13 +914,16 @@ class ValidateTest(common.HeatTestCase): self.engine = service.EngineService('a', 't') def _mock_get_image_id_success(self, imageId_input, imageId): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id( + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( imageId_input).MultipleTimes().AndReturn(imageId) def _mock_get_image_id_fail(self, image_id, exp): - self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image_id') - glance.GlanceClientPlugin.get_image_id(image_id).AndRaise(exp) + self.m.StubOutWithMock(glance.GlanceClientPlugin, + 'find_image_by_name_or_id') + glance.GlanceClientPlugin.find_image_by_name_or_id( + image_id).AndRaise(exp) def test_validate_volumeattach_valid(self): t = template_format.parse(test_template_volumeattach % 'vdq') @@ -1422,10 +1424,8 @@ class ValidateTest(common.HeatTestCase): t = template_format.parse(test_template_glance_client_exception) template = tmpl.Template(t) stack = parser.Stack(self.ctx, 'test_stack', template) - - self.m.StubOutWithMock(self.gc.images, 'list') - self.gc.images.list().AndRaise( - glance_exceptions.ClientException(500)) + self.m.StubOutWithMock(self.gc.images, 'get') + self.gc.images.get('image_name').AndRaise(glance.exc.HTTPNotFound()) self.m.StubOutWithMock(glance.GlanceClientPlugin, '_create') glance.GlanceClientPlugin._create().AndReturn(self.gc) self.stub_FlavorConstraint_validate()