diff --git a/collections/inv.objectmodels/Rotek/4250L.json b/collections/inv.objectmodels/Rotek/4250L.json new file mode 100644 index 0000000000000000000000000000000000000000..129b53fb130950f9170d214a8ef454e234a7e1bc --- /dev/null +++ b/collections/inv.objectmodels/Rotek/4250L.json @@ -0,0 +1,151 @@ +{ + "name": "Rotek | Controller | RT-PWR-220-U,4250L", + "$collection": "inv.objectmodels", + "uuid": "b21dd341-9569-4853-a5db-fec21984df69", + "vendor__code": "ROTEK", + "description": "ЭПУ предназначена для обеспечения бесперебойного питания оборудования общей потребляемой мощностью от 30 до 250 Вт напряжением питания от 42 до 56 В. \nПрименение в ЭПУ контроллера обеспечивает непрерывный мониторинг состояния, подключённого к нему оборудования, в том числе и аккумуляторных батарей (АКБ). Связь с системой мониторинга осуществляется по проводному каналу связи Ethernet по протоколу SNMP, а также посредством встроенного Web-интерфейса.", + "cr_context": "CHASSIS", + "connections": [ + { + "description": null, + "direction": "s", + "gender": "f", + "name": "eth0", + "protocols": ["10BASET"], + "type__name": "Electrical | RJ45" + }, + { + "description": "Подключение к промышленной сети питания 220 В", + "direction": "s", + "gender": "f", + "name": "pwr", + "type__name": "Power | MSTB 2.5/3-ST-5.08" + }, + { + "description": "1-Wire (для подключения датчика температуры воздуха)", + "direction": "s", + "gender": "f", + "group": "1", + "name": "1", + "type__name": "Power | MSTB 2.5/4-ST-5.08" + }, + { + "description": "Общий провод (0) ", + "direction": "s", + "gender": "f", + "group": "1", + "name": "2", + "type__name": "Power | MSTB 2.5/4-ST-5.08" + }, + { + "description": "Vout + ", + "direction": "s", + "gender": "f", + "group": "1", + "name": "3", + "type__name": "Power | MSTB 2.5/4-ST-5.08" + }, + { + "description": "Дискретный вход (резервный)", + "direction": "s", + "gender": "f", + "group": "1", + "name": "4", + "type__name": "Power | MSTB 2.5/4-ST-5.08" + }, + { + "description": "+B (Положительный полюс АКБ)", + "direction": "s", + "gender": "f", + "group": "2", + "name": "akb_1", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "-B (Отрицательный полюс АКБ) ", + "direction": "s", + "gender": "f", + "group": "2", + "name": "akb_2", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "+V (Плюс источника питания)", + "direction": "s", + "gender": "f", + "group": "3", + "name": "load_1", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "+V (Плюс источника питания)", + "direction": "s", + "gender": "f", + "group": "3", + "name": "load_2", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "-V (Минус источника питания)", + "direction": "s", + "gender": "f", + "group": "3", + "name": "load_3", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "-V (Минус источника питания)", + "direction": "s", + "gender": "f", + "group": "3", + "name": "load_4", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + } + ], + "data": { + "asset": { + "part_no": ["4250L", "RT-PWR-220-U"] + }, + "management": { + "is_managed": "true" + } + }, + "sensors": [ + { + "description": "Дверь", + "name": "in", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.1.0", + "units__name": "Unknown" + }, + { + "description": "Флаг наличия сетевого напряжения AC 230В", + "name": "v230_state", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.9.0", + "units__name": "Unknown" + }, + { + "description": "Температура в шкафу", + "name": "temp", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.2.0", + "units__name": "Celsius" + }, + { + "description": "Ток потребления нагрузки", + "name": "current_load", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.3.0", + "units__name": "Ampere" + }, + { + "description": "ИБП. Напряжение батареи ИБП.", + "name": "ups_battery_U", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.6.0", + "units__name": "Volt AC" + }, + { + "description": "Ток заряда АКБ", + "name": "current_battery", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.5.0", + "units__name": "Ampere" + } + ] +} diff --git a/collections/inv.objectmodels/Rotek/BT6037.json b/collections/inv.objectmodels/Rotek/BT6037.json new file mode 100644 index 0000000000000000000000000000000000000000..1107c24da098d39cdc8277bb178cdd803159c6cb --- /dev/null +++ b/collections/inv.objectmodels/Rotek/BT6037.json @@ -0,0 +1,151 @@ +{ + "name": "Rotek | Controller | BT6037", + "$collection": "inv.objectmodels", + "uuid": "4ce589f7-ff19-4bf9-9a89-e3c0eb2c587c", + "vendor__code": "ROTEK", + "description": "ЭПУ предназначена для обеспечения бесперебойного питания оборудования общей потребляемой мощностью от 30 до 250 Вт напряжением питания от 42 до 56 В. \nПрименение в ЭПУ контроллера обеспечивает непрерывный мониторинг состояния, подключённого к нему оборудования, в том числе и аккумуляторных батарей (АКБ). Связь с системой мониторинга осуществляется по проводному каналу связи Ethernet по протоколу SNMP, а также посредством встроенного Web-интерфейса.", + "cr_context": "CHASSIS", + "connections": [ + { + "description": null, + "direction": "s", + "gender": "f", + "name": "eth0", + "protocols": ["10BASET"], + "type__name": "Electrical | RJ45" + }, + { + "description": "Подключение к промышленной сети питания 220 В", + "direction": "s", + "gender": "f", + "name": "pwr", + "type__name": "Power | MSTB 2.5/3-ST-5.08" + }, + { + "description": "1-Wire (для подключения датчика температуры воздуха)", + "direction": "s", + "gender": "f", + "group": "1", + "name": "1", + "type__name": "Power | MSTB 2.5/4-ST-5.08" + }, + { + "description": "Общий провод (0) ", + "direction": "s", + "gender": "f", + "group": "1", + "name": "2", + "type__name": "Power | MSTB 2.5/4-ST-5.08" + }, + { + "description": "Vout + ", + "direction": "s", + "gender": "f", + "group": "1", + "name": "3", + "type__name": "Power | MSTB 2.5/4-ST-5.08" + }, + { + "description": "Дискретный вход (резервный)", + "direction": "s", + "gender": "f", + "group": "1", + "name": "4", + "type__name": "Power | MSTB 2.5/4-ST-5.08" + }, + { + "description": "+B (Положительный полюс АКБ)", + "direction": "s", + "gender": "f", + "group": "2", + "name": "akb_1", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "-B (Отрицательный полюс АКБ) ", + "direction": "s", + "gender": "f", + "group": "2", + "name": "akb_2", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "+V (Плюс источника питания)", + "direction": "s", + "gender": "f", + "group": "3", + "name": "load_1", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "+V (Плюс источника питания)", + "direction": "s", + "gender": "f", + "group": "3", + "name": "load_2", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "-V (Минус источника питания)", + "direction": "s", + "gender": "f", + "group": "3", + "name": "load_3", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + }, + { + "description": "-V (Минус источника питания)", + "direction": "s", + "gender": "f", + "group": "3", + "name": "load_4", + "type__name": "Power | MSTB 2.5/2-ST-5.08" + } + ], + "data": { + "asset": { + "part_no": ["BT-6037v1rev3", "BT6037", "BT6037(V1.REV2)"] + }, + "management": { + "is_managed": "true" + } + }, + "sensors": [ + { + "description": "Дверь", + "name": "in", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.1.0", + "units__name": "Unknown" + }, + { + "description": "Флаг наличия сетевого напряжения AC 230В", + "name": "v230_state", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.9.0", + "units__name": "Unknown" + }, + { + "description": "Температура в шкафу", + "name": "temp", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.2.0", + "units__name": "Celsius" + }, + { + "description": "Ток потребления нагрузки", + "name": "current_load", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.3.0", + "units__name": "Ampere" + }, + { + "description": "ИБП. Напряжение батареи ИБП.", + "name": "ups_battery_U", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.6.0", + "units__name": "Volt AC" + }, + { + "description": "Ток заряда АКБ", + "name": "current_battery", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.5.0", + "units__name": "Ampere" + } + ] +} diff --git a/sa/profiles/Generic/get_metrics.py b/sa/profiles/Generic/get_metrics.py index 0c3f4fc3cdfb7d9414f25b172f62d0919f4d12d5..fb8eb9e40bccdc85c8728308efb010a7baf2d112 100644 --- a/sa/profiles/Generic/get_metrics.py +++ b/sa/profiles/Generic/get_metrics.py @@ -592,13 +592,16 @@ class Script(BaseScript, metaclass=MetricScriptBase): def collect_sensor_metrics(self, metrics): for m in metrics: if m.oid: - value = self.snmp.get(m.oid) - self.set_metric( - id=m.id, - metric=m.metric, - labels=m.labels, - value=value, - ) + try: + value = self.snmp.get(m.oid) + self.set_metric( + id=m.id, + metric=m.metric, + labels=m.labels, + value=float(value), + ) + except Exception: + continue # @metrics( # [ diff --git a/sa/profiles/Rotek/BT/get_chassis_id.py b/sa/profiles/Rotek/BT/get_chassis_id.py index e82825bb6186af654d4bf8eeb2fa0a68da50f298..8bd26ec6113dea3fa94440fcd08342ef3db7a1ea 100644 --- a/sa/profiles/Rotek/BT/get_chassis_id.py +++ b/sa/profiles/Rotek/BT/get_chassis_id.py @@ -11,7 +11,6 @@ import re # NOC modules from noc.sa.profiles.Generic.get_chassis_id import Script as BaseScript from noc.sa.interfaces.igetchassisid import IGetChassisID -from noc.core.http.client import fetch_sync from noc.core.mib import mib @@ -19,21 +18,21 @@ class Script(BaseScript): name = "Rotek.BT.get_chassis_id" cache = True interface = IGetChassisID - rx_mac = re.compile(rb"MAC(?:\S+:|:)\s(?P\S+)<", re.MULTILINE) + rx_mac = re.compile(r"MAC(?:\S+:|:)\s(?P\S+)<", re.MULTILINE) SNMP_GET_OIDS = {"SNMP": [mib["IF-MIB::ifPhysAddress", 1]]} always_prefer = "S" def execute_cli(self, **kwargs): - # Fallback to CLI - get = "http://" + self.credentials.get("address", "") + "/" - code, header, body = fetch_sync(get, allow_proxy=False, eof_mark=b"") - if 200 <= code <= 299: - try: - match = self.rx_mac.search(body) - if match: - mac = (match.group("mac")).strip() - return [{"first_chassis_mac": mac, "last_chassis_mac": mac}] - except ValueError: - pass + mac = None + if self.is_4250: + v = self.http.get("/info.cgi?_", json=True, cached=True, eof_mark=b"}") + mac = v["macaddr"] + elif self.is_6037_v1: + v = self.http.get("/", cached=True, eof_mark=b"") + match = self.rx_mac.search(v) + mac = match.group("mac") + if not mac: + raise NotImplementedError + return [{"first_chassis_mac": mac, "last_chassis_mac": mac}] diff --git a/sa/profiles/Rotek/BT/get_interfaces.py b/sa/profiles/Rotek/BT/get_interfaces.py index c753a9b76b72736a29ca061f78dfc767db13bbd7..24ffb9aabe98541e6ff4082973c73f2d8de3d8fd 100644 --- a/sa/profiles/Rotek/BT/get_interfaces.py +++ b/sa/profiles/Rotek/BT/get_interfaces.py @@ -16,7 +16,26 @@ class Script(BaseScript): name = "Rotek.BT.get_interfaces" interface = IGetInterfaces + def execute_cli(self, **kwargs): + if self.is_4250: + v = self.http.get("/info.cgi?_", json=True, cached=True, eof_mark=b"}") + return [ + { + "interfaces": [ + { + "type": "physical", + "name": "eth0", + "mac": v["macaddr"], + "subinterfaces": [], + } + ] + } + ] + raise NotImplementedError + def execute_snmp(self): + if self.is_4250: + raise NotImplementedError interfaces = [] try: ifindex = self.snmp.get("1.3.6.1.2.1.2.2.1.1.1") diff --git a/sa/profiles/Rotek/BT/get_inventory.py b/sa/profiles/Rotek/BT/get_inventory.py new file mode 100644 index 0000000000000000000000000000000000000000..470583c96037806d98179748d66160d249539453 --- /dev/null +++ b/sa/profiles/Rotek/BT/get_inventory.py @@ -0,0 +1,74 @@ +# --------------------------------------------------------------------- +# Ttronics.KUB.get_inventory +# --------------------------------------------------------------------- +# Copyright (C) 2007-2019 The NOC Project +# See LICENSE for details +# --------------------------------------------------------------------- + +# NOC modules +from noc.sa.profiles.Generic.get_inventory import Script as BaseScript +from noc.sa.interfaces.igetinventory import IGetInventory + + +class Script(BaseScript): + name = "Rotek.BT.get_inventory" + interface = IGetInventory + + def get_chassis_sensors(self): + r = [ + # In + { + "name": "in", + "status": True, + "description": "Дверь", + "measurement": "enum", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.1.0", + }, + # v230 + { + "name": "v230_state", + "status": True, + "description": "Флаг наличия сетевого напряжения AC 230В", + "measurement": "enum", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.9.0", + }, + # temp1 + { + "name": "temp", + "status": True, + "description": "Температура в шкафу", + "measurement": "Celsius", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.2.0", + }, + ] + r += [ + { + "name": "current_load", + "status": True, + "description": "Ток потребления нагрузки", + "measurement": "Ampere", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.3.0", + }, + { + "name": "ups_battery_U", + "status": True, + "description": "ИБП. Напряжение батареи ИБП.", + "measurement": "Volt AC", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.6.0", + }, + { + "name": "current_battery", + "status": True, + "description": "Ток заряда АКБ", + "measurement": "Ampere", + "snmp_oid": "1.3.6.1.4.1.41752.5.15.1.5.0", + }, + ] + return r + + def execute_snmp(self): + r = self.get_inv_from_version() + sensors = self.get_chassis_sensors() + if sensors: + r[0]["sensors"] = sensors + return r diff --git a/sa/profiles/Rotek/BT/get_version.py b/sa/profiles/Rotek/BT/get_version.py index e3b54c552a806c1dfc32f773e0f905c4f3343878..5144d3101b606735d111cf86f76f5a25c59c8c1e 100644 --- a/sa/profiles/Rotek/BT/get_version.py +++ b/sa/profiles/Rotek/BT/get_version.py @@ -16,6 +16,18 @@ class Script(BaseScript): reuse_cli_session = False keep_cli_session = False + def execute_cli(self, **kwargs): + v = self.http.get("/info.cgi?_", json=True, cached=True, eof_mark=b"}") + platform = v["model"] + if "," in platform: + platform = platform.split(",")[0] + return { + "vendor": "Rotek", + "version": v["fwversion"], + "platform": platform, + "attributes": {"Serial Number": v["serno"]}, + } + def execute_snmp(self): oid = self.snmp.get("1.3.6.1.2.1.1.1.0") sn = self.snmp.get("1.3.6.1.4.1.41752.5.15.1.10.0") @@ -40,6 +52,8 @@ class Script(BaseScript): else: platform = oid.split()[0].strip() version = oid.split()[1].strip() + if "," in platform: + platform = platform.split(",")[0] result = { "vendor": "Rotek", "version": version, diff --git a/sa/profiles/Rotek/BT/profile.py b/sa/profiles/Rotek/BT/profile.py index 6f0e99c18038e43611f58a67842b7645bbad7c27..93b828118cad7ab7ff42c7ab11654c920a34a151 100644 --- a/sa/profiles/Rotek/BT/profile.py +++ b/sa/profiles/Rotek/BT/profile.py @@ -17,6 +17,11 @@ class Profile(BaseProfile): # Timeout for snmp GET request snmp_metrics_get_timeout = 3 + matchers = { + "is_4250": {"platform": {"$regex": r"4250LSR"}}, + "is_6037_v1": {"platform": {"$regex": r"6037.+[Vv]1"}}, + } + PORT_TYPE = { 1: "Порт датчика двери", 2: "Порт датчика температуры", diff --git a/services/discovery/jobs/periodic/metrics.py b/services/discovery/jobs/periodic/metrics.py index 6235cb0032871518eb6d740737813679c29bf721..cea7038d1de0f16e7760f5ebfa444b289d239b32 100644 --- a/services/discovery/jobs/periodic/metrics.py +++ b/services/discovery/jobs/periodic/metrics.py @@ -385,14 +385,14 @@ class MetricsCheck(DiscoveryCheck): ) ): if not s.get("profile"): - self.logger.debug("[%s] Sensor has no profile. Skipping", s["name"]) + self.logger.debug("[%s] Sensor has no profile. Skipping", s["local_id"]) continue pm: "SensorProfile" = SensorProfile.get_by_id(s["profile"]) if not pm.enable_collect: continue state = State.get_by_id(s["state"]) if not state.is_productive: - self.logger.debug("[%s] Sensor is not productive state. Skipping", s["name"]) + self.logger.debug("[%s] Sensor is not productive state. Skipping", s["local_id"]) continue for mtype in ["Sensor | Value", "Sensor | Status"]: m_id = next(self.id_count)