diff options
author | Matthew Sherborne <msherborne@gmail.com> | 2013-06-04 20:44:17 +1000 |
---|---|---|
committer | Matthew Sherborne <msherborne@gmail.com> | 2013-06-12 14:14:42 +1000 |
commit | 980fe5f790d000a44d4bd3ca066d2011be461a05 (patch) | |
tree | 742b6ac55905c296706e8484a7dd7b20cd02d419 /openstack/common | |
parent | da554770974706ffa6f69f12d9051062cd0d0b80 (diff) | |
download | oslo-980fe5f790d000a44d4bd3ca066d2011be461a05.tar.gz oslo-980fe5f790d000a44d4bd3ca066d2011be461a05.tar.xz oslo-980fe5f790d000a44d4bd3ca066d2011be461a05.zip |
Allow exceptions to hop up cells
When an exception happens in an RPC call using nova cells, it can travel
back up several RPC boundaries. eg, child-cell=>parent-cell=>nova-api
Before this patch if an exception (eg. AggregateNotFound) was raised in
the bottom layer, the next layer up would turn it into a special
exception ( AggregateNotFound_Remote ), then in the final layer, it would
see this as an unrecognizable exception and raise RemoteException.
After this patch, at each layer where the expeption is deserialized,
it'll recognize exceptions with the _Remote postfix, and leave them as
they are, instead of turning them into RemoteExceptions.
It also preserves the exception's original __module__ now.
Change-Id: I158a80f1cec20d3e1805b565ffddaffd7a15295b
Diffstat (limited to 'openstack/common')
-rw-r--r-- | openstack/common/rpc/common.py | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/openstack/common/rpc/common.py b/openstack/common/rpc/common.py index f880608..5eacd32 100644 --- a/openstack/common/rpc/common.py +++ b/openstack/common/rpc/common.py @@ -70,6 +70,8 @@ _RPC_ENVELOPE_VERSION = '2.0' _VERSION_KEY = 'oslo.version' _MESSAGE_KEY = 'oslo.message' +_REMOTE_POSTFIX = '_Remote' + class RPCException(Exception): message = _("An unknown RPC related exception occurred.") @@ -313,9 +315,18 @@ def serialize_remote_exception(failure_info, log_failure=True): if hasattr(failure, 'kwargs'): kwargs = failure.kwargs + # NOTE(matiu): With cells, it's possible to re-raise remote, remote + # exceptions. Lets turn it back into the original exception type. + cls_name = str(failure.__class__.__name__) + mod_name = str(failure.__class__.__module__) + if (cls_name.endswith(_REMOTE_POSTFIX) and + mod_name.endswith(_REMOTE_POSTFIX)): + cls_name = cls_name[:-len(_REMOTE_POSTFIX)] + mod_name = mod_name[:-len(_REMOTE_POSTFIX)] + data = { - 'class': str(failure.__class__.__name__), - 'module': str(failure.__class__.__module__), + 'class': cls_name, + 'module': mod_name, 'message': six.text_type(failure), 'tb': tb, 'args': failure.args, @@ -352,8 +363,9 @@ def deserialize_remote_exception(conf, data): ex_type = type(failure) str_override = lambda self: message - new_ex_type = type(ex_type.__name__ + "_Remote", (ex_type,), + new_ex_type = type(ex_type.__name__ + _REMOTE_POSTFIX, (ex_type,), {'__str__': str_override, '__unicode__': str_override}) + new_ex_type.__module__ = '%s%s' % (module, _REMOTE_POSTFIX) try: # NOTE(ameade): Dynamically create a new exception type and swap it in # as the new type for the exception. This only works on user defined |