glance/glance/openstack/common/excutils.py
Matt Riedemann dde2cbafd3 Sync processutils and lockutils from oslo with deps
This is a sync of processutils and lockutils from oslo-incubator
along with their dependencies.

The main target for the sync is to pick up the get_worker_count() method
in commit 85f178489a128a04a7ee3ed44018403caa109ef0 so that we can set
glance-api workers equal to the number of CPUs on the host.

lockutils is also copied over due to the nature running multiple
workers and how the glance functional tests are setup, it'd be
prudent to have the latest lockutils code since it hasn't been updated
in over six months.

The change to require posix_ipc is due to commit
edce46cf5efd6d738d379205f9bf526a498845e3 in lockutils.

Changes:

processutils
------------
85f1784 Move nova.utils.cpu_count() to processutils module
cdcc19c Mask passwords that are included in commands
8a0f567 Remove str() from LOG.* and exceptions
51778f9 Allow passing environment variables to execute()
fcf517d Update oslo log messages with translation domains
af41592 Catch OSError in processutils
f773ea2 Fix i18n problem in processutils module
8b2b0b7 Use hacking import_exceptions for gettextutils._
3b71f46 Fixed misspellings of common words
12bcdb7 Remove vim header
a4dab73 Correct execute() to check 0 in check_exit_code
d6a963e Fix processutils.execute errors on windows
aa5b658 Allow passing a logging level to processutils.execute
1a2df89 Enable H302 hacking check
7119e29 Enable hacking H404 test.
2f01388 Use Python 3.x compatible except construct

lockutils
---------
de4adbc pep8: fixed multiple violations
9e88af1 fixed typos found by RETF rules
fe3389e Improve help strings
f3f14c9 Fixed several typos
0f495ee Emit a log statement when releasing internal lock
f0dd798 Remove rendundant parentheses of cfg help strings
006d9a2 Allow external locks to work with threads
9b73c19 Re-enable file-based locking behavior
edce46c Use Posix IPC in lockutils
ac84a40 Update log translation domains
fcf517d Update oslo log messages with translation domains
37a1de8 Move the released file lock to the successful path
b0d0c33 Add remove external lock files API in lockutils
4f6190a Use threading.ThreadError instead of reraising IOError
195f0b1 Have the interprocess lock follow lock conventions
15cca4b lockutils: move directory creation in lock class
81fe39e lockutils: remove lock_path parameter
14d3669 lockutils: expand add_prefix
dc06d55 lockutils: do not grab the lock in creators
a0948cb lockutils: remove local usage
df8e051 lockutils: split code handling internal/external lock

log
---
109e325 Use oslo.messaging to publish log errors
de4adbc pep8: fixed multiple violations
eac71f5 Fix common.log.ContextFormatter for Python 3
d78b633 Fixes a simple spelling mistake
621d831 always log a traceback in the sys.excepthook
90ae24b Remove redundant default=None for config options
af36c2a Fix logging setup for Python 3.4
cdcc19c Mask passwords that are included in commands

excutils
--------
33a2cee save_and_reraise_exception: make logging respect the reraise parameter
fcf517d Update oslo log messages with translation domains

fileutils
---------
9c88dc3 file_open: fixed docstring to refer to open() instead of file()
6c7407b fileutils: port to Python 3
fcf517d Update oslo log messages with translation domains

Partial-Bug: #1333325

Change-Id: I6c9d8961af2bd3bbe4d149f21cd6d4fad676ba14
2014-06-27 07:00:05 -07:00

114 lines
4.2 KiB
Python

# 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 glance.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