Merge pull request #52 from jeromelebleu/dev

Implement monitoring and statistics management
This commit is contained in:
Alexis Gavoty 2013-12-17 07:55:42 -08:00
commit 2cee93d846
5 changed files with 126 additions and 33 deletions

View file

@ -39,7 +39,7 @@ general_arguments:
full: --version full: --version
help: Display YunoHost version help: Display YunoHost version
action: version action: version
version: YunoHost 2.0 beta1 version: YunoHost %version%
############################# #############################
# User # # User #
@ -569,6 +569,19 @@ monitor:
- week - week
- month - month
### monitor_enable()
enable:
action_help: Enable server monitoring
arguments:
-n:
full: --no-stats
help: Disable monitoring statistics
action: store_true
### monitor_disable()
disable:
action_help: Disable server monitoring
############################# #############################
# Service # # Service #

View file

@ -1,25 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
__credits__ = """
Copyright (C) 2012 YunoHost
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, see http://www.gnu.org/licenses
"""
__author__ = 'Kload <kload@kload.fr>'
__version__ = '2.0 beta1'
import os import os
import sys import sys
import argparse import argparse

View file

@ -22,6 +22,26 @@
""" """
YunoHost core classes & functions YunoHost core classes & functions
""" """
__credits__ = """
Copyright (C) 2012 YunoHost
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, see http://www.gnu.org/licenses
"""
__author__ = 'Kload <kload@kload.fr>'
__version__ = '2.0-beta3'
import os import os
import sys import sys
try: try:
@ -468,10 +488,13 @@ def parse_dict(action_map):
# Add general arguments # Add general arguments
for arg_name, arg_params in action_map['general_arguments'].items(): for arg_name, arg_params in action_map['general_arguments'].items():
if 'version' in arg_params:
v = arg_params['version']
arg_params['version'] = v.replace('%version%', __version__)
if 'full' in arg_params: if 'full' in arg_params:
arg_names = [arg_name, arg_params['full']] arg_names = [arg_name, arg_params['full']]
arg_fullname = arg_params['full'] arg_fullname = arg_params['full']
del arg_params['full'] del arg_params['full']
else: arg_names = [arg_name] else: arg_names = [arg_name]
parsers['general'].add_argument(*arg_names, **arg_params) parsers['general'].add_argument(*arg_names, **arg_params)

View file

@ -34,10 +34,13 @@ import os.path
import cPickle as pickle import cPickle as pickle
from urllib import urlopen from urllib import urlopen
from datetime import datetime, timedelta from datetime import datetime, timedelta
from yunohost import YunoHostError from yunohost import YunoHostError, win_msg
from yunohost_service import (service_enable, service_disable,
service_start, service_stop, service_status)
glances_uri = 'http://127.0.0.1:61209' glances_uri = 'http://127.0.0.1:61209'
stats_path = '/var/lib/yunohost/stats' stats_path = '/var/lib/yunohost/stats'
crontab_path = '/etc/cron.d/yunohost-monitor'
def monitor_disk(units=None, mountpoint=None, human_readable=False): def monitor_disk(units=None, mountpoint=None, human_readable=False):
""" """
@ -336,6 +339,60 @@ def monitor_show_stats(period, date=None):
return result return result
def monitor_enable(no_stats=False):
"""
Enable server monitoring
Keyword argument:
no_stats -- Disable monitoring statistics
"""
glances = service_status('glances')
if glances['status'] != 'running':
service_start('glances')
if glances['loaded'] != 'enabled':
try:
service_enable('glances')
except:
# TODO: log error
pass
# Install crontab
if not no_stats:
cmd = 'yunohost monitor update-stats'
rules = ('*/5 * * * * root %(cmd)s day --no-ldap >> /dev/null\n' + \
'0 * * * * root %(cmd)s week --no-ldap >> /dev/null\n' + \
'* */4 * * * root %(cmd)s month --no-ldap >> /dev/null') % {'cmd': cmd}
os.system("touch %s" % crontab_path)
os.system("echo '%s' >%s" % (rules, crontab_path))
win_msg(_("Server monitoring enabled"))
def monitor_disable():
"""
Disable server monitoring
"""
glances = service_status('glances')
if glances['status'] != 'inactive':
service_stop('glances')
if glances['loaded'] != 'disabled':
try:
service_disable('glances')
except:
# TODO: log error
pass
# Remove crontab
try:
os.remove(crontab_path)
except:
pass
win_msg(_("Server monitoring disabled"))
def _get_glances_api(): def _get_glances_api():
""" """
Retrieve Glances API running on the local server Retrieve Glances API running on the local server
@ -345,10 +402,13 @@ def _get_glances_api():
p = xmlrpclib.ServerProxy(glances_uri) p = xmlrpclib.ServerProxy(glances_uri)
p.system.methodHelp('getAll') p.system.methodHelp('getAll')
except (xmlrpclib.ProtocolError, IOError): except (xmlrpclib.ProtocolError, IOError):
# TODO: Try to start Glances service pass
raise YunoHostError(1, _("Connection to Glances server failed")) else:
return p
return p if service_status('glances')['status'] != 'running':
raise YunoHostError(1, _("Monitoring is disabled"))
raise YunoHostError(1, _("Connection to Glances server failed"))
def _extract_inet(string, skip_netmask=False): def _extract_inet(string, skip_netmask=False):
@ -563,8 +623,12 @@ def _calculate_stats_mean(stats):
if isinstance(v, dict): if isinstance(v, dict):
s[k] = _mean(v, t, ts) s[k] = _mean(v, t, ts)
elif isinstance(v, list): elif isinstance(v, list):
nums = [ float(x * t[i]) for i, x in enumerate(v) ] try:
s[k] = sum(nums) / float(ts) nums = [ float(x * t[i]) for i, x in enumerate(v) ]
except:
pass
else:
s[k] = sum(nums) / float(ts)
return s return s
stats = _mean(stats, timestamp, t_sum) stats = _mean(stats, timestamp, t_sum)

View file

@ -38,6 +38,8 @@ def service_start(names):
names -- Services name to start names -- Services name to start
""" """
if isinstance(names, str):
names = [names]
for name in names: for name in names:
if _run_service_command('start', name): if _run_service_command('start', name):
win_msg(_("'%s' service started") % name) win_msg(_("'%s' service started") % name)
@ -53,6 +55,8 @@ def service_stop(names):
name -- Services name to stop name -- Services name to stop
""" """
if isinstance(names, str):
names = [names]
for name in names: for name in names:
if _run_service_command('stop', name): if _run_service_command('stop', name):
win_msg(_("'%s' service stopped") % name) win_msg(_("'%s' service stopped") % name)
@ -68,6 +72,8 @@ def service_enable(names):
names -- Services name to enable names -- Services name to enable
""" """
if isinstance(names, str):
names = [names]
for name in names: for name in names:
if _run_service_command('enable', name): if _run_service_command('enable', name):
win_msg(_("'%s' service enabled") % name) win_msg(_("'%s' service enabled") % name)
@ -83,6 +89,8 @@ def service_disable(names):
names -- Services name to disable names -- Services name to disable
""" """
if isinstance(names, str):
names = [names]
for name in names: for name in names:
if _run_service_command('disable', name): if _run_service_command('disable', name):
win_msg(_("'%s' service disabled") % name) win_msg(_("'%s' service disabled") % name)
@ -90,7 +98,7 @@ def service_disable(names):
raise YunoHostError(1, _("Service disabling failed for '%s'") % name) raise YunoHostError(1, _("Service disabling failed for '%s'") % name)
def service_status(names=None): def service_status(names=[]):
""" """
Show status information about one or more services (all by default) Show status information about one or more services (all by default)
@ -102,7 +110,9 @@ def service_status(names=None):
check_names = True check_names = True
result = {} result = {}
if names is None or len(names) == 0: if isinstance(names, str):
names = [names]
elif len(names) == 0:
names = services.keys() names = services.keys()
check_names = False check_names = False
@ -141,6 +151,8 @@ def service_status(names=None):
else: else:
result[name]['loaded'] = _("not-found") result[name]['loaded'] = _("not-found")
if len(names) == 1:
return result[names[0]]
return result return result