diff options
| author | Dan Smith <danms@us.ibm.com> | 2012-12-06 12:34:35 -0800 |
|---|---|---|
| committer | Dan Smith <danms@us.ibm.com> | 2012-12-06 14:24:00 -0800 |
| commit | b68e63bba09ec6c34ea1324041504696dfa78a9a (patch) | |
| tree | 9b1a18920c073e21741f7b8b54381d45345b8c6e /nova/openstack | |
| parent | 92a14591ff2d34959e0b96779d8e89f93f441c97 (diff) | |
| download | nova-b68e63bba09ec6c34ea1324041504696dfa78a9a.tar.gz nova-b68e63bba09ec6c34ea1324041504696dfa78a9a.tar.xz nova-b68e63bba09ec6c34ea1324041504696dfa78a9a.zip | |
Sync RPC logging-related bits from oslo
These are the RPC common changes for squelching exception
logging, oslo change I4e7b19dc730342091fd70a717065741d56da4555
Change-Id: I8b5040d0ec2e70b8cc1e784151df60ac2bf3f457
Diffstat (limited to 'nova/openstack')
| -rw-r--r-- | nova/openstack/common/rpc/amqp.py | 15 | ||||
| -rw-r--r-- | nova/openstack/common/rpc/common.py | 41 | ||||
| -rw-r--r-- | nova/openstack/common/rpc/impl_fake.py | 2 | ||||
| -rw-r--r-- | nova/openstack/common/rpc/impl_zmq.py | 7 |
4 files changed, 58 insertions, 7 deletions
diff --git a/nova/openstack/common/rpc/amqp.py b/nova/openstack/common/rpc/amqp.py index 60bff59fe..a5a79cc30 100644 --- a/nova/openstack/common/rpc/amqp.py +++ b/nova/openstack/common/rpc/amqp.py @@ -150,7 +150,7 @@ class ConnectionContext(rpc_common.Connection): def msg_reply(conf, msg_id, connection_pool, reply=None, failure=None, - ending=False): + ending=False, log_failure=True): """Sends a reply or an error on the channel signified by msg_id. Failure should be a sys.exc_info() tuple. @@ -158,7 +158,8 @@ def msg_reply(conf, msg_id, connection_pool, reply=None, failure=None, """ with ConnectionContext(conf, connection_pool) as conn: if failure: - failure = rpc_common.serialize_remote_exception(failure) + failure = rpc_common.serialize_remote_exception(failure, + log_failure) try: msg = {'result': reply, 'failure': failure} @@ -185,10 +186,10 @@ class RpcContext(rpc_common.CommonRpcContext): return self.__class__(**values) def reply(self, reply=None, failure=None, ending=False, - connection_pool=None): + connection_pool=None, log_failure=True): if self.msg_id: msg_reply(self.conf, self.msg_id, connection_pool, reply, failure, - ending) + ending, log_failure) if ending: self.msg_id = None @@ -282,6 +283,12 @@ class ProxyCallback(object): ctxt.reply(rval, None, connection_pool=self.connection_pool) # This final None tells multicall that it is done. ctxt.reply(ending=True, connection_pool=self.connection_pool) + except rpc_common.ClientException as e: + LOG.debug(_('Expected exception during message handling (%s)') % + e._exc_info[1]) + ctxt.reply(None, e._exc_info, + connection_pool=self.connection_pool, + log_failure=False) except Exception: LOG.exception(_('Exception during message handling')) ctxt.reply(None, sys.exc_info(), diff --git a/nova/openstack/common/rpc/common.py b/nova/openstack/common/rpc/common.py index 73a18012c..a941ab1d0 100644 --- a/nova/openstack/common/rpc/common.py +++ b/nova/openstack/common/rpc/common.py @@ -18,6 +18,7 @@ # under the License. import copy +import sys import traceback from nova.openstack.common.gettextutils import _ @@ -195,7 +196,7 @@ def _safe_log(log_func, msg, msg_data): return log_func(msg, msg_data) -def serialize_remote_exception(failure_info): +def serialize_remote_exception(failure_info, log_failure=True): """Prepares exception data to be sent over rpc. Failure_info should be a sys.exc_info() tuple. @@ -203,8 +204,9 @@ def serialize_remote_exception(failure_info): """ tb = traceback.format_exception(*failure_info) failure = failure_info[1] - LOG.error(_("Returning exception %s to caller"), unicode(failure)) - LOG.error(tb) + if log_failure: + LOG.error(_("Returning exception %s to caller"), unicode(failure)) + LOG.error(tb) kwargs = {} if hasattr(failure, 'kwargs'): @@ -309,3 +311,36 @@ class CommonRpcContext(object): context.values['read_deleted'] = read_deleted return context + + +class ClientException(Exception): + """This encapsulates some actual exception that is expected to be + hit by an RPC proxy object. Merely instantiating it records the + current exception information, which will be passed back to the + RPC client without exceptional logging.""" + def __init__(self): + self._exc_info = sys.exc_info() + + +def catch_client_exception(exceptions, func, *args, **kwargs): + try: + return func(*args, **kwargs) + except Exception, e: + if type(e) in exceptions: + raise ClientException() + else: + raise + + +def client_exceptions(*exceptions): + """Decorator for manager methods that raise expected exceptions. + Marking a Manager method with this decorator allows the declaration + of expected exceptions that the RPC layer should not consider fatal, + and not log as if they were generated in a real error scenario. Note + that this will cause listed exceptions to be wrapped in a + ClientException, which is used internally by the RPC layer.""" + def outer(func): + def inner(*args, **kwargs): + return catch_client_exception(exceptions, func, *args, **kwargs) + return inner + return outer diff --git a/nova/openstack/common/rpc/impl_fake.py b/nova/openstack/common/rpc/impl_fake.py index 0e60da3f7..4d133a1af 100644 --- a/nova/openstack/common/rpc/impl_fake.py +++ b/nova/openstack/common/rpc/impl_fake.py @@ -79,6 +79,8 @@ class Consumer(object): else: res.append(rval) done.send(res) + except rpc_common.ClientException as e: + done.send_exception(e._exc_info[1]) except Exception as e: done.send_exception(e) diff --git a/nova/openstack/common/rpc/impl_zmq.py b/nova/openstack/common/rpc/impl_zmq.py index 0daf07cf4..4ab47b8f8 100644 --- a/nova/openstack/common/rpc/impl_zmq.py +++ b/nova/openstack/common/rpc/impl_zmq.py @@ -259,7 +259,14 @@ class InternalContext(object): except greenlet.GreenletExit: # ignore these since they are just from shutdowns pass + except rpc_common.ClientException, e: + LOG.debug(_("Expected exception during message handling (%s)") % + e._exc_info[1]) + return {'exc': + rpc_common.serialize_remote_exception(e._exc_info, + log_failure=False)} except Exception: + LOG.error(_("Exception during message handling")) return {'exc': rpc_common.serialize_remote_exception(sys.exc_info())} |
