diff --git a/heat/engine/clients/client_exception.py b/heat/engine/clients/client_exception.py new file mode 100644 index 0000000000..19a58bf0af --- /dev/null +++ b/heat/engine/clients/client_exception.py @@ -0,0 +1,27 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from heat.common import exception +from heat.common.i18n import _ + + +class EntityMatchNotFound(exception.HeatException): + msg_fmt = _("No %(entity)s matching %(args)s.") + + def __init__(self, entity=None, args=None, **kwargs): + super(EntityMatchNotFound, self).__init__(entity=entity, args=args, + **kwargs) + + +class EntityUniqueMatchNotFound(EntityMatchNotFound): + msg_fmt = _("No %(entity)s unique match found for %(args)s.") diff --git a/heat/engine/clients/os/glance.py b/heat/engine/clients/os/glance.py index 10bfeed0d8..91a48a5747 100644 --- a/heat/engine/clients/os/glance.py +++ b/heat/engine/clients/os/glance.py @@ -13,9 +13,8 @@ from glanceclient import client as gc from glanceclient import exc -from glanceclient.openstack.common.apiclient import exceptions -from heat.common.i18n import _ +from heat.engine.clients import client_exception from heat.engine.clients import client_plugin from heat.engine.clients import os as os_client from heat.engine import constraints @@ -25,7 +24,7 @@ CLIENT_NAME = 'glance' class GlanceClientPlugin(client_plugin.ClientPlugin): - exceptions_module = [exceptions, exc] + exceptions_module = [client_exception, exc] service_types = [IMAGE] = ['image'] @@ -47,17 +46,11 @@ class GlanceClientPlugin(client_plugin.ClientPlugin): 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) + raise client_exception.EntityMatchNotFound(entity=entity, + args=kwargs) elif num_matches > 1: - msg = _("No %(name)s unique match found for %(args)s.") % { - 'name': entity, - 'args': kwargs - } - raise exceptions.NoUniqueMatch(msg) + raise client_exception.EntityUniqueMatchNotFound(entity=entity, + args=kwargs) else: return matches[0] @@ -68,13 +61,14 @@ class GlanceClientPlugin(client_plugin.ClientPlugin): return func.list(**filters) def is_not_found(self, ex): - return isinstance(ex, (exceptions.NotFound, exc.HTTPNotFound)) + return isinstance(ex, (client_exception.EntityMatchNotFound, + exc.HTTPNotFound)) def is_over_limit(self, ex): return isinstance(ex, exc.HTTPOverLimit) def is_conflict(self, ex): - return isinstance(ex, (exceptions.Conflict, exc.Conflict)) + return isinstance(ex, exc.Conflict) def find_image_by_name_or_id(self, image_identifier): """Return the ID for the specified image name or identifier. @@ -104,7 +98,8 @@ class GlanceClientPlugin(client_plugin.ClientPlugin): class ImageConstraint(constraints.BaseCustomConstraint): - expected_exceptions = (exceptions.NotFound, exceptions.NoUniqueMatch) + expected_exceptions = (client_exception.EntityMatchNotFound, + client_exception.EntityUniqueMatchNotFound) resource_client_name = CLIENT_NAME resource_getter_name = 'find_image_by_name_or_id' diff --git a/heat/tests/aws/test_instance.py b/heat/tests/aws/test_instance.py index 4ba93c3d2a..20ea29959b 100644 --- a/heat/tests/aws/test_instance.py +++ b/heat/tests/aws/test_instance.py @@ -422,9 +422,10 @@ class InstancesTest(common.HeatTestCase): resource_defns = tmpl.resource_definitions(stack) instance = instances.Instance('instance_create_image_err', resource_defns['WebServer'], stack) - - self._mock_get_image_id_fail('Slackware', - glance.exceptions.NotFound()) + self._mock_get_image_id_fail( + 'Slackware', + glance.client_exception.EntityMatchNotFound( + entity='image', args='Slackware')) self.stub_VolumeConstraint_validate() self.stub_FlavorConstraint_validate() self.stub_KeypairConstraint_validate() @@ -436,7 +437,7 @@ class InstancesTest(common.HeatTestCase): self.assertEqual( "StackValidationFailed: resources.instance_create_image_err: " "Property error: WebServer.Properties.ImageId: " - "Error validating value 'Slackware': Not Found (HTTP 404)", + "Error validating value 'Slackware': No image matching Slackware.", six.text_type(error)) self.m.VerifyAll() @@ -452,9 +453,10 @@ class InstancesTest(common.HeatTestCase): instance = instances.Instance('instance_create_image_err', resource_defns['WebServer'], stack) - msg = 'No image unique match found for CentOS 5.2.' - self._mock_get_image_id_fail('CentOS 5.2', - glance.exceptions.NoUniqueMatch(msg)) + self._mock_get_image_id_fail( + 'CentOS 5.2', + glance.client_exception.EntityUniqueMatchNotFound( + entity='image', args='CentOS 5.2')) self.stub_KeypairConstraint_validate() self.stub_SnapshotConstraint_validate() @@ -483,7 +485,9 @@ 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()) + self._mock_get_image_id_fail( + '1', glance.client_exception.EntityMatchNotFound(entity='image', + args='1')) self.stub_VolumeConstraint_validate() self.stub_FlavorConstraint_validate() @@ -496,7 +500,7 @@ class InstancesTest(common.HeatTestCase): self.assertEqual( "StackValidationFailed: resources.instance_create_image_err: " "Property error: WebServer.Properties.ImageId: " - "Error validating value '1': Not Found (HTTP 404)", + "Error validating value '1': No image matching 1.", six.text_type(error)) self.m.VerifyAll() diff --git a/heat/tests/clients/test_clients.py b/heat/tests/clients/test_clients.py index 8195db6b4e..a34352ecab 100644 --- a/heat/tests/clients/test_clients.py +++ b/heat/tests/clients/test_clients.py @@ -16,7 +16,6 @@ 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 keystoneauth1 import exceptions as keystone_exc @@ -34,6 +33,7 @@ from zaqarclient.transport import errors as zaqar_exc from heat.common import exception from heat.engine import clients +from heat.engine.clients import client_exception from heat.engine.clients import client_plugin from heat.tests import common from heat.tests import fakes @@ -490,7 +490,7 @@ class TestIsNotFound(common.HeatTestCase): is_client_exception=True, is_conflict=False, plugin='glance', - exception=lambda: g_a_exc.NotFound(), + exception=lambda: client_exception.EntityMatchNotFound(), )), ('glance_not_found_2', dict( is_not_found=True, @@ -516,14 +516,6 @@ class TestIsNotFound(common.HeatTestCase): plugin='glance', exception=lambda: glance_exc.HTTPOverLimit(details='over'), )), - ('glance_conflict_1', dict( - is_not_found=False, - is_over_limit=False, - is_client_exception=True, - is_conflict=True, - plugin='glance', - exception=lambda: g_a_exc.Conflict(), - )), ('glance_conflict_1', dict( is_not_found=False, is_over_limit=False, diff --git a/heat/tests/clients/test_glance_client.py b/heat/tests/clients/test_glance_client.py index f73083f83f..738f471d82 100644 --- a/heat/tests/clients/test_glance_client.py +++ b/heat/tests/clients/test_glance_client.py @@ -14,9 +14,9 @@ import uuid from glanceclient import exc -from glanceclient.openstack.common.apiclient import exceptions import mock +from heat.engine.clients import client_exception as exception from heat.engine.clients.os import glance from heat.tests import common from heat.tests import utils @@ -53,10 +53,10 @@ class GlanceUtilsTest(common.HeatTestCase): 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.assertRaises(exception.EntityMatchNotFound, self.glance_plugin.find_image_by_name_or_id, 'noimage') - self.assertRaises(exceptions.NoUniqueMatch, + self.assertRaises(exception.EntityUniqueMatchNotFound, self.glance_plugin.find_image_by_name_or_id, 'myfakeimage') @@ -72,9 +72,9 @@ class ImageConstraintTest(common.HeatTestCase): self.constraint = glance.ImageConstraint() def test_validation(self): - self.mock_find_image.side_effect = ["id1", - exceptions.NotFound(), - exceptions.NoUniqueMatch()] + self.mock_find_image.side_effect = [ + "id1", exception.EntityMatchNotFound(), + exception.EntityUniqueMatchNotFound()] self.assertTrue(self.constraint.validate("foo", self.ctx)) self.assertFalse(self.constraint.validate("bar", self.ctx)) self.assertFalse(self.constraint.validate("baz", self.ctx)) diff --git a/heat/tests/openstack/nova/test_server.py b/heat/tests/openstack/nova/test_server.py index 15c763d1f2..1fb8efd2c6 100644 --- a/heat/tests/openstack/nova/test_server.py +++ b/heat/tests/openstack/nova/test_server.py @@ -546,17 +546,18 @@ class ServersTest(common.HeatTestCase): (tmpl, stack) = self._setup_test_stack(stack_name) mock_image = self.patchobject(glance.GlanceClientPlugin, 'find_image_by_name_or_id') - mock_image.side_effect = [glance.exceptions.NotFound( - 'Image Slackware Not Found')] + mock_image.side_effect = [ + glance.client_exception.EntityMatchNotFound( + entity='image', args={'name': 'Slackware'})] # Init a server with non exist image name tmpl['Resources']['WebServer']['Properties']['image'] = 'Slackware' resource_defns = tmpl.resource_definitions(stack) server = servers.Server('WebServer', resource_defns['WebServer'], stack) - error = self.assertRaises(glance.exceptions.NotFound, + error = self.assertRaises(glance.client_exception.EntityMatchNotFound, scheduler.TaskRunner(server.create)) - self.assertEqual("Image Slackware Not Found (HTTP 404)", + self.assertEqual("No image matching {'name': 'Slackware'}.", six.text_type(error)) def test_server_duplicate_image_name_err(self): @@ -564,15 +565,17 @@ class ServersTest(common.HeatTestCase): (tmpl, stack) = self._setup_test_stack(stack_name) mock_image = self.patchobject(glance.GlanceClientPlugin, 'find_image_by_name_or_id') - mock_image.side_effect = [glance.exceptions.NoUniqueMatch( - 'No image unique match found for CentOS 5.2.')] + mock_image.side_effect = [ + glance.client_exception.EntityUniqueMatchNotFound( + entity='image', args='CentOS 5.2')] tmpl['Resources']['WebServer']['Properties']['image'] = 'CentOS 5.2' resource_defns = tmpl.resource_definitions(stack) server = servers.Server('WebServer', resource_defns['WebServer'], stack) - error = self.assertRaises(glance.exceptions.NoUniqueMatch, - scheduler.TaskRunner(server.create)) + error = self.assertRaises( + glance.client_exception.EntityUniqueMatchNotFound, + scheduler.TaskRunner(server.create)) self.assertEqual('No image unique match found for CentOS 5.2.', six.text_type(error)) @@ -2655,8 +2658,9 @@ class ServersTest(common.HeatTestCase): server = servers.Server('image_not_found', resource_defns['WebServer'], stack) self.patchobject(glance.GlanceClientPlugin, 'get_image', - side_effect=[glance.exceptions.NotFound(), - self.mock_image]) + side_effect=[ + glance.client_exception.EntityMatchNotFound, + self.mock_image]) self.patchobject(nova.NovaClientPlugin, 'get_flavor', side_effect=nova.exceptions.NotFound('')) self.assertIsNone(server.validate()) @@ -3570,7 +3574,8 @@ class ServersTest(common.HeatTestCase): server = self._create_test_server(return_server, 'my_server') - ex = glance.exceptions.NotFound() + ex = glance.client_exception.EntityMatchNotFound(entity='image', + args='Update Image') self.patchobject(glance.GlanceClientPlugin, 'find_image_by_name_or_id', side_effect=[1, ex]) @@ -3580,8 +3585,9 @@ class ServersTest(common.HeatTestCase): # update updater = scheduler.TaskRunner(server.update, update_template) - err = self.assertRaises(glance.exceptions.NotFound, updater) - self.assertEqual('Not Found (HTTP 404)', + err = self.assertRaises(glance.client_exception.EntityMatchNotFound, + updater) + self.assertEqual('No image matching Update Image.', six.text_type(err)) def test_server_snapshot(self):