initial commit source files
This commit is contained in:
parent
be36e53edf
commit
2e8733a1b3
80
hal9002/agent_based/hal9002_status.py
Normal file
80
hal9002/agent_based/hal9002_status.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=missing-module-docstring, unused-argument, missing-function-docstring
|
||||||
|
|
||||||
|
# import necessary elements from API version 2
|
||||||
|
from cmk.agent_based.v2 import (
|
||||||
|
AgentSection,
|
||||||
|
CheckPlugin,
|
||||||
|
Service,
|
||||||
|
Result,
|
||||||
|
State,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_hal9002_status(string_table):
|
||||||
|
"""the parse function"""
|
||||||
|
parsed_data = {}
|
||||||
|
# we only expect one line with four entries
|
||||||
|
line = string_table[0]
|
||||||
|
parsed_data["status"] = line[0]
|
||||||
|
parsed_data["version"] = line[1]
|
||||||
|
parsed_data["username"] = line[2]
|
||||||
|
parsed_data["ipaddress"] = line[3]
|
||||||
|
return parsed_data
|
||||||
|
|
||||||
|
|
||||||
|
def discover_hal9002_status(section):
|
||||||
|
"""the discover function"""
|
||||||
|
yield Service()
|
||||||
|
|
||||||
|
|
||||||
|
def check_hal9002_status(params, section):
|
||||||
|
"""the check function"""
|
||||||
|
# print(params["state_if_update_is_available"])
|
||||||
|
status = section["status"]
|
||||||
|
version = section["version"]
|
||||||
|
username = section["username"]
|
||||||
|
ipaddress = section["ipaddress"]
|
||||||
|
# check what status is reported and set state accordingly
|
||||||
|
if status == "ok":
|
||||||
|
state = State.OK
|
||||||
|
elif status == "update available":
|
||||||
|
state = params["state_if_update_is_available"]
|
||||||
|
elif status == "storage down":
|
||||||
|
state = State.CRIT
|
||||||
|
else:
|
||||||
|
state = State.UNKNOWN
|
||||||
|
summary = f'Status is "{status}", Version is "{version}"'
|
||||||
|
details = f'User/IP used for access is "{username}/{ipaddress}"'
|
||||||
|
# no metrics, just a simple service
|
||||||
|
yield Result(state=state, summary=summary, details=details)
|
||||||
|
|
||||||
|
|
||||||
|
# create the new agent section, must begin with "agent_section_"
|
||||||
|
# and must be an instance of "AgentSection"
|
||||||
|
agent_section_hal9002_status = AgentSection(
|
||||||
|
# "name" must exactly match the section name within the agent output
|
||||||
|
name="hal9002_status",
|
||||||
|
# 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_status,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create the new check plugin, must begin with "check_plugin_"
|
||||||
|
# and must be an instance of "CheckPlugin"
|
||||||
|
check_plugin_hal9002_status = CheckPlugin(
|
||||||
|
# "name" should be the same as the corresponding section within the agent output
|
||||||
|
name="hal9002_status",
|
||||||
|
service_name="HAL9002 Status",
|
||||||
|
# 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_status,
|
||||||
|
# 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_status,
|
||||||
|
# define the default parameters
|
||||||
|
check_default_parameters={"state_if_update_is_available": State.WARN},
|
||||||
|
# connect to the ruleset where parameters can be defined
|
||||||
|
# must match the name of the ruleset exactly
|
||||||
|
check_ruleset_name="hal9002_status",
|
||||||
|
)
|
162
hal9002/agent_based/hal9002_storages.py
Normal file
162
hal9002/agent_based/hal9002_storages.py
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
"""HAL9002 check for storages"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
# 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"""
|
||||||
|
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",
|
||||||
|
)
|
107
hal9002/agent_based/hal9002_users.py
Normal file
107
hal9002/agent_based/hal9002_users.py
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
"""HAL9002 checks for users"""
|
||||||
|
|
||||||
|
# import necessary elements from API version 2
|
||||||
|
from cmk.agent_based.v2 import (
|
||||||
|
AgentSection,
|
||||||
|
CheckPlugin,
|
||||||
|
Service,
|
||||||
|
Result,
|
||||||
|
State,
|
||||||
|
render,
|
||||||
|
check_levels,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_hal9002_users(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:
|
||||||
|
userid = line[0]
|
||||||
|
realname = line[1]
|
||||||
|
quota_used = float(line[2])
|
||||||
|
quota_total = float(line[3])
|
||||||
|
parsed_data[f"{userid}"] = [realname, quota_used, quota_total]
|
||||||
|
return parsed_data
|
||||||
|
|
||||||
|
|
||||||
|
def discover_hal9002_users(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_users(item, params, section):
|
||||||
|
"""the check function"""
|
||||||
|
attr = section.get(item)
|
||||||
|
if not attr:
|
||||||
|
# if a previously found user does not exist anymore, create a meaningful result
|
||||||
|
yield Result(
|
||||||
|
state=State.UNKNOWN, summary="User not found anymore, maybe it was deleted?"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
# this refers to the definition of the parameters
|
||||||
|
# within the appropriate ruleset dictionary element
|
||||||
|
levels = params["quota_used_percent"]
|
||||||
|
|
||||||
|
# get all info of the user
|
||||||
|
user_name = attr[0]
|
||||||
|
used_bytes = attr[1]
|
||||||
|
quota_max_bytes = attr[2]
|
||||||
|
# calculate percentage of quota used
|
||||||
|
quota_used_percent = used_bytes * 100 / quota_max_bytes
|
||||||
|
|
||||||
|
# create graphs and results for used quota
|
||||||
|
# this replaces all calls of yield Result|Metric
|
||||||
|
# metric_name must be used within the graphing templates
|
||||||
|
yield from check_levels(
|
||||||
|
value=quota_used_percent,
|
||||||
|
levels_upper=levels,
|
||||||
|
metric_name="hal_user_quota_used_percent",
|
||||||
|
render_func=render.percent,
|
||||||
|
label=f"Used quota of {user_name}",
|
||||||
|
notice_only=False,
|
||||||
|
)
|
||||||
|
yield from check_levels(
|
||||||
|
value=used_bytes,
|
||||||
|
metric_name="hal_user_used_bytes",
|
||||||
|
render_func=render.bytes,
|
||||||
|
label=f"Used from {render.disksize(quota_max_bytes)}",
|
||||||
|
notice_only=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# create the new agent section, must begin with "agent_section_"
|
||||||
|
# and must be an instance of "AgentSection"
|
||||||
|
agent_section_hal9002_users = AgentSection(
|
||||||
|
# "name" must exactly match the section name within the agent output
|
||||||
|
name="hal9002_users",
|
||||||
|
# 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_users,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create the new check plugin, must begin with "check_plugin_"
|
||||||
|
# and must be an instance of "CheckPlugin"
|
||||||
|
check_plugin_hal9002_users = CheckPlugin(
|
||||||
|
# "name" should be the same as the corresponding section within the agent output
|
||||||
|
name="hal9002_users",
|
||||||
|
# this is a service with item, so you have to include a place holder for the item id
|
||||||
|
service_name="HAL9002 user %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_users,
|
||||||
|
# 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_users,
|
||||||
|
# define the default parameters
|
||||||
|
check_default_parameters={"quota_used_percent": ("fixed", (80.0, 90.0))},
|
||||||
|
# connect to the ruleset where parameters can be defined
|
||||||
|
# must match the name of the ruleset exactly
|
||||||
|
check_ruleset_name="hal9002_users",
|
||||||
|
)
|
12
hal9002/checkman/hal9002_status
Normal file
12
hal9002/checkman/hal9002_status
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
title: HAL9002: Overall Status
|
||||||
|
agents: linux
|
||||||
|
catalog: unsorted
|
||||||
|
license: GPL
|
||||||
|
distribution: check_mk
|
||||||
|
description:
|
||||||
|
Show info about HAL9002 storage systems, e.g. overall status and version
|
||||||
|
The check will raise WARN/CRIT if not "ok", dependig on the reported internal state
|
||||||
|
item:
|
||||||
|
none
|
||||||
|
inventory:
|
||||||
|
one service with overall information
|
13
hal9002/checkman/hal9002_storages
Normal file
13
hal9002/checkman/hal9002_storages
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
title: HAL9002: Storage Upload/Download Rate
|
||||||
|
agents: linux
|
||||||
|
catalog: unsorted
|
||||||
|
license: GPL
|
||||||
|
distribution: check_mk
|
||||||
|
description:
|
||||||
|
Shows the upload/download rate of storages in bytes/s
|
||||||
|
The check will raise WARN/CRIT if rates are above the levels which can be defined
|
||||||
|
with the appropriate rule set.
|
||||||
|
item:
|
||||||
|
storageid
|
||||||
|
inventory:
|
||||||
|
one service is created for each storage
|
13
hal9002/checkman/hal9002_users
Normal file
13
hal9002/checkman/hal9002_users
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
title: HAL9001: Quota Usage of Users
|
||||||
|
agents: linux
|
||||||
|
catalog: unsorted
|
||||||
|
license: GPL
|
||||||
|
distribution: check_mk
|
||||||
|
description:
|
||||||
|
Shows the usage of storage quota used by each user in percent of the maximum allowed quota
|
||||||
|
The check will raise WARN/CRIT if usage is above the levels which can be defined
|
||||||
|
with the apprppriate rule set.
|
||||||
|
item:
|
||||||
|
userid
|
||||||
|
inventory:
|
||||||
|
one service is created for each user
|
97
hal9002/graphing/graph_hal9002.py
Normal file
97
hal9002/graphing/graph_hal9002.py
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""graphing and metrics definitions"""
|
||||||
|
|
||||||
|
from cmk.graphing.v1 import Title
|
||||||
|
from cmk.graphing.v1.graphs import Graph, MinimalRange
|
||||||
|
from cmk.graphing.v1.metrics import Color, DecimalNotation, Metric, Unit, SINotation
|
||||||
|
from cmk.graphing.v1.perfometers import (
|
||||||
|
Open,
|
||||||
|
Closed,
|
||||||
|
FocusRange,
|
||||||
|
Perfometer,
|
||||||
|
Bidirectional,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
## Metrics
|
||||||
|
# metrics must begin with "metric_" and be an instance of "Metric"
|
||||||
|
metric_hal9002_user_quota_used = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="hal_user_quota_used_percent",
|
||||||
|
title=Title("Percentage of storage quota used"),
|
||||||
|
unit=Unit(DecimalNotation("%")),
|
||||||
|
color=Color.DARK_ORANGE,
|
||||||
|
)
|
||||||
|
|
||||||
|
metric_hal9002_user_bytes_used = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="hal_user_used_bytes",
|
||||||
|
title=Title("Used storage"),
|
||||||
|
unit=Unit(SINotation("bytes")),
|
||||||
|
color=Color.DARK_CYAN,
|
||||||
|
)
|
||||||
|
|
||||||
|
metric_hal9002_storage_upload_rate = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="hal_storage_upload_rate",
|
||||||
|
title=Title("Storage upload rate"),
|
||||||
|
unit=Unit(SINotation("bytes/s")),
|
||||||
|
color=Color.DARK_GREEN,
|
||||||
|
)
|
||||||
|
|
||||||
|
metric_hal9002_storage_download_rate = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="hal_storage_download_rate",
|
||||||
|
title=Title("Storage download rate"),
|
||||||
|
unit=Unit(SINotation("bytes/s")),
|
||||||
|
color=Color.LIGHT_GREEN,
|
||||||
|
)
|
||||||
|
|
||||||
|
metric_hal9002_storage_upload_last = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="hal_storage_last_upload",
|
||||||
|
title=Title("Upload since last check"),
|
||||||
|
unit=Unit(SINotation("bytes")),
|
||||||
|
color=Color.DARK_BLUE,
|
||||||
|
)
|
||||||
|
|
||||||
|
metric_hal9002_storage_download_last = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="hal_storage_last_download",
|
||||||
|
title=Title("Download since last check"),
|
||||||
|
unit=Unit(SINotation("bytes")),
|
||||||
|
color=Color.LIGHT_BLUE,
|
||||||
|
)
|
||||||
|
|
||||||
|
## Perfometers
|
||||||
|
# perfometers must begin with "perfometer_" and be an instance of "Perfometer"
|
||||||
|
perfometer_hal9002_users_quota_used = Perfometer(
|
||||||
|
name="hal9002_users_quota_used",
|
||||||
|
focus_range=FocusRange(Closed(0), Closed(100)),
|
||||||
|
# "segments" must be exactly the name of the metric
|
||||||
|
segments=["hal_user_quota_used_percent"],
|
||||||
|
)
|
||||||
|
|
||||||
|
perfometer_hal9002_storage_rates = Bidirectional(
|
||||||
|
name="hal9002_storage_rates",
|
||||||
|
left=Perfometer(
|
||||||
|
name="hal9002_storage_download_rate",
|
||||||
|
focus_range=FocusRange(Open(0.0), Open(500.0)),
|
||||||
|
segments=["hal_storage_download_rate"],
|
||||||
|
),
|
||||||
|
right=Perfometer(
|
||||||
|
name="hal9002_storage_upload_rate",
|
||||||
|
focus_range=FocusRange(Open(0.0), Open(500.0)),
|
||||||
|
segments=["hal_storage_upload_rate"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
## Combined Graphs
|
||||||
|
# combined graphs must begin with "graph_" and be an instance of "Graph"
|
||||||
|
graph_hal9002_storages_upload_download = Graph(
|
||||||
|
name="hal9002_storage_upload_download",
|
||||||
|
title=Title("Storage upload/download rate"),
|
||||||
|
# names here refer to the metric names above
|
||||||
|
simple_lines=["hal_storage_download_rate", "hal_storage_upload_rate"],
|
||||||
|
minimal_range=MinimalRange(0, 100),
|
||||||
|
)
|
349
hal9002/libexec/agent_hal9002
Executable file
349
hal9002/libexec/agent_hal9002
Executable file
@ -0,0 +1,349 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""HAL9002 special agent"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import getopt
|
||||||
|
import random
|
||||||
|
|
||||||
|
"""
|
||||||
|
Sample output
|
||||||
|
|
||||||
|
<<<hal9002_status:sep(59)>>>
|
||||||
|
ok;SK-1st-Edition 1965-12-17;arthur;127.0.0.1
|
||||||
|
|
||||||
|
1. Status, possible values: ok, update available, storage down (String)
|
||||||
|
2. Version (String)
|
||||||
|
3. Username used for login (String)
|
||||||
|
4. IP used for access (String)
|
||||||
|
5. Desired state, id an update is available (String)
|
||||||
|
|
||||||
|
<<<hal9002_users:sep(59)>>>
|
||||||
|
user1;David Bowman;65536.0;262144.0
|
||||||
|
user2;Frank Poole;16384.0;131072.0
|
||||||
|
user3;Elena;32768.0;65536.0
|
||||||
|
|
||||||
|
1. User ID (string)
|
||||||
|
2. User Real Name (string)
|
||||||
|
3. Quota Used (float in bytes, absolut)
|
||||||
|
4. Quota Max (float in bytes, absolut)
|
||||||
|
|
||||||
|
<<<hal9002_storages:sep(59)>>>
|
||||||
|
storage1;DATA_Dullea;8192.0;262144.0
|
||||||
|
storage2;DATA_Poole;2048.0;131072.0
|
||||||
|
|
||||||
|
1. Storage ID (string)
|
||||||
|
2. Storage Custom Name (string)
|
||||||
|
3. Upload (float in bytes, counter)
|
||||||
|
4. Download (float in bytes, counter)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def show_usage() -> None:
|
||||||
|
"""shows help for usage"""
|
||||||
|
sys.stderr.write(
|
||||||
|
"""HAL9002 Special Agent
|
||||||
|
USAGE: agent_hal9002 -H [hostname] -u [username] -p [password]
|
||||||
|
agent_hal9002 -h
|
||||||
|
OPTIONS:
|
||||||
|
-H, --hostname Hostname (FQDN or IP) of HAL System
|
||||||
|
-u, --username Username
|
||||||
|
-p, --password Password
|
||||||
|
-s, --state-if-update-is-available State of service if an update is available (0/1/2/3)
|
||||||
|
-h, --help Show this help message and exit
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
SEP: str = "|"
|
||||||
|
TIMEFMT: str = "%Y-%m-%d %H:%M:%S"
|
||||||
|
FLOATFMT: str = "{:.4f}"
|
||||||
|
|
||||||
|
# Parameters coming from CheckMK
|
||||||
|
opt_hostname: str = ""
|
||||||
|
opt_username: str = ""
|
||||||
|
opt_password: str = ""
|
||||||
|
opt_state_if_update_is_available: str = ""
|
||||||
|
|
||||||
|
# Base values for randomly calculating the use of the storage system per user
|
||||||
|
base_usage: float = float(65536 * 8) # 0.5 MByte
|
||||||
|
max_quota: float = 1073741824.0 # 1 GByte
|
||||||
|
|
||||||
|
# these dicts are used as starting points, feel free to extend and/or adjust them
|
||||||
|
# each user/storage results in an additional service
|
||||||
|
users_dict: dict[str, str] = {
|
||||||
|
"user1": {
|
||||||
|
"realname": "David Bowman",
|
||||||
|
"usage": base_usage * 2,
|
||||||
|
"quota_max": max_quota,
|
||||||
|
},
|
||||||
|
"user2": {
|
||||||
|
"realname": "Frank Poole",
|
||||||
|
"usage": base_usage * 3,
|
||||||
|
"quota_max": max_quota / 2,
|
||||||
|
},
|
||||||
|
"user3": {"realname": "Elena", "usage": base_usage * 4, "quota_max": max_quota * 2},
|
||||||
|
}
|
||||||
|
|
||||||
|
storages_dict: dict[str, str] = {
|
||||||
|
"storage1": {
|
||||||
|
"realname": "DATA_Dullea",
|
||||||
|
"download": float(1024**3),
|
||||||
|
"upload": float((1024**2) * 6),
|
||||||
|
},
|
||||||
|
"storage2": {
|
||||||
|
"realname": "DATA_Poole",
|
||||||
|
"download": float(1024**3),
|
||||||
|
"upload": float((1024**2) * 4),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
hal_status_list: list[str] = ["ok", "update available", "storage down"]
|
||||||
|
hal_version: str = "SK-1st-Edition 1965-12-17"
|
||||||
|
|
||||||
|
short_options: str = "hH:u:p:s:"
|
||||||
|
long_options: list[str] = [
|
||||||
|
"hostname=",
|
||||||
|
"username=",
|
||||||
|
"password=",
|
||||||
|
"state-if-update-is-available=",
|
||||||
|
"help",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_options() -> None:
|
||||||
|
"""retrieves all command line options"""
|
||||||
|
global opt_hostname
|
||||||
|
global opt_username
|
||||||
|
global opt_password
|
||||||
|
global opt_state_if_update_is_available
|
||||||
|
|
||||||
|
opts, _ = getopt.getopt(sys.argv[1:], short_options, long_options)
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt in ["-H", "--hostname"]:
|
||||||
|
opt_hostname = arg
|
||||||
|
if opt in ["-u", "--username"]:
|
||||||
|
opt_username = arg
|
||||||
|
elif opt in ["-p", "--password"]:
|
||||||
|
opt_password = arg
|
||||||
|
elif opt in ["-s", "--state-if-update-is-available"]:
|
||||||
|
opt_state_if_update_is_available = arg
|
||||||
|
elif opt in ["-h", "--help"]:
|
||||||
|
show_usage()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def show_options() -> None:
|
||||||
|
"""show the options from the command line"""
|
||||||
|
print(f"Hostname: {opt_hostname}")
|
||||||
|
print(f"Username: {opt_username}")
|
||||||
|
print(f"Password: {opt_password}")
|
||||||
|
print(f"State if update is available: {opt_state_if_update_is_available}")
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_new_user_storage(current_storage: float) -> float:
|
||||||
|
"""calculates new values for the user's storage"""
|
||||||
|
# let the chance that no change occured be at 90%
|
||||||
|
no_change: int = random.randint(1, 100)
|
||||||
|
if no_change > 10:
|
||||||
|
return float(current_storage)
|
||||||
|
else:
|
||||||
|
# create some variance, value of "amount" is interpreted in bytes
|
||||||
|
factor: int = random.randint(1, 4)
|
||||||
|
amount: int = random.randint(1024000, 4096000)
|
||||||
|
amount *= factor
|
||||||
|
# increase or decrease, give increase a better chance (60:40), that's more real :-)
|
||||||
|
plus_or_minus: int = random.randint(1, 100)
|
||||||
|
if plus_or_minus > 40:
|
||||||
|
new_storage: int = current_storage + amount
|
||||||
|
else:
|
||||||
|
new_storage: int = current_storage - amount
|
||||||
|
# avoid negative values
|
||||||
|
if new_storage < 0:
|
||||||
|
new_storage = 1024000
|
||||||
|
return float(new_storage)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_new_storage_counters(
|
||||||
|
ul_bytes: float, dl_bytes: float
|
||||||
|
) -> tuple[float, float]:
|
||||||
|
"""calculates new values for the user's storage counters"""
|
||||||
|
# let the chance that no change occured be at 2%
|
||||||
|
no_change: int = random.randint(1, 100)
|
||||||
|
if no_change > 98:
|
||||||
|
return float(ul_bytes), float(dl_bytes)
|
||||||
|
# create some variance, values of "amount_<ul|dl>" is interpreted in bytes
|
||||||
|
factor_ul: int = random.randint(1, 7)
|
||||||
|
amount_ul: int = random.randint(20240000, 50960000)
|
||||||
|
amount_ul *= factor_ul
|
||||||
|
factor_dl: int = random.randint(1, 14)
|
||||||
|
amount_dl: int = random.randint(30240000, 60960000)
|
||||||
|
amount_dl *= factor_dl
|
||||||
|
# we are simulating counters, so only increasing makes sense
|
||||||
|
new_ul_bytes: int = ul_bytes + amount_ul
|
||||||
|
new_dl_bytes: int = dl_bytes + amount_dl
|
||||||
|
return float(new_ul_bytes), float(new_dl_bytes)
|
||||||
|
|
||||||
|
|
||||||
|
def do_cmk_hal_status_output(
|
||||||
|
status: str,
|
||||||
|
version: str,
|
||||||
|
username: str,
|
||||||
|
ipaddress: str,
|
||||||
|
state_if_update_is_available: str,
|
||||||
|
) -> None:
|
||||||
|
"""prints out the section for status"""
|
||||||
|
print("<<<hal9002_status:sep(59)>>>")
|
||||||
|
print(f"{status};{version};{username};{ipaddress};{state_if_update_is_available}")
|
||||||
|
|
||||||
|
|
||||||
|
def do_cmk_hal_users_output(users: dict, hostname: str) -> None:
|
||||||
|
"""prints out the section for users"""
|
||||||
|
print("<<<hal9002_users:sep(59)>>>")
|
||||||
|
current_storage: float = 0.0
|
||||||
|
home_path: str = os.getenv("HOME")
|
||||||
|
tmp_path: str = f"{home_path}/tmp"
|
||||||
|
for user in users:
|
||||||
|
# we need a way to store the current value for storage usage between runs of the agent
|
||||||
|
help_file: str = f"{tmp_path}/hal9002_{hostname}_{user}_current_storage.txt"
|
||||||
|
if os.path.exists(help_file):
|
||||||
|
# help file exists, so get the content
|
||||||
|
with open(help_file, "r", encoding="utf-8") as file:
|
||||||
|
current_storage = float(file.read())
|
||||||
|
else:
|
||||||
|
# help file does not exist, create it and store the start value in it
|
||||||
|
with open(help_file, "w", encoding="utf-8") as file:
|
||||||
|
file.write(str(users[user]["usage"]))
|
||||||
|
current_storage = users[user]["usage"]
|
||||||
|
realname: str = users[user]["realname"]
|
||||||
|
quota_max: str = users[user]["quota_max"]
|
||||||
|
# simulate changes in storage usage
|
||||||
|
new_storage: float = calculate_new_user_storage(current_storage)
|
||||||
|
# save the new value in help file
|
||||||
|
with open(help_file, "w", encoding="utf-8") as file:
|
||||||
|
file.write(str(new_storage))
|
||||||
|
# create output
|
||||||
|
print(f"{user};{realname};{new_storage};{quota_max}")
|
||||||
|
|
||||||
|
|
||||||
|
def do_cmk_hal_storages_output(storages: dict, hostname: str) -> None:
|
||||||
|
"""prints out the section for storages"""
|
||||||
|
print("<<<hal9002_storages:sep(59)>>>")
|
||||||
|
current_dl_bytes: float = 0.0
|
||||||
|
current_ul_bytes: float = 0.0
|
||||||
|
new_dl_bytes: float = 0.0
|
||||||
|
new_ul_bytes: float = 0.0
|
||||||
|
home_path: str = os.getenv("HOME")
|
||||||
|
tmp_path: str = f"{home_path}/tmp"
|
||||||
|
for storage in storages:
|
||||||
|
# we need a way to store the current values for storage usage between runs of the agent
|
||||||
|
# so we can simulate counters for uploaded/downloaded bytes
|
||||||
|
help_file_ul: str = f"{tmp_path}/hal9002_{hostname}_{storage}_ul_bytes.txt"
|
||||||
|
help_file_dl: str = f"{tmp_path}/hal9002_{hostname}_{storage}_dl_bytes.txt"
|
||||||
|
if os.path.exists(help_file_ul):
|
||||||
|
# help file exists, so get the content
|
||||||
|
with open(help_file_ul, "r", encoding="utf-8") as file:
|
||||||
|
current_ul_bytes = float(file.read())
|
||||||
|
else:
|
||||||
|
# help file does not exist, create it and store the start value in it
|
||||||
|
with open(help_file_ul, "w", encoding="utf-8") as file:
|
||||||
|
file.write(str(storages[storage]["upload"]))
|
||||||
|
current_ul_bytes = storages[storage]["upload"]
|
||||||
|
if os.path.exists(help_file_dl):
|
||||||
|
# help file exists, so get the content
|
||||||
|
with open(help_file_dl, "r", encoding="utf-8") as file:
|
||||||
|
current_dl_bytes = float(file.read())
|
||||||
|
else:
|
||||||
|
# help file does not exist, create it and store the start value in it
|
||||||
|
with open(help_file_dl, "w", encoding="utf-8") as file:
|
||||||
|
file.write(str(storages[storage]["download"]))
|
||||||
|
current_dl_bytes = storages[storage]["download"]
|
||||||
|
realname: str = storages[storage]["realname"]
|
||||||
|
# simulate changes in storage usage
|
||||||
|
new_ul_bytes, new_dl_bytes = calculate_new_storage_counters(
|
||||||
|
current_ul_bytes, current_dl_bytes
|
||||||
|
)
|
||||||
|
# save the new values in help files
|
||||||
|
with open(help_file_ul, "w", encoding="utf-8") as file:
|
||||||
|
file.write(str(new_ul_bytes))
|
||||||
|
with open(help_file_dl, "w", encoding="utf-8") as file:
|
||||||
|
file.write(str(new_dl_bytes))
|
||||||
|
# create output
|
||||||
|
print(f"{storage};{realname};{new_ul_bytes};{new_dl_bytes}")
|
||||||
|
|
||||||
|
|
||||||
|
def get_status() -> tuple[str, str]:
|
||||||
|
"""returns status and version"""
|
||||||
|
# randomly set one of the three available states
|
||||||
|
hal_status: str = ""
|
||||||
|
status_index: int = random.randint(1, 100)
|
||||||
|
if status_index <= 5:
|
||||||
|
# should result in critical state
|
||||||
|
hal_status = hal_status_list[2]
|
||||||
|
elif status_index <= 15:
|
||||||
|
# should result in warning state
|
||||||
|
hal_status = hal_status_list[1]
|
||||||
|
else:
|
||||||
|
# should result in ok state
|
||||||
|
hal_status = hal_status_list[0]
|
||||||
|
return hal_status, hal_version
|
||||||
|
|
||||||
|
|
||||||
|
def do_login(_hostname: str, _username: str, _password: str) -> tuple[bool, int]:
|
||||||
|
"""returns whetjer login was successful or not and a status code"""
|
||||||
|
# simulate the login to our HAL system
|
||||||
|
# give it a chance of 2% to fail to demonstrate an error from time to time
|
||||||
|
success: int = random.randint(1, 100)
|
||||||
|
if success > 2:
|
||||||
|
return True, 200
|
||||||
|
return False, 401
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""main function"""
|
||||||
|
success: bool = False
|
||||||
|
code: int = -1
|
||||||
|
status: str = "no status"
|
||||||
|
version: str = "no version"
|
||||||
|
get_options()
|
||||||
|
# show_options()
|
||||||
|
# some checks
|
||||||
|
# keep in mind: the 1st line printed out to std.err will be shown as check result in CheckMK
|
||||||
|
if opt_hostname == "":
|
||||||
|
sys.stderr.write("No hostname given.\n")
|
||||||
|
show_usage()
|
||||||
|
sys.exit(1)
|
||||||
|
if opt_username == "":
|
||||||
|
sys.stderr.write("No username given.\n")
|
||||||
|
show_usage()
|
||||||
|
sys.exit(1)
|
||||||
|
if opt_password == "":
|
||||||
|
sys.stderr.write("No password given.\n")
|
||||||
|
show_usage()
|
||||||
|
sys.exit(1)
|
||||||
|
# if opt_state_if_update_is_available == "":
|
||||||
|
# sys.stderr.write("No state given when update is available.\n")
|
||||||
|
# show_usage()
|
||||||
|
# sys.exit(1)
|
||||||
|
success, code = do_login(opt_hostname, opt_username, opt_password)
|
||||||
|
if success:
|
||||||
|
status, version = get_status()
|
||||||
|
do_cmk_hal_status_output(
|
||||||
|
status,
|
||||||
|
version,
|
||||||
|
opt_username,
|
||||||
|
opt_hostname,
|
||||||
|
opt_state_if_update_is_available,
|
||||||
|
)
|
||||||
|
do_cmk_hal_users_output(users_dict, opt_hostname)
|
||||||
|
do_cmk_hal_storages_output(storages_dict, opt_hostname)
|
||||||
|
else:
|
||||||
|
sys.stderr.write(
|
||||||
|
f"Login to {opt_hostname} with user {opt_username} failed with error code {code}\n"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
58
hal9002/rulesets/rs_hal9002_params.py
Normal file
58
hal9002/rulesets/rs_hal9002_params.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
"""defines the form for typing in all needed HAL9002 parameters"""
|
||||||
|
|
||||||
|
from cmk.rulesets.v1 import Help, Title
|
||||||
|
from cmk.rulesets.v1.form_specs import (
|
||||||
|
DictElement,
|
||||||
|
Dictionary,
|
||||||
|
migrate_to_password,
|
||||||
|
Password,
|
||||||
|
String,
|
||||||
|
validators,
|
||||||
|
)
|
||||||
|
from cmk.rulesets.v1.rule_specs import SpecialAgent, Topic
|
||||||
|
|
||||||
|
|
||||||
|
def _form_spec_special_agent_hal9002() -> Dictionary:
|
||||||
|
return Dictionary(
|
||||||
|
title=Title("HAL 9002 Server Information"),
|
||||||
|
help_text=Help("Checking HAL servers via API"),
|
||||||
|
elements={
|
||||||
|
"hostname": DictElement(
|
||||||
|
required=True,
|
||||||
|
parameter_form=String(
|
||||||
|
title=Title("Hostname"),
|
||||||
|
help_text=Help(
|
||||||
|
"Hostname of HAL server (bare FQDN or IP), mandatory, eg. hal9002.yourdomain.tld"
|
||||||
|
),
|
||||||
|
custom_validate=(validators.LengthInRange(min_value=1),),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"username": DictElement(
|
||||||
|
required=True,
|
||||||
|
parameter_form=String(
|
||||||
|
title=Title("Username"),
|
||||||
|
help_text=Help("Username with administrative rights, mandatory"),
|
||||||
|
custom_validate=(validators.LengthInRange(min_value=1),),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"password": DictElement(
|
||||||
|
required=True,
|
||||||
|
parameter_form=Password(
|
||||||
|
title=Title("Password"),
|
||||||
|
help_text=Help("Specify password, mandatory"),
|
||||||
|
custom_validate=(validators.LengthInRange(min_value=1),),
|
||||||
|
migrate=migrate_to_password,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
rule_spec_hal9002 = SpecialAgent(
|
||||||
|
name="hal9002",
|
||||||
|
title=Title("HAL9002 connection parameters"),
|
||||||
|
topic=Topic.APPLICATIONS,
|
||||||
|
parameter_form=_form_spec_special_agent_hal9002,
|
||||||
|
)
|
48
hal9002/rulesets/rs_hal9002_status.py
Normal file
48
hal9002/rulesets/rs_hal9002_status.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#!/user/bin/env python3
|
||||||
|
"""general parameter form for HAL9002"""
|
||||||
|
|
||||||
|
from cmk.rulesets.v1 import Help, Title
|
||||||
|
from cmk.rulesets.v1.form_specs import (
|
||||||
|
DictElement,
|
||||||
|
Dictionary,
|
||||||
|
ServiceState,
|
||||||
|
DefaultValue,
|
||||||
|
)
|
||||||
|
from cmk.agent_based.v2 import (
|
||||||
|
State,
|
||||||
|
)
|
||||||
|
|
||||||
|
from cmk.rulesets.v1.rule_specs import CheckParameters, Topic, HostCondition
|
||||||
|
|
||||||
|
|
||||||
|
# function name should begin with an underscore to limit it's visibility
|
||||||
|
def _parameter_form():
|
||||||
|
return Dictionary(
|
||||||
|
elements={
|
||||||
|
"state_if_update_is_available": DictElement(
|
||||||
|
required=True,
|
||||||
|
parameter_form=ServiceState(
|
||||||
|
title=Title("State if update is available"),
|
||||||
|
help_text=Help(
|
||||||
|
"State of service if an update is available, mandatory"
|
||||||
|
),
|
||||||
|
prefill=DefaultValue(value=State.WARN),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# name must begin with "rule_spec_", should refer to the used check plugin
|
||||||
|
# must be an instance of "CheckParameters"
|
||||||
|
rule_spec_hal9002_status = CheckParameters(
|
||||||
|
# "name" should be the same as the check plugin
|
||||||
|
name="hal9002_status",
|
||||||
|
# the title is shown in the GUI
|
||||||
|
title=Title("HAL9002 general parameters"),
|
||||||
|
# this ruleset can be found under Setup|Service monitoring rules|Applications...
|
||||||
|
topic=Topic.APPLICATIONS,
|
||||||
|
# define the name of the function which creates the GUI elements
|
||||||
|
parameter_form=_parameter_form,
|
||||||
|
condition=HostCondition(),
|
||||||
|
)
|
47
hal9002/rulesets/rs_hal9002_storages.py
Normal file
47
hal9002/rulesets/rs_hal9002_storages.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/user/bin/env python3
|
||||||
|
"""parameter form ruleset for HAL9002 storages"""
|
||||||
|
|
||||||
|
from cmk.rulesets.v1 import Title
|
||||||
|
from cmk.rulesets.v1.form_specs import (
|
||||||
|
DefaultValue,
|
||||||
|
DictElement,
|
||||||
|
Dictionary,
|
||||||
|
Float,
|
||||||
|
LevelDirection,
|
||||||
|
SimpleLevels,
|
||||||
|
)
|
||||||
|
from cmk.rulesets.v1.rule_specs import CheckParameters, HostAndItemCondition, Topic
|
||||||
|
|
||||||
|
|
||||||
|
# function name should begin with an underscore to limit it's visibility
|
||||||
|
def _parameter_form():
|
||||||
|
return Dictionary(
|
||||||
|
elements={
|
||||||
|
"levels_hal_storages_rates": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Levels for storage up and download rate"),
|
||||||
|
form_spec_template=Float(unit_symbol="MBytes/s"),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(200.0, 300.0)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# name must begin with "rule_spec_", should refer to the used check plugin
|
||||||
|
# must be an instance of "CheckParameters"
|
||||||
|
rule_spec_hal9002_storages = CheckParameters(
|
||||||
|
# "name" should be the same as the check plugin
|
||||||
|
name="hal9002_storages",
|
||||||
|
# the title is shown in the GUI
|
||||||
|
title=Title("HAL9002 levels for storage upload/download"),
|
||||||
|
# this ruleset can be found under Setup|Service monitoring rules|Applications...
|
||||||
|
topic=Topic.APPLICATIONS,
|
||||||
|
# define the name of the function which creates the GUI elements
|
||||||
|
parameter_form=_parameter_form,
|
||||||
|
# define the label in the GUI where you can restrict the
|
||||||
|
# settings to one or mor specific storages (item)
|
||||||
|
condition=HostAndItemCondition(item_title=Title("Storage ID")),
|
||||||
|
)
|
47
hal9002/rulesets/rs_hal9002_users.py
Normal file
47
hal9002/rulesets/rs_hal9002_users.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/user/bin/env python3
|
||||||
|
"""parameter form ruleset for HAL9002 users"""
|
||||||
|
|
||||||
|
from cmk.rulesets.v1 import Title
|
||||||
|
from cmk.rulesets.v1.form_specs import (
|
||||||
|
DefaultValue,
|
||||||
|
DictElement,
|
||||||
|
Dictionary,
|
||||||
|
Float,
|
||||||
|
LevelDirection,
|
||||||
|
SimpleLevels,
|
||||||
|
)
|
||||||
|
from cmk.rulesets.v1.rule_specs import CheckParameters, HostAndItemCondition, Topic
|
||||||
|
|
||||||
|
|
||||||
|
# function name should begin with an underscore to limit it's visibility
|
||||||
|
def _parameter_form():
|
||||||
|
return Dictionary(
|
||||||
|
elements={
|
||||||
|
"quota_used_percent": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Percentage thresholds for storage quota used"),
|
||||||
|
form_spec_template=Float(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(80.0, 90.0)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# name must begin with "rule_spec_", should refer to the used check plugin
|
||||||
|
# must be an instance of "CheckParameters"
|
||||||
|
rule_spec_hal9002_users = CheckParameters(
|
||||||
|
# "name" should be the same as the check plugin
|
||||||
|
name="hal9002_users",
|
||||||
|
# the title is shown in the GUI
|
||||||
|
title=Title("HAL9002 levels for user storage quota"),
|
||||||
|
# this ruleset can be found under Setup|Service monitoring rules|Applications...
|
||||||
|
topic=Topic.APPLICATIONS,
|
||||||
|
# define the name of the function which creates the GUI elements
|
||||||
|
parameter_form=_parameter_form,
|
||||||
|
# define the label in the GUI where you can restrict the
|
||||||
|
# settings to one or mor specific users (item)
|
||||||
|
condition=HostAndItemCondition(item_title=Title("User ID")),
|
||||||
|
)
|
42
hal9002/server_side_calls/agent_hal9002.py
Normal file
42
hal9002/server_side_calls/agent_hal9002.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
"""HAL9002 parameter handling for the special agent"""
|
||||||
|
|
||||||
|
from collections.abc import Iterable
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from cmk.server_side_calls.v1 import (
|
||||||
|
HostConfig,
|
||||||
|
Secret,
|
||||||
|
SpecialAgentCommand,
|
||||||
|
SpecialAgentConfig,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Hal9002Params(BaseModel):
|
||||||
|
"""defines all needed parameters for the special agent"""
|
||||||
|
|
||||||
|
hostname: str | None = None
|
||||||
|
username: str | None = None
|
||||||
|
password: Secret | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def agent_hal9002_arguments(
|
||||||
|
params: Hal9002Params, _host_config: HostConfig
|
||||||
|
) -> Iterable[SpecialAgentCommand]:
|
||||||
|
"""replaces the argument_thingy from the old API"""
|
||||||
|
command_arguments: list[str | Secret] = []
|
||||||
|
if params.hostname is not None:
|
||||||
|
command_arguments += ["--hostname", params.hostname]
|
||||||
|
if params.username is not None:
|
||||||
|
command_arguments += ["--username", params.username]
|
||||||
|
if params.password is not None:
|
||||||
|
command_arguments += ["--password", params.password.unsafe()]
|
||||||
|
yield SpecialAgentCommand(command_arguments=command_arguments)
|
||||||
|
|
||||||
|
|
||||||
|
special_agent_hal9002 = SpecialAgentConfig(
|
||||||
|
# name must be the filename of the executable for the special agent (without prefix)
|
||||||
|
name="hal9002",
|
||||||
|
parameter_parser=Hal9002Params.model_validate,
|
||||||
|
commands_function=agent_hal9002_arguments,
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user