From d32ab073ba2719170bb3d5254d772d8100be9445 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Fri, 11 May 2018 04:21:24 +0200 Subject: [PATCH 1/9] [mod] removes status key from /etc/yunohost/service.yml for generic approach --- data/hooks/conf_regen/01-yunohost | 18 ++++++++++++++++++ data/templates/yunohost/services.yml | 25 +++++-------------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost index e1daa7c3..faf04111 100755 --- a/data/hooks/conf_regen/01-yunohost +++ b/data/hooks/conf_regen/01-yunohost @@ -61,11 +61,17 @@ do_pre_regen() { _update_services() { sudo python2 - << EOF import yaml + + with open('services.yml') as f: new_services = yaml.load(f) + with open('/etc/yunohost/services.yml') as f: services = yaml.load(f) + updated = False + + for service, conf in new_services.items(): # remove service with empty conf if conf is None: @@ -73,20 +79,32 @@ for service, conf in new_services.items(): print("removing '{0}' from services".format(service)) del services[service] updated = True + # add new service elif not services.get(service, None): print("adding '{0}' to services".format(service)) services[service] = conf updated = True + # update service conf else: 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: print("update '{0}' service".format(service)) services[service].update(conf) updated = True + if conffiles: services[service]['conffiles'] = conffiles + + if updated: with open('/etc/yunohost/services.yml-new', 'w') as f: yaml.safe_dump(services, f, default_flow_style=False) diff --git a/data/templates/yunohost/services.yml b/data/templates/yunohost/services.yml index fb8c076f..b4c9ab36 100644 --- a/data/templates/yunohost/services.yml +++ b/data/templates/yunohost/services.yml @@ -1,57 +1,42 @@ nginx: - status: service log: /var/log/nginx avahi-daemon: - status: service log: /var/log/daemon.log dnsmasq: - status: service log: /var/log/daemon.log fail2ban: - status: service log: /var/log/fail2ban.log dovecot: - status: service log: [/var/log/mail.log,/var/log/mail.err] postfix: - status: service log: [/var/log/mail.log,/var/log/mail.err] rmilter: - status: systemctl status rmilter.service log: /var/log/mail.log rspamd: - status: systemctl status rspamd.service log: /var/log/mail.log redis-server: - status: service log: /var/log/redis/redis-server.log mysql: - status: service log: [/var/log/mysql.log,/var/log/mysql.err] -glances: - status: service +glances: {} ssh: - status: service log: /var/log/auth.log +ssl: + status: null metronome: - status: metronomectl status log: [/var/log/metronome/metronome.log,/var/log/metronome/metronome.err] slapd: - status: service log: /var/log/syslog php5-fpm: - status: service log: /var/log/php5-fpm.log yunohost-api: - status: service log: /var/log/yunohost/yunohost-api.log yunohost-firewall: - status: service need_lock: true nslcd: - status: service log: /var/log/syslog -nsswitch: {} +nsswitch: + status: null bind9: null tahoe-lafs: null memcached: null From 312e9bb22ef2b1ee50eecdebb1c940099a2fca1a Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Fri, 11 May 2018 04:21:53 +0200 Subject: [PATCH 2/9] [mod] respect yaml indentation --- data/templates/yunohost/services.yml | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/data/templates/yunohost/services.yml b/data/templates/yunohost/services.yml index b4c9ab36..0c12b9e6 100644 --- a/data/templates/yunohost/services.yml +++ b/data/templates/yunohost/services.yml @@ -1,40 +1,40 @@ nginx: - log: /var/log/nginx + log: /var/log/nginx avahi-daemon: - log: /var/log/daemon.log + log: /var/log/daemon.log dnsmasq: - log: /var/log/daemon.log + log: /var/log/daemon.log fail2ban: - log: /var/log/fail2ban.log + log: /var/log/fail2ban.log dovecot: - log: [/var/log/mail.log,/var/log/mail.err] + log: [/var/log/mail.log,/var/log/mail.err] postfix: - log: [/var/log/mail.log,/var/log/mail.err] + log: [/var/log/mail.log,/var/log/mail.err] rmilter: - log: /var/log/mail.log + log: /var/log/mail.log rspamd: - log: /var/log/mail.log + log: /var/log/mail.log redis-server: - log: /var/log/redis/redis-server.log + log: /var/log/redis/redis-server.log mysql: - log: [/var/log/mysql.log,/var/log/mysql.err] + log: [/var/log/mysql.log,/var/log/mysql.err] glances: {} ssh: - log: /var/log/auth.log + log: /var/log/auth.log ssl: status: null metronome: - log: [/var/log/metronome/metronome.log,/var/log/metronome/metronome.err] + log: [/var/log/metronome/metronome.log,/var/log/metronome/metronome.err] slapd: - log: /var/log/syslog + log: /var/log/syslog php5-fpm: - log: /var/log/php5-fpm.log + log: /var/log/php5-fpm.log yunohost-api: - log: /var/log/yunohost/yunohost-api.log + log: /var/log/yunohost/yunohost-api.log yunohost-firewall: need_lock: true nslcd: - log: /var/log/syslog + log: /var/log/syslog nsswitch: status: null bind9: null From f4df8c8ec83fc30ca1b79f0f032812eb8b70b03b Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Fri, 11 May 2018 04:35:28 +0200 Subject: [PATCH 3/9] [enh] move to dbus to retreive service status --- debian/control | 2 +- src/yunohost/service.py | 63 +++++++++++++++++++++-------------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/debian/control b/debian/control index d1505994..17961b83 100644 --- a/debian/control +++ b/debian/control @@ -12,7 +12,7 @@ Architecture: all Depends: ${python:Depends}, ${misc:Depends} , moulinette (>= 2.7.1), ssowat (>= 2.7.1) , python-psutil, python-requests, python-dnspython, python-openssl - , python-apt, python-miniupnpc + , python-apt, python-miniupnpc, python-dbus , glances , dnsutils, bind9utils, unzip, git, curl, cron, wget , ca-certificates, netcat-openbsd, iproute diff --git a/src/yunohost/service.py b/src/yunohost/service.py index ef61154b..a5a97d67 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -202,46 +202,47 @@ def service_status(names=[]): raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service=name)) - status = None - if services[name].get('status') == 'service': - status = 'service %s status' % name - elif "status" in services[name]: - status = str(services[name]['status']) - else: + # this "service" isn't a service actually so we skip it + # + # the historical reason is because regenconf has been hacked into the + # service part of YunoHost will in some situation we need to regenconf + # for things that aren't services + # 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 - runlevel = 5 - if 'runlevel' in services[name].keys(): - runlevel = int(services[name]['runlevel']) + status = _get_service_information_from_systemd(name) - result[name] = {'status': 'unknown', 'loaded': 'unknown'} - - # Retrieve service status - try: - ret = subprocess.check_output(status, stderr=subprocess.STDOUT, - shell=True) - except subprocess.CalledProcessError as e: - if 'usage:' in e.output.lower(): - logger.warning(m18n.n('service_status_failed', service=name)) - else: - 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' + result[name] = { + 'status': str(status.get("SubState", "unknown")), + 'loaded': str(status.get("LoadState", "unknown")), + } if len(names) == 1: return result[names[0]] 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): """ Log every log files of a service From 07139e7bc1de5f89cfc3b1a0ac4974444881b38b Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Fri, 11 May 2018 04:40:35 +0200 Subject: [PATCH 4/9] [enh] display service description on status --- src/yunohost/service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index a5a97d67..7284f95b 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -218,6 +218,7 @@ def service_status(names=[]): result[name] = { 'status': str(status.get("SubState", "unknown")), 'loaded': str(status.get("LoadState", "unknown")), + 'description': str(status.get("Description", "")), } if len(names) == 1: From 929515ba940f5a439a2dab02eb21e1476323a22d Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Fri, 11 May 2018 04:49:20 +0200 Subject: [PATCH 5/9] [mod] remove useless import --- src/yunohost/service.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index 7284f95b..fed7ff3b 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -27,7 +27,6 @@ import os import time import yaml import json -import glob import subprocess import errno import shutil From 1b774527d87ac8a3bafd10a0e6a982adf59f6fc4 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Fri, 11 May 2018 04:49:43 +0200 Subject: [PATCH 6/9] [enh] get active status of service --- src/yunohost/service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index fed7ff3b..31ed54a5 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -217,6 +217,7 @@ def service_status(names=[]): result[name] = { 'status': str(status.get("SubState", "unknown")), 'loaded': str(status.get("LoadState", "unknown")), + 'active': str(status.get("ActiveState", "unknown")), 'description': str(status.get("Description", "")), } From 0011c4ab56a6b4b4cd49f82097eb5a81ae69f76b Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Fri, 11 May 2018 04:49:52 +0200 Subject: [PATCH 7/9] [enh] get since how much time a service is running --- src/yunohost/service.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index 31ed54a5..b5fd3a9e 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -31,7 +31,9 @@ import subprocess import errno import shutil import hashlib + from difflib import unified_diff +from datetime import datetime from moulinette import m18n from moulinette.core import MoulinetteError @@ -218,6 +220,10 @@ def service_status(names=[]): 'status': str(status.get("SubState", "unknown")), 'loaded': str(status.get("LoadState", "unknown")), 'active': str(status.get("ActiveState", "unknown")), + 'active_at': { + "timestamp": str(status.get("ActiveEnterTimestamp", "unknown")), + "human": datetime.fromtimestamp(status.get("ActiveEnterTimestamp") / 1000000).strftime("%F %X"), + }, 'description': str(status.get("Description", "")), } From 2bef98a519b4a7635b16e9285ac18797264b2e5d Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Fri, 11 May 2018 04:51:28 +0200 Subject: [PATCH 8/9] [enh] add path to service file in service status --- src/yunohost/service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index b5fd3a9e..e73da343 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -225,6 +225,7 @@ def service_status(names=[]): "human": datetime.fromtimestamp(status.get("ActiveEnterTimestamp") / 1000000).strftime("%F %X"), }, 'description': str(status.get("Description", "")), + 'service_file_path': str(status.get("FragmentPath", "unknown")), } if len(names) == 1: From 8b0295aa0423b72180ed74cae119432072b066b2 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 17 May 2018 04:52:55 +0200 Subject: [PATCH 9/9] [fix] keep backward compatibility --- src/yunohost/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index 7adecce3..d02adc08 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -229,7 +229,7 @@ def service_status(names=[]): result[name] = { 'status': str(status.get("SubState", "unknown")), - 'loaded': str(status.get("LoadState", "unknown")), + 'loaded': "enabled" if str(status.get("LoadState", "unknown")) == "loaded" else str(status.get("LoadState", "unknown")), 'active': str(status.get("ActiveState", "unknown")), 'active_at': { "timestamp": str(status.get("ActiveEnterTimestamp", "unknown")),