]> Frank Brehm's Git Trees - pixelpark/puppetmaster-webhooks.git/commitdiff
Removing lib/webhooks/lock_handler.py
authorFrank Brehm <frank.brehm@pixelpark.com>
Wed, 9 Jan 2019 16:55:05 +0000 (17:55 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Wed, 9 Jan 2019 16:55:05 +0000 (17:55 +0100)
lib/webhooks/lock_handler.py [deleted file]

diff --git a/lib/webhooks/lock_handler.py b/lib/webhooks/lock_handler.py
deleted file mode 100644 (file)
index f99a664..0000000
+++ /dev/null
@@ -1,1201 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-@author: Frank Brehm
-@contact: frank.brehm@pixelpark.com
-@copyright: © 2018 by Frank Brehm, Publicies Pixelpark GmbH, Berlin
-@summary: Module for a extended handler module, which has additional
-          methods for locking
-"""
-from __future__ import absolute_import
-
-# Standard modules
-import sys
-import os
-import logging
-import time
-import errno
-import traceback
-import datetime
-import fcntl
-
-from numbers import Number
-
-# Third party modules
-from six import reraise
-
-# Own modules
-from fb_tools.common import to_utf8
-from fb_tools.errors import CouldntOccupyLockfileError, HandlerError
-from fb_tools.obj import FbBaseObject
-from fb_tools.handler import BaseHandler
-
-__version__ = '0.5.0'
-
-LOG = logging.getLogger(__name__)
-
-# Module variables
-DEFAULT_LOCKRETRY_DELAY_START = 0.1
-DEFAULT_LOCKRETRY_DELAY_INCREASE = 0.2
-DEFAULT_LOCKRETRY_MAX_DELAY = 10
-DEFAULT_MAX_LOCKFILE_AGE = 300
-DEFAULT_LOCKING_USE_PID = True
-
-
-# =============================================================================
-class LockHandlerError(HandlerError):
-    """
-    Base exception class for all exceptions belonging to locking issues
-    in this module
-    """
-
-    pass
-
-
-# =============================================================================
-class LockObjectError(LockHandlerError):
-    """
-    Special exception class for exceptions raising inside methods of
-    the LockObject.
-    """
-
-    pass
-
-
-# =============================================================================
-class LockdirNotExistsError(LockHandlerError):
-    """
-    Exception class for the case, that the parent directory of the lockfile
-    (lockdir) doesn't exists.
-    """
-
-    # -------------------------------------------------------------------------
-    def __init__(self, lockdir):
-        """
-        Constructor.
-
-        @param lockdir: the directory, wich doesn't exists.
-        @type lockdir: str
-
-        """
-
-        self.lockdir = lockdir
-
-    # -------------------------------------------------------------------------
-    def __str__(self):
-        """Typecasting into a string for error output."""
-
-        return "Locking directory {!r} doesn't exists or is not a directory.".format(self.lockdir)
-
-
-# =============================================================================
-class LockdirNotWriteableError(LockHandlerError):
-    """
-    Exception class for the case, that the parent directory of the lockfile
-    (lockdir) isn't writeable for the current process.
-    """
-
-    # -------------------------------------------------------------------------
-    def __init__(self, lockdir):
-        """
-        Constructor.
-
-        @param lockdir: the directory, wich isn't writeable
-        @type lockdir: str
-
-        """
-
-        self.lockdir = lockdir
-
-    # -------------------------------------------------------------------------
-    def __str__(self):
-        """Typecasting into a string for error output."""
-
-        return "Locking directory {!r} isn't writeable.".format(self.lockdir)
-
-
-# =============================================================================
-class LockObject(FbBaseObject):
-    """
-    Capsulation class as a result of a successful lock action. It contains all
-    important informations about the lock.
-
-    It can be used for holding these informations and, if desired, to remove
-    the lock automatically, if the current instance of LockObject is removed.
-
-    """
-
-    # -------------------------------------------------------------------------
-    def __init__(
-        self, lockfile, ctime=None, mtime=None, fcontent=None, fd=None, simulate=False,
-            autoremove=False, appname=None, verbose=0, version=__version__,
-            base_dir=None, silent=False):
-        """
-        Initialisation of the LockObject object.
-
-        @raise LockObjectError: on a uncoverable error.
-
-        @param lockfile: the file, which represents the lock, must exists
-        @type lockfile: str
-        @param ctime: the creation time of the lockfile
-        @type ctime: datetime
-        @param mtime: the modification time of the lockfile
-        @type mtime: datetime
-        @param fcontent: the content of the lockfile
-        @type fcontent: str
-        @param fd: The numeric file descriptor of the lockfile, if opened, if not opened, then None
-        @type fd: int or None
-        @param simulate: don't execute actions, only display them
-        @type simulate: bool
-        @param autoremove: removing the lockfile on deleting the current object
-        @type autoremove: bool
-        @param appname: name of the current running application
-        @type appname: str
-        @param verbose: verbose level
-        @type verbose: int
-        @param version: the version string of the current object or application
-        @type version: str
-        @param base_dir: the base directory of all operations
-        @type base_dir: str
-        @param silent: Remove silently the lockfile (except on verbose level >= 2)
-        @type silent: bool
-
-        @return: None
-        """
-
-        self._fd = None
-
-        super(LockObject, self).__init__(
-            appname=appname, verbose=verbose, version=version,
-            base_dir=base_dir, initialized=False,
-        )
-
-        if not lockfile:
-            raise LockObjectError("No lockfile given on init of a LockObject object.")
-
-        if not os.path.exists(lockfile):
-            raise LockObjectError("Lockfile {!r} doesn't exists.".format(lockfile))
-
-        if not os.path.isfile(lockfile):
-            raise LockObjectError("Lockfile {!r} is not a regular file.".format(lockfile))
-
-        if fd is not None:
-            self._fd = fd
-
-        self._lockfile = os.path.realpath(lockfile)
-
-        self._fcontent = None
-        if fcontent is not None:
-            self._fcontent = str(fcontent)
-        self._simulate = bool(simulate)
-        self._autoremove = bool(autoremove)
-        self._silent = bool(silent)
-
-        self._ctime = ctime
-        self._mtime = mtime
-
-        # Detecting self._ctime and self._mtime from filestat of the lockfile
-        if not self._ctime or not self._mtime:
-            fstat = os.stat(lockfile)
-            if not self._ctime:
-                self._ctime = datetime.datetime.utcfromtimestamp(fstat.st_ctime)
-            if not self._mtime:
-                self._mtime = datetime.datetime.utcfromtimestamp(fstat.st_mtime)
-
-        self.initialized = True
-
-    # -----------------------------------------------------------
-    @property
-    def lockfile(self):
-        """The file, which represents the lock."""
-        return self._lockfile
-
-    # -----------------------------------------------------------
-    @property
-    def ctime(self):
-        """The creation time of the lockfile."""
-        return self._ctime
-
-    # -----------------------------------------------------------
-    @property
-    def mtime(self):
-        """The last modification time of the lockfile."""
-        return self._mtime
-
-    # -----------------------------------------------------------
-    @property
-    def fcontent(self):
-        """The content of the lockfile."""
-        return self._fcontent
-
-    # -----------------------------------------------------------
-    @property
-    def fd(self):
-        "The numeric file descriptor of the lockfile."
-        return self._fd
-
-    # -----------------------------------------------------------
-    @property
-    def simulate(self):
-        """Don't execute actions, only display them."""
-        return self._simulate
-
-    @simulate.setter
-    def simulate(self, value):
-        self._simulate = bool(value)
-
-    # -----------------------------------------------------------
-    @property
-    def autoremove(self):
-        """Removing the lockfile on deleting the current object."""
-        return self._autoremove
-
-    @autoremove.setter
-    def autoremove(self, value):
-        self._autoremove = bool(value)
-
-    # -----------------------------------------------------------
-    @property
-    def silent(self):
-        """Remove silently the lockfile (except on verbose level >= 2)."""
-        return self._silent
-
-    @silent.setter
-    def silent(self, value):
-        self._silent = bool(value)
-
-    # -------------------------------------------------------------------------
-    def as_dict(self, short=True):
-        """
-        Transforms the elements of the object into a dict
-
-        @param short: don't include local properties in resulting dict.
-        @type short: bool
-
-        @return: structure as dict
-        @rtype:  dict
-        """
-
-        res = super(LockObject, self).as_dict(short=short)
-        res['lockfile'] = self.lockfile
-        res['ctime'] = self.ctime
-        res['mtime'] = self.mtime
-        res['fcontent'] = self.fcontent
-        res['simulate'] = self.simulate
-        res['autoremove'] = self.autoremove
-        res['silent'] = self.silent
-        res['fd'] = self.fd
-
-        return res
-
-    # -------------------------------------------------------------------------
-    def __repr__(self):
-        """Typecasting into a string for reproduction."""
-
-        out = super(LockObject, self).__repr__()[:-2]
-
-        fields = []
-        fields.append("lockfile={!r}".format(self.lockfile))
-        if self.fcontent:
-            fields.append("fcontent={!r}".format(self.fcontent))
-        fields.append("ctime={!r}".format(self.ctime))
-        fields.append("mtime={!r}".format(self.mtime))
-        fields.append("fcontent={!r}".format(self.fcontent))
-        fields.append("fd={!r}".format(self.fd))
-        fields.append("simulate={!r}".format(self.simulate))
-        fields.append("autoremove={!r}".format(self.autoremove))
-        fields.append("silent={!r}".format(self.silent))
-
-        if fields:
-            out += ', ' + ", ".join(fields)
-        out += ")>"
-        return out
-
-    # -------------------------------------------------------------------------
-    def __del__(self):
-        """Destructor.
-
-        Removes the lockfile, if self.autoremove is True
-
-        """
-
-        if not getattr(self, '_initialized', False):
-            return
-
-        if self.fd is not None:
-            msg = "Closing file descriptor {} ...".format(self.fd)
-            if self.silent:
-                if self.verbose >= 2:
-                    LOG.debug(msg)
-            else:
-                LOG.debug(msg)
-            os.close(self.fd)
-            self._fd = None
-
-        if self.autoremove and self.exists:
-
-            msg = "Automatic removing of {!r} ...".format(self.lockfile)
-            if self.silent:
-                if self.verbose >= 2:
-                    LOG.debug(msg)
-            else:
-                LOG.info(msg)
-
-            if not self.simulate:
-                os.remove(self.lockfile)
-
-    # -------------------------------------------------------------------------
-    def exists(self):
-        """Returns, whether the lockfile exists or not."""
-
-        if self.simulate:
-            return True
-
-        return os.path.exists(self.lockfile)
-
-    # -------------------------------------------------------------------------
-    def refresh(self):
-        """
-        Refreshes the atime and mtime of the lockfile to the current time.
-        """
-
-        msg = "Refreshing atime and mtime of {!r} to the current timestamp.".format(self.lockfile)
-        LOG.debug(msg)
-
-        if not self.simulate:
-            os.utime(self.lockfile, None)
-
-        self._mtime = datetime.datetime.utcnow()
-
-
-# =============================================================================
-class LockHandler(BaseHandler):
-    """
-    Handler class with additional properties and methods to create,
-    check and remove lock files.
-    """
-
-    # -------------------------------------------------------------------------
-    def __init__(
-        self, lockdir=None,
-            lockretry_delay_start=DEFAULT_LOCKRETRY_DELAY_START,
-            lockretry_delay_increase=DEFAULT_LOCKRETRY_DELAY_INCREASE,
-            lockretry_max_delay=DEFAULT_LOCKRETRY_MAX_DELAY,
-            max_lockfile_age=DEFAULT_MAX_LOCKFILE_AGE,
-            locking_use_pid=DEFAULT_LOCKING_USE_PID,
-            stay_opened=True, appname=None, verbose=0, version=__version__, base_dir=None,
-            simulate=False, sudo=False, quiet=False, silent=False, *targs, **kwargs):
-        """
-        Initialisation of the locking handler object.
-
-        @raise LockdirNotExistsError: if the lockdir (or base_dir) doesn't exists
-        @raise LockHandlerError: on a uncoverable error.
-
-        @param lockdir: a special directory for searching and creating the
-                        lockfiles, if not given, self.base_dir will used
-        @type lockdir: str
-        @param lockretry_delay_start: the first delay in seconds after an
-                                      unsuccessful lockfile creation
-        @type lockretry_delay_start: Number
-        @param lockretry_delay_increase: seconds to increase the delay in every
-                                         wait cycle
-        @type lockretry_delay_increase: Number
-        @param lockretry_max_delay: the total maximum delay in seconds for
-                                    trying to create a lockfile
-        @type lockretry_max_delay: Number
-        @param max_lockfile_age: the maximum age of the lockfile (in seconds),
-                                 for the existing lockfile is valid (if
-                                 locking_use_pid is False).
-        @type max_lockfile_age: Number
-        @param locking_use_pid: write the PID of creating process into the
-                                fresh created lockfile, if False, the lockfile
-                                will be leaved empty, the PID in the lockfile
-                                can be used to check the validity of the
-                                lockfile
-        @type locking_use_pid: bool
-        @param stay_opened: should the lockfile stay opened after creation
-        @@type stay_opened: bool
-        @param appname: name of the current running application
-        @type appname: str
-        @param verbose: verbose level
-        @type verbose: int
-        @param version: the version string of the current object or application
-        @type version: str
-        @param base_dir: the base directory of all operations
-        @type base_dir: str
-        @param simulate: don't execute actions, only display them
-        @type simulate: bool
-        @param sudo: should the command executed by sudo by default
-        @type sudo: bool
-        @param quiet: don't display ouput of action after calling
-        @type quiet: bool
-        @param silent: Create and remove silently the lockfile (except on verbose level >= 2)
-        @type silent: bool
-
-        @return: None
-
-        """
-
-        self._stay_opened = bool(stay_opened)
-
-        super(LockHandler, self).__init__(
-            appname=appname, verbose=verbose, version=version, base_dir=base_dir,
-            initialized=False, simulate=simulate, sudo=sudo, quiet=quiet,
-        )
-
-        self._lockdir = None
-        if lockdir is not None:
-            self.lockdir = lockdir
-
-        self._lockretry_delay_start = DEFAULT_LOCKRETRY_DELAY_START
-        self.lockretry_delay_start = lockretry_delay_start
-
-        self._lockretry_delay_increase = DEFAULT_LOCKRETRY_DELAY_INCREASE
-        self.lockretry_delay_increase = lockretry_delay_increase
-
-        self._lockretry_max_delay = DEFAULT_LOCKRETRY_MAX_DELAY
-        self.lockretry_max_delay = lockretry_max_delay
-
-        self._max_lockfile_age = DEFAULT_MAX_LOCKFILE_AGE
-        self.max_lockfile_age = max_lockfile_age
-
-        self._locking_use_pid = DEFAULT_LOCKING_USE_PID
-        self.locking_use_pid = locking_use_pid
-
-        self._silent = bool(silent)
-
-    # -----------------------------------------------------------
-    @property
-    def lockdir(self):
-        """The directory for searching and creating the lockfiles."""
-        if self._lockdir:
-            return self._lockdir
-        return self.base_dir
-
-    @lockdir.setter
-    def lockdir(self, value):
-        if not value:
-            self._lockdir = None
-            return
-
-        if os.path.isabs(value):
-            self._lockdir = os.path.normpath(value)
-        else:
-            self._lockdir = os.path.normpath(os.path.join(self.base_dir, value))
-
-    # -----------------------------------------------------------
-    @property
-    def lockretry_delay_start(self):
-        """
-        The first delay in seconds after an unsuccessful lockfile creation.
-        """
-        return self._lockretry_delay_start
-
-    @lockretry_delay_start.setter
-    def lockretry_delay_start(self, value):
-        if not isinstance(value, Number):
-            msg = "Value {val!r} for {what} is not a Number.".format(
-                val=value, what='lockretry_delay_start')
-            raise LockHandlerError(msg)
-
-        if value <= 0:
-            msg = "The value for {what} must be greater than zero (is {val!r}).".format(
-                val=value, what='lockretry_delay_start')
-            raise LockHandlerError(msg)
-
-        self._lockretry_delay_start = value
-
-    # -----------------------------------------------------------
-    @property
-    def lockretry_delay_increase(self):
-        """
-        The seconds to increase the delay in every wait cycle.
-        """
-        return self._lockretry_delay_increase
-
-    @lockretry_delay_increase.setter
-    def lockretry_delay_increase(self, value):
-        if not isinstance(value, Number):
-            msg = "Value {val!r} for {what} is not a Number.".format(
-                val=value, what='lockretry_delay_increase')
-            raise LockHandlerError(msg)
-
-        if value < 0:
-            msg = "The value for {what} must be greater than zero (is {val!r}).".format(
-                val=value, what='lockretry_delay_increase')
-            raise LockHandlerError(msg)
-
-        self._lockretry_delay_increase = value
-
-    # -----------------------------------------------------------
-    @property
-    def lockretry_max_delay(self):
-        """
-        The total maximum delay in seconds for trying to create a lockfile.
-        """
-        return self._lockretry_max_delay
-
-    @lockretry_max_delay.setter
-    def lockretry_max_delay(self, value):
-        if not isinstance(value, Number):
-            msg = "Value {val!r} for {what} is not a Number.".format(
-                val=value, what='lockretry_max_delay')
-            raise LockHandlerError(msg)
-
-        if value <= 0:
-            msg = "The value for {what} must be greater than zero (is {val!r}).".format(
-                val=value, what='lockretry_max_delay')
-            raise LockHandlerError(msg)
-
-        self._lockretry_max_delay = value
-
-    # -----------------------------------------------------------
-    @property
-    def max_lockfile_age(self):
-        """
-        The maximum age of the lockfile (in seconds), for the existing lockfile
-        is valid (if locking_use_pid is False).
-        """
-        return self._max_lockfile_age
-
-    @max_lockfile_age.setter
-    def max_lockfile_age(self, value):
-        if not isinstance(value, Number):
-            msg = "Value {val!r} for {what} is not a Number.".format(
-                val=value, what='max_lockfile_age')
-            raise LockHandlerError(msg)
-
-        if value <= 0:
-            msg = "The value for {what} must be greater than zero (is {val!r}).".format(
-                val=value, what='max_lockfile_age')
-            raise LockHandlerError(msg)
-
-        self._max_lockfile_age = value
-
-    # -----------------------------------------------------------
-    @property
-    def locking_use_pid(self):
-        """
-        Write the PID of creating process into the fresh created lockfile.
-        """
-        return self._locking_use_pid
-
-    @locking_use_pid.setter
-    def locking_use_pid(self, value):
-        self._locking_use_pid = bool(value)
-
-    # -----------------------------------------------------------
-    @property
-    def stay_opened(self):
-        """
-        Should the lockfile stay opened after creation. If yes, then it will be closed
-        on deleting the LockObject.
-        """
-        return self._stay_opened
-
-    @stay_opened.setter
-    def stay_opened(self, value):
-        self._stay_opened = bool(value)
-
-    # -----------------------------------------------------------
-    @property
-    def silent(self):
-        """Create and remove silently the lockfile (except on verbose level >= 2)."""
-        return self._silent
-
-    @silent.setter
-    def silent(self, value):
-        self._silent = bool(value)
-
-    # -------------------------------------------------------------------------
-    def as_dict(self, short=True):
-        """
-        Transforms the elements of the object into a dict
-
-        @param short: don't include local properties in resulting dict.
-        @type short: bool
-
-        @return: structure as dict
-        @rtype:  dict
-        """
-
-        res = super(LockHandler, self).as_dict(short=short)
-        res['lockdir'] = self.lockdir
-        res['lockretry_delay_start'] = self.lockretry_delay_start
-        res['lockretry_delay_increase'] = self.lockretry_delay_increase
-        res['lockretry_max_delay'] = self.lockretry_max_delay
-        res['max_lockfile_age'] = self.max_lockfile_age
-        res['locking_use_pid'] = self.locking_use_pid
-        res['silent'] = self.silent
-        res['stay_opened'] = self.stay_opened
-
-        return res
-
-    # -------------------------------------------------------------------------
-    def __repr__(self):
-        """Typecasting into a string for reproduction."""
-
-        out = super(LockHandler, self).__repr__()[:-2]
-
-        fields = []
-        if self._lockdir:
-            fields.append("lockdir=%r" % (self.lockdir))
-        fields.append("lockretry_delay_start=%r" % (self.lockretry_delay_start))
-        fields.append("lockretry_delay_increase=%r" % (self.lockretry_delay_increase))
-        fields.append("lockretry_max_delay=%r" % (self.lockretry_max_delay))
-        fields.append("max_lockfile_age=%r" % (self.max_lockfile_age))
-        fields.append("locking_use_pid=%r" % (self.locking_use_pid))
-        fields.append("silent=%r" % (self.silent))
-        fields.append("stay_opened=%r" % (self.stay_opened))
-
-        if fields:
-            out += ', ' + ", ".join(fields)
-        out += ")>"
-        return out
-
-    # -------------------------------------------------------------------------
-    def check_for_number(self, value, default, what, must_gt_zero=False, must_ge_zero=False):
-
-        if value is None:
-            return default
-
-        if not isinstance(value, Number):
-            msg = "Value {val!r} for {what} is not a Number.".format(
-                val=value, what=what)
-            raise LockHandlerError(msg)
-
-        if must_gt_zero and value <= 0:
-            msg = "The value for {what} must be greater than zero (is {val!r}).".format(
-                val=value, what=what)
-            raise LockHandlerError(msg)
-
-        if must_ge_zero and value < 0:
-            msg = (
-                "The value for {what} must be greater than "
-                "or equal to zero (is {val!r}).").format(
-                val=value, what=what)
-            raise LockHandlerError(msg)
-
-        return value
-
-    # -------------------------------------------------------------------------
-    def create_lockfile(
-        self, lockfile, delay_start=None, delay_increase=None, max_delay=None,
-            use_pid=None, max_age=None, pid=None, raise_on_fail=True, stay_opened=None):
-        """
-        Tries to create the given lockfile exclusive.
-
-        If the lockfile exists and is valid, it waits a total maximum
-        of max_delay seconds an increasing amount of seconds to get exclusive
-        access to the lockfile.
-
-        @raise CouldntOccupyLockfileError: if the lockfile couldn't occupied
-                                           and raise_on_fail is set to True
-
-        @param lockfile: the lockfile to use as a semaphore, if not given
-                         as an absolute path, it will be supposed to be
-                         relative to self.lockdir.
-        @type lockfile: str
-        @param delay_start: the first delay in seconds after an unsuccessful
-                            lockfile creation, if not given,
-                            self.lockretry_delay_start will used.
-        @type delay_start: Number (or None)
-        @param delay_increase: seconds to increase the delay in every wait
-                               cycle, if not given, self.lockretry_delay_increase
-                               will used.
-        @type delay_increase: Number
-        @param max_delay: the total maximum delay in seconds for trying
-                          to create a lockfile, if not given,
-                          self.lockretry_max_delay will used.
-        @type max_delay: Number
-        @param use_pid: write the PID of creating process into the fresh
-                        created lockfile, if not given, self.locking_use_pid
-                        will used.
-        @type use_pid: bool
-        @param max_age: the maximum age of the lockfile (in seconds), for the
-                        existing lockfile is valid (if locking_use_pid is False).
-        @type max_age: Number
-        @param pid: the pid to write into the lockfile, if use_pid is set
-                    to True, if not given, the PID of the current process is used.
-        @type pid: int
-        @param raise_on_fail: raise an exception instead of returning False, if
-                              the lockfile couldn't occupied.
-        @type raise_on_fail: bool
-
-        @param stay_opened: should the lockfile stay opened after creation,
-        @@type stay_opened: bool or None
-
-        @return: a lock object on success, else None
-        @rtype: LockObject or None
-
-        """
-
-        delay_start = self.check_for_number(
-            delay_start, self.lockretry_delay_start,
-            what='delay_start', must_gt_zero=True)
-
-        delay_increase = self.check_for_number(
-            delay_increase, self.lockretry_delay_increase,
-            what='delay_increase', must_ge_zero=True)
-
-        max_delay = self.check_for_number(
-            max_delay, self.lockretry_max_delay,
-            what='max_delay', must_ge_zero=True)
-
-        if use_pid is None:
-            use_pid = self.locking_use_pid
-        else:
-            use_pid = bool(use_pid)
-
-        max_age = self.check_for_number(
-            max_age, self.max_lockfile_age,
-            what='max_age', must_ge_zero=True)
-
-        if pid is None:
-            pid = os.getpid()
-        else:
-            pid = int(pid)
-            if pid <= 0:
-                msg = "Invalid PID {} given on calling create_lockfile().".format(pid)
-                raise LockHandlerError(msg)
-
-        if os.path.isabs(lockfile):
-            lockfile = os.path.normpath(lockfile)
-        else:
-            lockfile = os.path.normpath(os.path.join(self.lockdir, lockfile))
-
-        lockdir = os.path.dirname(lockfile)
-        LOG.debug("Trying to lock lockfile {!r} ...".format(lockfile))
-        if self.verbose > 1:
-            LOG.debug("Using lock directory {!r} ...".format(lockdir))
-
-        if not os.path.isdir(lockdir):
-            raise LockdirNotExistsError(lockdir)
-
-        if not os.access(lockdir, os.W_OK):
-            msg = "Locking directory {!r} isn't writeable.".format(lockdir)
-            if self.simulate:
-                LOG.error(msg)
-            else:
-                raise LockdirNotWriteableError(lockdir)
-
-        if stay_opened is None:
-            stay_opened = self.stay_opened
-        else:
-            stay_opened = bool(stay_opened)
-
-        return self._do_create_lockfile(
-            lockfile=lockfile, delay_start=delay_start, max_delay=max_delay, max_age=max_age,
-            delay_increase=delay_increase, pid=pid, use_pid=use_pid, raise_on_fail=raise_on_fail,
-            stay_opened=stay_opened)
-
-    # -------------------------------------------------------------------------
-    def _do_create_lockfile(
-        self, lockfile, delay_start, max_delay, max_age, delay_increase,
-            pid, use_pid, raise_on_fail, stay_opened):
-
-        counter = 0
-        delay = delay_start
-
-        fd = None
-        time_diff = 0
-        start_time = time.time()
-
-        ctime = None
-        mtime = None
-
-        # Big try block to ensure closing open file descriptor
-        try:
-
-            # Big loop on trying to create the lockfile
-            while fd is None and time_diff < max_delay:
-
-                time_diff = time.time() - start_time
-                counter += 1
-
-                if self.verbose > 3:
-                    LOG.debug("Current time difference: {:0.3f} seconds.".format(time_diff))
-                if time_diff >= max_delay:
-                    break
-
-                # Try creating lockfile exclusive
-                LOG.debug("Try {try_nr} on creating lockfile {lfile!r} ...".format(
-                    try_nr=counter, lfile=lockfile))
-                ctime = datetime.datetime.utcnow()
-                fd = self._create_lockfile(lockfile)
-                if fd is not None:
-                    # success, then exit
-                    break
-
-                # Check for other process, using this lockfile
-                if not self.check_lockfile(lockfile, max_age, use_pid):
-                    # No other process is using this lockfile
-                    if os.path.exists(lockfile):
-                        LOG.info("Removing lockfile {!r} ...".format(lockfile))
-                    try:
-                        if not self.simulate:
-                            os.remove(lockfile)
-                    except Exception as e:
-                        msg = "Error on removing lockfile {lfile!r): {err}".format(
-                            lfile=lockfile, err=e)
-                        LOG.error(msg)
-                        time.sleep(delay)
-                        delay += delay_increase
-                        continue
-
-                    fd = self._create_lockfile(lockfile)
-                    if fd:
-                        break
-
-                # No success, then retry later
-                if self.verbose > 2:
-                    LOG.debug("Sleeping for {:0.1f} seconds.".format(float(delay)))
-                time.sleep(delay)
-                delay += delay_increase
-
-            # fd is either None, for no success on locking
-            if fd is None:
-                time_diff = time.time() - start_time
-                e = CouldntOccupyLockfileError(lockfile, time_diff, counter)
-                if raise_on_fail:
-                    raise e
-                else:
-                    LOG.error(str(e))
-                return None
-
-            # or an int for success
-            msg = "Got a lock for lockfile {!r}.".format(lockfile)
-            if self.silent:
-                LOG.debug(msg)
-            else:
-                LOG.info(msg)
-            out = to_utf8("{}\n".format(pid))
-            LOG.debug("Write {what!r} in lockfile {lfile!r} ...".format(
-                what=out, lfile=lockfile))
-
-        finally:
-
-            if fd is not None and not self.simulate:
-                os.write(fd, out)
-
-                if stay_opened:
-                    LOG.debug("Seeking and syncing {!r} ...".format(lockfile))
-                    os.lseek(fd, 0, 0)
-                    os.fsync(fd)
-                else:
-                    LOG.debug("Closing {!r} ...".format(lockfile))
-                    os.close(fd)
-                    fd = None
-
-        if fd is not None and self.simulate:
-            fd = None
-
-        mtime = datetime.datetime.utcnow()
-
-        lock_object = LockObject(
-            lockfile, ctime=ctime, mtime=mtime, fcontent=out, fd=fd, simulate=self.simulate,
-            appname=self.appname, verbose=self.verbose, base_dir=self.base_dir, silent=self.silent,
-        )
-
-        return lock_object
-
-    # -------------------------------------------------------------------------
-    def _create_lockfile(self, lockfile):
-        """
-        Handles exclusive creation of a lockfile.
-
-        @return: a file decriptor of the opened lockfile (if possible),
-                 or None, if it isn't.
-        @rtype: int or None
-
-        """
-
-        if self.verbose > 1:
-            LOG.debug("Trying to open {!r} exclusive ...".format(lockfile))
-        if self.simulate:
-            LOG.debug("Simulation mode, no real creation of a lockfile.")
-            return -1
-
-        fd = None
-        try:
-            fd = os.open(lockfile, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o644)
-            fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
-        except OSError as e:
-            msg = "Error on creating lockfile {lfile!r}: {err}".format(
-                lfile=lockfile, err=e)
-            if e.errno == errno.EEXIST:
-                LOG.debug(msg)
-                return None
-            else:
-                error_tuple = sys.exc_info()
-                reraise(LockHandlerError, msg, error_tuple[2])
-
-        return fd
-
-    # -------------------------------------------------------------------------
-    def remove_lockfile(self, lockfile):
-        """
-        Removing lockfile.
-
-        @param lockfile: the lockfile to remove.
-        @type lockfile: str
-
-        @return: the lockfile was removed (or not)
-        @rtype: bool
-
-        """
-
-        if os.path.isabs(lockfile):
-            lockfile = os.path.normpath(lockfile)
-        else:
-            lockfile = os.path.normpath(os.path.join(self.lockdir, lockfile))
-
-        if not os.path.exists(lockfile):
-            LOG.debug("Lockfile {!r} to remove doesn't exists.".format(lockfile))
-            return True
-
-        LOG.info("Removing lockfile {!r} ...".format(lockfile))
-        if self.simulate:
-            LOG.debug("Simulation mode - lockfile won't removed.")
-            return True
-
-        try:
-            os.remove(lockfile)
-        except Exception as e:
-            LOG.error("Error on removing lockfile {lfile!r}: {err}".format(lfile=lockfile, err=e))
-            if self.verbose:
-                tb = traceback.format_exc()
-                LOG.debug("Stacktrace:\n" + tb)
-            return False
-
-        return True
-
-    # -------------------------------------------------------------------------
-    def check_lockfile(self, lockfile, max_age=None, use_pid=None):
-        """
-        Checks the validity of the given lockfile.
-
-        If use_pid is True, and there is a PID inside the lockfile, then
-        this PID is checked for a running process.
-        If use_pid is not True, then the age of the lockfile is checked
-        against the parameter max_age.
-
-        @param lockfile: the lockfile to check
-        @type lockfile: str
-        @param max_age: the maximum age of the lockfile (in seconds), for
-                        this lockfile is valid (if use_pid is False).
-        @type max_age: int
-        @param use_pid: check the content of the lockfile for a PID
-                          of a running process
-        @type use_pid: bool
-
-        @return: Validity of the lockfile (PID exists and shows to a
-                 running process or the lockfile is not too old).
-                 Returns False, if the lockfile is not existing, contains an
-                 invalid PID or is too old.
-        @rtype: bool
-
-        """
-
-        if use_pid is None:
-            use_pid = self.locking_use_pid
-        else:
-            use_pid = bool(use_pid)
-
-        if max_age is None:
-            max_age = self.max_lockfile_age
-        else:
-            if not isinstance(max_age, Number):
-                msg = "Value {val!r} for {what} is not a Number.".format(
-                    val=max_age, what='max_age')
-                raise LockHandlerError(msg)
-            if max_age <= 0:
-                msg = "The value for {what} must be greater than zero (is {val!r}).".format(
-                    val=max_age, what='max_age')
-                raise LockHandlerError(msg)
-
-        LOG.debug("Checking lockfile {!r} ...".format(lockfile))
-
-        if not os.path.exists(lockfile):
-            if self.verbose > 2:
-                LOG.debug("Lockfile {!r} doesn't exists.".format(lockfile))
-            return False
-
-        if not os.access(lockfile, os.R_OK):
-            LOG.warn("No read access for lockfile {!r}.".format(lockfile))
-            return True
-
-        if not os.access(lockfile, os.W_OK):
-            LOG.warn("No write access for lockfile {!r}.".format(lockfile))
-            return True
-
-        if use_pid:
-            pid = self.get_pid_from_file(lockfile, True)
-            if pid is None:
-                LOG.warn("Unusable lockfile {!r}.".format(lockfile))
-            else:
-                if self.dead(pid):
-                    LOG.warn("Process with PID {} is unfortunately dead.".format(pid))
-                    return False
-                else:
-                    LOG.debug("Process with PID {} is still running.".format(pid))
-                    return True
-
-        fstat = None
-        try:
-            fstat = os.stat(lockfile)
-        except OSError as e:
-            if e.errno == errno.ENOENT:
-                LOG.info("Could not stat for file {lfile!r}: {err}".format(
-                    lfile=lockfile, err=e.strerror))
-                return False
-            raise
-
-        age = time.time() - fstat.st_mtime
-        if age >= max_age:
-            LOG.debug("Lockfile {lfile!r} is older than {max} seconds ({age} seconds).".format(
-                lfile=lockfile, max=max_age, age=age))
-            return False
-        msg = "Lockfile {lfile!r} is {age} seconds old, but not old enough ({max}seconds).".format(
-            lfile=lockfile, max=max_age, age=age)
-        LOG.debug(msg)
-        return True
-
-    # -------------------------------------------------------------------------
-    def get_pid_from_file(self, pidfile, force=False):
-        """
-        Tries to read the PID of some process from the given file.
-
-        @raise LockHandlerError: if the pidfile could not be read
-
-        @param pidfile: The file, where the PID should be in.
-        @type pidfile: str
-        @param force: Don't raise an exception, if something is going wrong.
-                      Only return None.
-        @type force: bool
-
-        @return: PID from pidfile
-        @rtype: int (or None)
-
-        """
-
-        if self.verbose > 1:
-            LOG.debug("Trying to open pidfile {!r} ...".format(pidfile))
-        try:
-            fh = open(pidfile, "rb")
-        except Exception as e:
-            msg = "Could not open pidfile {!r} for reading: ".format(pidfile)
-            msg += str(e)
-            if force:
-                LOG.warn(msg)
-                return None
-            else:
-                raise LockHandlerError(str(e))
-
-        content = fh.readline()
-        fh.close()
-
-        content = content.strip()
-        if content == "":
-            msg = "First line of pidfile {!r} was empty.".format(pidfile)
-            if force:
-                LOG.warn(msg)
-                return None
-            else:
-                raise LockHandlerError(msg)
-
-        pid = None
-        try:
-            pid = int(content)
-        except Exception as e:
-            msg = "Could not interprete {cont!r} as a PID from {file!r}: {err}".format(
-                cont=content, file=pidfile, err=e)
-            if force:
-                LOG.warn(msg)
-                return None
-            else:
-                raise LockHandlerError(msg)
-
-        if pid <= 0:
-            msg = "Invalid PID {pid} in {file!r} found.".format(pid=pid, file=pidfile)
-            if force:
-                LOG.warn(msg)
-                return None
-            else:
-                raise LockHandlerError(msg)
-
-        return pid
-
-    # -------------------------------------------------------------------------
-    def kill(self, pid, signal=0):
-        """
-        Sends a signal to a process.
-
-        @raise OSError: on some unpredictable errors
-
-        @param pid: the PID of the process
-        @type pid: int
-        @param signal: the signal to send to the process, if the signal is 0
-                       (the default), no real signal is sent to the process,
-                       it will only checked, whether the process is dead or not
-        @type signal: int
-
-        @return: the process is dead or not
-        @rtype: bool
-
-        """
-
-        try:
-            return os.kill(pid, signal)
-        except OSError as e:
-            # process is dead
-            if e.errno == errno.ESRCH:
-                return True
-            # no permissions
-            elif e.errno == errno.EPERM:
-                return False
-            else:
-                # reraise the error
-                raise
-
-    # -------------------------------------------------------------------------
-    def dead(self, pid):
-        """
-        Gives back, whether the process with the given pid is dead
-
-        @raise OSError: on some unpredictable errors
-
-        @param pid: the PID of the process to check
-        @type pid: int
-
-        @return: the process is dead or not
-        @rtype: bool
-
-        """
-
-        if self.kill(pid):
-            return True
-
-        # maybe the pid is a zombie that needs us to wait4 it
-        from os import waitpid, WNOHANG
-
-        try:
-            dead = waitpid(pid, WNOHANG)[0]
-        except OSError as e:
-            # pid is not a child
-            if e.errno == errno.ECHILD:
-                return False
-            else:
-                raise
-
-        return dead
-
-
-# =============================================================================
-if __name__ == "__main__":
-
-    pass
-
-# =============================================================================
-
-# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4