Parse additional info from Raspberry Pi devices

CMK version:
2.0.0p39.cre

Server address:
http://10.11.1.47/MubeaPRO/check_mk
(running on local virtual server)

Monitored system address:
10.11.66.104

OS version:
Ubuntu 22.04.5 LTS on Checkmk server / Debian GNU / Linux 12 (bookworm) on monitored system

Error description:
Hello, community. I would like to use Check_MK to monitor multiple Raspberry Pi devices. It is already able to read multiple services from IP address of each Raspberry Pi (as soon as an agent has been installed) like CPU utilization, memory, temperature, but some important ones are missing and I am trying to parse them using scripts created with ChatGPT. I am not able to make CMK read the services from a plugin, but at least it seems that everything on the Raspberry side is working correctly so far.

Let’s start with RPi:

/usr/lib/check_mk_agent/plugins/raspberry_info.sh

#!/bin/bash
echo "<<<raspberry_info>>>"
echo "Model: $(cat /proc/device-tree/model)"
echo "OS Version: $(lsb_release -d | awk -F'\t' '{print $2}')"
echo "Kernel Version: $(uname -r)"

/etc/xinetd.d/check_mk contains (amongst the default content) one uncommented line with server IP address:

only_from      = 10.11.1.47

Should it contain complete server address?

Now the Check_MK server side:

/omd/sites/MubeaPRO/local/share/check_mk/checks/raspberry_info.py

def parse_raspberry_info(section):
    parsed = {}
    for row in section:
        if len(row) > 0:
            line = row[0]
            if isinstance(line, str):
                if line.startswith("Model:"):
                    parsed["model"] = line.split(":", 1)[1].strip()
                elif line.startswith("OS Version:"):
                    parsed["os_version"] = line.split(":", 1)[1].strip()
                elif line.startswith("Kernel Version:"):
                    parsed["kernel_version"] = line.split(":", 1)[1].strip()
    return parsed

def inventory_raspberry_info(parsed):
    inventory = []
    if "model" in parsed:
        inventory.append(("model", parsed["model"]))
    if "os_version" in parsed:
        inventory.append(("os_version", parsed["os_version"]))
    if "kernel_version" in parsed:
        inventory.append(("kernel_version", parsed["kernel_version"]))
    return inventory

def check_raspberry_info(item, params, parsed):
    model = parsed.get("model", "Unknown Model")
    os_version = parsed.get("os_version", "Unknown OS")
    kernel_version = parsed.get("kernel_version", "Unknown Kernel")
    message = f"Model: {model}, OS: {os_version}, Kernel: {kernel_version}"
    return (0, message)

check_info["raspberry_info"] = {
    "parse_function": parse_raspberry_info,
    "inventory_function": inventory_raspberry_info,
    "check_function": check_raspberry_info,
    "service_description": "Raspberry Info",
    "has_perfdata": False,
    "default_levels_variable": None,
}

Output of “cmk --debug -vII hostname”:

Discovering services and host labels on: 10.11.66.104
10.11.66.104:
+ FETCHING DATA
Using data from cache file /omd/sites/MubeaPRO/tmp/check_mk/cache/10.11.66.104
[TCPFetcher] Use cached data
[PiggybackFetcher] Execute data source
No piggyback files for '10.11.66.104'. Skip processing.
No piggyback files for '10.11.66.104'. Skip processing.
+ PARSE FETCHER RESULTS
Received no piggyback data
+ EXECUTING HOST LABEL DISCOVERY
+ PERFORM HOST LABEL DISCOVERY
+ EXECUTING DISCOVERY PLUGINS (31)
Traceback (most recent call last):
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/api/agent_based/register/check_plugins_legacy.py", line 130, in _resolve_string_parameters
    return eval(params_unresolved, context, context)
  File "<string>", line 0

    ^
SyntaxError: unexpected EOF while parsing

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/omd/sites/MubeaPRO/bin/cmk", line 92, in <module>
    exit_status = modes.call(mode_name, mode_args, opts, args)
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/modes/__init__.py", line 69, in call
    return handler(*handler_args)
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/modes/check_mk.py", line 1542, in mode_discover
    discovery.do_discovery(
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/discovery.py", line 378, in do_discovery
    _do_discovery_for(
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/discovery.py", line 435, in _do_discovery_for
    discovered_services, host_label_discovery_result = _discover_host_labels_and_services(
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/discovery.py", line 1431, in _discover_host_labels_and_services
    discovered_services = [] if discovery_parameters.only_host_labels else _discover_services(
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/discovery.py", line 1480, in _discover_services
    service_table.update({
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/discovery.py", line 1480, in <dictcomp>
    service_table.update({
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/discovery.py", line 1548, in _execute_discovery
    yield from _enriched_discovered_services(hostname, check_plugin.name, plugins_services)
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/discovery.py", line 1562, in _enriched_discovered_services
    for service in plugins_services:
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/api/agent_based/register/check_plugins.py", line 72, in filtered_generator
    for element in generator(*args, **kwargs):
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/api/agent_based/register/check_plugins_legacy.py", line 94, in discovery_migration_wrapper
    parameters = _resolve_string_parameters(raw_params, check_name, get_check_context)
  File "/omd/sites/MubeaPRO/lib/python3/cmk/base/api/agent_based/register/check_plugins_legacy.py", line 132, in _resolve_string_parameters
    raise ValueError("Invalid check parameter string '%s' found in discovered service %r" %
ValueError: Invalid check parameter string '' found in discovered service 'raspberry_info'

Could you please help me to get it working?

the first mistake I see (I don’t know if I’m right) is that you are passing the data to checkmk in a way that I don’t know if he’s going to like it. When you define <<<raspberry_info>>> by default it generates a list with the data separated by space, I mean.
model my_model
os version 1.2
kernel version 8.2

section = [
  [model:, my_model],
  [os, version:, 1.2],
  [kernel, version:, 8.2]
]

in this case you should use the separator 58 in this way <<<raspberry_info:58>>>
ASCII - Wikipedia
image

if it were my choice I would simplify the script so that it would output as follows

#!/bin/bash
MODEL=$(cat /proc/device-tree/model | tr ' ' '_')
OS_VERSION=$(lsb_release -d | awk -F'\t' '{print $2}' | tr ' ' '_')
KERNEL_VERSION=$(uname -r | tr ' ' '_')

echo "<<<raspberry_info>>>"
echo "Model $MODEL"
echo "OS_Version $OS_VERSION"
echo "Kernel_Version $KERNEL_VERSION"

depending on the way you want the service(s) you will have to restructure the parse function

you should have something like this

{ 
    'model': 'MYMODEL', 
    'os_version': 'MYOSVERSION', 
    'kernel_version': 'MYKERNELVERSION'
}

maybe this will work for you

section = [ 
    ["model", "MYMODEL"], 
    ["os_version", "MYOSVERSION"], 
    ["kernel_version", "MYKERNELVERSION"] 
]

parsed = {}
for key, value in section:
    parsed[key] = value

print(parsed)

Hello Mario, thank you for your reply and effort.

I have changed both the script and plugin. CheckMK and debug are not reporting any errors now, but they are still unable to read required info :man_shrugging: I can still only see it when contacting RPi using telnet command:

telnet 10.11.66.104 6556

...
<<<raspberry_info>>>
Model Raspberry_Pi_5_Model_B_Rev_1.0
OS_Version Debian_GNU/Linux_12_(bookworm)
Kernel_Version 6.6.62+rpt-rpi-2712

I have read the check function, I see that the intention is to get a single service, it would be necessary to modify the function again since the way I have commented it would generate 3 services, one for each information.

The simplest way to do this is to generate a local check and distribute it in the folder of each raspberry. The script would be as simple as

#!/bin/bash

MODEL=$(cat /proc/device-tree/model)
OS_VERSION=$(lsb_release -d | awk -F'\t' '{print $2}')
KERNEL_VERSION=$(uname -r)

echo “0 \"Raspberry Info\" - Model: $MODEL, OS: $OS_VERSION, Kernel: $KERNEL_VERSION”

As soon as I have some time, I’ll keep checking. at first I see that the discovery and register functions are missing.
However, depending on how the path goes, the check function you have would not be useful either.

I will check it later as soon as I have some time and I will pass it to you without any problem.

1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed. Contact an admin if you think this should be re-opened.