Response¶
ResponseLevel¶
-
class
naghelp.
ResponseLevel
(name, exit_code)¶ Object to use when exiting a naghelp plugin
Instead of using numeric code that may be hard to memorize, predefined objects has be created :
Response level object exit code OK 0 WARNING 1 CRITICAL 2 UNKNOWN 3 To exit a plugin with the correct exit code number, one have just to call the
exit()
method of the wanted ResonseLevel object-
exit
()¶ This is the official way to exit a naghelp plugin
Example
>>> level = CRITICAL >>> level.exit() SystemExit: 2
-
info
()¶ Get name and exit code for a Response Level
Examples
>>> level = CRITICAL >>> level.info() 'CRITICAL (exit_code=2)' >>> level.name 'CRITICAL' >>> level.exit_code 2
-
PluginResponse¶
-
class
naghelp.
PluginResponse
(default_level=OK)¶ Response to return to Nagios for a naghelp plugin
Parameters: default_level ( ResponseLevel
) – The level to return when no level messages has been added to the response (for exemple when no error has be found). usually it is set toOK
orUNKNOWN
A naghelp response has got many sections :
- A synopsis (The first line that is directl visible onto Nagios interface)
- A body (informations after the first line, only visible in detailed views)
- Some performance Data
The body itself has got some sub-sections :
Begin messages (Usually for a title, an introduction …)
Levels messages, that are automatically splitted into Nagios levels in this order:
- Critical messages
- Warning messages
- Unkown messages
- OK messages
More messages (Usually to give more information about the monitored host)
- End messages (Custom conclusion messages. naghelp
Plugin
use this section to add automatically some informations about the plugin.
- End messages (Custom conclusion messages. naghelp
Each section can be updated by adding a message through dedicated methods.
PluginResponse object takes care to calculate the right ResponseLevel to return to Nagios : it will depend on the Levels messages you will add to the plugin response. For example, if you add one
OK
message and oneWARNING
message, the response level will beWARNING
. if you add again oneCRITICAL
message then anOK
message , the response level will beCRITICAL
.About the synopsis section : if not manualy set, the PluginResponse class will build one for you : It will be the unique level message if you add only one in the response or a summary giving the number of messages in each level.
Examples
>>> r = PluginResponse(OK) >>> print r OK
-
add
(level, msg, *args, **kwargs)¶ Add a message in levels messages section and sets the response level at the same time
Use this method each time your plugin detects a WARNING or a CRITICAL error. You can also use this method to add a message saying there is an UNKNOWN or OK state somewhere. You can use this method several times and at any time until the
send()
is used. This method updates the calculated ResponseLevel. When the response is rendered, the added messages are splitted into sub-sectionParameters: - level (ResponseLevel) – the message level (Will affect the final response level)
- msg (str) – the message to add in levels messages section.
- args (list) – if additional arguments are given,
msg
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are given,
msg
will be formatted withstr.format()
Examples
>>> r = PluginResponse(OK) >>> print r.get_current_level() OK >>> r.add(CRITICAL,'The system crashed') >>> r.add(WARNING,'Found some almost full file system') >>> r.add(UNKNOWN,'Cannot find FAN %s status',0) >>> r.add(OK,'Power {power_id} is ON',power_id=1) >>> print r.get_current_level() CRITICAL >>> print r STATUS : CRITICAL:1, WARNING:1, UNKNOWN:1, OK:1 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- The system crashed ----( WARNING )----------------------------------------------------------------- Found some almost full file system ----( UNKNOWN )----------------------------------------------------------------- Cannot find FAN 0 status ----( OK )---------------------------------------------------------------------- Power 1 is ON
-
add_begin
(msg, *args, **kwargs)¶ Add a message in begin section
You can use this method several times and at any time until the
send()
is used. The messages will be displayed in begin section in the same order as they have been added. This method does not change the calculated ResponseLevel.Parameters: - msg (str) – the message to add in begin section.
- args (list) – if additionnal arguments are given,
msg
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are given,
msg
will be formatted withstr.format()
Examples
>>> r = PluginResponse(OK) >>> r.add_begin('='*40) >>> r.add_begin('{hostname:^40}', hostname='MyHost') >>> r.add_begin('='*40) >>> r.add_begin('Date : %s, Time : %s','2105-12-18','14:55:11') >>> r.add_begin('\n') >>> r.add(CRITICAL,'This is critical !') >>> print r This is critical ! ======================================== MyHost ======================================== Date : 2105-12-18, Time : 14:55:11 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- This is critical !
-
add_comment
(level, msg, *args, **kwargs)¶ Add a comment in levels messages section and sets the response level at the same time
it works like
add()
except that the message is not counted into the synopsisParameters: - level (ResponseLevel) – the message level (Will affect the final response level)
- msg (str) – the message to add in levels messages section.
- args (list) – if additionnal arguments are given,
msg
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are given,
msg
will be formatted withstr.format()
Examples
>>> r = PluginResponse(OK) >>> print r.get_current_level() OK >>> r.add_comment(CRITICAL,'Here are some errors') >>> r.add(CRITICAL,'error 1') >>> r.add(CRITICAL,'error 2') >>> print r STATUS : CRITICAL:2 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- Here are some errors error 1 error 2
-
add_elif
(*add_ifs, **kwargs)¶ Multi-conditionnal message add
This works like
add_if()
except that it accepts multiple tests. Like pythonelif
, the method stops on first True test and send corresponding message. If you want to build the equivalent of a default message, just useTrue
as the last test.Parameters: - add_ifs (list) – list of tuple (test,level,message).
- kwargs (dict) – if named arguments are given,
messages will be formatted with
str.format()
Examples
>>> r = PluginResponse(OK) >>> print r.get_current_level() OK >>> logs = ''' ... Power 0 is critical ... Power 1 is OK ... Power 2 is degraded ... Power 3 is failed ... Power 4 is OK ... Power 5 is degraded ... Power 6 is smoking ... ''' >>> from textops import * >>> for log in logs | rmblank(): ... r.add_elif( (log|haspattern('critical|failed'), CRITICAL, log), ... (log|haspattern('degraded|warning'), WARNING, log), ... (log|haspattern('OK'), OK, log), ... (True, UNKNOWN, log) ) >>> print r.get_current_level() CRITICAL >>> print r STATUS : CRITICAL:2, WARNING:2, UNKNOWN:1, OK:2 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- Power 0 is critical Power 3 is failed ----( WARNING )----------------------------------------------------------------- Power 2 is degraded Power 5 is degraded ----( UNKNOWN )----------------------------------------------------------------- Power 6 is smoking ----( OK )---------------------------------------------------------------------- Power 1 is OK Power 4 is OK
-
add_end
(msg, *args, **kwargs)¶ Add a message in end section
You can use this method several times and at any time until the
send()
is used. The messages will be displayed in end section in the same order as they have been added. This method does not change the calculated ResponseLevel.Parameters: - msg (str) – the message to add in end section.
- args (list) – if additional arguments are given,
msg
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are give,
msg
will be formatted withstr.format()
Examples
>>> r = PluginResponse(OK) >>> r.add_end('='*40) >>> r.add_end('{hostname:^40}', hostname='MyHost') >>> r.add_end('='*40) >>> r.add_end('Date : %s, Time : %s','2105-12-18','14:55:11') >>> r.add_end('\n') >>> r.add(CRITICAL,'This is critical !') >>> print r This is critical ! ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- This is critical ! ======================================== MyHost ======================================== Date : 2105-12-18, Time : 14:55:11
-
add_if
(test, level, msg=None, header=None, footer=None, *args, **kwargs)¶ Test than add a message in levels messages section and sets the response level at the same time
This works like
add()
except that it is conditionnal :test
must be True. If no message is given, the value oftest
is used.Parameters: - test (any) – the message is added to the response only if bool(test) is True.
- level (ResponseLevel) – the message level (Will affect the final response level)
- msg (str) – the message to add in levels messages section. If no message is given, the value of test is used.
- header (str) – Displayed before the message as a level comment if not None (Default : None)
- footer (str) – Displayed after the message as a level comment if not None (Default : None)
- args (list) – if additional arguments are given,
msg
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are given,
msg
will be formatted withstr.format()
Examples
>>> r = PluginResponse(OK) >>> print r.get_current_level() OK >>> logs = ''' ... Power 0 is critical ... Power 1 is OK ... Power 2 is degraded ... Power 3 is failed ... Power 4 is OK ... Power 5 is degraded ... ''' >>> from textops import * >>> nb_criticals = logs | grepc('critical|failed') >>> print nb_criticals 2 >>> warnings = logs | grep('degraded|warning').tostr() >>> print warnings Power 2 is degraded Power 5 is degraded >>> unknowns = logs | grep('unknown').tostr() >>> print unknowns >>> r.add_if(nb_criticals,CRITICAL,'{n} power(s) are critical',n=nb_criticals) >>> r.add_if(warnings,WARNING) >>> r.add_if(unknowns,UNKNOWN) >>> print r.get_current_level() CRITICAL >>> print r STATUS : CRITICAL:1, WARNING:1 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- 2 power(s) are critical ----( WARNING )----------------------------------------------------------------- Power 2 is degraded Power 5 is degraded
-
add_list
(level, msg_list, header=None, footer=None, *args, **kwargs)¶ Add several level messages having a same level
Sometimes, you may have to specify a list of faulty parts in the response : this can be done by this method in a single line. If a message is empty in the list, it is not added.
Parameters: - level (ResponseLevel) – the message level (Will affect the final response level)
- msg_list (list) – the messages list to add in levels messages section.
- header (str) – Displayed before the message as a level comment if not None (Default : None)
one can use
{_len}
in the comment to get list count. - footer (str) – Displayed after the message as a level comment if not None (Default : None)
one can use
{_len}
in the comment to get list count. - args (list) – if additional arguments are given, messages in
msg_list
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are given, messages in
msg_list
will be formatted withstr.format()
Examples
>>> r = PluginResponse(OK) >>> print r.get_current_level() OK >>> logs = ''' ... Power 0 is critical ... Power 1 is OK ... Power 2 is degraded ... Power 3 is failed ... Power 4 is OK ... Power 5 is degraded ... ''' >>> from textops import grep >>> criticals = logs >> grep('critical|failed') >>> warnings = logs >> grep('degraded|warning') >>> print criticals ['Power 0 is critical', 'Power 3 is failed'] >>> print warnings ['Power 2 is degraded', 'Power 5 is degraded'] >>> r.add_list(CRITICAL,criticals) >>> r.add_list(WARNING,warnings) >>> print r.get_current_level() CRITICAL >>> print r STATUS : CRITICAL:2, WARNING:2 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- Power 0 is critical Power 3 is failed ----( WARNING )----------------------------------------------------------------- Power 2 is degraded Power 5 is degraded
>>> r = PluginResponse() >>> r.add_list(WARNING,['Power warning1','Power warning2'],'{_len} Power warnings:','Power warnings : {_len}') >>> r.add_list(WARNING,['CPU warning1','CPU warning2'],'{_len} CPU warnings:','CPU warnings : {_len}') >>> print r STATUS : WARNING:4 ==================================[ STATUS ]================================== ----( WARNING )----------------------------------------------------------------- 2 Power warnings: Power warning1 Power warning2 Power warnings : 2 2 CPU warnings: CPU warning1 CPU warning2 CPU warnings : 2
-
add_many
(lst, *args, **kwargs)¶ Add several level messages NOT having a same level
This works like
add_list()
except that instead of giving a list of messages one have to specify a list of tuples (level,message). By this way, one can give a level to each message into the list. If a message is empty in the list, it is not added.Parameters: - lst (list) – A list of (level,message) tuples to add in levels messages section.
- args (list) – if additional arguments are given, messages in
lst
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are given, messages in
lst
will be formatted withstr.format()
Examples
>>> r = PluginResponse(OK) >>> print r.get_current_level() OK >>> logs = ''' ... Power 0 is critical ... Power 1 is OK ... Power 2 is degraded ... Power 3 is failed ... Power 4 is OK ... Power 5 is degraded ... ''' >>> from textops import * >>> errors = [ (CRITICAL if error|haspatterni('critical|failed') else WARNING,error) ... for error in logs | grepv('OK') ] >>> print errors [(WARNING, ''), (CRITICAL, 'Power 0 is critical'), (WARNING, 'Power 2 is degraded'), (CRITICAL, 'Power 3 is failed'), (WARNING, 'Power 5 is degraded')] >>> r.add_many(errors) >>> print r.get_current_level() CRITICAL >>> print r STATUS : CRITICAL:2, WARNING:2 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- Power 0 is critical Power 3 is failed ----( WARNING )----------------------------------------------------------------- Power 2 is degraded Power 5 is degraded
-
add_mlist
(levels, lists, headers=[], footers=[], *args, **kwargs)¶ Add a list of lists of messages
This is useful with
textops.sgrep
utility that returns lists of lists of messages. first level will be affected to first list, second level to the second list and so on.Parameters: - levels (ResponseLevel) – a list of message levels. use a
None
level to skip a list. - lists (list) – list of message lists.
- header (str) – Displayed before the message as a level comment if not None (Default : None)
one can use
{_len}
in the comment to get list count. - footer (str) – Displayed after the message as a level comment if not None (Default : None)
one can use
{_len}
in the comment to get list count. - args (list) – if additional arguments are given, messages in
msg_list
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are given, messages in
msg_list
will be formatted withstr.format()
Examples
>>> from textops import StrExt >>> r = PluginResponse(OK) >>> logs = StrExt(''' ... Power 0 is critical ... Power 1 is OK ... Power 2 is degraded ... Power 3 is failed ... Power 4 is OK ... Power 5 is degraded ... ''') >>> >>> print logs.sgrep(('critical|failed','degraded|warning')) [['Power 0 is critical', 'Power 3 is failed'], ['Power 2 is degraded', 'Power 5 is degraded'], ['', 'Power 1 is OK', 'Power 4 is OK']] >>> r.add_mlist((CRITICAL,WARNING,OK),logs.sgrep(('critical|failed','degraded|warning'))) >>> print r STATUS : CRITICAL:2, WARNING:2, OK:2 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- Power 0 is critical Power 3 is failed ----( WARNING )----------------------------------------------------------------- Power 2 is degraded Power 5 is degraded ----( OK )---------------------------------------------------------------------- Power 1 is OK Power 4 is OK >>> r = PluginResponse(OK) >>> r.add_mlist((CRITICAL,WARNING,None),logs.sgrep(('critical|failed','degraded|warning'))) >>> print r STATUS : CRITICAL:2, WARNING:2 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- Power 0 is critical Power 3 is failed ----( WARNING )----------------------------------------------------------------- Power 2 is degraded Power 5 is degraded
- levels (ResponseLevel) – a list of message levels. use a
-
add_more
(msg, *args, **kwargs)¶ Add a message in “more messages” section (aka “Additionnal informations”)
You can use this method several times and at any time until the
send()
is used. The messages will be displayed in the section in the same order as they have been added. This method does not change the calculated ResponseLevel.Parameters: - msg (str) – the message to add in end section.
- args (list) – if additional arguments are given,
msg
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are give,
msg
will be formatted withstr.format()
Note
The “Additionnal informations” section title will be added automatically if the section is not empty.
Examples
>>> r = PluginResponse(OK) >>> r.add(CRITICAL,'This is critical !') >>> r.add_more('Date : %s, Time : %s','2105-12-18','14:55:11') >>> print r This is critical ! ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- This is critical ! ==========================[ Additionnal informations ]========================== Date : 2105-12-18, Time : 14:55:11
-
add_perf_data
(data)¶ Add performance object into the response
Parameters: data (str or PerfData
) – the perf data string or PerfData object to add to the response. Have a look to Performance data string syntax.Examples
>>> r = PluginResponse(OK) >>> r.add_begin('Begin\n') >>> r.add_end('End') >>> r.add_perf_data(PerfData('filesystem_/','55','%','95','98','0','100')) >>> r.add_perf_data(PerfData('filesystem_/usr','34','%','95','98','0','100')) >>> r.add_perf_data('cpu_wait=88%;40;60;0;100') >>> r.add_perf_data('cpu_user=12%;80;95;0;100') >>> print r OK|filesystem_/=55%;95;98;0;100 Begin End| filesystem_/usr=34%;95;98;0;100 cpu_wait=88%;40;60;0;100 cpu_user=12%;80;95;0;100
-
escape_msg
(msg)¶ Escapes forbidden chars in messages
Nagios does not accept the pipe symbol in messages because it is a separator for performance data. This method escapes or replace such forbidden chars. Default behaviour is to replace the pipe
|
by an exclamation mark!
.Parameters: msg (str) – The message to escape Returns
str : The escaped message
-
get_current_level
()¶ get current level
If no level has not been set yet, it will return the default_level. Use this method if you want to know what ResponseLevel will be sent.
Returns: the response level to be sent Return type: ResponseLevel
Examples
>>> r = PluginResponse(OK) >>> print r.get_current_level() OK >>> r.set_level(WARNING) >>> print r.get_current_level() WARNING
-
get_default_synopsis
()¶ Returns the default synopsis
This method is called if no synopsis has been set manually, the response synopsis (first line of the text returned by the plugin) will be :
- The error message if there is only one level message
- Otherwise, some statistics like :
STATUS : CRITICAL:2, WARNING:2, UNKNOWN:1, OK:2
If you want to have a different default synopsis, you can subclass the
PluginResponse
class and redefine this method.Examples
>>> r = PluginResponse(OK) >>> r.add(CRITICAL,'This is critical !') >>> print r.get_default_synopsis() This is critical ! >>> r.add(WARNING,'This is just a warning.') >>> print r.get_default_synopsis() STATUS : CRITICAL:1, WARNING:1
-
get_output
(body_max_length=None)¶ Renders the whole response following the Nagios syntax
This method is automatically called when the response is sent by
send()
. If you want to have a different output, you can subclass thePluginResponse
class and redefine this method.Returns: The response text output following the Nagios syntax Return type: str Note
As
__str__
directly callsget_output()
, printing aPluginResponse
object is equivalent to callget_output()
.Example
>>> r = PluginResponse(OK) >>> r.add(CRITICAL,'This is critical !') >>> r.add(WARNING,'This is just a warning.')
>>> print r.get_output() STATUS : CRITICAL:1, WARNING:1 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- This is critical ! ----( WARNING )----------------------------------------------------------------- This is just a warning.
>>> print r STATUS : CRITICAL:1, WARNING:1 ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- This is critical ! ----( WARNING )----------------------------------------------------------------- This is just a warning.
-
get_sublevel
()¶ get sublevel
Returns: sublevel (0,1,2 or 3) Return type: int Exemples:
>>> r = PluginResponse(OK) >>> print r.get_sublevel() 0 >>> r.set_sublevel(2) >>> print r.get_sublevel() 2
-
level_msgs_render
()¶ Renders level messages
This method is automatically called when the response is rendered by
get_outpout()
. If you want to have a different output, you can subclass thePluginResponse
class and redefine this method.Returns: The foramtted level messages Return type: str Example
>>> r = PluginResponse(OK) >>> r.add(CRITICAL,'This is critical !') >>> r.add(WARNING,'This is just a warning.') >>> print r.level_msgs_render() ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- This is critical ! ----( WARNING )----------------------------------------------------------------- This is just a warning.
-
section_format
(title)¶ Returns the section title string
This method is automatically called when the response is rendered by
get_outpout()
. If you want to have a different output, you can subclass thePluginResponse
class and redefine this method.Parameters: title (str) – the section name to be formatted Returns: The foramtted section title Return type: str Example
>>> r = PluginResponse(OK) >>> print r.section_format('My section') =================================[ My section ]=================================
-
send
(level=None, synopsis='', msg='', sublevel=None, nagios_host=None, nagios_svc=None, nagios_cmd=None)¶ Send the response to Nagios
This method is automatically called by
naghelp.ActivePlugin.run()
method and follow these steps :- if defined, force a level, a sublevel, a synopsis or add a last message
- render the response string following the Nagios syntax
- display the string on stdout
- exit the plugin with the exit code corresponding to the response level.
Parameters: - level (
ResponseLevel
) – force a level (optional), - synopsis (str) – force a synopsis (optional),
- msg (str) – add a last level message (optional),
- sublevel (int) – force a sublevel [0-3] (optional),
- nagios_host (str) – nagios hostname (only for passive response)
- nagios_svc (str) – nagios service (only for passive response)
- nagios_cmd (str or pynag obj) – if None, the response goes to stdout : this is for
active plugin. if string the response is sent to the corresponding file for debug.
if it is a pynag cmd object, the response is sent to the nagios pipe for
host
nagios_host
and for servicenagios_svc
: this is for a passive plugin.
-
set_level
(level)¶ Manually set the response level
Parameters: level ( ResponseLevel
) – OK, WARNING, CRITICAL or UNKNOWNExamples
>>> r = PluginResponse(OK) >>> print r.level None >>> r.set_level(WARNING) >>> print r.level WARNING
-
set_sublevel
(sublevel)¶ sets sublevel attribute
Parameters: sublevel (int) – 0,1,2 or 3 (Default : 0) From time to time, the CRITICAL status meaning is not detailed enough : It may be useful to color it by a sub-level. The
sublevel
value is not used directly byPluginResponse
, but byActivePlugin
class which adds a__sublevel__=<sublevel>
string in the plugin informations section. This string can be used for external filtering.Actually, the sublevel meanings are :
Sub-level Description 0 The plugin is 100% sure there is a critical error 1 The plugin was able to contact remote host (ping) but got no answer from agent (timeout,credentials) 2 The plugin was unable to contact the remote host, it may be a network issue (firewall, …) 3 The plugin raised an unexpected exception : it should be a bug.
-
set_synopsis
(msg, *args, **kwargs)¶ Sets the response synopsis.
By default, if no synopsis has been set manually, the response synopsis (first line of the text returned by the plugin) will be :
- The error message if there is only one level message
- Otherwise, some statistics like :
STATUS : CRITICAL:2, WARNING:2, UNKNOWN:1, OK:2
If something else is wanted, one can define a custom synopsis with this method.
Parameters: - msg (str) – the synopsis.
- args (list) – if additional arguments are given,
msg
will be formatted with%
(old-style python string formatting) - kwargs (dict) – if named arguments are give,
msg
will be formatted withstr.format()
Examples
>>> r = PluginResponse(OK) >>> r.add(CRITICAL,'This is critical !') >>> print r This is critical ! ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- This is critical ! >>> r.set_synopsis('Mayday, Mayday, Mayday') >>> print r Mayday, Mayday, Mayday ==================================[ STATUS ]================================== ----( CRITICAL )---------------------------------------------------------------- This is critical !
-
subsection_format
(title)¶ Returns the subsection title string
This method is automatically called when the response is rendered by
get_outpout()
. If you want to have a different output, you can subclass thePluginResponse
class and redefine this method.Parameters: title (str) – the subsection name to be formatted Returns: The foramtted subsection title Return type: str Example
>>> r = PluginResponse(OK) >>> print r.subsection_format('My subsection') ----( My subsection )-----------------------------------------------------------