#!/usr/bin/env python3 # pylint: disable=too-many-locals """HAL9002 check for storages""" import time from pprint import pprint from cmk.utils import debug # import necessary elements from API version 2 from cmk.agent_based.v2 import ( AgentSection, CheckPlugin, Service, Result, State, render, get_value_store, check_levels, ) def parse_hal9002_storages(string_table): """the parse function""" parsed_data = {} # convert the raw output of the agent section in an meaningful structure # do type conversions and so on parsed_data = {} for line in string_table: storageid = line[0] realname = line[1] upload = int(float(line[2])) download = int(float(line[3])) parsed_data[f"{storageid}"] = [realname, upload, download] return parsed_data def discover_hal9002_storages(section): """the discover function""" # since we have a service with item here we must create one service per item for key in section: yield Service(item=key) def check_hal9002_storages(item, params, section): """the check function""" if debug.enabled(): pprint(section) curr_time = time.time() # needed for calculating rates attr = section.get(item) if not attr: # if a previously found storage does not exist anymore, create a meaningful result yield Result( state=State.UNKNOWN, summary="Storage not found anymore, maybe it was deleted?", ) return # get all info of the storage storage_id = item realname = attr[0] ul_bytes = attr[1] dl_bytes = attr[2] # these are the keys for our value_store vs_key_ul = f"hal9002_{storage_id}_ul" vs_key_dl = f"hal9002_{storage_id}_dl" vs_key_time = f"hal9002_{storage_id}_time" # we have to persist our upload/download values so that we can calculate rates value_store = get_value_store() # get the values from last run ul_last = value_store.get(vs_key_ul, 0) dl_last = value_store.get(vs_key_dl, 0) time_last = value_store.get(vs_key_time, 0) # store the new values value_store[vs_key_ul] = ul_bytes value_store[vs_key_dl] = dl_bytes value_store[vs_key_time] = curr_time # now calculate the rates time_delta = curr_time - time_last # avoid dividing by null and getting negative rates if time_delta <= 0: # should not happen at all :-) ul_rate = 1024.0 dl_rate = 2048.0 else: ul_rate = (ul_bytes - ul_last) / time_delta dl_rate = (dl_bytes - dl_last) / time_delta diff_ul = ul_bytes - ul_last diff_dl = dl_bytes - dl_last # levels are defined as MBytes/s in our rule, so we have to adjust this here # because we are getting Bytes/s from our rate calculation level_type, levels = params["levels_hal_storages_rates"] warn, crit = levels warn = warn * (1024**2) crit = crit * (1024**2) levels = (level_type, (warn, crit)) # create graphs and results for upload/download rates # this replaces all calls of yield Result|Metric # metric_name must be used within the graphing templates yield from check_levels( value=ul_rate, levels_upper=levels, metric_name="hal_storage_upload_rate", render_func=render.iobandwidth, label=f"Transfer rates of {realname} - Up", notice_only=False, ) yield from check_levels( value=dl_rate, levels_upper=levels, metric_name="hal_storage_download_rate", render_func=render.iobandwidth, label="Down", notice_only=False, ) # these appear only in the details section yield from check_levels( value=diff_ul, metric_name="hal_storage_last_upload", render_func=render.bytes, label="Upload since last check: ", notice_only=True, ) yield from check_levels( value=diff_dl, metric_name="hal_storage_last_download", render_func=render.bytes, label="Download since last check: ", notice_only=True, ) # create the new agent section, must begin with "agent_section_" # and must be an instance of "AgentSection" agent_section_hal9002_storages = AgentSection( # "name" must exactly match the section name within the agent output name="hal9002_storages", # define the parse function, name is arbitrary, a good choice is to choose # "parse_" as prefix and append the section name parse_function=parse_hal9002_storages, ) # create the new check plugin, must begin with "check_plugin_" # and must be an instance of "CheckPlugin" check_plugin_hal9002_storages = CheckPlugin( # "name" should be the same as the corresponding section within the agent output name="hal9002_storages", # this is a service with item, so you have to include a place holder for the item id service_name="HAL9002 storage %s", # define the discovery function, name is arbitrary, a good choice is to choose # "discover_" as prefix and append the section name discovery_function=discover_hal9002_storages, # define the check function, name is arbitrary, a good choice is to choose # "check_" as prefix and append the section name check_function=check_hal9002_storages, # define the default parameters check_default_parameters={"levels_hal_storages_rates": ("fixed", (200.0, 300.0))}, # connect to the ruleset where parameters can be defined # must match the name of the ruleset exactly check_ruleset_name="hal9002_storages", )