From 1b3cbc537ee1b69940cfb3a5d5b408db13df266d Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Tue, 1 May 2012 17:31:26 -0400 Subject: [PATCH] Use save_and_reraise_exception() from common. This patch common.excutils from openstack-common, which includes save_and_reraise_exception(). The patch also converts the code base to use it from there instead of cinder.utils and then removes it from cinder.utils. The initial motivation for this was removing another cinder dependency from cinder.rpc so that it can eventually be moved to openstack-common. Change-Id: I7354ca51a02aec9c709cf33f77d4abc46acc2742 --- cinder/openstack/common/excutils.py | 49 +++++++++++++++++++++++++++++ cinder/rpc/amqp.py | 5 +-- cinder/scheduler/manager.py | 8 ++--- cinder/utils.py | 33 +++---------------- cinder/volume/manager.py | 9 +++--- openstack-common.conf | 2 +- 6 files changed, 66 insertions(+), 40 deletions(-) create mode 100644 cinder/openstack/common/excutils.py diff --git a/cinder/openstack/common/excutils.py b/cinder/openstack/common/excutils.py new file mode 100644 index 000000000..3cb678e9d --- /dev/null +++ b/cinder/openstack/common/excutils.py @@ -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 diff --git a/cinder/rpc/amqp.py b/cinder/rpc/amqp.py index 0208fb2e8..c7cfb8afb 100644 --- a/cinder/rpc/amqp.py +++ b/cinder/rpc/amqp.py @@ -34,9 +34,10 @@ from eventlet import greenpool from eventlet import pools from eventlet import semaphore +from cinder.openstack.common import excutils from cinder.openstack.common import local import cinder.rpc.common as rpc_common -from cinder import utils + LOG = logging.getLogger(__name__) @@ -312,7 +313,7 @@ class MulticallWaiter(object): try: self._iterator.next() except Exception: - with utils.save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): self.done() if self._got_ending: self.done() diff --git a/cinder/scheduler/manager.py b/cinder/scheduler/manager.py index 5b67c407c..6f84c4f1c 100644 --- a/cinder/scheduler/manager.py +++ b/cinder/scheduler/manager.py @@ -30,8 +30,8 @@ from cinder import log as logging from cinder import manager from cinder.notifier import api as notifier from cinder.openstack.common import cfg +from cinder.openstack.common import excutils from cinder.openstack.common import importutils -from cinder import utils LOG = logging.getLogger(__name__) @@ -96,7 +96,7 @@ class SchedulerManager(manager.Manager): try: return driver_method(*args, **kwargs) except Exception as ex: - with utils.save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): self._set_vm_state_and_notify(method, {'vm_state': vm_states.ERROR}, context, ex, *args, **kwargs) @@ -114,7 +114,7 @@ class SchedulerManager(manager.Manager): {'vm_state': vm_states.ERROR}, context, ex, *args, **kwargs) except Exception as ex: - with utils.save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): self._set_vm_state_and_notify('run_instance', {'vm_state': vm_states.ERROR}, context, ex, *args, **kwargs) @@ -133,7 +133,7 @@ class SchedulerManager(manager.Manager): 'task_state': None}, context, ex, *args, **kwargs) except Exception as ex: - with utils.save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): self._set_vm_state_and_notify('prep_resize', {'vm_state': vm_states.ERROR}, context, ex, *args, **kwargs) diff --git a/cinder/utils.py b/cinder/utils.py index 5db8dc953..c09a310c1 100644 --- a/cinder/utils.py +++ b/cinder/utils.py @@ -52,6 +52,7 @@ from cinder import exception from cinder import flags from cinder import log as logging from cinder.openstack.common import cfg +from cinder.openstack.common import excutils from cinder.openstack.common import importutils from cinder.openstack.common import timeutils @@ -867,32 +868,6 @@ def generate_glance_url(): return "http://%s:%d" % (FLAGS.glance_host, FLAGS.glance_port) -@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, traceback = sys.exc_info() - try: - yield - except Exception: - # NOTE(jkoelker): Using LOG.error here since it accepts exc_info - # as a kwargs. - LOG.error(_('Original exception being dropped'), - exc_info=(type_, value, traceback)) - raise - raise type_, value, traceback - - @contextlib.contextmanager def logging_error(message): """Catches exception, write message to the log, re-raise. @@ -902,7 +877,7 @@ def logging_error(message): try: yield except Exception as error: - with save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): LOG.exception(message) @@ -914,7 +889,7 @@ def remove_path_on_error(path): try: yield except Exception: - with save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): delete_if_exists(path) @@ -1281,7 +1256,7 @@ class UndoManager(object): .. note:: (sirp) This should only be called within an exception handler. """ - with save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): if msg: LOG.exception(msg, **kwargs) diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py index f4c4bc82e..2afa1e380 100644 --- a/cinder/volume/manager.py +++ b/cinder/volume/manager.py @@ -44,6 +44,7 @@ from cinder import flags from cinder import log as logging from cinder import manager from cinder.openstack.common import cfg +from cinder.openstack.common import excutils from cinder.openstack.common import importutils from cinder.openstack.common import timeutils from cinder import rpc @@ -135,7 +136,7 @@ class VolumeManager(manager.SchedulerDependentManager): if model_update: self.db.volume_update(context, volume_ref['id'], model_update) except Exception: - with utils.save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): self.db.volume_update(context, volume_ref['id'], {'status': 'error'}) @@ -169,7 +170,7 @@ class VolumeManager(manager.SchedulerDependentManager): {'status': 'available'}) return True except Exception: - with utils.save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): self.db.volume_update(context, volume_ref['id'], {'status': 'error_deleting'}) @@ -193,7 +194,7 @@ class VolumeManager(manager.SchedulerDependentManager): model_update) except Exception: - with utils.save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): self.db.snapshot_update(context, snapshot_ref['id'], {'status': 'error'}) @@ -219,7 +220,7 @@ class VolumeManager(manager.SchedulerDependentManager): {'status': 'available'}) return True except Exception: - with utils.save_and_reraise_exception(): + with excutils.save_and_reraise_exception(): self.db.snapshot_update(context, snapshot_ref['id'], {'status': 'error_deleting'}) diff --git a/openstack-common.conf b/openstack-common.conf index c0e470fa0..febc2366e 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -1,7 +1,7 @@ [DEFAULT] # The list of modules to copy from openstack-common -modules=cfg,exception,importutils,iniparser,jsonutils,local,timeutils +modules=cfg,exception,excutils,importutils,iniparser,jsonutils,local,timeutils # The base module to hold the copy of openstack.common base=cinder -- 2.45.2