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
|
log: /var/log/yunohost/yunohost-api.log
|
||||||
yunohost-firewall:
|
yunohost-firewall:
|
||||||
status: service
|
status: service
|
||||||
|
need_lock: true
|
||||||
nslcd:
|
nslcd:
|
||||||
status: service
|
status: service
|
||||||
log: /var/log/syslog
|
log: /var/log/syslog
|
||||||
|
|
|
@ -39,10 +39,10 @@ from moulinette.utils import log, filesystem
|
||||||
|
|
||||||
from yunohost.hook import hook_callback
|
from yunohost.hook import hook_callback
|
||||||
|
|
||||||
|
|
||||||
BASE_CONF_PATH = '/home/yunohost.conf'
|
BASE_CONF_PATH = '/home/yunohost.conf'
|
||||||
BACKUP_CONF_DIR = os.path.join(BASE_CONF_PATH, 'backup')
|
BACKUP_CONF_DIR = os.path.join(BASE_CONF_PATH, 'backup')
|
||||||
PENDING_CONF_DIR = os.path.join(BASE_CONF_PATH, 'pending')
|
PENDING_CONF_DIR = os.path.join(BASE_CONF_PATH, 'pending')
|
||||||
|
MOULINETTE_LOCK = "/var/run/moulinette_yunohost.lock"
|
||||||
|
|
||||||
logger = log.getActionLogger('yunohost.service')
|
logger = log.getActionLogger('yunohost.service')
|
||||||
|
|
||||||
|
@ -493,7 +493,8 @@ def _run_service_command(action, service):
|
||||||
service -- Service name
|
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))
|
raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service=service))
|
||||||
|
|
||||||
cmd = None
|
cmd = None
|
||||||
|
@ -505,8 +506,23 @@ def _run_service_command(action, service):
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unknown action '%s'" % action)
|
raise ValueError("Unknown action '%s'" % action)
|
||||||
|
|
||||||
|
need_lock = (services[service].get('need_lock') or False) \
|
||||||
|
and action in ['start', 'stop', 'restart', 'reload']
|
||||||
|
|
||||||
try:
|
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:
|
except subprocess.CalledProcessError as e:
|
||||||
# TODO: Log output?
|
# TODO: Log output?
|
||||||
logger.warning(m18n.n('service_cmd_exec_failed', command=' '.join(e.cmd)))
|
logger.warning(m18n.n('service_cmd_exec_failed', command=' '.join(e.cmd)))
|
||||||
|
@ -514,6 +530,41 @@ def _run_service_command(action, service):
|
||||||
return True
|
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():
|
def _get_services():
|
||||||
"""
|
"""
|
||||||
Get a dict of managed services with their parameters
|
Get a dict of managed services with their parameters
|
||||||
|
|
Loading…
Add table
Reference in a new issue