-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from bithon/master
Implemented perfdata metrics and lots of code improvements. Thanks, @bithon !
- Loading branch information
Showing
6 changed files
with
236 additions
and
166 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Change Log | ||
|
||
All notable changes to this project will be documented in this file. | ||
|
||
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to | ||
[Semantic Versioning](http://semver.org/). | ||
|
||
## 0.2.0 | ||
### Added | ||
- parsed arguments: `label` | ||
- parfdata to output (https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/3/en/perfdata.html) | ||
- exception for UnicodeDecodeError in `CheckPcMeasure.check()` | ||
### Changes | ||
- code is now more generic for NAGIOS and ICINGA | ||
- restructuring the class | ||
|
||
# 0.1.0 Initial release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# TODO | ||
- Create a release | ||
- Upload to NAGIOS and ICINGA exchange ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,127 +1,139 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
|
||
import argparse | ||
import os | ||
import re | ||
import socket | ||
import sys | ||
import textwrap | ||
import time | ||
|
||
|
||
STATUS_OK = 0 | ||
STATUS_WARNING = 1 | ||
STATUS_CRITICAL = 2 | ||
STATUS_UNKNOWN = 3 | ||
|
||
|
||
class CheckPcMeasure(object): | ||
def __init__(self, host="127.0.0.1", port=4000): | ||
version = "0.2.0" | ||
if __name__ == '__main__': | ||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, | ||
description=textwrap.dedent(os.path.basename(__file__) + " " + version + | ||
" (GPLv3) 2018 - " + time.strftime("%Y")), | ||
epilog=textwrap.dedent("GitHub: https://github.com/mpibpc-mroose/" | ||
"nagios_plugin_pcmeasure")) | ||
parser.add_argument("-H", dest="host", type=str, required=True, help="hostname of the etherbox") | ||
parser.add_argument("-p", type=int, dest="port", default=4000, required=False, help="port to use") | ||
parser.add_argument("-S", dest="sensor_name", type=str, required=True, help="sensor name, e.g. com1.1") | ||
parser.add_argument("-w", dest="warning_threshold", type=float, required=True, help="warning threshold") | ||
parser.add_argument("-c", dest="critical_threshold", type=float, required=True, help="critical threshold") | ||
parser.add_argument("-l", dest="label", type=str, required=False, help="label for perfdata, e.g. 'celsius'") | ||
|
||
NAGIOS_OK = 0 | ||
NAGIOS_WARNING = 1 | ||
NAGIOS_CRITICAL = 2 | ||
NAGIOS_UNKNOWN = 3 | ||
self.arguments = parser.parse_args() | ||
self.critical_threshold = self.arguments.critical_threshold | ||
self.warning_threshold = self.arguments.warning_threshold | ||
self.host = self.arguments.host | ||
self.port = self.arguments.port | ||
self.sensor_name = self.arguments.sensor_name | ||
|
||
if self.arguments.label: | ||
self.label_name = " " + self.arguments.label | ||
self.label_perfdata = self.arguments.label | ||
else: | ||
self.label_name = "" | ||
self.label_perfdata = "sensor_output" | ||
|
||
class MessPCCheck(object): | ||
def __init__(self, host, port=4000): | ||
self.host = host | ||
self.port = port | ||
self.socket = self.connect() | ||
if self.warning_threshold > self.critical_threshold: | ||
print("UNKNOWN: warning threshold should be lower than critical threshold") | ||
sys.exit(STATUS_UNKNOWN) | ||
else: | ||
self.label_name = "" | ||
self.label_perfdata = "sensor_output" | ||
self.critical_threshold = False | ||
self.warning_threshold = False | ||
self.host = host | ||
self.port = port | ||
self.sensor_name = False | ||
self.socket = self._connect() | ||
|
||
def connect(self): | ||
def _connect(self): | ||
_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
_socket.settimeout(0.5) | ||
_socket.connect((self.host, self.port)) | ||
try: | ||
_socket.connect((self.host, self.port)) | ||
except socket.timeout: | ||
print("UNKNOWN: timeout on connect to {host}:{port}".format(host=self.host, | ||
port=self.port)) | ||
sys.exit(STATUS_UNKNOWN) | ||
except ConnectionRefusedError as error: | ||
print("UNKNOWN: {error} by {host}:{port}".format(error=str(error), | ||
host=self.host, | ||
port=self.port)) | ||
sys.exit(STATUS_UNKNOWN) | ||
return _socket | ||
|
||
def close(self): | ||
self.socket.close() | ||
|
||
def __delete__(self, instance): | ||
self.socket.close() | ||
|
||
def _get_value(self, sensor_name: bytes) -> float: | ||
self.socket.send( | ||
b'pcmeasure.' + sensor_name + b'\n' | ||
) | ||
def _get_value(self, sensor_name) -> float: | ||
self.socket.send(b'pcmeasure.' + bytes(sensor_name, 'utf-8') + b'\n') | ||
raw_data = self.socket.recv(2096).decode() | ||
sensor_reply_pattern = re.compile(r"value=\s(?P<value>.+);") | ||
return float(sensor_reply_pattern.findall(raw_data)[0]) | ||
|
||
def check(self, sensor_name: bytes, warning_threshold: float, critical_threshold: float) -> int: | ||
def check(self, sensor_name=False, warning_threshold=False, critical_threshold=False, label=False) -> int: | ||
if sensor_name: | ||
self.sensor_name = sensor_name | ||
if warning_threshold: | ||
self.warning_threshold = warning_threshold | ||
if critical_threshold: | ||
self.critical_threshold = critical_threshold | ||
if label: | ||
self.label_name = " " + label | ||
self.label_perfdata = label | ||
try: | ||
value = self._get_value(sensor_name=sensor_name) | ||
if value > critical_threshold: | ||
print("CRITICAL: {value} exceeds {threshold}".format( | ||
value=value, | ||
threshold=critical_threshold | ||
)) | ||
return NAGIOS_CRITICAL | ||
elif value > warning_threshold: | ||
print("WARNING: {value} exceeds {threshold}".format( | ||
value=value, | ||
threshold=warning_threshold | ||
)) | ||
return NAGIOS_WARNING | ||
value = self._get_value(sensor_name=self.sensor_name) | ||
if value > self.critical_threshold: | ||
print("CRITICAL: {value} exceeds {threshold} | " | ||
"{label_perfdata}={value};;;0".format(value=value, | ||
label=self.label_name, | ||
label_perfdata=self.label_perfdata, | ||
threshold=self.critical_threshold)) | ||
return STATUS_CRITICAL | ||
elif value > self.warning_threshold: | ||
print("WARNING: {value} exceeds {threshold} | " | ||
"{label_perfdata}={value};;;0".format(value=value, | ||
label=self.label_name, | ||
label_perfdata=self.label_perfdata, | ||
threshold=self.warning_threshold)) | ||
return STATUS_WARNING | ||
else: | ||
print("OK: {value}".format( | ||
value=value | ||
)) | ||
return NAGIOS_OK | ||
print("OK: {value}{label} | {label_perfdata}={value};;;0".format(value=value, | ||
label_perfdata=self.label_perfdata, | ||
label=self.label_name)) | ||
return STATUS_OK | ||
except UnicodeDecodeError: | ||
print("UNKNOWN: can not read from sensor '{sensor_name}'! " | ||
"use {app_name} -h for further information!".format(sensor_name=self.sensor_name, | ||
app_name=os.path.basename(__file__))) | ||
return STATUS_UNKNOWN | ||
except Exception as error: | ||
print("UNKNOWN: " + str(error)) | ||
return NAGIOS_UNKNOWN | ||
return STATUS_UNKNOWN | ||
|
||
def check_command(self): | ||
return_code = self.check(sensor_name=self.sensor_name, | ||
warning_threshold=self.warning_threshold, | ||
critical_threshold=self.critical_threshold) | ||
sys.exit(return_code) | ||
|
||
|
||
if __name__ == '__main__': | ||
parser = argparse.ArgumentParser() | ||
""" | ||
check_pcmeasure2.pl -H <host> -S <sensor>[,<sensor] [-p <port>] | ||
[-w <threshold>] [-c <threshold>] | ||
""" | ||
parser.add_argument( | ||
"-H", | ||
dest="host", | ||
type=str, | ||
required=True, | ||
help="hostname of the MessPC unit" | ||
) | ||
parser.add_argument( | ||
"-p", | ||
type=int, | ||
dest="port", | ||
default=4000, | ||
required=False, | ||
help="port to use for communication" | ||
) | ||
parser.add_argument( | ||
"-S", | ||
dest="sensor_name", | ||
type=str, | ||
required=True, | ||
help="sensor name, e.g. com1.1" | ||
) | ||
parser.add_argument( | ||
"-w", | ||
dest="warning_threshold", | ||
type=float, | ||
required=True, | ||
help="warning threshold" | ||
) | ||
parser.add_argument( | ||
"-c", | ||
dest="critical_threshold", | ||
type=float, | ||
required=True, | ||
help="critical threshold" | ||
) | ||
arguments = parser.parse_args() | ||
|
||
if arguments.warning_threshold > arguments.critical_threshold: | ||
print("UNKNOWN: warning threshold should be lower than critical threshold") | ||
sys.exit(NAGIOS_UNKNOWN) | ||
|
||
try: | ||
mess_pc = MessPCCheck( | ||
host=arguments.host, port=arguments.port | ||
) | ||
except TimeoutError: | ||
print( | ||
"CRITICAL: timeout on connect to {host}:{port}".format( | ||
host=arguments.host, | ||
port=arguments.port | ||
)) | ||
sys.exit(NAGIOS_CRITICAL) | ||
|
||
return_code = mess_pc.check( | ||
sensor_name=arguments.sensor_name.encode(), | ||
warning_threshold=arguments.warning_threshold, | ||
critical_threshold=arguments.critical_threshold | ||
) | ||
sys.exit(return_code) | ||
check_pcmeasure = CheckPcMeasure() | ||
check_pcmeasure.check_command() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,43 @@ | ||
import sys | ||
import os | ||
from setuptools import setup | ||
#!/usr/bin/env python3 | ||
|
||
version = '0.1.0' | ||
import setuptools | ||
|
||
setup( | ||
name='nagios_plugin_pcmeasure', | ||
|
||
version = '0.2.0' | ||
|
||
with open("README.md", "r") as fh: | ||
long_description = fh.read() | ||
|
||
setuptools.setup( | ||
name='check__pcmeasure.py', | ||
version=version, | ||
author='Dr. Marco Roose', | ||
author_email='[email protected]', | ||
url='https://github.com/mpibpc-mroose/nagios_plugin_pcmeasure/', | ||
license='GPL-3.0', | ||
description='Nagios Plugin for ethernet sensor boxes from http://messpc.de', | ||
long_description='Please see our GitHub README', | ||
description='Nagios/Icinga2 Plugin for ethernet sensor boxes from http://messpc.de and http://pcmeasure.com', | ||
long_description=long_description, | ||
long_description_content_type="text/markdown", | ||
install_requires=[], | ||
python_requires='>=3.5', | ||
packages=setuptools.find_packages(), | ||
project_urls={ | ||
'Source': 'https://github.com/mpibpc-mroose/nagios_plugin_pcmeasure/', | ||
'Nagios Exchange': 'https://exchange.nagios.org/', | ||
'Icinga Exchange': 'https://exchange.icinga.com', | ||
}, | ||
keywords=[ | ||
'Nagios', | ||
'Icinga2', | ||
'pcmeasure', | ||
'messpc', | ||
'etherbox' | ||
], | ||
classifiers=[ | ||
"Development Status :: 5 - Production/Stable", | ||
"Operating System :: OS Independent", | ||
'Programming Language :: Python :: 3.5', | ||
'Programming Language :: Python :: 3.6' | ||
'Programming Language :: Python :: 3.6', | ||
'Programming Language :: Python :: 3.7' | ||
] | ||
) |
Oops, something went wrong.