Sync excutils from Oslo
This patch adds the excutils module to openstack-common.conf, sync excutils from oslo-incubator and uses save_and_reraise_exception where it is relevant. Change-Id: Id190aad9a4fd2dd7bf962f001f88b6a0884c18a1
This commit is contained in:
parent
b1ff9e7677
commit
df06729fdb
@ -1,6 +1,7 @@
|
||||
[DEFAULT]
|
||||
|
||||
# The list of modules to copy from oslo-incubator.git
|
||||
module=excutils
|
||||
module=gettextutils
|
||||
|
||||
script=tools/run_cross_tests.sh
|
||||
|
@ -27,6 +27,7 @@ import six
|
||||
|
||||
from oslo.vmware.common import loopingcall
|
||||
from oslo.vmware import exceptions
|
||||
from oslo.vmware.openstack.common import excutils
|
||||
from oslo.vmware.openstack.common.gettextutils import _
|
||||
from oslo.vmware import pbm
|
||||
from oslo.vmware import vim
|
||||
@ -87,29 +88,32 @@ class RetryDecorator(object):
|
||||
"after %(retry_count)d retries.",
|
||||
{'func_name': func_name,
|
||||
'retry_count': self._retry_count})
|
||||
except self._exceptions as excep:
|
||||
LOG.warn(_("Exception which is in the suggested list of "
|
||||
"exceptions occurred while invoking function:"
|
||||
" %s."),
|
||||
func_name,
|
||||
exc_info=True)
|
||||
if (self._max_retry_count != -1 and
|
||||
self._retry_count >= self._max_retry_count):
|
||||
LOG.error(_("Cannot retry upon suggested exception since "
|
||||
"retry count (%(retry_count)d) reached "
|
||||
"max retry count (%(max_retry_count)d)."),
|
||||
{'retry_count': self._retry_count,
|
||||
'max_retry_count': self._max_retry_count})
|
||||
raise excep
|
||||
else:
|
||||
self._retry_count += 1
|
||||
self._sleep_time += self._inc_sleep_time
|
||||
return self._sleep_time
|
||||
except Exception as excep:
|
||||
LOG.exception(_("Exception which is not in the suggested list "
|
||||
"of exceptions occurred while invoking %s."),
|
||||
func_name)
|
||||
raise excep
|
||||
except self._exceptions:
|
||||
with excutils.save_and_reraise_exception() as ctxt:
|
||||
LOG.warn(_("Exception which is in the suggested list of "
|
||||
"exceptions occurred while invoking function:"
|
||||
" %s."),
|
||||
func_name,
|
||||
exc_info=True)
|
||||
if (self._max_retry_count != -1 and
|
||||
self._retry_count >= self._max_retry_count):
|
||||
LOG.error(_("Cannot retry upon suggested exception "
|
||||
"since retry count (%(retry_count)d) "
|
||||
"reached max retry count "
|
||||
"(%(max_retry_count)d)."),
|
||||
{'retry_count': self._retry_count,
|
||||
'max_retry_count': self._max_retry_count})
|
||||
else:
|
||||
ctxt.reraise = False
|
||||
self._retry_count += 1
|
||||
self._sleep_time += self._inc_sleep_time
|
||||
return self._sleep_time
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_("Exception which is not in the "
|
||||
"suggested list of exceptions occurred "
|
||||
"while invoking %s."),
|
||||
func_name)
|
||||
raise loopingcall.LoopingCallDone(result)
|
||||
|
||||
def func(*args, **kwargs):
|
||||
@ -318,14 +322,15 @@ class VMwareAPISession(object):
|
||||
raise
|
||||
|
||||
except exceptions.VimConnectionException:
|
||||
# Re-create the session during connection exception.
|
||||
LOG.warn(_("Re-creating session due to connection problems "
|
||||
"while invoking method %(module)s.%(method)s."),
|
||||
{'module': module,
|
||||
'method': method},
|
||||
exc_info=True)
|
||||
self._create_session()
|
||||
raise
|
||||
with excutils.save_and_reraise_exception():
|
||||
# Re-create the session during connection exception.
|
||||
LOG.warn(_("Re-creating session due to connection "
|
||||
"problems while invoking method "
|
||||
"%(module)s.%(method)s."),
|
||||
{'module': module,
|
||||
'method': method},
|
||||
exc_info=True)
|
||||
self._create_session()
|
||||
|
||||
return _invoke_api(module, method, *args, **kwargs)
|
||||
|
||||
@ -384,10 +389,11 @@ class VMwareAPISession(object):
|
||||
self.vim,
|
||||
task,
|
||||
'info')
|
||||
except exceptions.VimException as excep:
|
||||
LOG.exception(_("Error occurred while reading info of task: %s."),
|
||||
task)
|
||||
raise excep
|
||||
except exceptions.VimException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_("Error occurred while reading info of "
|
||||
"task: %s."),
|
||||
task)
|
||||
else:
|
||||
if task_info.state in ['queued', 'running']:
|
||||
if hasattr(task_info, 'progress'):
|
||||
@ -438,11 +444,11 @@ class VMwareAPISession(object):
|
||||
self.vim,
|
||||
lease,
|
||||
'state')
|
||||
except exceptions.VimException as excep:
|
||||
LOG.exception(_("Error occurred while checking state of lease: "
|
||||
"%s."),
|
||||
lease)
|
||||
raise excep
|
||||
except exceptions.VimException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_("Error occurred while checking "
|
||||
"state of lease: %s."),
|
||||
lease)
|
||||
else:
|
||||
if state == 'ready':
|
||||
LOG.debug("Lease: %s is ready.", lease)
|
||||
|
113
oslo/vmware/openstack/common/excutils.py
Normal file
113
oslo/vmware/openstack/common/excutils.py
Normal file
@ -0,0 +1,113 @@
|
||||
# Copyright 2011 OpenStack Foundation.
|
||||
# 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 logging
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import six
|
||||
|
||||
from oslo.vmware.openstack.common.gettextutils import _LE
|
||||
|
||||
|
||||
class save_and_reraise_exception(object):
|
||||
"""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 re-raised 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 re-raised.
|
||||
|
||||
In some cases the caller may not want to re-raise the exception, and
|
||||
for those circumstances this context provides a reraise flag that
|
||||
can be used to suppress the exception. For example::
|
||||
|
||||
except Exception:
|
||||
with save_and_reraise_exception() as ctxt:
|
||||
decide_if_need_reraise()
|
||||
if not should_be_reraised:
|
||||
ctxt.reraise = False
|
||||
|
||||
If another exception occurs and reraise flag is False,
|
||||
the saved exception will not be logged.
|
||||
|
||||
If the caller wants to raise new exception during exception handling
|
||||
he/she sets reraise to False initially with an ability to set it back to
|
||||
True if needed::
|
||||
|
||||
except Exception:
|
||||
with save_and_reraise_exception(reraise=False) as ctxt:
|
||||
[if statements to determine whether to raise a new exception]
|
||||
# Not raising a new exception, so reraise
|
||||
ctxt.reraise = True
|
||||
"""
|
||||
def __init__(self, reraise=True):
|
||||
self.reraise = reraise
|
||||
|
||||
def __enter__(self):
|
||||
self.type_, self.value, self.tb, = sys.exc_info()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
if exc_type is not None:
|
||||
if self.reraise:
|
||||
logging.error(_LE('Original exception being dropped: %s'),
|
||||
traceback.format_exception(self.type_,
|
||||
self.value,
|
||||
self.tb))
|
||||
return False
|
||||
if self.reraise:
|
||||
six.reraise(self.type_, self.value, self.tb)
|
||||
|
||||
|
||||
def forever_retry_uncaught_exceptions(infunc):
|
||||
def inner_func(*args, **kwargs):
|
||||
last_log_time = 0
|
||||
last_exc_message = None
|
||||
exc_count = 0
|
||||
while True:
|
||||
try:
|
||||
return infunc(*args, **kwargs)
|
||||
except Exception as exc:
|
||||
this_exc_message = six.u(str(exc))
|
||||
if this_exc_message == last_exc_message:
|
||||
exc_count += 1
|
||||
else:
|
||||
exc_count = 1
|
||||
# Do not log any more frequently than once a minute unless
|
||||
# the exception message changes
|
||||
cur_time = int(time.time())
|
||||
if (cur_time - last_log_time > 60 or
|
||||
this_exc_message != last_exc_message):
|
||||
logging.exception(
|
||||
_LE('Unexpected exception occurred %d time(s)... '
|
||||
'retrying.') % exc_count)
|
||||
last_log_time = cur_time
|
||||
last_exc_message = this_exc_message
|
||||
exc_count = 0
|
||||
# This should be a very rare event. In case it isn't, do
|
||||
# a sleep.
|
||||
time.sleep(1)
|
||||
return inner_func
|
@ -31,6 +31,7 @@ import urlparse
|
||||
import netaddr
|
||||
|
||||
from oslo.vmware import exceptions
|
||||
from oslo.vmware.openstack.common import excutils
|
||||
from oslo.vmware.openstack.common.gettextutils import _
|
||||
from oslo.vmware import vim_util
|
||||
|
||||
@ -408,11 +409,11 @@ class VmdkWriteHandle(FileHandle):
|
||||
"URL = %(url)s to %(percent)d%%.",
|
||||
{'url': self._url,
|
||||
'percent': percent})
|
||||
except exceptions.VimException as excep:
|
||||
LOG.exception(_("Error occurred while updating the write progress "
|
||||
"of VMDK file with URL = %s."),
|
||||
self._url)
|
||||
raise excep
|
||||
except exceptions.VimException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_("Error occurred while updating the "
|
||||
"write progress of VMDK file with URL = %s."),
|
||||
self._url)
|
||||
|
||||
def close(self):
|
||||
"""Releases the lease and close the connection.
|
||||
@ -570,11 +571,11 @@ class VmdkReadHandle(FileHandle):
|
||||
"URL = %(url)s to %(percent)d%%.",
|
||||
{'url': self._url,
|
||||
'percent': percent})
|
||||
except exceptions.VimException as excep:
|
||||
LOG.exception(_("Error occurred while updating the read progress "
|
||||
"of VMDK file with URL = %s."),
|
||||
self._url)
|
||||
raise excep
|
||||
except exceptions.VimException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_("Error occurred while updating the "
|
||||
"read progress of VMDK file with URL = %s."),
|
||||
self._url)
|
||||
|
||||
def close(self):
|
||||
"""Releases the lease and close the connection.
|
||||
|
Loading…
x
Reference in New Issue
Block a user