-def _GetLockFile(subsystem):
- """Compute the file name for a given lock name."""
- return "%s/ganeti_lock_%s" % (constants.LOCK_DIR, subsystem)
-
-
-def Lock(name, max_retries=None, debug=False):
- """Lock a given subsystem.
-
- In case the lock is already held by an alive process, the function
- will sleep indefintely and poll with a one second interval.
-
- When the optional integer argument 'max_retries' is passed with a
- non-zero value, the function will sleep only for this number of
- times, and then it will will raise a LockError if the lock can't be
- acquired. Passing in a negative number will cause only one try to
- get the lock. Passing a positive number will make the function retry
- for approximately that number of seconds.
-
- """
- lockfile = _GetLockFile(name)
-
- if name in _locksheld:
- raise errors.LockError('Lock "%s" already held!' % (name,))
-
- errcount = 0
-
- retries = 0
- while True:
- try:
- fd = os.open(lockfile, os.O_CREAT | os.O_EXCL | os.O_RDWR | os.O_SYNC)
- break
- except OSError, creat_err:
- if creat_err.errno != errno.EEXIST:
- raise errors.LockError("Can't create the lock file. Error '%s'." %
- str(creat_err))
-
- try:
- pf = open(lockfile, 'r')
- except IOError, open_err:
- errcount += 1
- if errcount >= 5:
- raise errors.LockError("Lock file exists but cannot be opened."
- " Error: '%s'." % str(open_err))
- time.sleep(1)
- continue
-
- try:
- pid = int(pf.read())
- except ValueError:
- raise errors.LockError("Invalid pid string in %s" %
- (lockfile,))
-
- if not IsProcessAlive(pid):
- raise errors.LockError("Stale lockfile %s for pid %d?" %
- (lockfile, pid))
-
- if max_retries and max_retries <= retries:
- raise errors.LockError("Can't acquire lock during the specified"
- " time, aborting.")
- if retries == 5 and (debug or sys.stdin.isatty()):
- logger.ToStderr("Waiting for '%s' lock from pid %d..." % (name, pid))
-
- time.sleep(1)
- retries += 1
- continue
-
- os.write(fd, '%d\n' % (os.getpid(),))
- os.close(fd)
-
- _locksheld.append(name)
-
-
-def Unlock(name):
- """Unlock a given subsystem.
-
- """
- lockfile = _GetLockFile(name)
-
- try:
- fd = os.open(lockfile, os.O_RDONLY)
- except OSError:
- raise errors.LockError('Lock "%s" not held.' % (name,))
-
- f = os.fdopen(fd, 'r')
- pid_str = f.read()
-
- try:
- pid = int(pid_str)
- except ValueError:
- raise errors.LockError('Unable to determine PID of locking process.')
-
- if pid != os.getpid():
- raise errors.LockError('Lock not held by me (%d != %d)' %
- (os.getpid(), pid,))
-
- os.unlink(lockfile)
- _locksheld.remove(name)
-
-
-def LockCleanup():
- """Remove all locks.
-
- """
- for lock in _locksheld:
- Unlock(lock)
-
-