Cleanup config.nodes_of
[check_mk.git] / checks / mem
blob2199dc51c5eace072a7b4f320ef428c56004072c
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 # .--mem.linux-----------------------------------------------------------.
28 # | _ _ |
29 # | _ __ ___ ___ _ __ ___ | (_)_ __ _ ___ __ |
30 # | | '_ ` _ \ / _ \ '_ ` _ \ | | | '_ \| | | \ \/ / |
31 # | | | | | | | __/ | | | | |_| | | | | | |_| |> < |
32 # | |_| |_| |_|\___|_| |_| |_(_)_|_|_| |_|\__,_/_/\_\ |
33 # | |
34 # +----------------------------------------------------------------------+
35 # | Specialized memory check for Linux that takes into account |
36 # | all of its specific information in /proc/meminfo. |
37 # '----------------------------------------------------------------------'
39 # BEWARE: half of the information and blob entries about /proc/meminfo
40 # in the internet is unprecise or even totally wrong!
42 # <<<mem>>>
43 # MemTotal: 24707592 kB
44 # MemFree: 441224 kB
45 # Buffers: 320672 kB
46 # Cached: 19981008 kB
47 # SwapCached: 6172 kB
48 # Active: 8756876 kB
49 # Inactive: 13360444 kB
50 # Active(anon): 1481236 kB
51 # Inactive(anon): 371260 kB
52 # Active(file): 7275640 kB
53 # Inactive(file): 12989184 kB
54 # Unevictable: 964808 kB
55 # Mlocked: 964808 kB
56 # SwapTotal: 16777212 kB
57 # SwapFree: 16703328 kB
58 # Dirty: 4408124 kB
59 # Writeback: 38020 kB
60 # AnonPages: 2774444 kB
61 # Mapped: 69456 kB
62 # Shmem: 33772 kB
63 # Slab: 861028 kB
64 # SReclaimable: 756236 kB
65 # SUnreclaim: 104792 kB
66 # KernelStack: 4176 kB
67 # PageTables: 15892 kB
68 # NFS_Unstable: 0 kB
69 # Bounce: 0 kB
70 # WritebackTmp: 0 kB
71 # CommitLimit: 39014044 kB
72 # Committed_AS: 3539808 kB
73 # VmallocTotal: 34359738367 kB
74 # VmallocUsed: 347904 kB
75 # VmallocChunk: 34346795572 kB
76 # HardwareCorrupted: 0 kB
77 # AnonHugePages: 0 kB
78 # HugePages_Total: 0
79 # HugePages_Free: 0
80 # HugePages_Rsvd: 0
81 # HugePages_Surp: 0
82 # Hugepagesize: 2048 kB
83 # DirectMap4k: 268288 kB
84 # DirectMap2M: 8112128 kB
85 # DirectMap1G: 16777216 kB
87 # This is from an earlier kernel (CentOS 5.5). Some entries
88 # are missing here:
89 # <<<mem>>>
90 # MemTotal: 377176 kB
91 # MemFree: 60112 kB
92 # Buffers: 93864 kB
93 # Cached: 116364 kB
94 # SwapCached: 0 kB
95 # Active: 169140 kB
96 # Inactive: 84144 kB
97 # HighTotal: 0 kB
98 # HighFree: 0 kB
99 # LowTotal: 377176 kB
100 # LowFree: 60112 kB
101 # SwapTotal: 2064376 kB
102 # SwapFree: 2062756 kB
103 # Dirty: 172 kB
104 # Writeback: 0 kB
105 # AnonPages: 43080 kB
106 # Mapped: 8352 kB
107 # Slab: 45892 kB
108 # PageTables: 3208 kB
109 # NFS_Unstable: 0 kB
110 # Bounce: 0 kB
111 # CommitLimit: 2252964 kB
112 # Committed_AS: 125968 kB
113 # VmallocTotal: 34359738367 kB
114 # VmallocUsed: 18112 kB
115 # VmallocChunk: 34359719415 kB
116 # HugePages_Total: 0
117 # HugePages_Free: 0
118 # HugePages_Rsvd: 0
119 # Hugepagesize: 2048 kB
121 # Yet earlier kernel (SLES 9):
122 # <<<mem>>>
123 # MemTotal: 6224268 kB
124 # MemFree: 2913660 kB
125 # Buffers: 84712 kB
126 # Cached: 1779052 kB
127 # SwapCached: 0 kB
128 # Active: 1931528 kB
129 # Inactive: 1276156 kB
130 # HighTotal: 5373824 kB
131 # HighFree: 2233984 kB
132 # LowTotal: 850444 kB
133 # LowFree: 679676 kB
134 # SwapTotal: 1052280 kB
135 # SwapFree: 1052280 kB
136 # Dirty: 55680 kB
137 # Writeback: 0 kB
138 # Mapped: 1469268 kB
139 # Slab: 71724 kB
140 # Committed_AS: 2758332 kB
141 # PageTables: 7672 kB
142 # VmallocTotal: 112632 kB
143 # VmallocUsed: 9324 kB
144 # VmallocChunk: 103180 kB
145 # HugePages_Total: 0
146 # HugePages_Free: 0
147 # Hugepagesize: 2048 kB
149 factory_settings["mem_linux_default_levels"] = {
150 "levels_virtual": ("perc_used", (80.0, 90.0)),
151 "levels_total": ("perc_used", (120.0, 150.0)),
152 "levels_shm": ("perc_used", (20.0, 30.0)),
153 "levels_pagetables": ("perc_used", (8.0, 16.0)),
154 "levels_committed": ("perc_used", (100.0, 150.0)),
155 "levels_commitlimit": ("perc_free", (20.0, 10.0)),
156 "levels_vmalloc": ("abs_free", (50 * 1024 * 1024, 30 * 1024 * 1024)),
157 "levels_hardwarecorrupted": ("abs_used", (1, 1)),
161 def is_linux_meminfo(meminfo):
162 return "PageTables" in meminfo and "Writeback" in meminfo and "Committed_AS" in meminfo
165 def inventory_mem_linux(info):
166 meminfo = parse_proc_meminfo_bytes(info)
167 if is_linux_meminfo(meminfo):
168 return [(None, {})]
171 def check_mem_levels(title,
172 used,
173 total,
174 levels,
175 of_what=None,
176 of_value=None,
177 show_percentage=False,
178 show_free=False):
179 if of_value is None:
180 of_value = total # Reference for percentage levels
181 state = 0
182 if of_what:
183 if show_free:
184 value = total - used
185 else:
186 value = used
187 infotext = "%s: %s" % (title, get_bytes_human_readable(value))
188 else:
189 infotext = "%s used: %s of %s" % (title, get_bytes_human_readable(used),
190 get_bytes_human_readable(total))
192 perc_shown = False
193 if levels and levels != "ignore":
194 how = levels[0]
195 if how == "predictive":
196 return 3, "Predictive levels for memory check not yet implemented"
197 # TODO: Hier brauchen wir den Namen der RRD-variable! Das klappt aber
198 # nicht, wenn hier Werte zusammengerechnet wurden. Wir sollten die
199 # Predictive Levels nur für ausgewählte Werte zulassen.
200 # return check_levels(used, levels[1], unit = "GB")
202 warn, crit = levels[1]
203 if how.startswith("perc_"):
204 perc_used = 100.0 * float(used) / of_value
205 perc_free = 100 - perc_used
206 if how == "perc_used":
207 if of_what:
208 t = " of " + of_what
209 else:
210 t = ""
211 levels_text = " (%.1f%%%s, " % (perc_used, t)
212 if perc_used >= crit:
213 state = 2
214 elif perc_used >= warn:
215 state = 1
217 elif how == "perc_free":
218 if of_what:
219 t = "of " + of_what
220 else:
221 t = "free"
222 levels_text = " (%.1f%% %s, " % (perc_free, t)
223 if perc_free < crit:
224 state = 2
225 elif perc_free < warn:
226 state = 1
228 if state:
229 perc_shown = True
230 infotext += levels_text + "warn/crit at %.1f%%/%.1f%%)" % (warn, crit)
232 else:
233 if how == "abs_used":
234 if used >= crit:
235 state = 2
236 elif used >= warn:
237 state = 1
238 else:
239 free = total - used
240 if free < crit:
241 state = 2
242 elif free < warn:
243 state = 1
245 if state:
246 infotext += " (warn/crit at %s/%s)" % (get_bytes_human_readable(warn),
247 get_bytes_human_readable(crit))
249 if not perc_shown and show_percentage:
250 infotext += " (%.1f%%)" % (100.0 * float(used) / of_value)
251 return state, infotext
254 def check_mem_linux(_no_item, params, info):
255 meminfo = parse_proc_meminfo_bytes(info)
256 if not meminfo:
257 yield 3, "Data not found in agent output"
258 return
260 # SReclaimable is not available for older kernels
261 if "SReclaimable" not in meminfo:
262 meminfo["SReclaimable"] = 0
263 meminfo["SUnreclaim"] = meminfo["Slab"]
265 # Compute memory used by caches, that can be considered "free"
266 meminfo["Caches"] = meminfo["Cached"] + meminfo["Buffers"] \
267 + meminfo["SwapCached"] + meminfo["SReclaimable"]
269 # RAM
270 meminfo["MemUsed"] = meminfo["MemTotal"] - meminfo["MemFree"] - meminfo["Caches"]
271 yield check_mem_levels(
272 "RAM",
273 meminfo["MemUsed"],
274 meminfo["MemTotal"],
275 params.get("levels_ram"),
276 show_percentage=not meminfo["SwapTotal"])
278 # Swap - but only if available
279 meminfo["SwapUsed"] = meminfo["SwapTotal"] - meminfo["SwapFree"]
280 if meminfo["SwapTotal"]:
281 yield check_mem_levels("Swap", meminfo["SwapUsed"], meminfo["SwapTotal"],
282 params.get("levels_swap"))
284 # Total virtual memory
285 meminfo["TotalTotal"] = meminfo["MemTotal"] + meminfo["SwapTotal"]
286 meminfo["TotalUsed"] = meminfo["MemUsed"] + meminfo["SwapUsed"]
287 r = check_mem_levels(
288 "Total virtual memory",
289 meminfo["TotalUsed"],
290 meminfo["TotalTotal"],
291 params.get("levels_virtual"),
292 show_percentage=True)
293 if r[0] or meminfo["SwapTotal"]:
294 yield r # only display if there is swap or status is non-OK
296 # Total memory / in relation to RAM
297 r = check_mem_levels(
298 "RAM + Swap",
299 meminfo["TotalUsed"],
300 meminfo["TotalTotal"],
301 params.get("levels_total"),
302 of_what="RAM",
303 of_value=meminfo["MemTotal"])
304 if r[0]:
305 yield r # only display if non-OK
307 # Shared memory
308 if "Shmem" in meminfo:
309 r = check_mem_levels(
310 "Shared memory",
311 meminfo["Shmem"],
312 meminfo["MemTotal"],
313 params.get("levels_shm"),
314 of_what="RAM")
315 if r[0]:
316 yield r # only display if non-OK
318 # Page tables
319 r = check_mem_levels(
320 "Page tables",
321 meminfo["PageTables"],
322 meminfo["MemTotal"],
323 params.get("levels_pagetables"),
324 of_what="RAM")
325 if r[0]:
326 yield r # only display if non-OK
328 # Disk Writeback
329 meminfo["Pending"] = \
330 meminfo["Dirty"] \
331 + meminfo.get("Writeback", 0) \
332 + meminfo.get("NFS_Unstable", 0) \
333 + meminfo.get("Bounce", 0) \
334 + meminfo.get("WritebackTmp", 0)
336 r = check_mem_levels(
337 "Disk Writeback",
338 meminfo["Pending"],
339 meminfo["MemTotal"],
340 params.get("levels_writeback"),
341 of_what="RAM")
342 if r[0]:
343 yield r # only display if non-OK
345 # Committed memory
346 r = check_mem_levels(
347 "Committed",
348 meminfo["Committed_AS"],
349 meminfo["TotalTotal"],
350 params.get("levels_committed"),
351 of_what="RAM + Swap")
352 if r[0]:
353 yield r # only display if non-OK
355 # Commit limit
356 if "CommitLimit" in meminfo:
357 r = check_mem_levels(
358 "Commit Limit",
359 meminfo["TotalTotal"] - meminfo["CommitLimit"],
360 meminfo["TotalTotal"],
361 params.get("levels_commitlimit"),
362 of_what="RAM + Swap")
363 if r[0]:
364 yield r # only display if non-OK
366 # Available Memory
367 if "MemAvailable" in meminfo:
368 r = check_mem_levels(
369 "RAM available",
370 meminfo["MemTotal"] - meminfo["MemAvailable"],
371 meminfo["MemTotal"],
372 params.get("levels_available"),
373 of_what="RAM",
374 show_free=True)
375 if r[0]:
376 yield r # only display if non-OK
378 # VMalloc,
379 # newer kernel version report wrong data,
380 # i.d. both VmallocUsed and Chunk equal zero
381 if not (meminfo["VmallocUsed"] == 0 and meminfo["VmallocChunk"] == 0):
382 r = check_mem_levels(
383 "Largest Free VMalloc Chunk",
384 meminfo["VmallocTotal"] - meminfo["VmallocChunk"],
385 meminfo["VmallocTotal"],
386 params.get("levels_vmalloc"),
387 of_what="VMalloc Area",
388 show_free=True)
389 if r[0]:
390 yield r # only display if non-OK
392 # HardwareCorrupted
393 if "HardwareCorrupted" in meminfo:
394 r = check_mem_levels(
395 "Hardware Corrupted",
396 meminfo["HardwareCorrupted"],
397 meminfo["MemTotal"],
398 params.get("levels_hardwarecorrupted"),
399 of_what="RAM")
400 if r[0]:
401 yield r # only display if non-OK
403 # Now send performance data. We simply output *all* fields of meminfo
404 # except for a few really useless values
405 perfdata = []
406 items = meminfo.items()
407 items.sort()
408 for name, value in items:
409 if name.startswith("DirectMap"):
410 continue
411 if name.startswith(
412 "Vmalloc") and meminfo["VmallocTotal"] > 2**40: # useless on 64 Bit system
413 continue
414 if name.startswith("Huge"):
415 if meminfo["HugePages_Total"] == 0: # omit useless data
416 continue
417 if name == "Hugepagesize":
418 continue # not needed
419 value = value * meminfo["Hugepagesize"] # convert number to actual memory size
420 perfdata.append((camelcase_to_underscored(name.replace("(", "_").replace(")", "")), value))
421 yield 0, "", perfdata
424 # ThisIsACamel -> this_is_a_camel
425 def camelcase_to_underscored(name):
426 previous_lower = False
427 previous_underscore = True
428 result = ""
429 for c in name:
430 if c.isupper():
431 if previous_lower and not previous_underscore:
432 result += "_"
433 previous_lower = False
434 previous_underscore = False
435 result += c.lower()
436 elif c == "_":
437 previous_lower = False
438 previous_underscore = True
439 result += c
440 else:
441 previous_lower = True
442 previous_underscore = False
443 result += c
444 return result
447 check_info["mem.linux"] = {
448 'inventory_function': inventory_mem_linux,
449 'check_function': check_mem_linux,
450 'service_description': 'Memory',
451 'default_levels_variable': 'mem_linux_default_levels',
452 'has_perfdata': True,
453 'group': 'memory_linux',
454 "handle_real_time_checks": True,
455 'includes': ['mem.include'],
459 # .--mem.used------------------------------------------------------------.
460 # | _ |
461 # | _ __ ___ ___ _ __ ___ _ _ ___ ___ __| | |
462 # | | '_ ` _ \ / _ \ '_ ` _ \ | | | / __|/ _ \/ _` | |
463 # | | | | | | | __/ | | | | || |_| \__ \ __/ (_| | |
464 # | |_| |_| |_|\___|_| |_| |_(_)__,_|___/\___|\__,_| |
465 # | |
466 # +----------------------------------------------------------------------+
467 # | Memory check that takes into account the swap space. This check is |
468 # | used for unixoide operating systems. |
469 # '----------------------------------------------------------------------'
472 def parse_proc_meminfo(info):
473 parsed = {}
474 for line in info:
475 try:
476 parsed[line[0][:-1]] = int(line[1])
477 except (ValueError, IndexError) as _exc:
478 pass
479 return parsed
482 # The following variable is obsolete. It is kept here so that Check_MK
483 # won't fail if it's found in main.mk
484 mem_extended_perfdata = None
487 def inventory_mem_used(info):
488 meminfo = parse_proc_meminfo(info)
489 if "MemTotal" in meminfo \
490 and "PageTotal" not in meminfo \
491 and not is_linux_meminfo(meminfo): # handled by more modern check
492 return [(None, {})]
495 def check_mem_used(_no_item, params, info):
496 meminfo = parse_proc_meminfo(info)
497 return check_memory(params, meminfo)
500 check_info['mem.used'] = {
501 "check_function": check_mem_used,
502 "inventory_function": inventory_mem_used,
503 "service_description": "Memory used",
504 "has_perfdata": True,
505 "group": "memory",
506 "default_levels_variable": "memory_default_levels",
507 "includes": ["mem.include"],
508 "handle_real_time_checks": True,
512 # .--mem.win-------------------------------------------------------------.
513 # | _ |
514 # | _ __ ___ ___ _ __ ___ __ _(_)_ __ |
515 # | | '_ ` _ \ / _ \ '_ ` _ \\ \ /\ / / | '_ \ |
516 # | | | | | | | __/ | | | | |\ V V /| | | | | |
517 # | |_| |_| |_|\___|_| |_| |_(_)_/\_/ |_|_| |_| |
518 # | |
519 # +----------------------------------------------------------------------+
520 # | Windows now has a dedicated memory check that reflect the special |
521 # | nature of the page file. |
522 # '----------------------------------------------------------------------'
524 # Special memory and page file check for Windows
525 factory_settings["memory_win_default_levels"] = {
526 "memory": (80.0, 90.0),
527 "pagefile": (80.0, 90.0),
531 def inventory_mem_win(info):
532 meminfo = parse_proc_meminfo(info)
533 if "MemTotal" in meminfo and "PageTotal" in meminfo:
534 yield None, {}
537 def check_mem_windows(_no_item, params, info):
538 meminfo = parse_proc_meminfo(info)
539 now = time.time()
541 def _get_levels_on_used_mb(param_key, total_mb):
542 levels = params.get(param_key)
543 if not isinstance(levels, tuple):
544 # Predictive levels have no level information in the performance data
545 return None, None
547 if isinstance(levels[0], float):
548 # float type means percent
549 warn = total_mb * levels[0] / 100
550 else:
551 # int means levels on *free* space
552 warn = total_mb - levels[0]
553 if isinstance(levels[1], float):
554 crit = total_mb * levels[1] / 100
555 else:
556 crit = total_mb - levels[1]
557 return warn, crit
559 for title, prefix, paramname in [("Memory usage", "Mem", "memory"),
560 ("Commit charge", "Page", "pagefile")]:
562 total_kb = meminfo.get("%sTotal" % prefix)
563 free_kb = meminfo.get("%sFree" % prefix)
564 if None in (total_kb, free_kb):
565 continue
567 total_mb = total_kb / 1024.0
568 free_mb = free_kb / 1024.0
569 used_kb = total_kb - free_kb
570 used_mb = total_mb - free_mb
571 perc = 100.0 * used_kb / total_kb
573 warn, crit = _get_levels_on_used_mb(paramname, total_mb)
575 infotext = "%s: %s (%s/%s)" % (title, get_percent_human_readable(perc),
576 get_bytes_human_readable(used_kb * 1024),
577 get_bytes_human_readable(total_kb * 1024))
579 perfdata = [(paramname, used_mb, warn, crit, 0, total_mb)]
580 if prefix == "Mem":
581 perfdata.append(("mem_total", total_mb))
582 elif prefix == "Page":
583 perfdata.append(("pagefile_total", total_mb))
585 # Do averaging, if configured, just for matching the levels
586 if "average" in params:
587 average_min = params["average"]
588 used_kb = get_average(
589 "mem.win.%s" % paramname, now, used_kb, average_min, initialize_zero=False)
590 used_mb = used_kb / 1024.0
591 perc = 100.0 * used_kb / total_kb
592 infotext += ", %d min average: %s (%s)" % (average_min,
593 get_percent_human_readable(perc),
594 get_bytes_human_readable(used_kb * 1024))
595 perfdata.append((paramname + "_avg", used_mb))
597 # Now check the levels
598 if (warn, crit) != (None, None):
599 state = 0
600 if used_mb >= crit:
601 state = 2
602 elif used_mb >= warn:
603 state = 1
605 # Predictive levels
606 else:
607 if "average" in params:
608 titleinfo = title
609 dsname = "%s_avg" % paramname
610 else:
611 titleinfo = title
612 dsname = paramname
614 state, infoadd, perfadd = check_levels(
615 used_mb, # Current value stored in MB in RRDs
616 dsname,
617 params[paramname],
618 unit="GB", # Levels are specified in GB...
619 scale=1024, # ... in WATO ValueSpec
620 infoname=titleinfo)
621 if infoadd:
622 infotext += ", " + infoadd
623 perfdata += perfadd
625 yield state, infotext, perfdata
628 check_info["mem.win"] = {
629 'check_function': check_mem_windows,
630 'inventory_function': inventory_mem_win,
631 'service_description': 'Memory and pagefile',
632 'has_perfdata': True,
633 'group': 'memory_pagefile_win',
634 'default_levels_variable': 'memory_win_default_levels',
635 "handle_real_time_checks": True,
639 # .--mem.vmalloc---------------------------------------------------------.
640 # | _ _ |
641 # | _ __ ___ ___ _ __ ___ __ ___ __ ___ __ _| | | ___ ___ |
642 # | | '_ ` _ \ / _ \ '_ ` _ \\ \ / / '_ ` _ \ / _` | | |/ _ \ / __| |
643 # | | | | | | | __/ | | | | |\ V /| | | | | | (_| | | | (_) | (__ |
644 # | |_| |_| |_|\___|_| |_| |_(_)_/ |_| |_| |_|\__,_|_|_|\___/ \___| |
645 # | |
646 # +----------------------------------------------------------------------+
647 # | This very specific check checks the usage and fragmentation of the |
648 # | address space 'vmalloc' that can be problematic on 32-Bit systems. |
649 # | It is superseeded by the new check mem.linux and will be removed |
650 # | soon. |
651 # '----------------------------------------------------------------------'
653 # warn, crit, warn_chunk, crit_chunk. Integers are in MB, floats are in percent
654 mem_vmalloc_default_levels = (80.0, 90.0, 64, 32)
657 def inventory_mem_vmalloc(info):
658 meminfo = parse_proc_meminfo(info)
659 if is_linux_meminfo(meminfo):
660 return # handled by new Linux memory check
662 # newer kernel version report wrong data,
663 # i.d. both VmallocUsed and Chunk equal zero
664 if "VmallocTotal" in meminfo and \
665 not (meminfo["VmallocUsed"] == 0 and meminfo["VmallocChunk"] == 0):
666 # Do not checks this on 64 Bit systems. They have almost
667 # infinitive vmalloc
668 vmalloc = meminfo["VmallocTotal"] / 1024.4
669 if vmalloc < 4096:
670 return [(None, "mem_vmalloc_default_levels")]
673 def check_mem_vmalloc(item, params, info):
674 meminfo = parse_proc_meminfo(info)
675 total_mb = meminfo["VmallocTotal"] / 1024.0
676 used_mb = meminfo["VmallocUsed"] / 1024.0
677 chunk_mb = meminfo["VmallocChunk"] / 1024.0
678 warn, crit, warn_chunk, crit_chunk = params
680 state = 0
681 infotxts = []
682 perfdata = []
683 for var, w, c, v, neg, what in [("used", warn, crit, used_mb, False, "used"),
684 ("chunk", warn_chunk, crit_chunk, chunk_mb, True,
685 "largest chunk")]:
687 # convert levels from percentage to MB values
688 if isinstance(w, float):
689 w_mb = total_mb * w / 100
690 else:
691 w_mb = float(w)
693 if isinstance(c, float):
694 c_mb = total_mb * c / 100
695 else:
696 c_mb = float(c)
698 infotxt = "%s %.1f MB" % (what, v)
699 if (v >= c_mb) != neg:
700 s = 2
701 infotxt += " (critical at %.1f MB!!)" % c_mb
702 elif (v >= w_mb) != neg:
703 s = 1
704 infotxt += " (warning at %.1f MB!)" % w_mb
705 else:
706 s = 0
707 state = max(state, s)
708 infotxts.append(infotxt)
709 perfdata.append((var, v, w_mb, c_mb, 0, total_mb))
710 return (state, ("total %.1f MB, " % total_mb) + ", ".join(infotxts), perfdata)
713 check_info["mem.vmalloc"] = {
714 'inventory_function': inventory_mem_vmalloc,
715 'check_function': check_mem_vmalloc,
716 'service_description': 'Vmalloc address space',
717 'has_perfdata': True,
718 "handle_real_time_checks": True,