mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
Merge pull request #151 from YunoHost/enh-simpler-lock-system
[enh] Simpler lock system
This commit is contained in:
commit
dfcfecc84a
4 changed files with 36 additions and 19 deletions
3
debian/control
vendored
3
debian/control
vendored
|
@ -15,7 +15,8 @@ Depends: ${misc:Depends}, ${python:Depends},
|
||||||
python-bottle (>= 0.12),
|
python-bottle (>= 0.12),
|
||||||
python-gnupg,
|
python-gnupg,
|
||||||
python-gevent-websocket,
|
python-gevent-websocket,
|
||||||
python-argcomplete
|
python-argcomplete,
|
||||||
|
python-psutil
|
||||||
Replaces: yunohost-cli
|
Replaces: yunohost-cli
|
||||||
Breaks: yunohost-cli
|
Breaks: yunohost-cli
|
||||||
Description: prototype interfaces with ease in Python
|
Description: prototype interfaces with ease in Python
|
||||||
|
|
|
@ -5,6 +5,7 @@ import time
|
||||||
import json
|
import json
|
||||||
import errno
|
import errno
|
||||||
import logging
|
import logging
|
||||||
|
import psutil
|
||||||
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
|
@ -429,7 +430,6 @@ class MoulinetteLock(object):
|
||||||
self._lockfile = '/var/run/moulinette_%s.lock' % namespace
|
self._lockfile = '/var/run/moulinette_%s.lock' % namespace
|
||||||
self._stale_checked = False
|
self._stale_checked = False
|
||||||
self._locked = False
|
self._locked = False
|
||||||
self._bypass = False
|
|
||||||
|
|
||||||
def acquire(self):
|
def acquire(self):
|
||||||
"""Attempt to acquire the lock for the moulinette instance
|
"""Attempt to acquire the lock for the moulinette instance
|
||||||
|
@ -442,17 +442,13 @@ class MoulinetteLock(object):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
if 'BYPASS_LOCK' in os.environ and os.environ['BYPASS_LOCK'] == 'yes':
|
lock_pid = self._lock_PID()
|
||||||
self._bypass = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not os.path.isfile(self._lockfile):
|
if lock_pid is None:
|
||||||
self._lock()
|
self._lock()
|
||||||
break
|
break
|
||||||
elif not self._stale_checked:
|
elif not self._stale_checked:
|
||||||
self._stale_checked = True
|
self._stale_checked = True
|
||||||
with open(self._lockfile) as f:
|
|
||||||
lock_pid = f.read().strip()
|
|
||||||
# Delete stale lock file
|
# Delete stale lock file
|
||||||
if not lock_pid or not os.path.exists(
|
if not lock_pid or not os.path.exists(
|
||||||
os.path.join('/proc', lock_pid, 'exe')):
|
os.path.join('/proc', lock_pid, 'exe')):
|
||||||
|
@ -476,9 +472,7 @@ class MoulinetteLock(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self._locked:
|
if self._locked:
|
||||||
if not self._bypass:
|
os.unlink(self._lockfile)
|
||||||
os.unlink(self._lockfile)
|
|
||||||
|
|
||||||
logger.debug('lock has been released')
|
logger.debug('lock has been released')
|
||||||
self._locked = False
|
self._locked = False
|
||||||
|
|
||||||
|
@ -492,8 +486,37 @@ class MoulinetteLock(object):
|
||||||
moulinette.m18n.g('permission_denied'),
|
moulinette.m18n.g('permission_denied'),
|
||||||
moulinette.m18n.g('root_required')))
|
moulinette.m18n.g('root_required')))
|
||||||
|
|
||||||
|
def _lock_PID(self):
|
||||||
|
|
||||||
|
if not os.path.isfile(self._lockfile):
|
||||||
|
return None
|
||||||
|
|
||||||
|
with open(self._lockfile) as f:
|
||||||
|
lock_pid = f.read().strip()
|
||||||
|
|
||||||
|
return lock_pid
|
||||||
|
|
||||||
|
def _is_son_of_locked(self):
|
||||||
|
|
||||||
|
lock_pid = self._lock_PID()
|
||||||
|
|
||||||
|
if lock_pid is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
parent = psutil.Process()
|
||||||
|
# While this is not the very first process
|
||||||
|
while parent.parent() is not None:
|
||||||
|
# If parent PID is the lock, the yes! we are a son of the process
|
||||||
|
# with the lock...
|
||||||
|
if parent.ppid() == int(lock_pid):
|
||||||
|
return True
|
||||||
|
# Otherwise, try 'next' parent
|
||||||
|
parent = parent.parent()
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
if not self._locked:
|
if not self._locked and not self._is_son_of_locked():
|
||||||
self.acquire()
|
self.acquire()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
|
@ -152,10 +152,6 @@ class BaseActionsMapParser(object):
|
||||||
namespace = argparse.Namespace()
|
namespace = argparse.Namespace()
|
||||||
namespace._tid = tid
|
namespace._tid = tid
|
||||||
|
|
||||||
# Check lock
|
|
||||||
if not self.get_conf(tid, 'lock'):
|
|
||||||
os.environ['BYPASS_LOCK'] = 'yes'
|
|
||||||
|
|
||||||
# Perform authentication if needed
|
# Perform authentication if needed
|
||||||
if self.get_conf(tid, 'authenticate'):
|
if self.get_conf(tid, 'authenticate'):
|
||||||
auth_conf, cls = self.get_conf(tid, 'authenticator')
|
auth_conf, cls = self.get_conf(tid, 'authenticator')
|
||||||
|
|
|
@ -634,9 +634,6 @@ class ActionsMapParser(BaseActionsMapParser):
|
||||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||||
ret = argparse.Namespace()
|
ret = argparse.Namespace()
|
||||||
|
|
||||||
if not self.get_conf(tid, 'lock'):
|
|
||||||
os.environ['BYPASS_LOCK'] = 'yes'
|
|
||||||
|
|
||||||
# Perform authentication if needed
|
# Perform authentication if needed
|
||||||
if self.get_conf(tid, 'authenticate'):
|
if self.get_conf(tid, 'authenticate'):
|
||||||
# TODO: Clean this hard fix and find a way to set an authenticator
|
# TODO: Clean this hard fix and find a way to set an authenticator
|
||||||
|
|
Loading…
Add table
Reference in a new issue