check_systemd 2.0.1__tar.gz → 2.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ include LICENSE
2
+ prune test
3
+ prune systemd_source_code
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.1
2
+ Name: check_systemd
3
+ Version: 2.0.3
4
+ Summary: Nagios / Icinga monitoring plugin to check systemd for failed units.
5
+ Home-page: https://github.com/Josef-Friedrich/check_systemd
6
+ Author: Josef Friedrich
7
+ Author-email: josef@friedrich.rocks
8
+ License: GNU LGPL v2
9
+ Description: [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https://pypi.python.org/pypi/check_systemd)
10
+ [![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd)
11
+
12
+ # check_systemd
13
+
14
+ Nagios / Icinga monitoring plugin to check systemd for failed units.
15
+
16
+ This Python script will report a degraded system to Nagios / Icinage.
17
+ It requires only the nagiosplugin library.
18
+
19
+ You can also test a single service with -s parameter.
20
+
21
+ Released under GNU GPLv2 License.
22
+
23
+ ## Installation
24
+
25
+ ```
26
+ pip3 install check_systemd
27
+ ```
28
+
29
+ ## Command line interface
30
+
31
+ ```
32
+ usage: nosetests [-h] [-c SECONDS] [-e UNIT | -u UNIT] [-v] [-V] [-w SECONDS]
33
+
34
+ Nagios / Icinga monitoring plugin to check systemd for failed units.
35
+
36
+ optional arguments:
37
+ -h, --help show this help message and exit
38
+ -c SECONDS, --critical SECONDS
39
+ Startup time in seconds to result in critical status.
40
+ -e UNIT, --exclude UNIT
41
+ Exclude a systemd unit from the checks. This option
42
+ can be applied multiple times. For example: -e mnt-
43
+ data.mount -e task.service.
44
+ -u UNIT, --unit UNIT Name of the systemd unit that is beeing tested.
45
+ -v, --verbose Increase output verbosity (use up to 3 times).
46
+ -V, --version show program's version number and exit
47
+ -w SECONDS, --warning SECONDS
48
+ Startup time in seconds to result in warning status.
49
+
50
+ ```
51
+
52
+ ## Project pages
53
+
54
+ * https://github.com/Josef-Friedrich/check_systemd
55
+ * https://exchange.icinga.com/joseffriedrich/check_systemd
56
+
57
+ ## Testing
58
+
59
+ ```
60
+ pip3 install tox
61
+ tox
62
+ ```
63
+ Keywords: nagios,systemd
64
+ Platform: UNKNOWN
65
+ Classifier: Development Status :: 5 - Production/Stable
66
+ Classifier: Environment :: Plugins
67
+ Classifier: Intended Audience :: System Administrators
68
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)
69
+ Classifier: Programming Language :: Python
70
+ Classifier: Programming Language :: Python :: 3
71
+ Classifier: Programming Language :: Python :: 3.6
72
+ Classifier: Operating System :: POSIX :: Linux
73
+ Classifier: Topic :: System :: Networking :: Monitoring
74
+ Requires-Python: >=3.6
75
+ Description-Content-Type: text/markdown
@@ -0,0 +1,54 @@
1
+ [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https://pypi.python.org/pypi/check_systemd)
2
+ [![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd)
3
+
4
+ # check_systemd
5
+
6
+ Nagios / Icinga monitoring plugin to check systemd for failed units.
7
+
8
+ This Python script will report a degraded system to Nagios / Icinage.
9
+ It requires only the nagiosplugin library.
10
+
11
+ You can also test a single service with -s parameter.
12
+
13
+ Released under GNU GPLv2 License.
14
+
15
+ ## Installation
16
+
17
+ ```
18
+ pip3 install check_systemd
19
+ ```
20
+
21
+ ## Command line interface
22
+
23
+ ```
24
+ usage: nosetests [-h] [-c SECONDS] [-e UNIT | -u UNIT] [-v] [-V] [-w SECONDS]
25
+
26
+ Nagios / Icinga monitoring plugin to check systemd for failed units.
27
+
28
+ optional arguments:
29
+ -h, --help show this help message and exit
30
+ -c SECONDS, --critical SECONDS
31
+ Startup time in seconds to result in critical status.
32
+ -e UNIT, --exclude UNIT
33
+ Exclude a systemd unit from the checks. This option
34
+ can be applied multiple times. For example: -e mnt-
35
+ data.mount -e task.service.
36
+ -u UNIT, --unit UNIT Name of the systemd unit that is beeing tested.
37
+ -v, --verbose Increase output verbosity (use up to 3 times).
38
+ -V, --version show program's version number and exit
39
+ -w SECONDS, --warning SECONDS
40
+ Startup time in seconds to result in warning status.
41
+
42
+ ```
43
+
44
+ ## Project pages
45
+
46
+ * https://github.com/Josef-Friedrich/check_systemd
47
+ * https://exchange.icinga.com/joseffriedrich/check_systemd
48
+
49
+ ## Testing
50
+
51
+ ```
52
+ pip3 install tox
53
+ tox
54
+ ```
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.1
2
+ Name: check-systemd
3
+ Version: 2.0.3
4
+ Summary: Nagios / Icinga monitoring plugin to check systemd for failed units.
5
+ Home-page: https://github.com/Josef-Friedrich/check_systemd
6
+ Author: Josef Friedrich
7
+ Author-email: josef@friedrich.rocks
8
+ License: GNU LGPL v2
9
+ Description: [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https://pypi.python.org/pypi/check_systemd)
10
+ [![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd)
11
+
12
+ # check_systemd
13
+
14
+ Nagios / Icinga monitoring plugin to check systemd for failed units.
15
+
16
+ This Python script will report a degraded system to Nagios / Icinage.
17
+ It requires only the nagiosplugin library.
18
+
19
+ You can also test a single service with -s parameter.
20
+
21
+ Released under GNU GPLv2 License.
22
+
23
+ ## Installation
24
+
25
+ ```
26
+ pip3 install check_systemd
27
+ ```
28
+
29
+ ## Command line interface
30
+
31
+ ```
32
+ usage: nosetests [-h] [-c SECONDS] [-e UNIT | -u UNIT] [-v] [-V] [-w SECONDS]
33
+
34
+ Nagios / Icinga monitoring plugin to check systemd for failed units.
35
+
36
+ optional arguments:
37
+ -h, --help show this help message and exit
38
+ -c SECONDS, --critical SECONDS
39
+ Startup time in seconds to result in critical status.
40
+ -e UNIT, --exclude UNIT
41
+ Exclude a systemd unit from the checks. This option
42
+ can be applied multiple times. For example: -e mnt-
43
+ data.mount -e task.service.
44
+ -u UNIT, --unit UNIT Name of the systemd unit that is beeing tested.
45
+ -v, --verbose Increase output verbosity (use up to 3 times).
46
+ -V, --version show program's version number and exit
47
+ -w SECONDS, --warning SECONDS
48
+ Startup time in seconds to result in warning status.
49
+
50
+ ```
51
+
52
+ ## Project pages
53
+
54
+ * https://github.com/Josef-Friedrich/check_systemd
55
+ * https://exchange.icinga.com/joseffriedrich/check_systemd
56
+
57
+ ## Testing
58
+
59
+ ```
60
+ pip3 install tox
61
+ tox
62
+ ```
63
+ Keywords: nagios,systemd
64
+ Platform: UNKNOWN
65
+ Classifier: Development Status :: 5 - Production/Stable
66
+ Classifier: Environment :: Plugins
67
+ Classifier: Intended Audience :: System Administrators
68
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)
69
+ Classifier: Programming Language :: Python
70
+ Classifier: Programming Language :: Python :: 3
71
+ Classifier: Programming Language :: Python :: 3.6
72
+ Classifier: Operating System :: POSIX :: Linux
73
+ Classifier: Topic :: System :: Networking :: Monitoring
74
+ Requires-Python: >=3.6
75
+ Description-Content-Type: text/markdown
@@ -7,7 +7,6 @@ setup.py
7
7
  check_systemd.egg-info/PKG-INFO
8
8
  check_systemd.egg-info/SOURCES.txt
9
9
  check_systemd.egg-info/dependency_links.txt
10
+ check_systemd.egg-info/entry_points.txt
10
11
  check_systemd.egg-info/requires.txt
11
- check_systemd.egg-info/top_level.txt
12
- test/test_mock.py
13
- test/test_subprocess.py
12
+ check_systemd.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ check_systemd = check_systemd:main
3
+
@@ -0,0 +1,347 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ You can redistribute it and/or modify it under the terms of the GNU General
5
+ Public License as published by the Free Software Foundation, either version 2
6
+ of the License.
7
+ Copyright 2014-18 Andrea Briganti a.k.a 'Kbyte'
8
+ Copyright 2019 Josef Friedrich
9
+ """
10
+ import io
11
+ import subprocess
12
+ import argparse
13
+ import re
14
+
15
+ import nagiosplugin
16
+ from nagiosplugin import Metric
17
+
18
+ __version__ = '2.0.3'
19
+
20
+
21
+ class SystemdctlListUnitsResource(nagiosplugin.Resource):
22
+ """
23
+ :param list excludes: A list of systemd unit names.
24
+ """
25
+ name = 'SYSTEMD'
26
+
27
+ def __init__(self, excludes=[]):
28
+ self.excludes = excludes
29
+
30
+ def probe(self):
31
+ """Query system state and return metrics.
32
+
33
+ :return: generator that emits
34
+ :class:`~nagiosplugin.metric.Metric` objects
35
+ """
36
+ # We don’t use `systemctl --failed --no-legend`, because we want to
37
+ # collect performance data of all units.
38
+ try:
39
+ p = subprocess.Popen(['systemctl', 'list-units', '--all',
40
+ '--no-legend'],
41
+ stderr=subprocess.PIPE,
42
+ stdin=subprocess.PIPE,
43
+ stdout=subprocess.PIPE)
44
+ stdout, stderr = p.communicate()
45
+ except OSError as e:
46
+ raise nagiosplugin.CheckError(e)
47
+
48
+ if stderr:
49
+ raise nagiosplugin.CheckError(stderr)
50
+
51
+ # Dictionary to store all units according their active state.
52
+ units = {
53
+ 'failed': [],
54
+ 'active': [],
55
+ 'activating': [],
56
+ 'inactive': [],
57
+ }
58
+ if stdout:
59
+ # Output of `systemctl list-units --all --no-legend`:
60
+ # UNIT LOAD ACTIVE SUB JOB DESCRIPTION
61
+ # foobar.service loaded active waiting Description text
62
+ count_units = 0
63
+ for line in io.StringIO(stdout.decode('utf-8')):
64
+ split_line = line.split()
65
+ # foobar.service
66
+ unit = split_line[0]
67
+ # failed
68
+ active = split_line[2]
69
+ # Only count not excludes units.
70
+ if unit not in self.excludes:
71
+ units[active].append(unit)
72
+ count_units += 1
73
+
74
+ for unit in units['failed']:
75
+ if unit not in self.excludes:
76
+ yield Metric(name=unit, value='failed', context='unit')
77
+
78
+ for active, unit_names in units.items():
79
+ yield Metric(name='units_{}'.format(active),
80
+ value=len(units[active]),
81
+ context='performance_data')
82
+
83
+ yield Metric(name='count_units', value=count_units,
84
+ context='performance_data')
85
+
86
+ if len(units['failed']) == 0:
87
+ yield Metric(name='all', value=None, context='unit')
88
+
89
+
90
+ def format_timespan_to_seconds(fmt_timespan):
91
+ """Convert a timespan format string into secondes.
92
+
93
+ :param str fmt_timespan: for example `2.345s` or `3min 45.234s`
94
+
95
+ :return: The seconds
96
+ :rtype: float
97
+ """
98
+ seconds = {
99
+ 'y': 365 * 24 * 60 * 60,
100
+ 'month': 30 * 24 * 60 * 60,
101
+ 'w': 7 * 24 * 60 * 60,
102
+ 'd': 24 * 60 * 60,
103
+ 'h': 60 * 60,
104
+ 'min': 60,
105
+ 's': 1,
106
+ }
107
+ result = 0
108
+ for span in fmt_timespan.split():
109
+ match = re.search(r'([\d\.]+)([a-z]+)', span)
110
+ value = match.group(1)
111
+ unit = match.group(2)
112
+ result += float(value) * seconds[unit]
113
+ return round(float(result), 3)
114
+
115
+
116
+ class SystemdAnalyseResource(nagiosplugin.Resource):
117
+
118
+ name = 'SYSTEMD'
119
+
120
+ def probe(self):
121
+ """Query system state and return metrics.
122
+
123
+ :return: generator that emits
124
+ :class:`~nagiosplugin.metric.Metric` objects
125
+ """
126
+ try:
127
+ p = subprocess.Popen(['systemd-analyze'],
128
+ stderr=subprocess.PIPE,
129
+ stdin=subprocess.PIPE,
130
+ stdout=subprocess.PIPE)
131
+ stdout, stderr = p.communicate()
132
+ except OSError as e:
133
+ raise nagiosplugin.CheckError(e)
134
+
135
+ if stderr:
136
+ raise nagiosplugin.CheckError(stderr)
137
+
138
+ if stdout:
139
+ # Second line:
140
+ # graphical.target reached after 1min 2.154s in userspace
141
+ match = re.search(r'reached after (.+) in userspace',
142
+ stdout.decode('utf-8'))
143
+
144
+ yield Metric(name='startup_time',
145
+ value=format_timespan_to_seconds(match.group(1)),
146
+ context='startup_time')
147
+
148
+
149
+ class SystemctlIsActiveResource(nagiosplugin.Resource):
150
+
151
+ name = 'SYSTEMD'
152
+
153
+ def __init__(self, *args, **kwargs):
154
+ self.unit = kwargs.pop('unit')
155
+ super(nagiosplugin.Resource, self).__init__(*args, **kwargs)
156
+
157
+ def probe(self):
158
+ """Query system state and return metrics.
159
+
160
+ :return: generator that emits
161
+ :class:`~nagiosplugin.metric.Metric` objects
162
+ """
163
+ # Execute `systemctl is-active <service>` and get output
164
+ # - active
165
+ # - inactive (by unkown unit file)
166
+ # - failed
167
+ try:
168
+ p = subprocess.Popen(['systemctl', 'is-active', self.unit],
169
+ stderr=subprocess.PIPE,
170
+ stdin=subprocess.PIPE,
171
+ stdout=subprocess.PIPE)
172
+ stdout, stderr = p.communicate()
173
+ except OSError as e:
174
+ raise nagiosplugin.CheckError(e)
175
+
176
+ if stderr:
177
+ raise nagiosplugin.CheckError(stderr)
178
+ if stdout:
179
+ for line in io.StringIO(stdout.decode('utf-8')):
180
+ active = line.strip()
181
+ yield Metric(name=self.unit, value=active, context='unit')
182
+
183
+
184
+ class UnitContext(nagiosplugin.Context):
185
+
186
+ def __init__(self):
187
+ super(UnitContext, self).__init__('unit')
188
+
189
+ def evaluate(self, metric, resource):
190
+ """Determines state of a given metric.
191
+
192
+ :param metric: associated metric that is to be evaluated
193
+ :param resource: resource that produced the associated metric
194
+ (may optionally be consulted)
195
+ :returns: :class:`~.result.Result`
196
+ """
197
+ hint = '%s: %s' % (metric.name, metric.value) \
198
+ if metric.value else metric.name
199
+ if metric.value and metric.value != 'active':
200
+ return self.result_cls(nagiosplugin.Critical, metric=metric,
201
+ hint=hint)
202
+ else:
203
+ return self.result_cls(nagiosplugin.Ok, metric=metric, hint=hint)
204
+
205
+
206
+ class PerformanceDataContext(nagiosplugin.Context):
207
+
208
+ def __init__(self):
209
+ super(PerformanceDataContext, self).__init__('performance_data')
210
+
211
+ def performance(self, metric, resource):
212
+ """Derives performance data from a given metric.
213
+
214
+ :param metric: associated metric from which performance data are
215
+ derived
216
+ :param resource: resource that produced the associated metric
217
+ (may optionally be consulted)
218
+
219
+ :returns: :class:`Perfdata` object
220
+ """
221
+ return nagiosplugin.Performance(label=metric.name, value=metric.value)
222
+
223
+
224
+ class SystemdSummary(nagiosplugin.Summary):
225
+
226
+ def ok(self, results):
227
+ """Formats status line when overall state is ok.
228
+
229
+ :param results: :class:`~nagiosplugin.result.Results` container
230
+ :returns: status line
231
+ """
232
+ for result in results.most_significant:
233
+ if isinstance(result.context, UnitContext):
234
+ return '{0}'.format(result)
235
+ return 'all'
236
+
237
+ def problem(self, results):
238
+ """Formats status line when overall state is not ok.
239
+
240
+ :param results: :class:`~.result.Results` container
241
+ :returns: status line
242
+ """
243
+ summary = []
244
+ for result in results.most_significant:
245
+ if result.context.name in ['startup_time', 'unit']:
246
+ summary.append(result)
247
+ return ', '.join(['{0}'.format(result) for result in summary])
248
+
249
+ def verbose(self, results):
250
+ """Provides extra lines if verbose plugin execution is requested.
251
+
252
+ :param results: :class:`~.result.Results` container
253
+ :returns: list of strings
254
+ """
255
+ summary = []
256
+ for result in results.most_significant:
257
+ if result.context.name in ['startup_time', 'unit']:
258
+ summary.append('{0}: {1}'.format(result.state, result))
259
+ return summary
260
+
261
+
262
+ def get_argparser():
263
+ parser = argparse.ArgumentParser(
264
+ description='Nagios / Icinga monitoring plugin to check systemd for '
265
+ 'failed units.'
266
+ )
267
+
268
+ exclusive_group = parser.add_mutually_exclusive_group()
269
+
270
+ parser.add_argument(
271
+ '-c', '--critical',
272
+ metavar='SECONDS',
273
+ default=120,
274
+ help='Startup time in seconds to result in critical status.',
275
+ )
276
+
277
+ exclusive_group.add_argument(
278
+ '-e', '--exclude',
279
+ metavar='UNIT',
280
+ action='append',
281
+ default=[],
282
+ help='Exclude a systemd unit from the checks. This option can be '
283
+ 'applied multiple times. For example: -e mnt-data.mount -e '
284
+ 'task.service.',
285
+ )
286
+
287
+ exclusive_group.add_argument(
288
+ '-u', '--unit',
289
+ type=str,
290
+ dest='unit',
291
+ help='Name of the systemd unit that is beeing tested.',
292
+ )
293
+
294
+ parser.add_argument(
295
+ '-v', '--verbose',
296
+ action='count',
297
+ default=0,
298
+ help='Increase output verbosity (use up to 3 times).'
299
+ )
300
+
301
+ parser.add_argument(
302
+ '-V', '--version',
303
+ action='version',
304
+ version='%(prog)s {}'.format(__version__),
305
+ )
306
+
307
+ parser.add_argument(
308
+ '-w', '--warning',
309
+ default=60,
310
+ metavar='SECONDS',
311
+ help='Startup time in seconds to result in warning status.',
312
+ )
313
+
314
+ return parser
315
+
316
+
317
+ @nagiosplugin.guarded
318
+ def main():
319
+ args = get_argparser().parse_args()
320
+
321
+ objects = []
322
+
323
+ if args.unit:
324
+ objects.append(SystemctlIsActiveResource(unit=args.unit))
325
+ else:
326
+ objects += [
327
+ SystemdctlListUnitsResource(excludes=args.exclude),
328
+ PerformanceDataContext(),
329
+ SystemdAnalyseResource(),
330
+ ]
331
+
332
+ objects += [
333
+ UnitContext(),
334
+ nagiosplugin.ScalarContext(
335
+ name='startup_time',
336
+ warning=args.warning,
337
+ critical=args.critical,
338
+ ),
339
+ SystemdSummary()
340
+ ]
341
+
342
+ check = nagiosplugin.Check(*objects)
343
+ check.main(args.verbose)
344
+
345
+
346
+ if __name__ == '__main__':
347
+ main()
@@ -4,8 +4,9 @@ from setuptools import setup, find_packages
4
4
 
5
5
  HERE = os.path.abspath(os.path.dirname(__file__))
6
6
 
7
+
7
8
  def read(*parts):
8
- with open(os.path.join(HERE, *parts), 'r') as fp:
9
+ with open(os.path.join(HERE, *parts), 'r', encoding='utf-8') as fp:
9
10
  return fp.read()
10
11
 
11
12
 
@@ -21,6 +22,7 @@ def find_version(*file_paths):
21
22
 
22
23
  raise RuntimeError("Unable to find version string.")
23
24
 
25
+
24
26
  setup(
25
27
  name='check_systemd',
26
28
  packages=find_packages(),
@@ -29,25 +31,31 @@ setup(
29
31
  install_requires=[
30
32
  'nagiosplugin>=1.2',
31
33
  ],
32
- description='A simple nagios plugin that detects failed systemd units.',
34
+ description='Nagios / Icinga monitoring plugin to check systemd for '
35
+ 'failed units.',
33
36
  long_description=read('README.md'),
34
37
  long_description_content_type='text/markdown',
35
- author='Andrea Briganti',
36
- author_email='kbytesys@gmail.com',
38
+ author='Josef Friedrich',
39
+ author_email='josef@friedrich.rocks',
37
40
  url='https://github.com/Josef-Friedrich/check_systemd',
38
41
  keywords=['nagios', 'systemd'],
39
42
  license='GNU LGPL v2',
43
+ python_requires='>=3.6',
40
44
  classifiers=[
41
45
  'Development Status :: 5 - Production/Stable',
42
46
  'Environment :: Plugins',
43
47
  'Intended Audience :: System Administrators',
44
- 'License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)',
48
+ 'License :: OSI Approved :: GNU Lesser General Public License v2 '
49
+ '(LGPLv2)',
45
50
  'Programming Language :: Python',
46
- 'Programming Language :: Python :: 2',
47
51
  'Programming Language :: Python :: 3',
52
+ 'Programming Language :: Python :: 3.6',
48
53
  'Operating System :: POSIX :: Linux',
49
54
  'Topic :: System :: Networking :: Monitoring'
50
55
  ],
56
+ entry_points={
57
+ 'console_scripts': [
58
+ 'check_systemd = check_systemd:main',
59
+ ],
60
+ },
51
61
  )
52
-
53
-
@@ -1 +0,0 @@
1
- include LICENSE
@@ -1,32 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: check_systemd
3
- Version: 2.0.1
4
- Summary: A simple nagios plugin that detects failed systemd units.
5
- Home-page: https://github.com/Josef-Friedrich/check_systemd
6
- Author: Andrea Briganti
7
- Author-email: kbytesys@gmail.com
8
- License: GNU LGPL v2
9
- Description: [![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd)
10
-
11
- # check_systemd
12
-
13
- Simple and easy nagios check for systemd status.
14
-
15
- This Python script will report a degraded system to nagios and requires only the nagiosplugin library.
16
-
17
- You can also test a single service with -s parameter.
18
-
19
- Released under GNU GPLv2 License.
20
-
21
- Keywords: nagios,systemd
22
- Platform: UNKNOWN
23
- Classifier: Development Status :: 5 - Production/Stable
24
- Classifier: Environment :: Plugins
25
- Classifier: Intended Audience :: System Administrators
26
- Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)
27
- Classifier: Programming Language :: Python
28
- Classifier: Programming Language :: Python :: 2
29
- Classifier: Programming Language :: Python :: 3
30
- Classifier: Operating System :: POSIX :: Linux
31
- Classifier: Topic :: System :: Networking :: Monitoring
32
- Description-Content-Type: text/markdown
@@ -1,11 +0,0 @@
1
- [![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd)
2
-
3
- # check_systemd
4
-
5
- Simple and easy nagios check for systemd status.
6
-
7
- This Python script will report a degraded system to nagios and requires only the nagiosplugin library.
8
-
9
- You can also test a single service with -s parameter.
10
-
11
- Released under GNU GPLv2 License.
@@ -1,32 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: check-systemd
3
- Version: 2.0.1
4
- Summary: A simple nagios plugin that detects failed systemd units.
5
- Home-page: https://github.com/Josef-Friedrich/check_systemd
6
- Author: Andrea Briganti
7
- Author-email: kbytesys@gmail.com
8
- License: GNU LGPL v2
9
- Description: [![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd)
10
-
11
- # check_systemd
12
-
13
- Simple and easy nagios check for systemd status.
14
-
15
- This Python script will report a degraded system to nagios and requires only the nagiosplugin library.
16
-
17
- You can also test a single service with -s parameter.
18
-
19
- Released under GNU GPLv2 License.
20
-
21
- Keywords: nagios,systemd
22
- Platform: UNKNOWN
23
- Classifier: Development Status :: 5 - Production/Stable
24
- Classifier: Environment :: Plugins
25
- Classifier: Intended Audience :: System Administrators
26
- Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)
27
- Classifier: Programming Language :: Python
28
- Classifier: Programming Language :: Python :: 2
29
- Classifier: Programming Language :: Python :: 3
30
- Classifier: Operating System :: POSIX :: Linux
31
- Classifier: Topic :: System :: Networking :: Monitoring
32
- Description-Content-Type: text/markdown
@@ -1,146 +0,0 @@
1
- #!/usr/bin/env python
2
- """
3
- You can redistribute it and/or modify it under the terms of the GNU General
4
- Public License as published by the Free Software Foundation, either version 2
5
- of the License.
6
- Copyright Andrea Briganti a.k.a 'Kbyte'
7
- """
8
- import io
9
- import subprocess
10
- import argparse
11
-
12
- import nagiosplugin
13
-
14
- __version__ = '2.0.1'
15
-
16
-
17
- class SystemdStatus(nagiosplugin.Resource):
18
- """
19
- :param list excludes: A list of systemd unit names.
20
- """
21
- name = 'SYSTEMD'
22
-
23
- def __init__(self, excludes=[]):
24
- self.excludes = excludes
25
-
26
- def probe(self):
27
- # Execute systemctl --failed --no-legend and get output
28
- try:
29
- p = subprocess.Popen(['systemctl', '--failed', '--no-legend'],
30
- stderr=subprocess.PIPE,
31
- stdin=subprocess.PIPE,
32
- stdout=subprocess.PIPE)
33
- stdout, stderr = p.communicate()
34
- except OSError as e:
35
- raise nagiosplugin.CheckError(e)
36
-
37
- if stderr:
38
- raise nagiosplugin.CheckError(stderr)
39
-
40
- if stdout:
41
- for line in io.StringIO(stdout.decode('utf-8')):
42
- split_line = line.split()
43
- unit = split_line[0]
44
- active = split_line[2]
45
- if unit not in self.excludes:
46
- yield nagiosplugin.Metric(unit, active, context='systemd')
47
-
48
- yield nagiosplugin.Metric('all', None, context='systemd')
49
-
50
-
51
- class ServiceStatus(nagiosplugin.Resource):
52
- name = 'SYSTEMD'
53
-
54
- def __init__(self, *args, **kwargs):
55
- self.service = kwargs.pop('service')
56
- super(nagiosplugin.Resource, self).__init__(*args, **kwargs)
57
-
58
- def probe(self):
59
- # Execute systemctl is-active and get output
60
- try:
61
- p = subprocess.Popen(['systemctl', 'is-active', self.service],
62
- stderr=subprocess.PIPE,
63
- stdin=subprocess.PIPE,
64
- stdout=subprocess.PIPE)
65
- stdout, stderr = p.communicate()
66
- except OSError as e:
67
- raise nagiosplugin.CheckError(e)
68
-
69
- if stderr:
70
- raise nagiosplugin.CheckError(stderr)
71
- if stdout:
72
- for line in io.StringIO(stdout.decode('utf-8')):
73
- yield nagiosplugin.Metric(self.service, line.strip(),
74
- context='systemd')
75
-
76
-
77
- class SystemdContext(nagiosplugin.Context):
78
-
79
- def __init__(self):
80
- super(SystemdContext, self).__init__('systemd')
81
-
82
- def evaluate(self, metric, resource):
83
- hint = '%s: %s' % (metric.name, metric.value) \
84
- if metric.value else metric.name
85
- if metric.value and metric.value != 'active':
86
- return self.result_cls(nagiosplugin.Critical, metric=metric,
87
- hint=hint)
88
- else:
89
- return self.result_cls(nagiosplugin.Ok, metric=metric, hint=hint)
90
-
91
-
92
- class SystemdSummary(nagiosplugin.Summary):
93
-
94
- def problem(self, results):
95
- return ', '.join(['{0}'.format(result)
96
- for result in results.most_significant])
97
-
98
- def verbose(self, results):
99
- return ['{0}: {1}'.format(result.state, result) for result in results]
100
-
101
-
102
- def main():
103
- parser = argparse.ArgumentParser()
104
- exclusive_group = parser.add_mutually_exclusive_group()
105
-
106
- exclusive_group.add_argument(
107
- '-e', '--exclude',
108
- metavar='UNIT',
109
- action='append',
110
- default=[],
111
- help='Exclude a systemd unit from the checks. This option can be '
112
- 'applied multiple times. For example: -e mnt-data.mount -e '
113
- 'task.service'
114
- )
115
-
116
- exclusive_group.add_argument(
117
- '-s', '--service',
118
- type=str,
119
- dest='service',
120
- help='Name of the Service that is beeing tested'
121
- )
122
-
123
- parser.add_argument(
124
- '-v', '--verbose',
125
- action='count',
126
- default=0,
127
- help='Increase output verbosity (use up to 3 times)'
128
- )
129
-
130
- args = parser.parse_args()
131
-
132
- if args.service is None:
133
- check = nagiosplugin.Check(
134
- SystemdStatus(excludes=args.exclude),
135
- SystemdContext(),
136
- SystemdSummary())
137
- else:
138
- check = nagiosplugin.Check(
139
- ServiceStatus(service=args.service),
140
- SystemdContext(),
141
- SystemdSummary())
142
- check.main(args.verbose)
143
-
144
-
145
- if __name__ == '__main__':
146
- main()
@@ -1,25 +0,0 @@
1
- import unittest
2
- from unittest import mock
3
- import check_systemd
4
-
5
-
6
- def mock_main(argv=['check_systemd.py'], stdout=None, stderr=None):
7
- with mock.patch('sys.exit') as sys_exit, \
8
- mock.patch('check_systemd.subprocess.Popen') as Popen, \
9
- mock.patch('sys.argv', argv):
10
- process = Popen.return_value
11
- process.communicate.return_value = (stdout, stderr)
12
- check_systemd.main()
13
-
14
- return {'sys_exit': sys_exit}
15
-
16
-
17
- class TestMock(unittest.TestCase):
18
-
19
- def test_ok(self):
20
- result = mock_main()
21
- result['sys_exit'].assert_called_with(0)
22
-
23
-
24
- if __name__ == '__main__':
25
- unittest.main()
@@ -1,142 +0,0 @@
1
- import unittest
2
- import os
3
- import subprocess
4
-
5
-
6
- class AddBin(object):
7
- """
8
- :param string bin_path: Path relative to the test folder.
9
- """
10
-
11
- def __init__(self, bin_path):
12
- self.bin_path = bin_path
13
- self.old_path = os.environ['PATH']
14
-
15
- def __enter__(self):
16
- BIN = os.path.abspath(os.path.join(os.path.dirname(__file__),
17
- self.bin_path))
18
- os.environ['PATH'] = BIN + ':' + os.environ['PATH']
19
-
20
- def __exit__(self, exc_type, exc_value, traceback):
21
- os.environ['PATH'] = self.old_path
22
-
23
-
24
- class TestSubprocess(unittest.TestCase):
25
-
26
- def test_ok(self):
27
- with AddBin('bin/ok'):
28
- process = subprocess.run(
29
- ['./check_systemd.py'],
30
- encoding='utf-8',
31
- stdout=subprocess.PIPE,
32
- )
33
- self.assertEqual(process.returncode, 0)
34
- self.assertEqual(process.stdout, 'SYSTEMD OK - all\n')
35
-
36
- def test_ok_verbose(self):
37
- with AddBin('bin/ok'):
38
- process = subprocess.run(
39
- ['./check_systemd.py', '--verbose'],
40
- encoding='utf-8',
41
- stdout=subprocess.PIPE,
42
- )
43
- self.assertEqual(process.returncode, 0)
44
- self.assertEqual(process.stdout, 'SYSTEMD OK - all\nok: all\n')
45
-
46
- def test_failure(self):
47
- with AddBin('bin/failure'):
48
- process = subprocess.run(
49
- ['./check_systemd.py'],
50
- encoding='utf-8',
51
- stdout=subprocess.PIPE,
52
- )
53
- self.assertEqual(process.returncode, 2)
54
- self.assertEqual(process.stdout,
55
- 'SYSTEMD CRITICAL - test.service: failed\n')
56
-
57
- def test_failure_verbose(self):
58
- with AddBin('bin/failure'):
59
- process = subprocess.run(
60
- ['./check_systemd.py', '-v'],
61
- encoding='utf-8',
62
- stdout=subprocess.PIPE,
63
- )
64
- self.assertEqual(process.returncode, 2)
65
- self.assertEqual(
66
- process.stdout,
67
- 'SYSTEMD CRITICAL - test.service: failed\n'
68
- 'critical: test.service: failed\n'
69
- 'ok: all\n'
70
- )
71
-
72
- def test_failure_multiple(self):
73
- with AddBin('bin/multiple_failure'):
74
- process = subprocess.run(
75
- ['./check_systemd.py'],
76
- encoding='utf-8',
77
- stdout=subprocess.PIPE,
78
- )
79
- self.assertEqual(process.returncode, 2)
80
- self.assertEqual(
81
- process.stdout,
82
- 'SYSTEMD CRITICAL - test1.service: failed, '
83
- 'test2.service: failed\n'
84
- )
85
-
86
- def test_failure_multiple_verbose(self):
87
- with AddBin('bin/multiple_failure'):
88
- process = subprocess.run(
89
- ['./check_systemd.py', '--verbose'],
90
- encoding='utf-8',
91
- stdout=subprocess.PIPE,
92
- )
93
- self.assertEqual(process.returncode, 2)
94
- self.assertEqual(
95
- process.stdout,
96
- 'SYSTEMD CRITICAL - test1.service: failed, '
97
- 'test2.service: failed\n'
98
- 'critical: test1.service: failed\n'
99
- 'critical: test2.service: failed\n'
100
- 'ok: all\n'
101
- )
102
-
103
- def test_exclusive_group(self):
104
- process = subprocess.run(
105
- ['./check_systemd.py', '-s', 'test1.service', '-e',
106
- 'test2.service'],
107
- encoding='utf-8',
108
- stderr=subprocess.PIPE
109
- )
110
- self.assertEqual(process.returncode, 2)
111
- self.assertIn(
112
- 'error: argument -e/--exclude: not allowed with argument '
113
- '-s/--service',
114
- process.stderr,
115
- )
116
-
117
- def test_option_exclude_known_service(self):
118
- with AddBin('bin/failure'):
119
- process = subprocess.run(
120
- ['./check_systemd.py', '-e', 'test.service'],
121
- encoding='utf-8',
122
- stdout=subprocess.PIPE
123
- )
124
- self.assertEqual(process.returncode, 0)
125
- self.assertEqual(process.stdout, 'SYSTEMD OK - all\n')
126
-
127
- def test_option_exclude_unknown_service(self):
128
- with AddBin('bin/failure'):
129
- process = subprocess.run(
130
- ['./check_systemd.py', '-e', 'testX.service'],
131
- encoding='utf-8',
132
- stdout=subprocess.PIPE
133
- )
134
- self.assertEqual(process.returncode, 2)
135
- self.assertEqual(
136
- process.stdout,
137
- 'SYSTEMD CRITICAL - test.service: failed\n'
138
- )
139
-
140
-
141
- if __name__ == '__main__':
142
- unittest.main()
File without changes
File without changes