commit 9d1b963f9ae6362dc9242bdb23627d979175dc8a
Author: Michael Hanselmann <hansmi@google.com>
Date:   Mon Jan 10 17:58:52 2011 +0100

    utils: Move code related to file locking into separate file
    
    Signed-off-by: Michael Hanselmann <hansmi@google.com>
    Reviewed-by: Iustin Pop <iustin@google.com>

diff --git a/lib/utils/__init__.py b/lib/utils/__init__.py
index eb8d1b0..a7b6033 100644
--- a/lib/utils/__init__.py
+++ b/lib/utils/__init__.py
@@ -60,6 +60,7 @@ from ganeti.utils.mlock import * # pylint: disable-msg=W0401
 from ganeti.utils.log import * # pylint: disable-msg=W0401
 from ganeti.utils.hash import * # pylint: disable-msg=W0401
 from ganeti.utils.wrapper import * # pylint: disable-msg=W0401
+from ganeti.utils.filelock import * # pylint: disable-msg=W0401
 
 
 #: when set to True, L{RunCmd} is disabled
@@ -2549,21 +2550,6 @@ def RunInSeparateProcess(fn, *args):
   return bool(exitcode)
 
 
-def LockFile(fd):
-  """Locks a file using POSIX locks.
-
-  @type fd: int
-  @param fd: the file descriptor we need to lock
-
-  """
-  try:
-    fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
-  except IOError, err:
-    if err.errno == errno.EAGAIN:
-      raise errors.LockError("File already locked")
-    raise
-
-
 def ReadWatcherPauseFile(filename, now=None, remove_after=3600):
   """Reads the watcher pause file.
 
@@ -2658,139 +2644,6 @@ def GenerateSelfSignedSslCert(filename, common_name=constants.X509_CERT_CN,
   WriteFile(filename, mode=0400, data=key_pem + cert_pem)
 
 
-class FileLock(object):
-  """Utility class for file locks.
-
-  """
-  def __init__(self, fd, filename):
-    """Constructor for FileLock.
-
-    @type fd: file
-    @param fd: File object
-    @type filename: str
-    @param filename: Path of the file opened at I{fd}
-
-    """
-    self.fd = fd
-    self.filename = filename
-
-  @classmethod
-  def Open(cls, filename):
-    """Creates and opens a file to be used as a file-based lock.
-
-    @type filename: string
-    @param filename: path to the file to be locked
-
-    """
-    # Using "os.open" is necessary to allow both opening existing file
-    # read/write and creating if not existing. Vanilla "open" will truncate an
-    # existing file -or- allow creating if not existing.
-    return cls(os.fdopen(os.open(filename, os.O_RDWR | os.O_CREAT), "w+"),
-               filename)
-
-  def __del__(self):
-    self.Close()
-
-  def Close(self):
-    """Close the file and release the lock.
-
-    """
-    if hasattr(self, "fd") and self.fd:
-      self.fd.close()
-      self.fd = None
-
-  def _flock(self, flag, blocking, timeout, errmsg):
-    """Wrapper for fcntl.flock.
-
-    @type flag: int
-    @param flag: operation flag
-    @type blocking: bool
-    @param blocking: whether the operation should be done in blocking mode.
-    @type timeout: None or float
-    @param timeout: for how long the operation should be retried (implies
-                    non-blocking mode).
-    @type errmsg: string
-    @param errmsg: error message in case operation fails.
-
-    """
-    assert self.fd, "Lock was closed"
-    assert timeout is None or timeout >= 0, \
-      "If specified, timeout must be positive"
-    assert not (flag & fcntl.LOCK_NB), "LOCK_NB must not be set"
-
-    # When a timeout is used, LOCK_NB must always be set
-    if not (timeout is None and blocking):
-      flag |= fcntl.LOCK_NB
-
-    if timeout is None:
-      self._Lock(self.fd, flag, timeout)
-    else:
-      try:
-        Retry(self._Lock, (0.1, 1.2, 1.0), timeout,
-              args=(self.fd, flag, timeout))
-      except RetryTimeout:
-        raise errors.LockError(errmsg)
-
-  @staticmethod
-  def _Lock(fd, flag, timeout):
-    try:
-      fcntl.flock(fd, flag)
-    except IOError, err:
-      if timeout is not None and err.errno == errno.EAGAIN:
-        raise RetryAgain()
-
-      logging.exception("fcntl.flock failed")
-      raise
-
-  def Exclusive(self, blocking=False, timeout=None):
-    """Locks the file in exclusive mode.
-
-    @type blocking: boolean
-    @param blocking: whether to block and wait until we
-        can lock the file or return immediately
-    @type timeout: int or None
-    @param timeout: if not None, the duration to wait for the lock
-        (in blocking mode)
-
-    """
-    self._flock(fcntl.LOCK_EX, blocking, timeout,
-                "Failed to lock %s in exclusive mode" % self.filename)
-
-  def Shared(self, blocking=False, timeout=None):
-    """Locks the file in shared mode.
-
-    @type blocking: boolean
-    @param blocking: whether to block and wait until we
-        can lock the file or return immediately
-    @type timeout: int or None
-    @param timeout: if not None, the duration to wait for the lock
-        (in blocking mode)
-
-    """
-    self._flock(fcntl.LOCK_SH, blocking, timeout,
-                "Failed to lock %s in shared mode" % self.filename)
-
-  def Unlock(self, blocking=True, timeout=None):
-    """Unlocks the file.
-
-    According to C{flock(2)}, unlocking can also be a nonblocking
-    operation::
-
-      To make a non-blocking request, include LOCK_NB with any of the above
-      operations.
-
-    @type blocking: boolean
-    @param blocking: whether to block and wait until we
-        can lock the file or return immediately
-    @type timeout: int or None
-    @param timeout: if not None, the duration to wait for the lock
-        (in blocking mode)
-
-    """
-    self._flock(fcntl.LOCK_UN, blocking, timeout,
-                "Failed to unlock %s" % self.filename)
-
-
 def SignalHandled(signums):
   """Signal Handled decoration.
 
