Merge ~nkoltsov/charm-nrpe:master into charm-nrpe:master

Proposed by Nikita Koltsov
Status: Merged
Approved by: Andrea Ieri
Approved revision: 9747cf9dda16539c075b8a0e15dece93c2254e51
Merged at revision: e8acb6598c65094211dc23c672ce713acbb699f3
Proposed branch: ~nkoltsov/charm-nrpe:master
Merge into: charm-nrpe:master
Diff against target: 220 lines (+80/-70)
2 files modified
hooks/nrpe_helpers.py (+24/-20)
tests/unit/test_nrpe_helpers.py (+56/-50)
Reviewer Review Type Date Requested Status
Andrea Ieri Approve
Eric Chen Needs Information
🤖 prod-jenkaas-bootstack (community) continuous-integration Approve
Robert Gildein Approve
Review via email: mp+450235@code.launchpad.net

Commit message

Add support for nested children sections in lsblk

Modified check_space definitions to support nested children sections
in lsblk output, as well as fixing Jammy support

Fix: LP#1986654, LP#2033521

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
🤖 prod-jenkaas-bootstack (prod-jenkaas-bootstack) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Gildein (rgildein) wrote :

Overall it looks good to me.

Revision history for this message
🤖 prod-jenkaas-bootstack (prod-jenkaas-bootstack) wrote :
review: Approve (continuous-integration)
Revision history for this message
🤖 prod-jenkaas-bootstack (prod-jenkaas-bootstack) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andrea Ieri (aieri) wrote :

I really like your recursive solution, it's much cleaner than the previous one!
I have added a couple of improvement suggestions, but +1 overall

review: Needs Fixing
Revision history for this message
Eric Chen (eric-chen) wrote :

Pleae check my inline comment. thanks

review: Needs Fixing
Revision history for this message
Nikita Koltsov (nkoltsov) wrote :

Ack, will fix all comments soon

Revision history for this message
🤖 prod-jenkaas-bootstack (prod-jenkaas-bootstack) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Eric Chen (eric-chen) wrote :

It's possible to filter the list in opposite without changing the implementation.

https://stackoverflow.com/questions/33989155/is-there-a-filter-opposite-builtin
negative = filter(lambda v: not some_test(v), values)

Therefore, I still prefer is_kubernetes_pv is better than is_not_kubernetes_pv. Sorry that I really don't like a function with opposite logic. When you are tired, it will be a place to push you into hell.

Need 3rd opinion. thanks!

Other than that, the code LGTM.

Revision history for this message
Robert Gildein (rgildein) wrote :

To me the whole `is_kubernetes_pv(mountpoint)` is useless, because I would
rather see usage of set comprehension instead of filter. I believe that filter
should be dropped from Python.

But those are just preferences :).

LGTM

review: Approve
Revision history for this message
🤖 prod-jenkaas-bootstack (prod-jenkaas-bootstack) wrote :
review: Approve (continuous-integration)
Revision history for this message
Eric Chen (eric-chen) :
review: Needs Information
Revision history for this message
Andrea Ieri (aieri) wrote :

lgtm

@eric-chen: there's also filterfalse from itertools if you want to filter() on a false condition

review: Approve
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision e8acb6598c65094211dc23c672ce713acbb699f3

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/hooks/nrpe_helpers.py b/hooks/nrpe_helpers.py
2index c529ca7..57963a8 100644
3--- a/hooks/nrpe_helpers.py
4+++ b/hooks/nrpe_helpers.py
5@@ -815,9 +815,25 @@ def is_valid_partition(device):
6 return True
7
8
9-def is_kubernetes_pv(mountpoint):
10+def is_not_kubernetes_pv(mountpoint):
11 """Check if a mountpoint is Kubernetes persistent volume."""
12- return mountpoint.startswith("/var/lib/kubelet/pods")
13+ return not mountpoint.startswith("/var/lib/kubelet/pods")
14+
15+
16+def process_block_devices(devices):
17+ """Recursively process all sections in lsblk output."""
18+ partitions_to_check = set()
19+
20+ for dev in devices:
21+ # Jammy returns a list of "mountpoints" instead of a single value
22+ # in the key "mountpoint"
23+ mountpoints = dev.get("mountpoints", []) or [dev.get("mountpoint")]
24+ if is_valid_partition(dev):
25+ partitions_to_check.update(mountpoints)
26+ children = dev.get("children", [])
27+ partitions_to_check.update(process_block_devices(children))
28+
29+ return partitions_to_check
30
31
32 def get_partitions_to_check():
33@@ -825,27 +841,15 @@ def get_partitions_to_check():
34 lsblk_cmd = "lsblk -J".split()
35 lsblk_output = subprocess.check_output(lsblk_cmd).decode("UTF-8")
36 block_devices = json.loads(lsblk_output).get("blockdevices", [])
37- partitions_to_check = set()
38
39- for dev in block_devices:
40- if not is_valid_partition(dev):
41- continue
42- mnt = dev.get("mountpoint", "")
43- if mnt and not is_kubernetes_pv(mnt):
44- partitions_to_check.add(mnt)
45- for child in dev.get("children", []):
46- if not is_valid_partition(child):
47- continue
48- # Jammy returns a list of "mountpoints" instead of a single value
49- # in the key "mountpoint"
50- mountpoints = child.get("mountpoints", []) or [child.get("mountpoint")]
51- for mnt in filter(bool, mountpoints):
52- if not is_kubernetes_pv(mnt):
53- partitions_to_check.add(mnt)
54+ partitions_to_check = process_block_devices(block_devices)
55+
56+ skipped_partitions = {"[SWAP]", "/boot/efi", None}
57+ partitions_to_check = partitions_to_check - skipped_partitions
58
59- skipped_partitions = {"[SWAP]", "/boot/efi"}
60+ partitions_to_check = set(filter(is_not_kubernetes_pv, partitions_to_check))
61
62- return partitions_to_check - skipped_partitions
63+ return partitions_to_check
64
65
66 def match_cidr_to_ifaces(cidr):
67diff --git a/tests/unit/test_nrpe_helpers.py b/tests/unit/test_nrpe_helpers.py
68index c7e6cd0..7af52aa 100644
69--- a/tests/unit/test_nrpe_helpers.py
70+++ b/tests/unit/test_nrpe_helpers.py
71@@ -218,7 +218,7 @@ class TestDiskSpaceCheck(unittest.TestCase):
72 "mountpoint": "/boot/efi"
73 },
74 {
75- "name": "nvme0n1p4",
76+ "name": "nvme0n1p2",
77 "maj:min": "259:4",
78 "rm": false,
79 "size": "100G",
80@@ -227,7 +227,7 @@ class TestDiskSpaceCheck(unittest.TestCase):
81 "mountpoint": "/"
82 },
83 {
84- "name": "nvme0n1p5",
85+ "name": "nvme0n1p3",
86 "maj:min": "259:5",
87 "rm": false,
88 "size": "4G",
89@@ -236,58 +236,57 @@ class TestDiskSpaceCheck(unittest.TestCase):
90 "mountpoint": "[SWAP]"
91 },
92 {
93- "name": "nvme0n1p6",
94+ "name": "nvme0n1p4",
95 "maj:min": "259:6",
96 "rm": false,
97 "size": "1000M",
98 "ro": false,
99 "type": "part",
100 "mountpoint": "/srv/instances"
101+ },
102+ {
103+ "name": "nvme0n1p5",
104+ "maj:min": "259:6",
105+ "rm": false,
106+ "size": "500G",
107+ "ro": false,
108+ "type": "part",
109+ "mountpoints": [
110+ null
111+ ],
112+ "children": [
113+ {
114+ "name": "vg0-var--log--audit",
115+ "maj:min": "253:1",
116+ "rm": "0",
117+ "size": "51.2G",
118+ "ro": "0",
119+ "type": "lvm",
120+ "mountpoint": "/var/log/audit"
121+ },
122+ {
123+ "name": "vg0-var--log",
124+ "maj:min": "253:3",
125+ "rm": "0",
126+ "size": "93.1G",
127+ "ro": "0",
128+ "type": "lvm",
129+ "mountpoint": "/var/log"
130+ }
131+ ]
132 }
133 ]
134 },
135 {
136- "name": "vda",
137- "maj:min": "252:0",
138- "rm": false,
139- "size": "20G",
140- "ro": false,
141- "type": "disk",
142- "mountpoints": [
143- null
144- ],
145- "children": [
146- {
147- "name": "vda1",
148- "maj:min": "252:1",
149- "rm": false,
150- "size": "19.9G",
151- "ro": false,
152- "type": "part",
153- "mountpoints": [
154- "/srv/jammy"
155- ]
156- },{
157- "name": "vda14",
158- "maj:min": "252:14",
159- "rm": false,
160- "size": "4M",
161- "ro": false,
162- "type": "part",
163- "mountpoints": [
164- null
165- ]
166- }
167- ]
168- },
169- {
170- "name":"vdb",
171- "maj:min":"252:16",
172- "rm":false,
173- "size":"1G",
174- "ro":false,
175- "type":"disk",
176- "mountpoint": "/var/lib/kubelet/pods/../k..s.io~csi/pvc../mount"
177+ "name":"vdb",
178+ "maj:min":"252:16",
179+ "rm":false,
180+ "size":"1G",
181+ "ro":false,
182+ "type":"disk",
183+ "mountpoints": [
184+ "/var/lib/kubelet/pods/../k..s.io~csi/pvc../mount"
185+ ]
186 }
187 ]
188 }"""
189@@ -295,18 +294,25 @@ class TestDiskSpaceCheck(unittest.TestCase):
190 @mock.patch("subprocess.check_output", return_value=lsblk_output)
191 def test_get_partitions_to_check(self, lock_lsblk_output):
192 """Test the list of partitions to check."""
193- result = nrpe_helpers.get_partitions_to_check()
194+ partitions = nrpe_helpers.get_partitions_to_check()
195 params = [
196- ("SWAP", False),
197+ ("/snap/charm/602", False),
198 ("/boot/efi", False),
199 ("/", True),
200+ ("SWAP", False),
201 ("/srv/instances", True),
202- ("/srv/jammy", True),
203+ ("/var/log/audit", True),
204+ ("/var/log", True),
205 ("/var/lib/kubelet/pods/../k..s.io~csi/pvc../mount", False),
206 ]
207- for p1, p2 in params:
208- with self.subTest(msg="Validate partition filtering", p1=p1, p2=p2):
209- self.assertEqual(p1 in result, p2)
210+ for partition, expected in params:
211+ with self.subTest(
212+ msg="Validate partition filtering", p1=partition, p2=expected
213+ ):
214+ if expected:
215+ self.assertIn(partition, partitions)
216+ else:
217+ self.assertNotIn(partition, partitions)
218
219
220 def load_default_config():

Subscribers

People subscribed via source and target branches

to all changes: