Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log temperature from juniper devices #2364

Merged
merged 3 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion python/nav/ipdevpoll/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class IpdevpollConfig(NAVConfigParser):
RARITAN_COMPUTER_INC = PDU2-MIB
IBM = IBM-PDU-MIB
RITTAL_WERK_RUDOLF_LOH_GMBH_COKG = RITTAL-CMC-III-MIB
JUNIPER_NETWORKS_INC = ENTITY-SENSOR-MIB JUNIPER-DOM-MIB
JUNIPER_NETWORKS_INC = ENTITY-SENSOR-MIB JUNIPER-DOM-MIB JUNIPER-MIB
SUPERIOR_POWER_SOLUTIONS_HK_COLTD = Pwt3PhaseV1Mib
ALCATEL_LUCENT_ENTERPRISE_FORMERLY_ALCATEL = ALCATEL-IND1-PORT-MIB
COMPAQ = CPQPOWER-MIB
Expand Down
1 change: 0 additions & 1 deletion python/nav/ipdevpoll/plugins/sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ def handle(self):
"Found %d sensors from %s", len(all_sensors), type(mib).__name__
)
self._store_sensors(all_sensors)
break
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was done so sensors are collected from all the MIBs listed in JUNIPER_NETWORKS_INC line in the config instead of stopping at the first one where it finds any sensors. This will impact all sensor MIBs, so I'm wondering 1) is there a reason why it should stop after finding sensors in one MIB? 2) If so, ideas for config that will allow only Juniper devices to collect sensors from multiple MIBs?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good point. The juniper chassis error counts will also need to look into two different MIBs if we are to support all juniper equipment that has these counters.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. is there a reason why it should stop after finding sensors in one MIB?

I think the main reason is that some of the first devices this code was tested
on would report the same sensors in multiple MIBs (i.e. the sensors reported in
a proprietary MIB would also appear in ENTITY-SENSOR-MIB, and there is no
generic way of determining that these records represent the same thing).

  1. If so, ideas for config that will allow only Juniper devices to collect
    sensors from multiple MIBs?

Naw. I think the original idea is a bit defeatist. If a device wants to report
multiple versions of the same sensors, that's not our problem, that's the
vendor's problem (and a little bit, the user's: Now ipdevpoll will spend twice
the time collecting data from this device, and twice the storage space to
persist it - but hey, storage is cheap these days).

So, IMO: It's a good idea to remove the break statement!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hmpf wrote:

Very good point. The juniper chassis error counts will also need to look into
two different MIBs if we are to support all juniper equipment that has these
counters.

The point is good, but I don't see how it related to the ongoing alert count
collection feature. It's unlikely this will touch the sensors framework at all
(unless you plan to also keep time series data of alert counts).


@defer.inlineCallbacks
def mibfactory(self):
Expand Down
69 changes: 69 additions & 0 deletions python/nav/mibs/juniper_mib.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
from nav.oids import OID
from nav.smidumps import get_mib
from nav.mibs.mibretriever import MibRetriever
from nav.mibs import reduce_index
from nav.models.manage import PowerSupplyOrFan as FRU
from nav.ipdevpoll.shadows import PowerSupplyOrFan, Device
from nav.models.manage import Sensor

MEGABYTE = 1024**2

Expand All @@ -46,6 +48,15 @@
"standby": FRU.STATE_WARNING,
}

SENSOR_TABLES = {
'jnxOperatingTable': {
'descr': 'jnxOperatingDescr',
'unit': Sensor.UNIT_CELSIUS,
'readout': 'jnxOperatingTemp',
'internal_prefix': 'temperature',
},
}


class JuniperMib(MibRetriever):
"""JUNIPER-MIB MibRetriever"""
Expand Down Expand Up @@ -150,6 +161,64 @@ def get_fru_status(self, internal_id):
get_fan_status = get_fru_status
get_power_supply_status = get_fru_status

@defer.inlineCallbacks
def get_all_sensors(self):
"""Returns a Deferred whose result is a list of sensor dictionaries"""
result = []
for table, config in SENSOR_TABLES.items():
sensors = yield self._get_sensors(config)
result.extend(sensors)
defer.returnValue(result)

@defer.inlineCallbacks
def _get_sensors(self, config):
"""
Collects sensor columns according to the config dict, and translates
the results into sensor dicts.

"""
columns = [config['descr'], config['readout']]

result = (
yield self.retrieve_columns(columns)
.addCallback(self.translate_result)
.addCallback(reduce_index)
)

sensors = (
self._row_to_sensor(config, index, row) for index, row in result.items()
)

defer.returnValue([s for s in sensors if s])

def _row_to_sensor(self, config, index, row):
"""
Converts a collect SNMP table row into a sensor dict, using the
options defined in the config dict.

"""
# Dont include sensor if temperature not set
readout = row.get(config['readout'], 0)
if not readout:
return

internal_name = config['internal_prefix'] + str(index)
descr = row.get(config['descr'], internal_name) + " Temperature"

mibobject = self.nodes.get(config['readout'])
readout_oid = str(mibobject.oid + str(index))

return {
'oid': readout_oid,
'unit_of_measurement': config['unit'],
'precision': 0,
'scale': None,
'description': descr,
'name': descr,
'internal_name': internal_name,
'mib': self.get_module_name(),
}

@staticmethod
def _translate_fru_status_value(oper_status):
"""Translates the FRU status value from the MIB to a NAV PSU status value.
Expand Down