Refactor monitor category

This commit is contained in:
Jerome Lebleu 2013-12-02 18:02:20 +01:00
parent e743cb8c89
commit ae1689e471
3 changed files with 246 additions and 107 deletions

View file

@ -57,7 +57,9 @@ Specifications
### Monitoring ### Monitoring
yunohost monitor info [-h] [-u] [-d] [-p] [-c] [-m] [-i] yunohost monitor disk [-u {io,filesystem}] [-m]
yunohost monitor network [-u {usage,infos}]
yunohost monitor system [-u {memory,cpu,process,uptime,infos}]
yunohost monitor process [-h] [-e PROCESS] [-d PROCESS] yunohost monitor process [-h] [-e PROCESS] [-d PROCESS]
[--stop PROCESS] [-c PORT] [-i] [--stop PROCESS] [-c PORT] [-i]
[--start PROCESS] [--start PROCESS]

View file

@ -421,41 +421,48 @@ backup:
# Monitor # # Monitor #
############################# #############################
monitor: monitor:
category_help: Monitoring functions category_help: Monitor the server
actions: actions:
### monitor_info() ### monitor_disk()
info: disk:
action_help: Check System action_help: Monitor disk space and usage
arguments: arguments:
-m:
full: --memory
help: Check Memory
action: store_true
-s:
full: --swap
help: Check Swap
action: store_true
-c:
full: --cpu
help: Check CPU
action: store_true
-d:
full: --disk
help: Check Disk
action: store_true
-i:
full: --ifconfig
help: Show Ip and MAC Adress
action: store_true
-u: -u:
full: --uptime full: --unit
help: Show Uptime help: Unit to monitor
action: store_true choices:
-p: - io
full: --public - filesystem
help: Show IP public -m:
action: store_true full: --mountpoint
help: Device mountpoint
### monitor_network()
network:
action_help: Monitor network interfaces
arguments:
-u:
full: --unit
help: Unit to monitor
choices:
- usage
- infos
### monitor_system()
system:
action_help: Monitor system informations and usage
arguments:
-u:
full: --unit
help: Unit to monitor
choices:
- memory
- cpu
- process
- uptime
- infos
process: process:
action_help: Check Process action_help: Check Process
arguments: arguments:

View file

@ -23,36 +23,18 @@
Monitoring functions Monitoring functions
""" """
import xmlrpclib import os
import re
import json import json
import yaml
import psutil import psutil
import subprocess
import xmlrpclib
from urllib import urlopen from urllib import urlopen
from datetime import datetime, timedelta from datetime import datetime, timedelta
from yunohost import YunoHostError, win_msg, colorize, validate, get_required_args from yunohost import YunoHostError, win_msg, colorize, validate, get_required_args
import os
import sys
try:
import yaml
except ImportError:
sys.stderr.write('Error: Yunohost CLI Require yaml lib\n')
sys.stderr.write('apt-get install python-yaml\n')
sys.exit(1)
import json
import socket
import fcntl
import struct
if not __debug__:
import traceback
s = xmlrpclib.ServerProxy('http://127.0.0.1:61209') glances_uri = 'http://127.0.0.1:61209'
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
def bytes2human(n): def bytes2human(n):
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
@ -113,64 +95,175 @@ def process_check(args):
return { 'Status' : result } return { 'Status' : result }
def monitor_info(memory=False, swap=False, cpu=False, disk=False, ifconfig=False, uptime=False, public=False):
def monitor_disk(unit=None, mountpoint=None):
""" """
Check System Monitor disk space and usage
Keyword argument: Keyword argument:
memory -- Check Memory unit -- Unit to monitor
ifconfig -- Show Ip and MAC Adress mountpoint -- Device mountpoint
disk -- Check Disk
uptime -- Show Uptime
swap -- Check Swap
public -- Show IP public
cpu -- Check CPU
""" """
if memory: glances = _get_glances_api()
return json.loads(s.getMem()) result_dname = None
result = {}
if swap:
return json.loads(s.getMemSwap())
elif cpu:
return json.loads(s.getLoad())
elif ifconfig:
result = {}
for k, fs in enumerate(json.loads(s.getNetwork())):
interface = fs['interface_name']
if interface != "lo":
ip = get_ip_address(str(interface))
del fs['interface_name']
result[ip] = fs
else:
del fs['interface_name']
result[interface] = fs
return result
elif disk:
result = {}
for k, fs in enumerate(json.loads(s.getFs())):
if fs['fs_type'] != 'tmpfs' and fs['fs_type'] != 'rpc_pipefs':
mnt_point = str(fs['mnt_point'])
del fs['mnt_point']
result[mnt_point] = fs
return result
elif uptime:
uptime_value = (str(datetime.now() - datetime.fromtimestamp(psutil.BOOT_TIME)).split('.')[0])
return { 'Uptime' : uptime_value }
elif public:
try:
ip = str(urlopen('http://ip.yunohost.org').read())
except:
raise YunoHostError(1, _("No connection") )
return { 'Public IP' : ip }
if unit is None:
units = ['io', 'filesystem']
else: else:
raise YunoHostError(1, _('No arguments provided')) units = [unit]
# Get mounted block devices
devices = {}
output = subprocess.check_output('lsblk -o NAME,MOUNTPOINT -l -n'.split())
for d in output.split('\n'):
m = re.search(r'([a-z]+[0-9]+)[ ]+(\/\S*)', d) # Extract device name (1) and its mountpoint (2)
if m and (mountpoint is None or m.group(2) == mountpoint):
(dn, dm) = (m.group(1), m.group(2))
devices[dn] = dm
result[dn] = {} if unit is None else []
result_dname = dn if mountpoint is not None else None
if len(devices) == 0:
raise YunoHostError(1, _("Unknown mountpoint '%s'") % mountpoint)
# Retrieve monitoring for unit(s)
for u in units:
if u == 'io':
for d in json.loads(glances.getDiskIO()):
dname = d['disk_name']
if dname in devices.keys():
del d['disk_name']
if unit is None:
result[dname][u] = d
else:
d['mnt_point'] = devices[dname]
result[dname] = d
elif u == 'filesystem':
for d in json.loads(glances.getFs()):
dmount = d['mnt_point']
for (dn, dm) in devices.items():
# TODO: Show non-block filesystems?
if dm != dmount:
continue
del d['device_name']
if unit is None:
result[dn][u] = d
else:
result[dn] = d
else:
raise YunoHostError(1, _("Unknown unit '%s'") % u)
if result_dname is not None:
return result[result_dname]
return result
def monitor_network(unit=None):
"""
Monitor network interfaces
Keyword argument:
unit -- Unit to monitor
"""
glances = _get_glances_api()
result = {}
if unit is None:
units = ['usage', 'infos']
else:
units = [unit]
# Get network devices and their addresses
devices = {}
output = subprocess.check_output('ip addr show'.split())
for d in re.split('^(?:[0-9]+: )', output, flags=re.MULTILINE):
d = re.sub('\n[ ]+', ' % ', d) # Replace new lines by %
m = re.match('([a-z]+[0-9]?): (.*)', d) # Extract device name (1) and its addresses (2)
if m:
devices[m.group(1)] = m.group(2)
# Retrieve monitoring for unit(s)
for u in units:
if u == 'usage':
result[u] = {}
for i in json.loads(glances.getNetwork()):
iname = i['interface_name']
if iname in devices.keys():
del i['interface_name']
result[u][iname] = i
elif u == 'infos':
try:
p_ip = str(urlopen('http://ip.yunohost.org').read())
except:
raise YunoHostError(1, _("Public IP resolution failed"))
l_ip = None
for name, addrs in devices.items():
if name == 'lo':
continue
if len(devices) == 2:
l_ip = _extract_inet(addrs)
else:
if l_ip is None:
l_ip = {}
l_ip[name] = _extract_inet(addrs)
result[u] = {
'public_ip': p_ip,
'local_ip': l_ip,
'gateway': 'TODO'
}
else:
raise YunoHostError(1, _("Unknown unit '%s'") % u)
if len(units) == 1:
return result[unit]
return result
def monitor_system(unit=None):
"""
Monitor system informations and usage
Keyword argument:
unit -- Unit to monitor
"""
glances = _get_glances_api()
result = {}
if unit is None:
units = ['memory', 'cpu', 'process', 'uptime', 'infos']
else:
units = [unit]
# Retrieve monitoring for unit(s)
for u in units:
if u == 'memory':
result[u] = {
'ram': json.loads(glances.getMem()),
'swap': json.loads(glances.getMemSwap())
}
elif u == 'cpu':
result[u] = {
'load': json.loads(glances.getLoad()),
'usage': json.loads(glances.getCpu())
}
elif u == 'process':
result[u] = json.loads(glances.getProcessCount())
elif u == 'uptime':
result[u] = (str(datetime.now() - datetime.fromtimestamp(psutil.BOOT_TIME)).split('.')[0])
elif u == 'infos':
result[u] = json.loads(glances.getSystem())
else:
raise YunoHostError(1, _("Unknown unit '%s'") % u)
if len(units) == 1 and type(result[unit]) is not str:
return result[unit]
return result
def monitor_process(enable=None, disable=None, start=None, stop=None, check=False, info=False): def monitor_process(enable=None, disable=None, start=None, stop=None, check=False, info=False):
""" """
@ -197,3 +290,40 @@ def monitor_process(enable=None, disable=None, start=None, stop=None, check=Fals
return process_check(check) return process_check(check)
elif info: elif info:
return json.loads(s.getProcessCount()) return json.loads(s.getProcessCount())
def _get_glances_api():
"""
Retrieve Glances API running on the local server
"""
try:
p = xmlrpclib.ServerProxy(glances_uri)
p.system.methodHelp('getAll')
except (xmlrpclib.ProtocolError, IOError):
# TODO: Try to start Glances service
raise YunoHostError(1, _("Connection to Glances server failed"))
return p
def _extract_inet(string):
"""
Extract IP address (v4 or v6) from a string
Keyword argument:
string -- String to search in
"""
# TODO: Return IPv4 and IPv6?
ip4_prog = re.compile('((25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}/[0-9]{1,2})')
ip6_prog = re.compile('((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?/[0-9]{1,2})')
m = ip4_prog.search(string)
if m:
return m.group(1)
m = ip6_prog.search(string)
if m:
return m.group(1)
return None