Don't use oslo-incubator in glance client plugin

There is plan to remove all oslo incubator code from the
clients. This removes the usage of deprecated
openstack.common.apiclient.exceptions in glance client
plugin.

The available glance HTTPNotFound exception is not usable
for validations(no message) and there is no UniqueMatch
exception.

This adds a new custom client_exception module with two
exceptions to ensure that the error messages remain the
same as before.

Change-Id: I5b32eef047a1fe38382f649532c8bb8a910315e5
This commit is contained in:
rabi 2016-09-27 16:52:22 +05:30
parent 0dcf342b88
commit e1237f48ef
6 changed files with 78 additions and 54 deletions

View File

@ -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.")

View File

@ -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'

View File

@ -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()

View File

@ -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,

View File

@ -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))

View File

@ -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):