Merge pull request #469 from YunoHost/services_dbus

move service_status to sytemd via dbus
This commit is contained in:
Bram 2018-05-18 04:09:34 +02:00 committed by GitHub
commit bc68bf39e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 69 deletions

View file

@ -61,11 +61,17 @@ do_pre_regen() {
_update_services() { _update_services() {
sudo python2 - << EOF sudo python2 - << EOF
import yaml import yaml
with open('services.yml') as f: with open('services.yml') as f:
new_services = yaml.load(f) new_services = yaml.load(f)
with open('/etc/yunohost/services.yml') as f: with open('/etc/yunohost/services.yml') as f:
services = yaml.load(f) services = yaml.load(f)
updated = False updated = False
for service, conf in new_services.items(): for service, conf in new_services.items():
# remove service with empty conf # remove service with empty conf
if conf is None: if conf is None:
@ -73,20 +79,32 @@ for service, conf in new_services.items():
print("removing '{0}' from services".format(service)) print("removing '{0}' from services".format(service))
del services[service] del services[service]
updated = True updated = True
# add new service # add new service
elif not services.get(service, None): elif not services.get(service, None):
print("adding '{0}' to services".format(service)) print("adding '{0}' to services".format(service))
services[service] = conf services[service] = conf
updated = True updated = True
# update service conf # update service conf
else: else:
conffiles = services[service].pop('conffiles', {}) conffiles = services[service].pop('conffiles', {})
# status need to be removed
if "status" not in conf and "status" in services[service]:
print("update '{0}' service status access".format(service))
del services[service]["status"]
updated = True
if services[service] != conf: if services[service] != conf:
print("update '{0}' service".format(service)) print("update '{0}' service".format(service))
services[service].update(conf) services[service].update(conf)
updated = True updated = True
if conffiles: if conffiles:
services[service]['conffiles'] = conffiles services[service]['conffiles'] = conffiles
if updated: if updated:
with open('/etc/yunohost/services.yml-new', 'w') as f: with open('/etc/yunohost/services.yml-new', 'w') as f:
yaml.safe_dump(services, f, default_flow_style=False) yaml.safe_dump(services, f, default_flow_style=False)

View file

@ -1,57 +1,42 @@
nginx: nginx:
status: service log: /var/log/nginx
log: /var/log/nginx
avahi-daemon: avahi-daemon:
status: service log: /var/log/daemon.log
log: /var/log/daemon.log
dnsmasq: dnsmasq:
status: service log: /var/log/daemon.log
log: /var/log/daemon.log
fail2ban: fail2ban:
status: service log: /var/log/fail2ban.log
log: /var/log/fail2ban.log
dovecot: dovecot:
status: service log: [/var/log/mail.log,/var/log/mail.err]
log: [/var/log/mail.log,/var/log/mail.err]
postfix: postfix:
status: service log: [/var/log/mail.log,/var/log/mail.err]
log: [/var/log/mail.log,/var/log/mail.err]
rmilter: rmilter:
status: systemctl status rmilter.service log: /var/log/mail.log
log: /var/log/mail.log
rspamd: rspamd:
status: systemctl status rspamd.service log: /var/log/mail.log
log: /var/log/mail.log
redis-server: redis-server:
status: service log: /var/log/redis/redis-server.log
log: /var/log/redis/redis-server.log
mysql: mysql:
status: service log: [/var/log/mysql.log,/var/log/mysql.err]
log: [/var/log/mysql.log,/var/log/mysql.err] glances: {}
glances:
status: service
ssh: ssh:
status: service log: /var/log/auth.log
log: /var/log/auth.log ssl:
status: null
metronome: metronome:
status: metronomectl status log: [/var/log/metronome/metronome.log,/var/log/metronome/metronome.err]
log: [/var/log/metronome/metronome.log,/var/log/metronome/metronome.err]
slapd: slapd:
status: service log: /var/log/syslog
log: /var/log/syslog
php5-fpm: php5-fpm:
status: service log: /var/log/php5-fpm.log
log: /var/log/php5-fpm.log
yunohost-api: yunohost-api:
status: service log: /var/log/yunohost/yunohost-api.log
log: /var/log/yunohost/yunohost-api.log
yunohost-firewall: yunohost-firewall:
status: service
need_lock: true need_lock: true
nslcd: nslcd:
status: service log: /var/log/syslog
log: /var/log/syslog nsswitch:
nsswitch: {} status: null
bind9: null bind9: null
tahoe-lafs: null tahoe-lafs: null
memcached: null memcached: null

2
debian/control vendored
View file

@ -12,7 +12,7 @@ Architecture: all
Depends: ${python:Depends}, ${misc:Depends} Depends: ${python:Depends}, ${misc:Depends}
, moulinette (>= 2.7.1), ssowat (>= 2.7.1) , moulinette (>= 2.7.1), ssowat (>= 2.7.1)
, python-psutil, python-requests, python-dnspython, python-openssl , python-psutil, python-requests, python-dnspython, python-openssl
, python-apt, python-miniupnpc , python-apt, python-miniupnpc, python-dbus
, glances , glances
, dnsutils, bind9utils, unzip, git, curl, cron, wget , dnsutils, bind9utils, unzip, git, curl, cron, wget
, ca-certificates, netcat-openbsd, iproute , ca-certificates, netcat-openbsd, iproute

View file

@ -27,12 +27,13 @@ import os
import time import time
import yaml import yaml
import json import json
import glob
import subprocess import subprocess
import errno import errno
import shutil import shutil
import hashlib import hashlib
from difflib import unified_diff from difflib import unified_diff
from datetime import datetime
from moulinette import m18n from moulinette import m18n
from moulinette.core import MoulinetteError from moulinette.core import MoulinetteError
@ -213,46 +214,54 @@ def service_status(names=[]):
raise MoulinetteError(errno.EINVAL, raise MoulinetteError(errno.EINVAL,
m18n.n('service_unknown', service=name)) m18n.n('service_unknown', service=name))
status = None # this "service" isn't a service actually so we skip it
if services[name].get('status') == 'service': #
status = 'service %s status' % name # the historical reason is because regenconf has been hacked into the
elif "status" in services[name]: # service part of YunoHost will in some situation we need to regenconf
status = str(services[name]['status']) # for things that aren't services
else: # the hack was to add fake services...
# we need to extract regenconf from service at some point, also because
# some app would really like to use it
if "status" in services[name] and services[name]["status"] is None:
continue continue
runlevel = 5 status = _get_service_information_from_systemd(name)
if 'runlevel' in services[name].keys():
runlevel = int(services[name]['runlevel'])
result[name] = {'status': 'unknown', 'loaded': 'unknown'} result[name] = {
'status': str(status.get("SubState", "unknown")),
# Retrieve service status 'loaded': "enabled" if str(status.get("LoadState", "unknown")) == "loaded" else str(status.get("LoadState", "unknown")),
try: 'active': str(status.get("ActiveState", "unknown")),
subprocess.check_output(status, stderr=subprocess.STDOUT, 'active_at': {
shell=True) "timestamp": str(status.get("ActiveEnterTimestamp", "unknown")),
except subprocess.CalledProcessError as e: "human": datetime.fromtimestamp(status.get("ActiveEnterTimestamp") / 1000000).strftime("%F %X"),
if 'usage:' in e.output.lower(): },
logger.warning(m18n.n('service_status_failed', service=name)) 'description': str(status.get("Description", "")),
else: 'service_file_path': str(status.get("FragmentPath", "unknown")),
result[name]['status'] = 'inactive' }
else:
result[name]['status'] = 'running'
# Retrieve service loading
rc_path = glob.glob("/etc/rc%d.d/S[0-9][0-9]%s" % (runlevel, name))
if len(rc_path) == 1 and os.path.islink(rc_path[0]):
result[name]['loaded'] = 'enabled'
elif os.path.isfile("/etc/init.d/%s" % name):
result[name]['loaded'] = 'disabled'
else:
result[name]['loaded'] = 'not-found'
if len(names) == 1: if len(names) == 1:
return result[names[0]] return result[names[0]]
return result return result
def _get_service_information_from_systemd(service):
"this is the equivalent of 'systemctl status $service'"
import dbus
d = dbus.SystemBus()
systemd = d.get_object('org.freedesktop.systemd1','/org/freedesktop/systemd1')
manager = dbus.Interface(systemd, 'org.freedesktop.systemd1.Manager')
service_path = manager.GetUnit(service + ".service")
service_proxy = d.get_object('org.freedesktop.systemd1', service_path)
# unit_proxy = dbus.Interface(service_proxy, 'org.freedesktop.systemd1.Unit',)
properties_interface = dbus.Interface(service_proxy, 'org.freedesktop.DBus.Properties')
return properties_interface.GetAll('org.freedesktop.systemd1.Unit')
def service_log(name, number=50): def service_log(name, number=50):
""" """
Log every log files of a service Log every log files of a service