mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Be able to give lock to son processes detached by systemctl (#367)
* Give lock to systemctl sons * Get the 'need_lock' flag from services.yml * Don't need the lock for enable/disable and other stuff
This commit is contained in:
parent
5ae558edc9
commit
9903c48f3a
2 changed files with 55 additions and 3 deletions
|
@ -47,6 +47,7 @@ yunohost-api:
|
|||
log: /var/log/yunohost/yunohost-api.log
|
||||
yunohost-firewall:
|
||||
status: service
|
||||
need_lock: true
|
||||
nslcd:
|
||||
status: service
|
||||
log: /var/log/syslog
|
||||
|
|
|
@ -39,10 +39,10 @@ from moulinette.utils import log, filesystem
|
|||
|
||||
from yunohost.hook import hook_callback
|
||||
|
||||
|
||||
BASE_CONF_PATH = '/home/yunohost.conf'
|
||||
BACKUP_CONF_DIR = os.path.join(BASE_CONF_PATH, 'backup')
|
||||
PENDING_CONF_DIR = os.path.join(BASE_CONF_PATH, 'pending')
|
||||
MOULINETTE_LOCK = "/var/run/moulinette_yunohost.lock"
|
||||
|
||||
logger = log.getActionLogger('yunohost.service')
|
||||
|
||||
|
@ -493,7 +493,8 @@ def _run_service_command(action, service):
|
|||
service -- Service name
|
||||
|
||||
"""
|
||||
if service not in _get_services().keys():
|
||||
services = _get_services()
|
||||
if service not in services.keys():
|
||||
raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service=service))
|
||||
|
||||
cmd = None
|
||||
|
@ -505,8 +506,23 @@ def _run_service_command(action, service):
|
|||
else:
|
||||
raise ValueError("Unknown action '%s'" % action)
|
||||
|
||||
need_lock = (services[service].get('need_lock') or False) \
|
||||
and action in ['start', 'stop', 'restart', 'reload']
|
||||
|
||||
try:
|
||||
ret = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
|
||||
# Launch the command
|
||||
logger.debug("Running '%s'" % cmd)
|
||||
p = subprocess.Popen(cmd.split(), stderr=subprocess.STDOUT)
|
||||
# If this command needs a lock (because the service uses yunohost
|
||||
# commands inside), find the PID and add a lock for it
|
||||
if need_lock:
|
||||
PID = _give_lock(action, service, p)
|
||||
# Wait for the command to complete
|
||||
p.communicate()
|
||||
# Remove the lock if one was given
|
||||
if need_lock and PID != 0:
|
||||
_remove_lock(PID)
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
# TODO: Log output?
|
||||
logger.warning(m18n.n('service_cmd_exec_failed', command=' '.join(e.cmd)))
|
||||
|
@ -514,6 +530,41 @@ def _run_service_command(action, service):
|
|||
return True
|
||||
|
||||
|
||||
def _give_lock(action, service, p):
|
||||
|
||||
# Depending of the action, systemctl calls the PID differently :/
|
||||
if action == "start" or action == "restart":
|
||||
systemctl_PID_name = "MainPID"
|
||||
else:
|
||||
systemctl_PID_name = "ControlPID"
|
||||
|
||||
cmd_get_son_PID ="systemctl show %s -p %s" % (service, systemctl_PID_name)
|
||||
son_PID = 0
|
||||
# As long as we did not found the PID and that the command is still running
|
||||
while son_PID == 0 and p.poll() == None:
|
||||
# Call systemctl to get the PID
|
||||
# Output of the command is e.g. ControlPID=1234
|
||||
son_PID = subprocess.check_output(cmd_get_son_PID.split()) \
|
||||
.strip().split("=")[1]
|
||||
son_PID = int(son_PID)
|
||||
time.sleep(1)
|
||||
|
||||
# If we found a PID
|
||||
if son_PID != 0:
|
||||
# Append the PID to the lock file
|
||||
logger.debug("Giving a lock to PID %s for service %s !"
|
||||
% (str(son_PID), service))
|
||||
filesystem.append_to_file(MOULINETTE_LOCK, "\n%s" % str(son_PID))
|
||||
|
||||
return son_PID
|
||||
|
||||
def _remove_lock(PID_to_remove):
|
||||
|
||||
PIDs = filesystem.read_file(MOULINETTE_LOCK).split("\n")
|
||||
PIDs_to_keep = [ PID for PID in PIDs if int(PID) != PID_to_remove ]
|
||||
filesystem.write_to_file(MOULINETTE_LOCK, '\n'.join(PIDs_to_keep))
|
||||
|
||||
|
||||
def _get_services():
|
||||
"""
|
||||
Get a dict of managed services with their parameters
|
||||
|
|
Loading…
Add table
Reference in a new issue