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:
@@ -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,
|
||||
|
49
nova/openstack/common/excutils.py
Normal file
49
nova/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
|
@@ -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()
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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'})
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user