Add save_and_reraise_exception().
This patch adds save_and_reraise_exception() to a new module, openstack.common.excutils. This is based on the function of the same name from nova.utils. It is used by nova.rpc, so something equivalent is needed in openstack-common before nova.rpc can be moved here. Change-Id: Icec574a081837e0f2d0548a5759d21b0352dbee6
This commit is contained in:
parent
c421e79d6b
commit
79ff0c4e83
49
openstack/common/excutils.py
Normal file
49
openstack/common/excutils.py
Normal file
@ -0,0 +1,49 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# Copyright 2012, Red Hat, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Exception related utilities.
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
import logging
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def save_and_reraise_exception():
|
||||
"""Save current exception, run some code and then re-raise.
|
||||
|
||||
In some cases the exception context can be cleared, resulting in None
|
||||
being attempted to be reraised after an exception handler is run. This
|
||||
can happen when eventlet switches greenthreads or when running an
|
||||
exception handler, code raises and catches an exception. In both
|
||||
cases the exception context will be cleared.
|
||||
|
||||
To work around this, we save the exception state, run handler code, and
|
||||
then re-raise the original exception. If another exception occurs, the
|
||||
saved exception is logged and the new exception is reraised.
|
||||
"""
|
||||
type_, value, tb = sys.exc_info()
|
||||
try:
|
||||
yield
|
||||
except Exception:
|
||||
logging.error('Original exception being dropped: %s' %
|
||||
(traceback.format_exception(type_, value, tb)))
|
||||
raise
|
||||
raise type_, value, tb
|
50
tests/unit/test_excutils.py
Normal file
50
tests/unit/test_excutils.py
Normal file
@ -0,0 +1,50 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012, Red Hat, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import unittest
|
||||
|
||||
from openstack.common import excutils
|
||||
|
||||
|
||||
class SaveAndReraiseTest(unittest.TestCase):
|
||||
|
||||
def test_save_and_reraise_exception(self):
|
||||
e = None
|
||||
msg = 'foo'
|
||||
try:
|
||||
try:
|
||||
raise Exception(msg)
|
||||
except:
|
||||
with excutils.save_and_reraise_exception():
|
||||
pass
|
||||
except Exception, _e:
|
||||
e = _e
|
||||
|
||||
self.assertEqual(str(e), msg)
|
||||
|
||||
def test_save_and_reraise_exception_dropped(self):
|
||||
e = None
|
||||
msg = 'second exception'
|
||||
try:
|
||||
try:
|
||||
raise Exception('dropped')
|
||||
except:
|
||||
with excutils.save_and_reraise_exception():
|
||||
raise Exception(msg)
|
||||
except Exception, _e:
|
||||
e = _e
|
||||
|
||||
self.assertEqual(str(e), msg)
|
Loading…
Reference in New Issue
Block a user