33d25e3cc3
We don't need this in a Python 3-only world. Change-Id: I56dca98d06458174af0f3d4dc585a754e8692f89
132 lines
4.4 KiB
Python
132 lines
4.4 KiB
Python
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
|
|
#
|
|
# 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.
|
|
|
|
"""Utilities and helper functions."""
|
|
|
|
import contextlib
|
|
import functools
|
|
import inspect
|
|
import pyclbr
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
|
|
from oslo_concurrency import lockutils
|
|
from oslo_concurrency import processutils
|
|
from oslo_log import log as logging
|
|
from oslo_utils import importutils
|
|
|
|
import masakarimonitors.conf
|
|
from masakarimonitors.i18n import _
|
|
from masakarimonitors import privsep
|
|
|
|
|
|
CONF = masakarimonitors.conf.CONF
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def monkey_patch():
|
|
"""monkey_patch function.
|
|
|
|
If the CONF.monkey_patch set as True,
|
|
this function patches a decorator
|
|
for all functions in specified modules.
|
|
You can set decorators for each modules
|
|
using CONF.monkey_patch_modules.
|
|
The format is "Module path:Decorator function".
|
|
name - name of the function
|
|
function - object of the function
|
|
"""
|
|
# If CONF.monkey_patch is not True, this function do nothing.
|
|
if not CONF.monkey_patch:
|
|
return
|
|
|
|
def is_method(obj):
|
|
return inspect.ismethod(obj) or inspect.isfunction(obj)
|
|
# Get list of modules and decorators
|
|
for module_and_decorator in CONF.monkey_patch_modules:
|
|
md_value = module_and_decorator.split(':')
|
|
if len(md_value) != 2:
|
|
msg = _("'monkey_patch_modules' config option is not configured "
|
|
"correctly")
|
|
raise Exception(msg)
|
|
module, decorator_name = md_value
|
|
# import decorator function
|
|
decorator = importutils.import_class(decorator_name)
|
|
__import__(module)
|
|
# Retrieve module information using pyclbr
|
|
module_data = pyclbr.readmodule_ex(module)
|
|
for key, value in module_data.items():
|
|
# set the decorator for the class methods
|
|
if isinstance(value, pyclbr.Class):
|
|
clz = importutils.import_class("%s.%s" % (module, key))
|
|
for method, func in inspect.getmembers(clz, is_method):
|
|
setattr(clz, method,
|
|
decorator("%s.%s.%s" % (module, key,
|
|
method), func))
|
|
# set the decorator for the function
|
|
if isinstance(value, pyclbr.Function):
|
|
func = importutils.import_class("%s.%s" % (module, key))
|
|
setattr(sys.modules[module], key,
|
|
decorator("%s.%s" % (module, key), func))
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def tempdir(**kwargs):
|
|
argdict = kwargs.copy()
|
|
if 'dir' not in argdict:
|
|
argdict['dir'] = CONF.tempdir
|
|
tmpdir = tempfile.mkdtemp(**argdict)
|
|
try:
|
|
yield tmpdir
|
|
finally:
|
|
try:
|
|
shutil.rmtree(tmpdir)
|
|
except OSError as e:
|
|
LOG.error('Could not remove tmpdir: %s', e)
|
|
|
|
|
|
@privsep.monitors_priv.entrypoint
|
|
def privsep_execute(*cmd, **kwargs):
|
|
return processutils.execute(*cmd, **kwargs)
|
|
|
|
|
|
def execute(*cmd, **kwargs):
|
|
"""Convenience wrapper around oslo's execute() method."""
|
|
if 'run_as_root' in kwargs and kwargs.get('run_as_root'):
|
|
return privsep_execute(*cmd, **kwargs)
|
|
else:
|
|
return processutils.execute(*cmd, **kwargs)
|
|
|
|
|
|
def synchronized(name, semaphores=None, blocking=False):
|
|
def wrap(f):
|
|
@functools.wraps(f)
|
|
def inner(*args, **kwargs):
|
|
lock_str = 'masakarimonitors-%s' % name
|
|
int_lock = lockutils.internal_lock(lock_str,
|
|
semaphores=semaphores)
|
|
msg = "Lock blocking: %s on resource %s " % (lock_str, f.__name__)
|
|
"""Acquiring lock: %(lock_str)s on resource """
|
|
if not int_lock.acquire(blocking=blocking):
|
|
raise Exception(msg)
|
|
try:
|
|
return f(*args, **kwargs)
|
|
finally:
|
|
"""Releasing lock: %(lock_str)s on resource """
|
|
int_lock.release()
|
|
return inner
|
|
return wrap
|