Add some Sentry PDU changes that have been laying around for a few months.

This commit is contained in:
Marsell Kukuljevic 2024-06-15 15:02:33 +02:00
parent 775f9515a1
commit 8f9970a40c
4 changed files with 202 additions and 61 deletions

View File

@ -30,7 +30,8 @@ SOCKET_ARR_SIZE = MAX_TOWERS * MAX_INFEEDS * MAX_SOCKETS
TOWER_NUM_OFFSET = 0 TOWER_NUM_OFFSET = 0
INFEED_NUM_OFFSET = TOWER_NUM_OFFSET + 1 INFEED_NUM_OFFSET = TOWER_NUM_OFFSET + 1
INFEED_ID_OFFSET = INFEED_NUM_OFFSET + TOWER_ARR_SIZE INFEED_ID_OFFSET = INFEED_NUM_OFFSET + TOWER_ARR_SIZE
INFEED_VOLT_OFFSET = INFEED_ID_OFFSET + INFEED_ARR_SIZE INFEED_NAME_OFFSET = INFEED_ID_OFFSET + INFEED_ARR_SIZE
INFEED_VOLT_OFFSET = INFEED_NAME_OFFSET + INFEED_ARR_SIZE
SOCKET_NUM_OFFSET = INFEED_VOLT_OFFSET + INFEED_ARR_SIZE SOCKET_NUM_OFFSET = INFEED_VOLT_OFFSET + INFEED_ARR_SIZE
SOCKET_ID_OFFSET = SOCKET_NUM_OFFSET + INFEED_ARR_SIZE SOCKET_ID_OFFSET = SOCKET_NUM_OFFSET + INFEED_ARR_SIZE
SOCKET_NAME_OFFSET = SOCKET_ID_OFFSET + SOCKET_ARR_SIZE SOCKET_NAME_OFFSET = SOCKET_ID_OFFSET + SOCKET_ARR_SIZE
@ -49,6 +50,7 @@ def parse_sentry_pdu(info):
infeed_idx = tower_id * MAX_TOWERS + infeed_id infeed_idx = tower_id * MAX_TOWERS + infeed_id
infeed_sid = results[INFEED_ID_OFFSET + infeed_idx] infeed_sid = results[INFEED_ID_OFFSET + infeed_idx]
infeed_name = results[INFEED_NAME_OFFSET + infeed_idx]
infeed_voltage = float(results[INFEED_VOLT_OFFSET + infeed_idx]) / 10 infeed_voltage = float(results[INFEED_VOLT_OFFSET + infeed_idx]) / 10
num_outlets = int(results[SOCKET_NUM_OFFSET + infeed_idx]) num_outlets = int(results[SOCKET_NUM_OFFSET + infeed_idx])
@ -61,19 +63,19 @@ def parse_sentry_pdu(info):
outlet_key = '%s.%s.%s' % (tower_id, infeed_id, outlet_id) outlet_key = '%s.%s.%s' % (tower_id, infeed_id, outlet_id)
outlets_info[outlet_key] = { outlets_info[outlet_key] = {
'infeed_id': infeed_sid, 'infeed_id': infeed_sid,
'infeed_name': infeed_name,
'infeed_voltage': infeed_voltage, 'infeed_voltage': infeed_voltage,
'outlet_id': outlet_sid, 'outlet_id': outlet_sid,
'outlet_name': outlet_name, 'outlet_name': outlet_name,
'outlet_load': outlet_load 'outlet_load': outlet_load,
} }
return outlets_info return outlets_info
def check_sentry_pdu(item, params, parsed): # Check function, returning warn/crit based upon SNMP parsed result above
id = params['id'] def check_sentry_pdu(item, params, section):
outlet = parsed.get(id) outlet = section.get(params['id'])
if outlet is None: if outlet is None:
return (3, 'item not found in snmp data') return (3, 'item not found in snmp data')
@ -82,39 +84,53 @@ def check_sentry_pdu(item, params, parsed):
if voltage < 0: if voltage < 0:
return (1, 'Infeed voltage unavailable') return (1, 'Infeed voltage unavailable')
elif amps < 0:
return (1, 'Outlet load unavailable')
power = voltage * amps if params['type'] == 'infeed':
return check_metric(params, 'volts', voltage)
elif params['type'] == 'outlet':
if amps < 0:
return (1, 'Outlet load unavailable')
return check_metric(params, 'watts', voltage * amps)
def check_metric(params, metric_name, metric_value):
crit_metric_above = params.get('crit_%s_above' % metric_name)
warn_metric_above = params.get('warn_%s_above' % metric_name)
warn_metric_below = params.get('warn_%s_below' % metric_name)
crit_metric_below = params.get('crit_%s_below' % metric_name)
state = 0 state = 0
crit_watts_above = params.get('crit_watts_above') if crit_metric_above and crit_metric_above < metric_value:
warn_watts_above = params.get('warn_watts_above')
warn_watts_below = params.get('warn_watts_below')
crit_watts_below = params.get('crit_watts_below')
if crit_watts_above and crit_watts_above < power:
state = 2 state = 2
elif crit_watts_below and crit_watts_below > power: elif crit_metric_below and crit_metric_below > metric_value:
state = 2 state = 2
elif warn_watts_above and warn_watts_above < power: elif warn_metric_above and warn_metric_above < metric_value:
state = 1 state = 1
elif warn_watts_below and warn_watts_below > power: elif warn_metric_below and warn_metric_below > metric_value:
state = 1 state = 1
return (state, '%.1f watts' % power) return (state, '%.1f %s' % (metric_value, metric_name))
# Inventory function, returning inventory based upon SNMP parsed result above
def inventory_sentry_pdu(parsed): def inventory_sentry_pdu(parsed):
items = [] items = []
for id, outlet in parsed.items(): for id, outlet in parsed.items():
name = '%s %s [infeed %s] power' % ( plug_name = '%s %s [infeed %s] power' % (
outlet['outlet_id'], outlet['outlet_id'],
outlet['outlet_name'], outlet['outlet_name'],
outlet['infeed_id']) outlet['infeed_id']
items.append((name, { 'id': id })) )
infeed_name = 'Infeed %s %s' % (
outlet['infeed_id'],
outlet['infeed_name']
)
items.append((plug_name, { 'id': id, 'type': 'outlet' }))
items.append((infeed_name, { 'id': id, 'type': 'infeed' }))
return items return items
@ -143,6 +159,11 @@ check_info['sentry_pdu_outlets_power'] = {
['2.2.1.2.%s.%s' % (x, y) for x in range(1, MAX_TOWERS+1) ['2.2.1.2.%s.%s' % (x, y) for x in range(1, MAX_TOWERS+1)
for y in range(1, MAX_INFEEDS+1)], for y in range(1, MAX_INFEEDS+1)],
# Infeed names:
# .1.3.6.1.4.1.1718.3.2.2.1.3.<tower #>.<infeed #>
['2.2.1.3.%s.%s' % (x, y) for x in range(1, MAX_TOWERS+1)
for y in range(1, MAX_INFEEDS+1)],
# Infeed voltage: # Infeed voltage:
# .1.3.6.1.4.1.1718.3.2.2.1.11.<tower #>.<infeed #> # .1.3.6.1.4.1.1718.3.2.2.1.11.<tower #>.<infeed #>
['2.2.1.11.%s.%s' % (x, y) for x in range(1, MAX_TOWERS+1) ['2.2.1.11.%s.%s' % (x, y) for x in range(1, MAX_TOWERS+1)

View File

@ -17,17 +17,68 @@ from cmk.gui.valuespec import (
def _valuespec_outlets_power_check(): def _valuespec_outlets_power_check():
return Dictionary( return Dictionary(
optional_keys=[ optional_keys=[
'crit_volts_above',
'warn_volts_above',
'warn_volts_below',
'crit_volts_below',
'crit_watts_above', 'crit_watts_above',
'warn_watts_above', 'warn_watts_above',
'warn_watts_below', 'warn_watts_below',
'crit_watts_below' 'crit_watts_below',
'type',
], ],
elements=[ elements=[
(
'crit_volts_above',
Integer(
minvalue=0,
title=_('Crit when infeed above voltage'),
unit=_('Volts'),
help=_(
'If the Voltage of an infeed goes above this number, enter a critical state.'
),
),
),
(
'warn_volts_above',
Integer(
minvalue=0,
title=_('Warn when infeed above voltage'),
unit=_('Volts'),
help=_(
'If the Voltage of an infeed goes above this number, enter a warning state.'
),
),
),
(
'warn_volts_below',
Integer(
minvalue=0,
title=_('Warn when infeed below voltage'),
unit=_('Volts'),
help=_(
'If the Voltage of an infeed goes below this number, enter a warning state.'
),
),
),
(
'crit_volts_below',
Integer(
minvalue=0,
title=_('Crit when infeed below voltage'),
unit=_('Volts'),
help=_(
'If the Voltage of an infeed goes below this number, enter a critical state.'
),
),
),
( (
'crit_watts_above', 'crit_watts_above',
Integer( Integer(
minvalue=0, minvalue=0,
title=_('Crit when above power'), title=_('Crit when outlet above power'),
unit=_('Watts'), unit=_('Watts'),
help=_( help=_(
'If the Wattage of an outlet goes above this number, enter a critical state.' 'If the Wattage of an outlet goes above this number, enter a critical state.'
@ -38,7 +89,7 @@ def _valuespec_outlets_power_check():
'warn_watts_above', 'warn_watts_above',
Integer( Integer(
minvalue=0, minvalue=0,
title=_('Warn when above power'), title=_('Warn when outlet above power'),
unit=_('Watts'), unit=_('Watts'),
help=_( help=_(
'If the Wattage of an outlet goes above this number, enter a warning state.' 'If the Wattage of an outlet goes above this number, enter a warning state.'
@ -49,7 +100,7 @@ def _valuespec_outlets_power_check():
'warn_watts_below', 'warn_watts_below',
Integer( Integer(
minvalue=0, minvalue=0,
title=_('Warn when below power'), title=_('Warn when outlet below power'),
unit=_('Watts'), unit=_('Watts'),
help=_( help=_(
'If the Wattage of an outlet goes below this number, enter a warning state.' 'If the Wattage of an outlet goes below this number, enter a warning state.'
@ -60,7 +111,7 @@ def _valuespec_outlets_power_check():
'crit_watts_below', 'crit_watts_below',
Integer( Integer(
minvalue=0, minvalue=0,
title=_('Crit when below power'), title=_('Crit when outlet below power'),
unit=_('Watts'), unit=_('Watts'),
help=_( help=_(
'If the Wattage of an outlet goes below this number, enter a critical state.' 'If the Wattage of an outlet goes below this number, enter a critical state.'

View File

@ -31,16 +31,18 @@ def parse_sentry_pdu(string_table):
for infeed_id in range(num_infeeds): for infeed_id in range(num_infeeds):
infeed_sid = string_table[2][infeed_id][tower_id] infeed_sid = string_table[2][infeed_id][tower_id]
infeed_voltage = float(string_table[3][infeed_id][tower_id]) / 10 infeed_name = string_table[3][infeed_id][tower_id]
num_outlets = int(string_table[4][infeed_id][tower_id]) infeed_voltage = float(string_table[4][infeed_id][tower_id]) / 10
num_outlets = int(string_table[5][infeed_id][tower_id])
for outlet_id in range(num_outlets): for outlet_id in range(num_outlets):
outlet_sid = extract_outlet(tower_id, infeed_id, outlet_id, string_table[5]) outlet_sid = extract_outlet(tower_id, infeed_id, outlet_id, string_table[6])
outlet_name = extract_outlet(tower_id, infeed_id, outlet_id, string_table[6]) outlet_name = extract_outlet(tower_id, infeed_id, outlet_id, string_table[7])
outlet_load = float(extract_outlet(tower_id, infeed_id, outlet_id, string_table[7])) / 100 outlet_load = float(extract_outlet(tower_id, infeed_id, outlet_id, string_table[8])) / 100
outlets_info[f'{tower_id}.{infeed_id}.{outlet_id}'] = { outlets_info[f'{tower_id}.{infeed_id}.{outlet_id}'] = {
'infeed_id': infeed_sid, 'infeed_id': infeed_sid,
'infeed_name': infeed_name,
'infeed_voltage': infeed_voltage, 'infeed_voltage': infeed_voltage,
'outlet_id': outlet_sid, 'outlet_id': outlet_sid,
'outlet_name': outlet_name, 'outlet_name': outlet_name,
@ -53,8 +55,11 @@ def parse_sentry_pdu(string_table):
# Inventory function, returning inventory based upon SNMP parsed result above # Inventory function, returning inventory based upon SNMP parsed result above
def discovery_sentry_pdu(section): def discovery_sentry_pdu(section):
for key, outlet in section.items(): for key, outlet in section.items():
name = f'{outlet["outlet_id"]} {outlet["outlet_name"]} (infeed {outlet["infeed_id"]}) power' plug_name = f'{outlet["outlet_id"]} {outlet["outlet_name"]} (infeed {outlet["infeed_id"]}) power'
yield Service(item=name, parameters={ 'id': key }) infeed_name = f'Infeed {outlet["infeed_id"]} {outlet["infeed_name"]}'
yield Service(item=plug_name, parameters={ 'id': key, 'type': 'outlet' })
yield Service(item=infeed_name, parameters={ 'id': key, 'type': 'infeed' })
# Check function, returning warn/crit based upon SNMP parsed result above # Check function, returning warn/crit based upon SNMP parsed result above
@ -69,28 +74,35 @@ def check_sentry_pdu(item, params, section):
if voltage < 0: if voltage < 0:
yield Result(state=State.WARN, summary='Infeed voltage unavailable') yield Result(state=State.WARN, summary='Infeed voltage unavailable')
return return
elif amps < 0:
if params['type'] == 'infeed':
yield check_metric(params, 'volts', voltage)
elif params['type'] == 'outlet':
if amps < 0:
yield Result(state=State.WARN, summary='Outlet load unavailable') yield Result(state=State.WARN, summary='Outlet load unavailable')
return return
yield check_metric(params, 'watts', voltage * amps)
def check_metric(params, metric_name, metric_value):
crit_metric_above = params.get('crit_%s_above' % metric_name)
warn_metric_above = params.get('warn_%s_above' % metric_name)
warn_metric_below = params.get('warn_%s_below' % metric_name)
crit_metric_below = params.get('crit_%s_below' % metric_name)
power = voltage * amps
state = State.OK state = State.OK
crit_watts_above = params.get('crit_watts_above') if crit_metric_above and crit_metric_above < metric_value:
warn_watts_above = params.get('warn_watts_above')
warn_watts_below = params.get('warn_watts_below')
crit_watts_below = params.get('crit_watts_below')
if crit_watts_above and crit_watts_above < power:
state = State.CRIT state = State.CRIT
elif crit_watts_below and crit_watts_below > power: elif crit_metric_below and crit_metric_below > metric_value:
state = State.CRIT state = State.CRIT
elif warn_watts_above and warn_watts_above < power: elif warn_metric_above and warn_metric_above < metric_value:
state = State.WARN state = State.WARN
elif warn_watts_below and warn_watts_below > power: elif warn_metric_below and warn_metric_below > metric_value:
state = State.WARN state = State.WARN
yield Result(state=state, summary=f'{power:.1f} watts') return Result(state=state, summary=f'{metric_value:.1f} {metric_name}')
register.snmp_section( register.snmp_section(
@ -117,6 +129,13 @@ register.snmp_section(
oids=['1', '2', '3', '4'], oids=['1', '2', '3', '4'],
), ),
# Infeed names:
# .1.3.6.1.4.1.1718.3.2.2.1.3.<tower #>.<infeed #>
SNMPTree(
base='.1.3.6.1.4.1.1718.3.2.2.1.3',
oids=['1', '2', '3', '4'],
),
# Infeed voltage: # Infeed voltage:
# .1.3.6.1.4.1.1718.3.2.2.1.11.<tower #>.<infeed #> # .1.3.6.1.4.1.1718.3.2.2.1.11.<tower #>.<infeed #>
SNMPTree( SNMPTree(

View File

@ -18,17 +18,67 @@ def _valuespec_agents_sentry_pdu_outlets_power_check():
return Dictionary( return Dictionary(
title=_('Sentry PDU Outlets Power Checks'), title=_('Sentry PDU Outlets Power Checks'),
optional_keys=[ optional_keys=[
'crit_volts_above',
'warn_volts_above',
'warn_volts_below',
'crit_volts_below',
'crit_watts_above', 'crit_watts_above',
'warn_watts_above', 'warn_watts_above',
'warn_watts_below', 'warn_watts_below',
'crit_watts_below' 'crit_watts_below',
], ],
elements=[ elements=[
(
'crit_volts_above',
Integer(
minvalue=0,
title=_('Crit when infeed above voltage'),
unit=_('Volts'),
help=_(
'If the Voltage of an infeed goes above this number, enter a critical state.'
),
),
),
(
'warn_volts_above',
Integer(
minvalue=0,
title=_('Warn when infeed above voltage'),
unit=_('Volts'),
help=_(
'If the Voltage of an infeed goes above this number, enter a warning state.'
),
),
),
(
'warn_volts_below',
Integer(
minvalue=0,
title=_('Warn when infeed below voltage'),
unit=_('Volts'),
help=_(
'If the Voltage of an infeed goes below this number, enter a warning state.'
),
),
),
(
'crit_volts_below',
Integer(
minvalue=0,
title=_('Crit when infeed below voltage'),
unit=_('Volts'),
help=_(
'If the Voltage of an infeed goes below this number, enter a critical state.'
),
),
),
( (
'crit_watts_above', 'crit_watts_above',
Integer( Integer(
minvalue=0, minvalue=0,
title=_('Crit when above power'), title=_('Crit when outlet above power'),
unit=_('Watts'), unit=_('Watts'),
help=_( help=_(
'If the Wattage of an outlet goes above this number, enter a critical state.' 'If the Wattage of an outlet goes above this number, enter a critical state.'
@ -39,7 +89,7 @@ def _valuespec_agents_sentry_pdu_outlets_power_check():
'warn_watts_above', 'warn_watts_above',
Integer( Integer(
minvalue=0, minvalue=0,
title=_('Warn when above power'), title=_('Warn when outlet above power'),
unit=_('Watts'), unit=_('Watts'),
help=_( help=_(
'If the Wattage of an outlet goes above this number, enter a warning state.' 'If the Wattage of an outlet goes above this number, enter a warning state.'
@ -50,7 +100,7 @@ def _valuespec_agents_sentry_pdu_outlets_power_check():
'warn_watts_below', 'warn_watts_below',
Integer( Integer(
minvalue=0, minvalue=0,
title=_('Warn when below power'), title=_('Warn when outlet below power'),
unit=_('Watts'), unit=_('Watts'),
help=_( help=_(
'If the Wattage of an outlet goes below this number, enter a warning state.' 'If the Wattage of an outlet goes below this number, enter a warning state.'
@ -61,7 +111,7 @@ def _valuespec_agents_sentry_pdu_outlets_power_check():
'crit_watts_below', 'crit_watts_below',
Integer( Integer(
minvalue=0, minvalue=0,
title=_('Crit when below power'), title=_('Crit when outlet below power'),
unit=_('Watts'), unit=_('Watts'),
help=_( help=_(
'If the Wattage of an outlet goes below this number, enter a critical state.' 'If the Wattage of an outlet goes below this number, enter a critical state.'