|
1 | 1 | #!/usr/bin/env python3
|
2 | 2 | # -*- coding: utf-8 -*-
|
| 3 | + |
3 | 4 | import argparse
|
| 5 | +import os |
4 | 6 | import re
|
5 | 7 | import socket
|
6 | 8 | import sys
|
| 9 | +import textwrap |
| 10 | +import time |
| 11 | + |
| 12 | + |
| 13 | +STATUS_OK = 0 |
| 14 | +STATUS_WARNING = 1 |
| 15 | +STATUS_CRITICAL = 2 |
| 16 | +STATUS_UNKNOWN = 3 |
| 17 | + |
| 18 | + |
| 19 | +class CheckPcMeasure(object): |
| 20 | + def __init__(self, host="127.0.0.1", port=4000): |
| 21 | + version = "0.2.0" |
| 22 | + if __name__ == '__main__': |
| 23 | + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, |
| 24 | + description=textwrap.dedent(os.path.basename(__file__) + " " + version + |
| 25 | + " (GPLv3) 2018 - " + time.strftime("%Y")), |
| 26 | + epilog=textwrap.dedent("GitHub: https://github.com/mpibpc-mroose/" |
| 27 | + "nagios_plugin_pcmeasure")) |
| 28 | + parser.add_argument("-H", dest="host", type=str, required=True, help="hostname of the etherbox") |
| 29 | + parser.add_argument("-p", type=int, dest="port", default=4000, required=False, help="port to use") |
| 30 | + parser.add_argument("-S", dest="sensor_name", type=str, required=True, help="sensor name, e.g. com1.1") |
| 31 | + parser.add_argument("-w", dest="warning_threshold", type=float, required=True, help="warning threshold") |
| 32 | + parser.add_argument("-c", dest="critical_threshold", type=float, required=True, help="critical threshold") |
| 33 | + parser.add_argument("-l", dest="label", type=str, required=False, help="label for perfdata, e.g. 'celsius'") |
7 | 34 |
|
8 |
| -NAGIOS_OK = 0 |
9 |
| -NAGIOS_WARNING = 1 |
10 |
| -NAGIOS_CRITICAL = 2 |
11 |
| -NAGIOS_UNKNOWN = 3 |
| 35 | + self.arguments = parser.parse_args() |
| 36 | + self.critical_threshold = self.arguments.critical_threshold |
| 37 | + self.warning_threshold = self.arguments.warning_threshold |
| 38 | + self.host = self.arguments.host |
| 39 | + self.port = self.arguments.port |
| 40 | + self.sensor_name = self.arguments.sensor_name |
12 | 41 |
|
| 42 | + if self.arguments.label: |
| 43 | + self.label_name = " " + self.arguments.label |
| 44 | + self.label_perfdata = self.arguments.label |
| 45 | + else: |
| 46 | + self.label_name = "" |
| 47 | + self.label_perfdata = "sensor_output" |
13 | 48 |
|
14 |
| -class MessPCCheck(object): |
15 |
| - def __init__(self, host, port=4000): |
16 |
| - self.host = host |
17 |
| - self.port = port |
18 |
| - self.socket = self.connect() |
| 49 | + if self.warning_threshold > self.critical_threshold: |
| 50 | + print("UNKNOWN: warning threshold should be lower than critical threshold") |
| 51 | + sys.exit(STATUS_UNKNOWN) |
| 52 | + else: |
| 53 | + self.label_name = "" |
| 54 | + self.label_perfdata = "sensor_output" |
| 55 | + self.critical_threshold = False |
| 56 | + self.warning_threshold = False |
| 57 | + self.host = host |
| 58 | + self.port = port |
| 59 | + self.sensor_name = False |
| 60 | + self.socket = self._connect() |
19 | 61 |
|
20 |
| - def connect(self): |
| 62 | + def _connect(self): |
21 | 63 | _socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
22 | 64 | _socket.settimeout(0.5)
|
23 |
| - _socket.connect((self.host, self.port)) |
| 65 | + try: |
| 66 | + _socket.connect((self.host, self.port)) |
| 67 | + except socket.timeout: |
| 68 | + print("UNKNOWN: timeout on connect to {host}:{port}".format(host=self.host, |
| 69 | + port=self.port)) |
| 70 | + sys.exit(STATUS_UNKNOWN) |
| 71 | + except ConnectionRefusedError as error: |
| 72 | + print("UNKNOWN: {error} by {host}:{port}".format(error=str(error), |
| 73 | + host=self.host, |
| 74 | + port=self.port)) |
| 75 | + sys.exit(STATUS_UNKNOWN) |
24 | 76 | return _socket
|
25 | 77 |
|
| 78 | + def close(self): |
| 79 | + self.socket.close() |
| 80 | + |
26 | 81 | def __delete__(self, instance):
|
27 | 82 | self.socket.close()
|
28 | 83 |
|
29 |
| - def _get_value(self, sensor_name: bytes) -> float: |
30 |
| - self.socket.send( |
31 |
| - b'pcmeasure.' + sensor_name + b'\n' |
32 |
| - ) |
| 84 | + def _get_value(self, sensor_name) -> float: |
| 85 | + self.socket.send(b'pcmeasure.' + bytes(sensor_name, 'utf-8') + b'\n') |
33 | 86 | raw_data = self.socket.recv(2096).decode()
|
34 | 87 | sensor_reply_pattern = re.compile(r"value=\s(?P<value>.+);")
|
35 | 88 | return float(sensor_reply_pattern.findall(raw_data)[0])
|
36 | 89 |
|
37 |
| - def check(self, sensor_name: bytes, warning_threshold: float, critical_threshold: float) -> int: |
| 90 | + def check(self, sensor_name=False, warning_threshold=False, critical_threshold=False, label=False) -> int: |
| 91 | + if sensor_name: |
| 92 | + self.sensor_name = sensor_name |
| 93 | + if warning_threshold: |
| 94 | + self.warning_threshold = warning_threshold |
| 95 | + if critical_threshold: |
| 96 | + self.critical_threshold = critical_threshold |
| 97 | + if label: |
| 98 | + self.label_name = " " + label |
| 99 | + self.label_perfdata = label |
38 | 100 | try:
|
39 |
| - value = self._get_value(sensor_name=sensor_name) |
40 |
| - if value > critical_threshold: |
41 |
| - print("CRITICAL: {value} exceeds {threshold}".format( |
42 |
| - value=value, |
43 |
| - threshold=critical_threshold |
44 |
| - )) |
45 |
| - return NAGIOS_CRITICAL |
46 |
| - elif value > warning_threshold: |
47 |
| - print("WARNING: {value} exceeds {threshold}".format( |
48 |
| - value=value, |
49 |
| - threshold=warning_threshold |
50 |
| - )) |
51 |
| - return NAGIOS_WARNING |
| 101 | + value = self._get_value(sensor_name=self.sensor_name) |
| 102 | + if value > self.critical_threshold: |
| 103 | + print("CRITICAL: {value} exceeds {threshold} | " |
| 104 | + "{label_perfdata}={value};;;0".format(value=value, |
| 105 | + label=self.label_name, |
| 106 | + label_perfdata=self.label_perfdata, |
| 107 | + threshold=self.critical_threshold)) |
| 108 | + return STATUS_CRITICAL |
| 109 | + elif value > self.warning_threshold: |
| 110 | + print("WARNING: {value} exceeds {threshold} | " |
| 111 | + "{label_perfdata}={value};;;0".format(value=value, |
| 112 | + label=self.label_name, |
| 113 | + label_perfdata=self.label_perfdata, |
| 114 | + threshold=self.warning_threshold)) |
| 115 | + return STATUS_WARNING |
52 | 116 | else:
|
53 |
| - print("OK: {value}".format( |
54 |
| - value=value |
55 |
| - )) |
56 |
| - return NAGIOS_OK |
| 117 | + print("OK: {value}{label} | {label_perfdata}={value};;;0".format(value=value, |
| 118 | + label_perfdata=self.label_perfdata, |
| 119 | + label=self.label_name)) |
| 120 | + return STATUS_OK |
| 121 | + except UnicodeDecodeError: |
| 122 | + print("UNKNOWN: can not read from sensor '{sensor_name}'! " |
| 123 | + "use {app_name} -h for further information!".format(sensor_name=self.sensor_name, |
| 124 | + app_name=os.path.basename(__file__))) |
| 125 | + return STATUS_UNKNOWN |
57 | 126 | except Exception as error:
|
58 | 127 | print("UNKNOWN: " + str(error))
|
59 |
| - return NAGIOS_UNKNOWN |
| 128 | + return STATUS_UNKNOWN |
| 129 | + |
| 130 | + def check_command(self): |
| 131 | + return_code = self.check(sensor_name=self.sensor_name, |
| 132 | + warning_threshold=self.warning_threshold, |
| 133 | + critical_threshold=self.critical_threshold) |
| 134 | + sys.exit(return_code) |
60 | 135 |
|
61 | 136 |
|
62 | 137 | if __name__ == '__main__':
|
63 |
| - parser = argparse.ArgumentParser() |
64 |
| - """ |
65 |
| - check_pcmeasure2.pl -H <host> -S <sensor>[,<sensor] [-p <port>] |
66 |
| - [-w <threshold>] [-c <threshold>] |
67 |
| - """ |
68 |
| - parser.add_argument( |
69 |
| - "-H", |
70 |
| - dest="host", |
71 |
| - type=str, |
72 |
| - required=True, |
73 |
| - help="hostname of the MessPC unit" |
74 |
| - ) |
75 |
| - parser.add_argument( |
76 |
| - "-p", |
77 |
| - type=int, |
78 |
| - dest="port", |
79 |
| - default=4000, |
80 |
| - required=False, |
81 |
| - help="port to use for communication" |
82 |
| - ) |
83 |
| - parser.add_argument( |
84 |
| - "-S", |
85 |
| - dest="sensor_name", |
86 |
| - type=str, |
87 |
| - required=True, |
88 |
| - help="sensor name, e.g. com1.1" |
89 |
| - ) |
90 |
| - parser.add_argument( |
91 |
| - "-w", |
92 |
| - dest="warning_threshold", |
93 |
| - type=float, |
94 |
| - required=True, |
95 |
| - help="warning threshold" |
96 |
| - ) |
97 |
| - parser.add_argument( |
98 |
| - "-c", |
99 |
| - dest="critical_threshold", |
100 |
| - type=float, |
101 |
| - required=True, |
102 |
| - help="critical threshold" |
103 |
| - ) |
104 |
| - arguments = parser.parse_args() |
105 |
| - |
106 |
| - if arguments.warning_threshold > arguments.critical_threshold: |
107 |
| - print("UNKNOWN: warning threshold should be lower than critical threshold") |
108 |
| - sys.exit(NAGIOS_UNKNOWN) |
109 |
| - |
110 |
| - try: |
111 |
| - mess_pc = MessPCCheck( |
112 |
| - host=arguments.host, port=arguments.port |
113 |
| - ) |
114 |
| - except TimeoutError: |
115 |
| - print( |
116 |
| - "CRITICAL: timeout on connect to {host}:{port}".format( |
117 |
| - host=arguments.host, |
118 |
| - port=arguments.port |
119 |
| - )) |
120 |
| - sys.exit(NAGIOS_CRITICAL) |
121 |
| - |
122 |
| - return_code = mess_pc.check( |
123 |
| - sensor_name=arguments.sensor_name.encode(), |
124 |
| - warning_threshold=arguments.warning_threshold, |
125 |
| - critical_threshold=arguments.critical_threshold |
126 |
| - ) |
127 |
| - sys.exit(return_code) |
| 138 | + check_pcmeasure = CheckPcMeasure() |
| 139 | + check_pcmeasure.check_command() |
0 commit comments