Add keystone exceptions wrapper for openstack clients

* Added decorator which wraps keystone exceptions
* Added unit tests with no auth_token and with heat client cached

Change-Id: If42efe5f6806b12e7aabfd943150917a0b8f7618
This commit is contained in:
Pierre Padrixe
2014-03-14 14:43:15 +01:00
parent a0e32b839d
commit 4e3f6cd0cb
3 changed files with 57 additions and 0 deletions

View File

@@ -16,6 +16,7 @@ from heatclient import client as heatclient
from keystoneclient.v2_0 import client as ksclient from keystoneclient.v2_0 import client as ksclient
from oslo.config import cfg from oslo.config import cfg
from solum.common import exception
from solum.openstack.common.gettextutils import _ from solum.openstack.common.gettextutils import _
from solum.openstack.common import log as logging from solum.openstack.common import log as logging
@@ -77,6 +78,7 @@ class OpenStackClients(object):
def _get_client_option(self, client, option): def _get_client_option(self, client, option):
return getattr(getattr(cfg.CONF, '%s_client' % client), option) return getattr(getattr(cfg.CONF, '%s_client' % client), option)
@exception.wrap_keystone_exception
def heat(self): def heat(self):
if self._heat: if self._heat:
return self._heat return self._heat

View File

@@ -20,8 +20,10 @@ Includes decorator for re-raising Solum-type exceptions.
import functools import functools
import pecan import pecan
import sys
import wsme import wsme
from keystoneclient import exceptions as keystone_exceptions
from oslo.config import cfg from oslo.config import cfg
import six import six
@@ -30,6 +32,7 @@ from solum.openstack.common import excutils
from solum.openstack.common.gettextutils import _ from solum.openstack.common.gettextutils import _
from solum.openstack.common import log as logging from solum.openstack.common import log as logging
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
exc_log_opts = [ exc_log_opts = [
@@ -96,6 +99,25 @@ def wrap_controller_exception(func):
return wrapped return wrapped
def wrap_keystone_exception(func):
"""This decorator wraps keystone exception by throwing Solum specific
exceptions.
"""
@functools.wraps(func)
def wrapped(*args, **kw):
try:
return func(*args, **kw)
except keystone_exceptions.AuthorizationFailure:
raise AuthorizationFailure(
client=func.__name__, message="reason: %s" % sys.exc_info()[1])
except keystone_exceptions.ClientException:
raise AuthorizationFailure(
client=func.__name__,
message="unexpected keystone client error occurred: %s"
% sys.exc_info()[1])
return wrapped
class SolumException(Exception): class SolumException(Exception):
"""Base Solum Exception """Base Solum Exception
@@ -152,3 +174,7 @@ class ResourceExists(SolumException):
class NotImplemented(SolumException): class NotImplemented(SolumException):
msg_fmt = _("The requested operation is not implemented.") msg_fmt = _("The requested operation is not implemented.")
code = 501 code = 501
class AuthorizationFailure(SolumException):
msg_fmt = _("%(client)s connection failed. %(message)s")

View File

@@ -14,6 +14,7 @@ import mock
from heatclient import client as heatclient from heatclient import client as heatclient
from solum.common import clients from solum.common import clients
from solum.common import exception
from solum.tests import base from solum.tests import base
@@ -37,3 +38,31 @@ class ClientsTest(base.BaseTestCase):
cert_file=None, token='3bcc3d3a03f44e3d8377f9247b0ad155', cert_file=None, token='3bcc3d3a03f44e3d8377f9247b0ad155',
auth_url='keystone_url', ca_file=None, key_file=None, auth_url='keystone_url', ca_file=None, key_file=None,
password=None, insecure=False) password=None, insecure=False)
def test_clients_heat_noauth(self):
con = mock.MagicMock()
con.auth_token = None
con.tenant = "b363706f891f48019483f8bd6503c54b"
auth_url = mock.PropertyMock(name="auth_url",
return_value="keystone_url")
type(con).auth_url = auth_url
con.get_url_for = mock.Mock(name="get_url_for")
con.get_url_for.return_value = "url_from_keystone"
obj = clients.OpenStackClients(con)
obj._heat = None
self.assertRaises(exception.AuthorizationFailure, obj.heat)
def test_clients_heat_cached(self):
con = mock.MagicMock()
con.tenant = "b363706f891f48019483f8bd6503c54b"
con.auth_token = "3bcc3d3a03f44e3d8377f9247b0ad155"
auth_url = mock.PropertyMock(name="auth_url",
return_value="keystone_url")
type(con).auth_url = auth_url
con.get_url_for = mock.Mock(name="get_url_for")
con.get_url_for.return_value = "url_from_keystone"
obj = clients.OpenStackClients(con)
obj._heat = None
heat = obj.heat()
heat_cached = obj.heat()
self.assertEqual(heat, heat_cached)