How to share code with other checks
March 06. 2011
Include files and share sections
Sometimes there are several checks that do something very similar but not entirely the same. A good examle is the pair of checks if and if64. They differ only in the name and in the OIDs fetched via SNMP. The actual check logic is 100% identical. So it would a shame if the two checks could not use the same code (in fact in versions < 1.1.9 that was the case!)
Because each check must be implemented in a file that is named after the check's data source, however, both checks must be implemented in the two separate files if and if64.
What is the data source name? It is the name of the agent section the check depends on (TCP) or the name of the entry in snmp_info. In most cases that is identical with the check name. In some cases - however - different checks make use of the same agent section. An example are the checks winperf.cpuusage and winperf.diskstat. Both use the section <<<winperf>>>. And both are therefore implemented in the file winperf. The period (dot) in the check name indicates this. Everything before the period is the name of the data source.
So winperf.cpuusage and winperf.diskstat do not share code but share the data source. In the case of if/if64 it's vice versa. They have different data sources but almost the same code.
How to use include files
In such a case you can work with include files. You simply put all code and global variables that are shared between several checks into a common file with the suffix .include. Then you declare that file in each of the checks that use stuff from the include file. This is done via the array check_includes, as you can see in the check if:
check_includes['if'] = [ "if.include" ]
It is also possible to include more than one file. So does df_netapp:
check_includes['df_netapp'] = [ "df.include", "df_netapp.include" ]
Please note: include files must not themselves include other files!
Why so complicated? Precompile!
You might ask, why a declaration is neccessary at all. Doesn't Check_MK anyway read in all files in checks/? In fact if you leave out the declaration you have a good chance that your check will work anyway - at least in adhoc mode with cmk -nv HOST.
The big surprise comes when you restart Nagios and let it do the actual checking. Check_MK creates a dedicated Python program for each host. And that contains only the check files used by that host - and - the declared include files needed by those checks!
If unsure you better try out whether your checks also work in precompiled mode. Precompilation can be triggered with cmk -C (and is implicitely done on -U, -O and -R). The files are stored in /var/lib/check_mk/precompiled (OMD: ~/var/check_mk/precompiled). You can run these files with python. They understand the (only) option -v:
root@linux# cmk -C root@linux# python /var/lib/check_mk/precompiled/localhost -v Check_mk version 1.1.9i9 NIC wlan0 OK - link is up OK - Agent version (unknown), execution time 0.0 sec|execution_time=0.022
Make sure that your monitoring core is running when you do this. Otherwise the precompiled script will not be able to submit its check results and run into an error.