Check_MK: Inventory erweitern mit SNMP Daten

Check_MK hat seit Version 1.2.5i1 das Feature Inventory an Board. Per Default werden von Systemen CPU, Memory, Harddisks, Softwarepakete und vieles mehr eingesammelt. Die Anleitung dient dazu das Inventory zu erweitern und eigene Informationen per SNMP einzusammeln und per View durchsuchbar zu machen.

Ich habe mittlerweile mehrere eigene Ergänzungen gemacht, darunter CDP Neighbors, Dot1X Authentications, Wireless Accesspoints und Hardware Inventory von Cisco Geräten.

Als Beispiel zeige ich das Cisco Hardware Inventory mit Seriennummern.

Bestandteile für eine Inventory Erweiterung:

  1. Daten sammeln -> Erweiterung für den Inventory Collector unter  ~/local/share/check_mk/inventory/
  2. Daten darstellen -> Erweiterung für die Inventory Views unter ~/local/share/check_mk/web/plugins/views/

1. Daten sammeln

Die Inventory Daten werden innerhalb einer Baumstruktur abgelegt. Man kann für seine eigenen Daten neue Knoten erzeugen. z.B. unter networking das hw_inventory wird im Tree dargestellt als networking.hw_inventory: . Der Doppelpunkt zeigt an das Daten unterhalb des Knotens folgen.

Das Inventory Plugin besteht aus einer Funktion und dem inv_info Directory welches alle Inventory Plugins kennt. In inv_info  im Key snmp_scan_function ist genauso wie bei den Check_MK SNMP Checks angegeben ob Check_MK überhaupt Daten finden wird bei einem SNMP Bulkwalk. snmp_info beinhaltet die OID und alle Untertabellen mit Daten die von Check_MK eingesammelt werden sollen.

Beispiel: ~/local/share/check_mk/inventory/my_hw_inventory.py

#!/usr/bin/python

port = {
0: "-",
1: "other",
2: "unknown",
3: "chassis",
4: "backplane",
5: "container",
6: "powerSupply",
7: "fan",
8: "sensor",
9: "module",
10: "port",
11: "stack",
12: "cpu"

}

def inv_hw_inventory(info, params):
    
    node = inv_tree("networking.hw_inventory:")

    for x in info[0]:
        
        #print x
        
        # If Serial Number is longer than 1 char
        if len(x[10]) >= 1:
        
            fru = "true" if "1" in x[15] else "false"
            
            classx = port[int(x[4])] if len(x[4]) is 1 else port[0]
            
            node.append(
            {
            "index": x[0],
            "description": x[1],
            "vendor_type": x[2],
            "contained_in_id": x[3],
            "class": classx,
            "parent_rel_pos": x[5],
            "name": x[6],
            "hw_rev": x[7],
            "fw_rev": x[8],
            "sw_rev": x[9],
            "serial_number": x[10],
            "manufactor": x[11],
            "model": x[12],
            "alias": x[13],
            "asset_id": x[14],
            "is_fru": fru,
            }
            )
        

inv_info["inv_hw_inventory"] = {
"inv_function": inv_hw_inventory,
"snmp_info": [(".1.3.6.1.2.1.47.1.1.1.1",[OID_END, # entPhysicalIndex
                                        "2", # entPhysicalDescr
                                        "3", # entPhysicalVendorType
                                        "4", # entPhysicalContainedIn
                                        "5", # entPhysicalClass
                                        "6", # entPhysicalParentRelPos
                                        "7", # entPhysicalName
                                        "8", # entPhysicalHardwareRev
                                        "9", # entPhysicalFirmwareRev
                                        "10", # entPhysicalSoftwareRev
                                        "11", # entPhysicalSerialNum                                        
                                        "12", # entPhysicalMfgName
                                        "13", # entPhysicalModelName
                                        "14", # entPhysicalAlias
                                        "15", # entPhysicalAssetID
                                        "16", # entPhysicalIsFRU
                                             ]),
             ],
"snmp_scan_function": lambda oid: oid(".1.3.6.1.2.1.1.2.0").startswith(".1.3.6.1.4.1.9.1"),
}

Mit der inv_tree Funktion wird ein neuer Inventory Baum eröffnet (siehe Code). Alle eingesammelten Informationen werden dann an diesen neuen Baum mit append als Dictionary hinzugefügt.

Die eigene Inventory Funktion kann man testen mit:

OMD[dev1]:~/local/share/check_mk/web/plugins/views$ cmk -v -i testswitch
Doing HW/SW-Inventory for testswitch...inv_hw_inventory snmp_extended_info snmp_os snmp_info ..unchanged..1603 entries..OK

Wenn in der Inventory Funktion ein pprint.pprint(info) eingebaut wird können auch die Rohdaten betrachtet werden.

2. Daten darstellen

Hierfür muss ein View gebaut werden der die Informationen des neuen Inventory Baums darstellt.

Beispiel ~/local/share/check_mk/web/plugins/views/my_inv_hw_inventory.py

#!/usr/bin/python

inventory_displayhints.update({

        ".networking.hw_inventory:"                          : { "title" : _("HW Inventory"), "render" : render_inv_dicttable,  "view" : "invhwi_of_host", "keyorder": 
                                                               ["index","name","description","model","contained_in_id","serial_number","hw_rev","fw_rev","sw_rev","class","manufactor","asset_id","alias","is_fru"] },
        ".networking.hw_inventory:*.index"                   : { "title" : _("Index") },
        ".networking.hw_inventory:*.description"             : { "title" : _("Description") },
        ".networking.hw_inventory:*.contained_in_id"         : { "title" : _("Contained in Index") },
        ".networking.hw_inventory:*.class"                   : { "title" : _("Class") },
        ".networking.hw_inventory:*.name"                    : { "title" : _("Name") },
        ".networking.hw_inventory:*.hw_rev"                  : { "title" : _("HW REV") },
        ".networking.hw_inventory:*.fw_rev"                  : { "title" : _("FW REV") },
        ".networking.hw_inventory:*.sw_rev"                  : { "title" : _("SW REV") },
        ".networking.hw_inventory:*.serial_number"           : { "title" : _("Serial Number") },
        ".networking.hw_inventory:*.manufactor"              : { "title" : _("Manufactor") },
        ".networking.hw_inventory:*.model"                   : { "title" : _("Model") },
        ".networking.hw_inventory:*.alias"                   : { "title" : _("Alias") },
        ".networking.hw_inventory:*.asset_id"                : { "title" : _("Asset ID") },
        ".networking.hw_inventory:*.is_fru"                  : { "title" : _("Is FRU") },
})

declare_invtable_view("invhwi", ".networking.hw_inventory:", _("HW Inventory"), _("HW Inventory"))

Danach sollte man mit „omd restart apache && cmk -v -R“ Check_MK und den Apachen neu starten, damit die neuen Views sichtbar werden. Damit Daten angezeigt werden muss 1 mal das Inventory auf dem Gerät gelaufen sein.

Im Views Menü sollte dann unser neuer View unter Inventory auftauchen:

Man kann sich alle Daten anzeigen lassen oder gezielt nach einzelnen Informationen oder Geräten suchen.

Wenn man im Host View ist kann man über das obere Menü auch direkt zu den Inventory Daten kommen, wurde der Button noch nicht genutzt kann er sichtbar gemacht werden mit dem „…“ Button.

Die Daten werden für den Host als Baumstruktur dargestellt.

Viel Spaß beim Erweitern 😉

4 Gedanken zu „Check_MK: Inventory erweitern mit SNMP Daten

  1. Ralf

    Es wäre super, wenn es diese Erweiterung auch als .mkp Download geben würde.
    Insbesondere der CDP Teil würde mich interessieren.

    Antworten
    1. Maximilian Thoma

      Hallo Ralf,

      anbei die Inventory Erweiterung als MKP.

      CDP und LLDP folgen noch … 😉

      Gruß

      Max

      Antworten
  2. Jens

    Hallo Maximilian,

    du schreibst
    „Ich habe mittlerweile mehrere eigene Ergänzungen gemacht, darunter CDP Neighbors, Dot1X Authentications, Wireless Accesspoints und Hardware Inventory von Cisco Geräten.“.

    Die Erweiterung für CDP und LLDP habe ich gefunden, hast Du die Ergänzungen bzgl. Dot1X und APs auch irgendwo veröffentlicht. Würde ich mir gerne einmal anschauen.

    Danke und Gruß
    Jens

    Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.