Collection of CheckMK checks (see https://checkmk.com/). All checks and plugins are provided as is. Absolutely no warranty. Send any comments to thl-cmk[at]outlook[dot]com

Skip to content
Snippets Groups Projects
Commit 485f48a3 authored by thl-cmk's avatar thl-cmk :flag_na:
Browse files

update project

parent 610b295c
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# License: GNU General Public License v2
#
# Author: thl-cmk[at]outlook[dot]com
# URL : https://thl-cmk.hopto.org
# Date : 2021-12-25
#
# rewritten for CMK 2.0 based on the check "Cisco Spanning-Tree Topology Change" (cisco_stptopo)
# by Udo Woehler (check-mk at bsw-com.de)
#
#
import time
from dataclasses import dataclass
from typing import Optional
from cmk.base.plugins.agent_based.agent_based_api.v1 import (
register,
Service,
Result,
State,
SNMPTree,
check_levels,
not_startswith,
get_value_store,
Metric,
OIDBytes,
)
from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
DiscoveryResult,
CheckResult,
# StringTable,
StringByteTable,
)
@dataclass
class StpTopo:
last_change: int
change_count: int
root_mac: str
root_cost: int
#
# [['527111100', '4', '\x80\x01\x00#\x04î¾\n']]
#
def parse_stp_topo_change(string_table: StringByteTable) -> Optional[StpTopo]:
try:
last_change, change_count, root_mac, root_cost = string_table[0]
except IndexError:
return
if len(root_mac) == 8: # vlan prefix
root_mac = ':'.join(['%02s' % hex(m)[2:] for m in root_mac[2:]]).replace(' ', '0')
elif len(root_mac) == 6: # no prefix
root_mac = ':'.join(['%02s' % hex(m)[2:] for m in root_mac]).replace(' ', '0')
elif len(root_mac) == 22: # Zyxel 4096/00:21:F7:DD:2C:00
root_mac = ''.join(['%s' % chr(m) for m in root_mac[5:]]).replace(' ', '0')
elif len(root_mac) == 23: # Zyxel 4096/00:21:F7:DD:2C:00
root_mac = ''.join(['%s' % chr(m) for m in root_mac[6:]]).replace(' ', '0')
else:
root_mac = 'N/A (wrong format)'
return StpTopo(
last_change=int(last_change) / 100 if last_change.isdigit() else 999999,
change_count=int(change_count),
root_mac=root_mac,
root_cost=int(root_cost)
)
def discovery_stp_topo_change(section: StpTopo) -> DiscoveryResult:
yield Service()
def check_stp_topo_change(params, section: StpTopo) -> CheckResult:
now = int(time.time())
days, rest = divmod(section.last_change, 60 * 60 * 24)
hours, rest = divmod(rest, 60 * 60)
minutes, seconds = divmod(rest, 60)
since = time.strftime('%c', time.localtime(now - section.last_change))
value_store = get_value_store()
last_topo1 = value_store.get('cisco.stp.topo', 1000000000)
last_topo2 = value_store.get('cisco.stp.topo2', 1000000000)
last_topo3 = value_store.get('cisco.stp.topo3', 1000000000)
last_count = value_store.get('cisco.stp.count', 0)
if last_count < section.change_count: # stp change occurred, rotate counters
value_store['cisco.stp.topo3'] = last_topo2
value_store['cisco.stp.topo2'] = last_topo1
value_store['cisco.stp.topo'] = section.last_change
value_store['cisco.stp.count'] = section.change_count
elif last_count > section.change_count: # switch restart or counter overflow, reinit
value_store['cisco.stp.topo3'] = 1000000000
value_store['cisco.stp.topo2'] = 1000000000
value_store['cisco.stp.topo'] = section.last_change
value_store['cisco.stp.count'] = section.change_count
warn, crit = params['levels_lower']
yield Result(state=State.OK, summary=f'Root MAC {section.root_mac.upper()}')
if section.root_cost == 0:
yield Result(state=State.OK, summary=f'This bridge is the root')
else:
yield from check_levels(
label='Cost to root bridge',
value=section.root_cost,
render_func=lambda v: str(v)
)
yield from check_levels(
label='Changes',
value=section.change_count,
metric_name='stp_change_count',
render_func=lambda v: str(v)
)
yield Result(state=State.OK, summary=f'Last change {since} ({days:.0f} {hours:02.0f}:{minutes:02.0f}:{seconds:02.0f})')
if section.last_change <= warn and last_topo2 <= warn and last_topo3 <= warn and params['always_ok']:
yield Result(
state=State.OK,
summary=f'OK - Forced - Three times below threshold.'
)
elif section.last_change <= crit and last_topo2 <= crit and last_topo3 <= crit:
yield Result(
state=State.CRIT,
summary=f'Three times below threshold.'
)
elif section.last_change <= warn and last_topo2 <= warn and last_topo3 <= warn:
yield Result(
state=State.WARN,
summary=f'Three times below threshold.'
)
yield Metric(
name='stp_last_topo',
value=section.last_change,
levels=(warn, crit),
)
register.snmp_section(
name='stp_topo_change',
parse_function=parse_stp_topo_change,
fetch=SNMPTree(
base='.1.3.6.1.2.1.17.2', # BRIDGE-MIB::dot1dStp
oids=[
'3', # dot1dStpTimeSinceTopologyChange
'4', # dot1dStpTopChanges
OIDBytes('5'), # dot1dStpDesignatedRoot
'6', # dot1dStpRootCost
]
),
detect=not_startswith('.1.3.6.1.2.1.17.2.4.0', '0'),
)
register.check_plugin(
name='stp_topo_change',
service_name='STP Topology change',
discovery_function=discovery_stp_topo_change,
check_function=check_stp_topo_change,
check_default_parameters={
'always_ok': False,
'levels_lower': (900, 600),
},
check_ruleset_name='stp_topo_change',
)
title: Dummy check man page - used as template for new check manuals
agents: linux, windows, aix, solaris, hpux, vms, freebsd, snmp
catalog: see modules/catalog.py for possible values
title: Check Spanning-Tree Topology Changes on Switches
agents: snmp
author: thl-cmk[at]outlook[dot]com
catalog: hw/network/cisco
license: GPL
distribution: check_mk
description:
Describe here: (1) what the check actually does, (2) under which
circumstances it goes warning/critical, (3) which devices are supported
by the check, (4) if the check requires a separated plugin or
tool or separate configuration on the target host.
item:
Describe the syntax and meaning of the check's item here. Provide all
information one needs if coding a manual check with {checks +=} in {main.mk}.
Give an example. If the check uses {None} as sole item,
then leave out this section.
examples:
# Give examples for configuration in {main.mk} here. If the check has
# configuration variable, then give example for them here.
# set default levels to 40 and 60 percent:
foo_default_values = (40, 60)
# another configuration variable here:
inventory_foo_filter = [ "superfoo", "superfoo2" ]
perfdata:
Describe precisely the number and meaning of performance variables
the check sends. If it outputs no performance data, then leave out this
section.
This check monitors the spanning-tree topology change timer on switches.
inventory:
Describe how the inventory for the check works. Which items
will it find? Describe the influence of check specific
configuration parameters to the inventory.
[parameters]
foofirst(int): describe the first parameter here (if parameters are grouped
as tuple)
fooother(string): describe another parameter here.
One check for each switch is created by the inventory.
[configuration]
foo_default_levels(int, int): Describe global configuration variable of
foo here. Important: also tell the user how they are preset.
{'author': 'Th.L. (thl-cmk[at]outlook[dot]com)',
'description': 'Check spanning-tree for topology change.\n'
'\n'
'rewritten for CMK 2.0 based on the check "Cisco Spanning-Tree '
'Topology Change" (cisco_stptopo) by Udo Woehler (check-mk at '
'bsw-com.de)\n',
'download_url': 'https://thl-cmk.hopto.org',
'files': {'agent_based': ['stp_topo_change.py'],
'checkman': ['stp_topo_change'],
'web': ['plugins/metrics/stp_topo_change.py',
'plugins/wato/stp_topo_change.py']},
'name': 'stp_topo_change',
'num_files': 4,
'title': 'Spanning-Tree Topology Change',
'version': '202201.v0.0.1',
'version.min_required': '2.0.0',
'version.packaged': '2021.09.20',
'version.usable_until': None}
\ No newline at end of file
File added
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# License: GNU General Public License v2
#
# Author: thl-cmk[at]outlook[dot]com
# URL : https://thl-cmk.hopto.org
# Date : 2021-07-22
#
#
#
from cmk.gui.i18n import _
from cmk.gui.plugins.metrics import (
metric_info,
graph_info,
perfometer_info
)
metric_info['stp_change_count'] = {
'title': _('STP topology changes'),
'unit': 'count',
'color': '11/a',
}
metric_info['stp_last_topo'] = {
'title': _('STP topology change'),
'unit': 's',
'color': '26/b',
}
graph_info['stp_last_topo'] = {
'title': _('STP topology change'),
'metrics': [
('stp_last_topo', 'area'),
],
'scalars': [
('stp_last_topo:crit', _('Lower critical level')),
('stp_last_topo:warn', _('Lower warning level')),
],
}
graph_info['stp_change_count'] = {
'title': _('STP Toplogy changes'),
'metrics': [
('stp_change_count', 'area'),
],
'scalars': [
('stp_change_count:crit', _('Upper critical level')),
('stp_change_count:warn', _('Upper warning level')),
],
'range': (0, 'stp_change_count:max'),
}
perfometer_info.append({
'type': 'logarithmic',
'metric': 'stp_last_topo',
'half_value': 31536000.0, # one year
'exponent': 10.0,
})
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# License: GNU General Public License v2
#
# Author: thl-cmk[at]outlook[dot]com
# URL : https://thl-cmk.hopto.org
#
from cmk.gui.i18n import _
from cmk.gui.valuespec import (
Dictionary,
Integer,
FixedValue,
Tuple,
)
from cmk.gui.plugins.wato import (
CheckParameterRulespecWithItem,
rulespec_registry,
RulespecGroupCheckParametersNetworking,
)
def _parameter_valuespec_checkpoint_fw_ls():
return Dictionary(
elements=[
('always_ok',
FixedValue(
True,
title=_('Always OK'),
totext=_('Always OK enabled'),
help=_('Always return state as OK.'),
)),
('levels_lower',
Tuple(
title=_('Time offset'),
help=_('This rule sets the parameters for the Cisco Spanning-Tree Topology Changes.'),
elements=[
Integer(title=_('Warning below'), minvalue=0, unit=_('Seconds'), default_value=900),
Integer(title=_('Critical below'), minvalue=0, unit=_('Seconds'), default_value=600),
])),
],
)
rulespec_registry.register(
CheckParameterRulespecWithItem(
check_group_name='stp_topo_change',
group=RulespecGroupCheckParametersNetworking,
match_type='dict',
parameter_valuespec=_parameter_valuespec_checkpoint_fw_ls,
title=lambda: _('STP Topology change'), # Cisco Spanning-Tree Topology Changes
))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment