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 nova.utils and then removes
it from nova.utils.

The initial motivation for this was removing another nova dependency
from nova.rpc so that it can eventually be moved to openstack-common.

Change-Id: I7354ca51a02aec9c709cf33f77d4abc46acc2742
This commit is contained in:
Russell Bryant
2012-05-01 17:31:26 -04:00
parent 1d97b77ea4
commit 29dc47bd50
9 changed files with 84 additions and 55 deletions

View File

@@ -62,6 +62,7 @@ from nova import network
from nova.network import model as network_model
from nova.notifier import api as notifier
from nova.openstack.common import cfg
from nova.openstack.common import excutils
from nova.openstack.common import importutils
from nova import rpc
from nova import utils
@@ -187,7 +188,7 @@ def wrap_instance_fault(function):
except exception.InstanceNotFound:
raise
except Exception, e:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
self.add_instance_fault_from_exc(context, instance_uuid, e,
sys.exc_info())
@@ -433,7 +434,7 @@ class ComputeManager(manager.SchedulerDependentManager):
network_info, block_device_info,
injected_files, admin_password)
except Exception:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
self._deallocate_network(context, instance)
if (is_first_time and not instance['access_ip_v4']
@@ -445,7 +446,7 @@ class ComputeManager(manager.SchedulerDependentManager):
except exception.InstanceNotFound:
LOG.warn(_("Instance not found."), instance_uuid=instance_uuid)
except Exception as e:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
self._set_instance_error_state(context, instance_uuid)
def _update_access_ip(self, context, instance, nw_info):
@@ -1335,7 +1336,7 @@ class ComputeManager(manager.SchedulerDependentManager):
context, instance_ref, migration_ref['dest_host'],
instance_type_ref, self._legacy_nw_info(network_info))
except Exception, error:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
LOG.error(_('%s. Setting instance vm_state to ERROR') % error,
instance=instance_ref)
self._set_instance_error_state(context, instance_uuid)
@@ -1425,7 +1426,7 @@ class ComputeManager(manager.SchedulerDependentManager):
self._finish_resize(context, instance_ref, migration_ref,
disk_info, image)
except Exception, error:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
LOG.error(_('%s. Setting instance vm_state to ERROR') % error,
instance=instance_ref)
self._set_instance_error_state(context, instance_ref.uuid)
@@ -1719,7 +1720,7 @@ class ComputeManager(manager.SchedulerDependentManager):
volume,
connector)
except Exception: # pylint: disable=W0702
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
msg = _("Failed to connect to volume %(volume_id)s "
"while attaching at %(mountpoint)s")
LOG.exception(msg % locals(), context=context,
@@ -1730,7 +1731,7 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_ref['name'],
mountpoint)
except Exception: # pylint: disable=W0702
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
msg = _("Failed to attach volume %(volume_id)s "
"at %(mountpoint)s")
LOG.exception(msg % locals(), context=context,
@@ -1975,7 +1976,7 @@ class ComputeManager(manager.SchedulerDependentManager):
'disk': disk}})
except Exception:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
instance_uuid = instance_ref['uuid']
LOG.exception(_('Pre live migration failed at %(dest)s'),
locals(), instance=instance_ref)
@@ -2506,7 +2507,7 @@ class ComputeManager(manager.SchedulerDependentManager):
try:
yield
except Exception, error:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
msg = _('%s. Setting instance vm_state to ERROR')
LOG.error(msg % error, instance_uuid=instance_uuid)
self._set_instance_error_state(context, instance_uuid)
@@ -2518,7 +2519,7 @@ class ComputeManager(manager.SchedulerDependentManager):
try:
self.driver.add_to_aggregate(context, aggregate, host, **kwargs)
except exception.AggregateError:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
self._undo_aggregate_operation(context,
self.db.aggregate_host_delete,
aggregate.id, host)
@@ -2532,7 +2533,7 @@ class ComputeManager(manager.SchedulerDependentManager):
aggregate, host, **kwargs)
except (exception.AggregateError,
exception.InvalidAggregateAction) as e:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
self._undo_aggregate_operation(
context, self.db.aggregate_host_add,
aggregate.id, host,

View 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

View File

@@ -36,9 +36,10 @@ from eventlet import semaphore
from nova import context
from nova import exception
from nova import log as logging
from nova.openstack.common import excutils
from nova.openstack.common import local
import nova.rpc.common as rpc_common
from nova 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()

View File

@@ -31,8 +31,8 @@ from nova import log as logging
from nova import manager
from nova.notifier import api as notifier
from nova.openstack.common import cfg
from nova.openstack.common import excutils
from nova.openstack.common import importutils
from nova import utils
LOG = logging.getLogger(__name__)
@@ -92,7 +92,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)
@@ -110,7 +110,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)
@@ -129,7 +129,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)

View File

@@ -57,6 +57,7 @@ from nova import exception
from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import excutils
from nova.openstack.common import importutils
@@ -1257,32 +1258,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.
@@ -1292,7 +1267,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)
@@ -1304,7 +1279,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)
@@ -1671,7 +1646,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)

View File

@@ -64,6 +64,7 @@ from nova import flags
import nova.image
from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import excutils
from nova.openstack.common import importutils
from nova import utils
from nova.virt import driver
@@ -2220,7 +2221,7 @@ class LibvirtConnection(driver.ComputeDriver):
FLAGS.live_migration_bandwidth)
except Exception:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
recover_method(ctxt, instance_ref, dest, block_migration)
# Waiting for completion of live_migration.

View File

@@ -35,14 +35,15 @@ from xml.parsers import expat
from eventlet import greenthread
from nova.compute import instance_types
from nova.compute import power_state
from nova import exception
from nova import flags
from nova.image import glance
from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import excutils
from nova import utils
from nova.compute import instance_types
from nova.compute import power_state
from nova.virt.disk import api as disk
from nova.virt import xenapi
from nova.virt.xenapi import volume_utils
@@ -558,7 +559,7 @@ class VMHelper(xenapi.HelperBase):
cls.create_vbd(session, vm_ref, vdi_ref, userdevice,
bootable=False)
except Exception:
with utils.save_and_reraise_exception():
with excutils.save_and_reraise_exception():
cls.destroy_vdi(session, vdi_ref)
@classmethod

View File

@@ -44,6 +44,7 @@ from nova import flags
from nova import log as logging
from nova import manager
from nova.openstack.common import cfg
from nova.openstack.common import excutils
from nova.openstack.common import importutils
from nova import rpc
from nova import utils
@@ -134,7 +135,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'})
@@ -168,7 +169,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'})
@@ -192,7 +193,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'})
@@ -218,7 +219,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'})

View File

@@ -1,7 +1,7 @@
[DEFAULT]
# The list of modules to copy from openstack-common
modules=cfg,local,importutils,iniparser
modules=cfg,excutils,local,importutils,iniparser
# The base module to hold the copy of openstack.common
base=nova