Merge ~xavpaice/charm-nrpe:bug/1824882 into ~nrpe-charmers/charm-nrpe:master

Proposed by Xav Paice
Status: Merged
Approved by: Jeremy Lounder
Approved revision: 16929cb933ed9eb35282f0238a251478610ebeb8
Merge reported by: Xav Paice
Merged at revision: 16929cb933ed9eb35282f0238a251478610ebeb8
Proposed branch: ~xavpaice/charm-nrpe:bug/1824882
Merge into: ~nrpe-charmers/charm-nrpe:master
Diff against target: 140 lines (+103/-1)
4 files modified
config.yaml (+9/-0)
files/plugins/check_ro_filesystem.py (+75/-0)
hooks/nrpe_helpers.py (+17/-0)
hooks/nrpe_utils.py (+2/-1)
Reviewer Review Type Date Requested Status
Jeremy Lounder (community) Approve
Alvaro Uria (community) Needs Fixing
Wouter van Bommel (community) Approve
Review via email: mp+380338@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Wouter van Bommel (woutervb) wrote :

Please see the inline comment(s)

review: Needs Fixing
Revision history for this message
Xav Paice (xavpaice) wrote :

updated; added python3 to the package list (although it's there on the current Trusty cloud image), added some validation on the inputs, and fixed up the syntax errors (forgot to push that change).

Revision history for this message
Wouter van Bommel (woutervb) wrote :

lgtm

review: Approve
Revision history for this message
Alvaro Uria (aluria) wrote :

I've suggested a few changes for readability, completeness (verify all read-only fs that are not excluded instead of returning the first one found), and a doubt about the input validation (match substrings could induce to errors, should we look for "start of string"?).

review: Needs Fixing
Revision history for this message
Xav Paice (xavpaice) wrote :

Many thanks for the detailed review! Have updated the commit with responses to the feedback.

Revision history for this message
Jeremy Lounder (jldev) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/config.yaml b/config.yaml
2index 44a6680..2c9eefd 100644
3--- a/config.yaml
4+++ b/config.yaml
5@@ -179,3 +179,12 @@ options:
6 dmesg history length to check for xfs errors, in minutes
7 .
8 Defaults to disabled, set the time to enable.
9+ ro_filesystem_excludes:
10+ default: "/snap/,/sys/fs/cgroup"
11+ type: string
12+ description: |
13+ Comma separated list of mount points to exclude from checks for readonly filesystem.
14+ Can be a substring rather than the entire mount point, e.g. /sys will match all filesystems
15+ beginning with the string /sys.
16+ The check is disabled on all LXD units, and also for non-container units if this parameter is
17+ set to ''.
18diff --git a/files/plugins/check_ro_filesystem.py b/files/plugins/check_ro_filesystem.py
19new file mode 100755
20index 0000000..c19ae31
21--- /dev/null
22+++ b/files/plugins/check_ro_filesystem.py
23@@ -0,0 +1,75 @@
24+#!/usr/bin/env python3
25+# -*- coding: us-ascii -*-
26+
27+# Copyright (C) 2020 Canonical
28+# All rights reserved
29+#
30+
31+import argparse
32+
33+from nagios_plugin3 import (
34+ CriticalError,
35+ UnknownError,
36+ try_check,
37+)
38+
39+EXCLUDE = {"/snap/", "/sys/fs/cgroup"}
40+
41+
42+def check_ro_filesystem(excludes=""):
43+ """Loops /proc/mounts looking for readonly mounts.
44+
45+ :param excludes: list of mount points to exclude from checks
46+ """
47+ # read /proc/mounts, add each line to a list
48+ try:
49+ with open("/proc/mounts") as fd:
50+ mounts = [mount.strip() for mount in fd.readlines()]
51+ except Exception as e:
52+ raise UnknownError("UNKNOWN: unable to read mounts with {}".format(e))
53+
54+ exclude_mounts = EXCLUDE
55+ ro_filesystems = []
56+ # if excludes != "" and excludes is not None:
57+ if excludes:
58+ try:
59+ exclude_mounts = EXCLUDE.union(set(excludes.split(",")))
60+ except Exception as e:
61+ msg = "UNKNOWN: unable to read list of mounts to exclude {}".format(e)
62+ raise UnknownError(msg)
63+ for mount in mounts:
64+ # for each line in the list, split by space to a new list
65+ split_mount = mount.split()
66+ # if mount[1] matches EXCLUDE_FS then next, else check it's not readonly
67+ if not any(split_mount[1].startswith(exclusion.strip()) for exclusion in exclude_mounts):
68+ mount_options = split_mount[3].split(",")
69+ if "ro" in mount_options:
70+ ro_filesystems.append(split_mount[1])
71+ if len(ro_filesystems) > 0:
72+ msg = "CRITICAL: filesystem(s) {} readonly".format(','.join(ro_filesystems))
73+ raise CriticalError(msg)
74+
75+ print("OK: no readonly filesystems found")
76+
77+
78+def parse_args():
79+ parser = argparse.ArgumentParser(description="Check for readonly filesystems")
80+ parser.add_argument(
81+ "--exclude",
82+ "-e",
83+ type=str,
84+ help="""Comma separated list of mount points to exclude from checks for readonly filesystem.
85+ Can be just a substring of the whole mount point.""",
86+ default='',
87+ )
88+ args = parser.parse_args()
89+ return args
90+
91+
92+def main():
93+ args = parse_args()
94+ try_check(check_ro_filesystem, args.exclude)
95+
96+
97+if __name__ == "__main__":
98+ main()
99diff --git a/hooks/nrpe_helpers.py b/hooks/nrpe_helpers.py
100index 63c7ba4..fac74ed 100644
101--- a/hooks/nrpe_helpers.py
102+++ b/hooks/nrpe_helpers.py
103@@ -437,6 +437,23 @@ class SubordinateCheckDefinitions(dict):
104 'cmd_params': '-w 60 -c 80', # Specify params here to enable the check, not required otherwise.
105 }
106 checks.append(arp_check)
107+ ro_filesystem_excludes = hookenv.config('ro_filesystem_excludes')
108+ if ro_filesystem_excludes == '':
109+ # specify cmd_params = '' to disable/remove the check from nrpe
110+ check_ro_filesystem = {
111+ 'description': 'Readonly filesystems',
112+ 'cmd_name': 'check_ro_filesystem',
113+ 'cmd_exec': os.path.join(local_plugin_dir, 'check_ro_filesystem.py'),
114+ 'cmd_params': '',
115+ }
116+ else:
117+ check_ro_filesystem = {
118+ 'description': 'Readonly filesystems',
119+ 'cmd_name': 'check_ro_filesystem',
120+ 'cmd_exec': os.path.join(local_plugin_dir, 'check_ro_filesystem.py'),
121+ 'cmd_params': '-e {}'.format(hookenv.config('ro_filesystem_excludes')),
122+ }
123+ checks.append(check_ro_filesystem)
124
125 if hookenv.config('lacp_bonds').strip():
126 for bond_iface in hookenv.config('lacp_bonds').strip().split():
127diff --git a/hooks/nrpe_utils.py b/hooks/nrpe_utils.py
128index 6e2e9ab..7d294d7 100644
129--- a/hooks/nrpe_utils.py
130+++ b/hooks/nrpe_utils.py
131@@ -31,7 +31,8 @@ def determine_packages():
132 pkgs = [
133 'nagios-nrpe-server',
134 'nagios-plugins-basic',
135- 'nagios-plugins-standard'
136+ 'nagios-plugins-standard',
137+ 'python3',
138 ]
139 if hookenv.config('export_nagios_definitions'):
140 pkgs.append('rsync')

Subscribers

People subscribed via source and target branches