Add {{mustache}} feature to the action script

This commit is contained in:
Nicolargo 2015-01-02 22:59:08 +01:00
parent e32089f40a
commit dfd2cf1c38
7 changed files with 65 additions and 37 deletions

5
NEWS
View File

@ -2,12 +2,13 @@
Glances Version 2.x
==============================================================================
Version 2.X
Version 2.3
===========
* Add actions on alerts (issue #132). It is now possible to run action (command line) by triggers. Action could containq {Mustache} {{tag}} (Mustache) with stat value.
* Add InfluxDB export module (--export-influxdb) (issue #455)
* Add Statsd export module (--export-statsd) (issue #465)
* Refactor export module (CSV export option is now --export-csv). It is now possible to export stats from the Glances client (issue #463)
* Refactor export module (CSV export option is now --export-csv). It is now possible to export stats from the Glances client mode (issue #463)
* The Web inteface is now based on BootStarp / RWD grid (issue #417, #366 and #461) Thanks to Nicolas Hart @nclsHart
* Add the RAID plugins (issue #447)

View File

@ -3,7 +3,7 @@
user_careful=50
user_warning=70
user_critical=90
user_critical_action=touch /tmp/glances.alert
user_critical_action=echo {{user}} {{value}} {{max}} > /tmp/cpu.alert
iowait_careful=50
iowait_warning=70
iowait_critical=90
@ -72,13 +72,14 @@ hide=sda2,sda5
# Default limits for free filesytem space in %
# Default values if not defined: 50/70/90
careful=50
careful_action=echo {{mnt_point}} {{used}}/{{size}} > /tmp/fs.alert
warning=70
critical=90
[sensors]
# Sensors core limits
# Default values if not defined: 60/70/80
temperature_core_careful=60
temperature_core_careful=50
temperature_core_warning=70
temperature_core_critical=80
# Temperatures in °C for hddtemp

View File

@ -21,6 +21,7 @@
# Import system lib
from subprocess import Popen
import pystache
# Import Glances lib
from glances.core.glances_logging import logger
@ -50,11 +51,12 @@ class GlancesActions(object):
"""Set the stat_name to criticity"""
self.status[stat_name] = criticity
def run(self, stat_name, criticity, commands):
def run(self, stat_name, criticity, commands, mustache_dict=None):
"""Run the commands (in background)
- stats_name: plugin_name (+ header)
- criticity: criticity of the trigger
- commands: a list of command line
- commands: a list of command line with optional {{mustache}}
- mustache_dict: Plugin stats (can be use within {{mustache}})
Return True if the commands have been ran"""
@ -64,10 +66,13 @@ class GlancesActions(object):
# Ran all actions in background
for cmd in commands:
logger.info("Action triggered for {0} ({1}): {2}".format(stat_name, criticity, cmd))
splitted_cmd = cmd.split()
# Replace {{arg}} by the dict one (Thk to {Mustache})
cmd_full = pystache.render(cmd, mustache_dict)
# Execute the action
logger.info("Action triggered for {0} ({1}): {2}".format(stat_name, criticity, cmd_full))
logger.debug("Stats value for the trigger: {0}".format(mustache_dict))
try:
Popen(splitted_cmd)
Popen(cmd_full, shell=True)
except OSError as e:
logger.error("Can't execute the action ({0})".format(e))

View File

@ -697,6 +697,7 @@ class _GlancesCurses(object):
# Display
x = display_x
x_max = x
y = display_y
for m in plugin_stats['msgdict']:
# New line
@ -740,9 +741,11 @@ class _GlancesCurses(object):
# good
offset = len(m['msg'])
x = x + offset
if x > x_max:
x_max = x
# Compute the next Glances column/line position
self.next_column = max(self.next_column, x + self.space_between_column)
self.next_column = max(self.next_column, x_max + self.space_between_column)
self.next_line = max(self.next_line, y + self.space_between_line)
def erase(self):

View File

@ -209,7 +209,9 @@ class Plugin(GlancesPlugin):
msg = '{0:>7}'.format(self.auto_unit(i['free']))
else:
msg = '{0:>7}'.format(self.auto_unit(i['used']))
ret.append(self.curse_add_line(msg, self.get_alert(i['used'], max=i['size'])))
ret.append(self.curse_add_line(msg, self.get_alert(i['used'],
max=i['size'],
header=i['mnt_point'])))
msg = '{0:>7}'.format(self.auto_unit(i['size']))
ret.append(self.curse_add_line(msg))

View File

@ -333,12 +333,25 @@ class GlancesPlugin(object):
# Manage action
# Here is a command line for the current trigger ?
command = self.__get_limit_action(ret.lower(), header=header)
if command is not None:
# Acommand line is available for the current alert, run it
self.actions.run(stat_name, ret.lower(), command)
else:
try:
command = self.__get_limit_action(ret.lower(), header=header)
except KeyError:
# Reset the trigger
self.actions.set(stat_name, ret.lower())
else:
# A command line is available for the current alert, run it
# Build the {{mustache}} dictionnary
if type(self.stats) is list:
# If the stats are stored in a list of dict (fs plugin for exemple)
# Return the dict for the current header
try:
mustache_dict = (item for item in self.stats if item[self.get_key()] == header).next()
except StopIteration:
mustache_dict = {}
else:
# Use the stats dict
mustache_dict = self.stats
self.actions.run(stat_name, ret.lower(), command, mustache_dict=mustache_dict)
# Default is ok
return ret + log_str
@ -352,38 +365,37 @@ class GlancesPlugin(object):
prefix = self.plugin_name + '_'
if header != "":
prefix += header + '_'
action = self.limits[prefix + criticity]
return action
# Get the limit for stat + header
# Exemple: network_wlan0_rx_careful
try:
limit = self.limits[prefix + criticity]
except KeyError:
# Try fallback to plugin default limit
# Exemple: network_careful
limit = self.limits[self.plugin_name + '_' + criticity]
# Return the limit
return limit
def __get_limit_action(self, criticity, header=""):
"""Return the action for the alert"""
prefix = self.plugin_name + '_'
if header != "":
prefix += header + '_'
# Get the limit for stat + header
# Exemple: network_wlan0_rx_careful_action
try:
action = self.limits[prefix + criticity + '_action']
except KeyError:
action = None
# Try fallback to plugin default limit
# Exemple: network_careful_action
action = self.limits[self.plugin_name + '_' + criticity + '_action']
# Return the action list
return action
# def __get_limit_critical(self, header=""):
# if header == "":
# return self.limits[self.plugin_name + '_' + 'critical']
# else:
# return self.limits[self.plugin_name + '_' + header + '_' + 'critical']
# def __get_limit_warning(self, header=""):
# if header == "":
# return self.limits[self.plugin_name + '_' + 'warning']
# else:
# return self.limits[self.plugin_name + '_' + header + '_' + 'warning']
# def __get_limit_careful(self, header=""):
# if header == "":
# return self.limits[self.plugin_name + '_' + 'careful']
# else:
# return self.limits[self.plugin_name + '_' + header + '_' + 'careful']
def get_conf_value(self, value, header="", plugin_name=None):
"""Return the configuration (header_)value for the current plugin (or the one given by the plugin_name var)"""
if plugin_name is None:

View File

@ -64,6 +64,10 @@ class Plugin(GlancesPlugin):
# Init the stats
self.reset()
def get_key(self):
"""Return the key of the list"""
return 'label'
def reset(self):
"""Reset/init the stats."""
self.stats = []