From fbc07dbbfd2ab75f6eff9b3f4fe626f924d5c5bf Mon Sep 17 00:00:00 2001 From: Marsell Kukuljevic Date: Sun, 28 Dec 2025 14:57:02 +0100 Subject: [PATCH] Port ScalityRing to CheckMK 2.4. --- scality-ring/{ => 2.0}/ScalityRing-1.0.1.mkp | Bin .../local/share/check_mk/checks/scality | 0 .../web/plugins/wato/scality_disks.py | 0 .../plugins/scality/agent_based/scality.py | 206 ++++++++++++++++++ .../plugins/scality/rulesets/scality.py | 47 ++++ scality-ring/2.4/scality_ring-1.2.0.mkp | Bin 0 -> 2521 bytes 6 files changed, 253 insertions(+) rename scality-ring/{ => 2.0}/ScalityRing-1.0.1.mkp (100%) rename scality-ring/{ => 2.0}/local/share/check_mk/checks/scality (100%) rename scality-ring/{ => 2.0}/local/share/check_mk/web/plugins/wato/scality_disks.py (100%) create mode 100644 scality-ring/2.4/local/lib/python3/cmk_addons/plugins/scality/agent_based/scality.py create mode 100644 scality-ring/2.4/local/lib/python3/cmk_addons/plugins/scality/rulesets/scality.py create mode 100755 scality-ring/2.4/scality_ring-1.2.0.mkp diff --git a/scality-ring/ScalityRing-1.0.1.mkp b/scality-ring/2.0/ScalityRing-1.0.1.mkp similarity index 100% rename from scality-ring/ScalityRing-1.0.1.mkp rename to scality-ring/2.0/ScalityRing-1.0.1.mkp diff --git a/scality-ring/local/share/check_mk/checks/scality b/scality-ring/2.0/local/share/check_mk/checks/scality similarity index 100% rename from scality-ring/local/share/check_mk/checks/scality rename to scality-ring/2.0/local/share/check_mk/checks/scality diff --git a/scality-ring/local/share/check_mk/web/plugins/wato/scality_disks.py b/scality-ring/2.0/local/share/check_mk/web/plugins/wato/scality_disks.py similarity index 100% rename from scality-ring/local/share/check_mk/web/plugins/wato/scality_disks.py rename to scality-ring/2.0/local/share/check_mk/web/plugins/wato/scality_disks.py diff --git a/scality-ring/2.4/local/lib/python3/cmk_addons/plugins/scality/agent_based/scality.py b/scality-ring/2.4/local/lib/python3/cmk_addons/plugins/scality/agent_based/scality.py new file mode 100644 index 0000000..bbc2036 --- /dev/null +++ b/scality-ring/2.4/local/lib/python3/cmk_addons/plugins/scality/agent_based/scality.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2025 Spearhead Systems SRL +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + + +from cmk.agent_based.v2 import ( + Result, + Metric, + Service, + State, + CheckPlugin, + SNMPTree, + SNMPSection, + contains, + get_value_store, +) +from cmk.plugins.lib.df import ( + df_check_filesystem_single, + FILESYSTEM_DEFAULT_PARAMS, +) + + +def check_scality_disks(item, params, section): + data = section["rings"].get(item) + if not data: + return + + ringdisktotal = data["disks"] + yield Metric("disks", ringdisktotal) + + if not params: + yield Result(state=State.OK, summary=f"Number of disks: {ringdisktotal}") + return + + warn = params["warn"] + crit = params["crit"] + infotext = f"Number of disks: {ringdisktotal}. " + + if ringdisktotal <= crit: + infotext += f"This is lower or equal to {crit} (critical level)" + yield Result(state=State.CRIT, summary=infotext) + elif ringdisktotal <= warn: + infotext += f"This is lower or equal to {warn} (warning level)" + yield Result(state=State.WARN, summary=infotext) + else: + yield Result(state=State.OK, summary=infotext) + + +def check_scality_storages(item, params, section): + data = section["rings"].get(item) + if not data: + return + + yield from df_check_filesystem_single( + value_store = get_value_store(), + mountpoint = item, + filesystem_size = data["avail_storage"], + free_space = data["total_storage"], + reserved_space = 0, + inodes_total = None, + inodes_avail = None, + params = params, + ) + + +def check_scality_states(item, params, section): + data = section["rings"].get(item) + if not data: + return + + ringstate = data["state"] + + if ringstate == "RUN": + status = State.OK + text = "Ring is in RUN state" + elif ringstate == "LOOP": + status = State.CRIT + text = "Ring is LOOP state" + else: + status = State.CRIT + text = "Ring is in balancing state" + + yield Result(state=status, summary=text) + + +def check_scality_supervisors(item, params, section): + data = section["supervisors"].get(item) + if not data: + return + + supNbSrvTotal = data["total"] + supNbSrvNok = data["not_ok"] + supAvailable = data["avail"] + + if supAvailable != 1: + yield Result(state=State.CRIT, summary="Supervisor is not available") + else: + yield Result(state=State.OK, summary="Supervisor is available") + + if supNbSrvNok > 0: + yield Result(state=State.CRIT, summary=f"{supNbSrvNok} out of {supNbSrvTotal} servers are unavailable") + else: + yield Result(state=State.OK, summary=f"all {supNbSrvTotal} servers are available") + + +def discover_scality_rings(section): + for name in section["rings"].keys(): + yield Service(item=name) + + +def discover_scality_supervisors(section): + for name in section["supervisors"].keys(): + yield Service(item=name) + + +def parse_scality(string_table): + rings = {} + supervisors = {} + + for name, state, disks, avail, total in string_table[0]: + rings[name] = { + "state": state, + "disks": int(disks), + "avail_storage": int(avail), + "total_storage": int(total), + } + + for name, total, not_ok, avail in string_table[1]: + supervisors[name] = { + "total": int(total), + "not_ok": int(not_ok), + "avail": int(avail), + } + + return { + "rings": rings, + "supervisors": supervisors, + } + + +check_plugin_scality_disk = CheckPlugin( + name = "scality_ring_disk", + sections = [ "scality_ring" ], + service_name = "Ring %s Disks", + discovery_function = discover_scality_rings, + check_function = check_scality_disks, + check_ruleset_name = "scality_ring_disk", + check_default_parameters = {}, +) +check_plugin_scality_storage = CheckPlugin( + name = "scality_ring_storage", + sections = [ "scality_ring" ], + service_name = "Ring %s Storage", + discovery_function = discover_scality_rings, + check_function = check_scality_storages, + check_default_parameters = FILESYSTEM_DEFAULT_PARAMS, +) +check_plugin_scality_state = CheckPlugin( + name = "scality_ring_state", + sections = [ "scality_ring" ], + service_name = "Ring %s State", + discovery_function = discover_scality_rings, + check_function = check_scality_states, + check_default_parameters = {}, +) +check_plugin_scality_supervisor = CheckPlugin( + name = "scality_ring_supervisor", + sections = [ "scality_ring" ], + service_name = "Supervison %s", + discovery_function = discover_scality_supervisors, + check_function = check_scality_supervisors, + check_default_parameters = {}, +) + + +snmp_section_scality = SNMPSection( + name = "scality_ring", + parse_function = parse_scality, + detect = contains(".1.3.6.1.2.1.1.1.0", "scality"), + fetch = [ + SNMPTree( + base=".1.3.6.1.4.1.37489.2.1.1.1.4.1.1", + oids=[ + "2", #ringName +# "3", #ringStateRun + "8", #ringState + "9", #ringDiskTotal +# "13", #ringStorageUsed + "14", #ringStorageAvailable + "15", #ringStorageTotal + ]), + SNMPTree( + base=".1.3.6.1.4.1.37489.2.1.1.1.4.2.1", + oids=[ + "2", #supName + "5", #supNbSrvTotal +# "6", #supNbSrvOK + "7", #supNbSrvNok + "8", #supAvailable + ], + ), + ] +) diff --git a/scality-ring/2.4/local/lib/python3/cmk_addons/plugins/scality/rulesets/scality.py b/scality-ring/2.4/local/lib/python3/cmk_addons/plugins/scality/rulesets/scality.py new file mode 100644 index 0000000..dd3ee28 --- /dev/null +++ b/scality-ring/2.4/local/lib/python3/cmk_addons/plugins/scality/rulesets/scality.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2025 Spearhead Systems SRL +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +from cmk.rulesets.v1.form_specs import Dictionary, DictElement, Integer +from cmk.rulesets.v1.rule_specs import CheckParameters, HostAndItemCondition, Topic, Title, Help +from cmk.rulesets.v1.form_specs.validators import NumberInRange + + +def _parameters_scality(): + return Dictionary( + title = Title("Minimum Number of Disks"), + help_text = Help( + "Set lower limits for the number of disks in the scality ring " + "system. Applied for each ring." + ), + elements = { + "warn": DictElement( + required = True, + parameter_form = Integer( + title = Title("Warn"), + help_text = Help("Warn if below this number of disks"), + custom_validate = (NumberInRange(min_value=0),), + ), + ), + "crit": DictElement( + required = True, + parameter_form = Integer( + title = Title("Crit"), + help_text = Help("Crit if below this number of disks"), + custom_validate = (NumberInRange(min_value=0),), + ), + ), + }, + ) + + +rule_spec_scality_ring = CheckParameters( + name = "scality_ring_disk", + title = Title("Scality Ring Disk Number"), + topic = Topic.GENERAL, + condition = HostAndItemCondition(item_title = Title("Ring")), + parameter_form = _parameters_scality, +) diff --git a/scality-ring/2.4/scality_ring-1.2.0.mkp b/scality-ring/2.4/scality_ring-1.2.0.mkp new file mode 100755 index 0000000000000000000000000000000000000000..cbfa4a65fe0f485091b0e05fcd18cde7f1241c30 GIT binary patch literal 2521 zcmV;~2`2U*iwFP+Hc@E;|Lq$6Pvbh0pZiz%Wp$#xE1@j~cB|`2h~@FnK^L{Go}N$@ zrHM=P$VXr7bdN**-*3it5~odJ%Ps7_yUZ?XVvpy`Gvl!xFPug@uM91Kqi$FH0<8YF zj#|e%?ZbAb+c`LBwXyx^=&-v(T03t53FCGQEO-7t;c?ea_$-Qddt`Ssr*=G}wo672 zjMIRT(eQG&StGkHWlrqPxfg|qDBGehp&!|WsdE8{9)g|qan8@HlyyoYBT2#NaI<^Xv7IHqnzmk#!D05MzUv^b}VSjly+^iW4820Gw?zyrhg<}OkKq2nB5hOx$WG8N}?Au-wW>NdpwGK z(l%Qws0p(tKDCmNduX>o6w+nwyUo7`@o)alqVPM$|6%KBCH{|(I-M&1-z5GG5fVnv z&?3TU8W=&)s0R?VYIy)Up+Pw{yojjDTe66NuJwS>@buUMToGDYw;nAL) zB9|pB6jMu0QcjVVjNYTMo|cT>t?_hLg7HtJ9Ams({(0wr-5w^!!yCqbr;E>p_-}U( zx>fwY2|Vrj-+cbt$A>Nb7atFfTAg(MI|s*r2QTg8x14`MFc6*#l>f!~fA`aV!s7jj z7w*$=LFNyTTEm0dJF@rJJ>o!6WaMe&V$J>WRF~W4hmB$L?9(13FE#r5&&)VN&i!PqMVR zP5No$t$}q1GsY&UAjUNWmNz9~#07FM+c3nGCvjL4?>G#Z@rZ*%^#$gwA=n#Zf$`u` z-&MA+tDa_YT%)Ellk(>5Bmp^*b%s;b7ZYZF`X?xr1c4nt^ryxk2_`f~rx840XH?*^ zG#aG}e6iyYfzQ8b7N+*X_WaZe##kEw3D07XYiUYQ4iH{ZHXw#tJzh{Z9n>eS zrsgz|xtS$hN>IbC_*%b^rmSDiOMWbo#-zm9G_~LgZla3@axBA z>h38s*;tUPDKkP-R!dE3-6oNX1Inz?zio}RutYAmNMej+3&+j<}}2Kxh(~A(Z}WinlezHG6JSUnZm;DV0EA zsDvbClrN=fr$kouRcgrGsIgZb-ILRk;}=}6r|TebfL=}JceyVr>|8)WZ679!BH`0T zfF(x{Krz&isD} ztn*T2NxEdKremvsdFu;Jocj7VxALe!_%-aD z7W>Z{@5#;f2Aj(A?`0On%=HTP%*novHLB3DNR#CSeEApQ11SZ(mMuAh_a;?r^W{fCS=wzQ4n5*2wa>))YIj%A zvbw(n_izPQ^44+2+A{rOV|TVQHkQk1>$Tp)v^OiJOYC%{BWYXS4B=QufDOTh`O>#c zMU&*JDC3MFcz%rgpOTBs*SP;Hx&LV$bdR(9zc&2swA$Un&S7=`Q{Dgk`R;$Ri z%thOTZB}5hIdxci!Sc})s~l|go8tM*rvVLllU#(H-qE<64n7y@$OC9f1N!l51BQMC)#s)1}Tp6QoO^D6S^Ph;nu0?|XsAnb_Ro zWQN77kaUjIDg{?DVytZ3g&&*bWIp#ja0?_wZEylaHjULZE{}P{46^lYu(-VG>C;?a zTRGA%V6vL;CQj)3$8edoEu1MpQ|?kP{cJ8bGbtMTSCptx{;geZ<#dp+wHSkEY7+`Z zmJzUG*i952NU>31DTl)HuU>GaI(`Bq?hyK|Mze&-O4I5Ifw%(uq3nB#5^ZT;9P`83 zcbQ*iWVxrXHOn?hSsGZ~C_QmhP?84JM`%QB7%>B=gplgaF_EQ1@Yy^+8=MVKF0*@Y znex!AC7DnhBU+Mg##4Op)@WqAkfH~aWVq&cui7f8pn?i2sGx!hDyX1>3M#0ef(k0A jpn?i2sGx!hDyX1>3M#0ef(k0AK*E0jEIl%108jt`=Dgo) literal 0 HcmV?d00001