From 8b827dbef5336bc7a5b9e606581dd3a969574a57 Mon Sep 17 00:00:00 2001 From: HalbeBruno Date: Mon, 13 Apr 2026 10:36:53 -0300 Subject: [PATCH] Templates Datacom DmOS --- datacom/datacom_dmos/README.md | 407 ++ .../datacom_dmos/Template_Datacom_DmOS.xml | 3403 +++++++++++++++++ .../dmos_hardware_monitor_mib_psu.py | 86 + 3 files changed, 3896 insertions(+) create mode 100644 datacom/datacom_dmos/README.md create mode 100644 datacom/datacom_dmos/Template_Datacom_DmOS.xml create mode 100644 datacom/datacom_dmos/dmos_hardware_monitor_mib_psu.py diff --git a/datacom/datacom_dmos/README.md b/datacom/datacom_dmos/README.md new file mode 100644 index 0000000..be73ee3 --- /dev/null +++ b/datacom/datacom_dmos/README.md @@ -0,0 +1,407 @@ +# IPv0 - Template Datacom DmOS + +## Visão Geral + +Template desenvolvido para monitoramento de equipamentos Datacom com sistema operacional **DmOS** via **SNMPv1/v2c**, compatível com o **Zabbix 7.2** ou superior. + +Realiza o monitoramento completo de disponibilidade (ICMP), informações de sistema, interfaces de rede, CPU, memória, ventiladores (FANs), sensores de temperatura e fontes de alimentação (PSU), fazendo uso extensivo de **Low-Level Discovery (LLD)** para descoberta automática de componentes. + +--- + +## Equipamentos Testados + +- Datacom DM4170 +- Datacom DM4270 +- Datacom DM4370 +- Datacom DM4610 +- Outros equipamentos Datacom com DmOS + +--- + +## Requisitos + +### MIBs + +Para o correto funcionamento das coletas SNMP, é necessário que os arquivos de MIB do equipamento estejam presentes no servidor Zabbix. Copie as MIBs diretamente do equipamento com o comando DmOS: + +``` +copy mibs +``` + +Em seguida, disponibilize os arquivos no diretório de MIBs do Zabbix (geralmente `/usr/share/snmp/mibs/` ou `/etc/snmp/mibs/`). As MIBs utilizadas por este template são: + +- `SNMPv2-MIB` +- `IF-MIB` +- `DMOS-SYSMON-MIB` +- `DMOS-HW-MONITOR-MIB` + +### Script Externo — PSU Discovery + +A regra de descoberta de fontes de alimentação (PSU) depende de um script Python externo. Copie o arquivo `dmos_hardware_monitor_mib_psu.py` para o diretório de scripts externos do Zabbix: + +```bash +# Ubuntu / Debian +cp dmos_hardware_monitor_mib_psu.py /usr/lib/zabbix/externalscripts/ +chmod +x /usr/lib/zabbix/externalscripts/dmos_hardware_monitor_mib_psu.py +``` + +### Versão Zabbix + +| Versão | Suporte | +|--------|---------| +| 7.2 | ✅ Testado | +| 7.0+ | ✅ Compatível | +| 6.x | ⚠️ Não garantido | + +--- + +## Configuração + +### SNMP + +Configure o host no Zabbix com interface **SNMP** apontando para o IP do equipamento. A macro `{$SNMP_COMMUNITY}` deve ser definida no host com a community correta: + +| Macro | Valor padrão | Descrição | +|-------------------|-------------|----------------------------------| +| `{$SNMP_COMMUNITY}` | `public` | Community SNMP do equipamento | + +### Filtros de Interface + +As interfaces descobertas podem ser filtradas pelas seguintes macros. Altere os valores conforme necessário no host ou template: + +| Macro | Valor padrão | Descrição | +|-------|-------------|-----------| +| `{$NET.IF.IFNAME.MATCHES}` | `^.*$` | Regex de nomes de interface a incluir | +| `{$NET.IF.IFNAME.NOT_MATCHES}` | `(^Software Loopback...\|^NULL...\|^[Ll]o...\|docker...\|br-...)` | Exclui loopbacks, docker e similares | +| `{$NET.IF.IFADMINSTATUS.MATCHES}` | `^.*` | Status administrativo a incluir | +| `{$NET.IF.IFADMINSTATUS.NOT_MATCHES}` | `^2$` | Exclui interfaces administrativamente down | +| `{$NET.IF.IFOPERSTATUS.MATCHES}` | `^u\|^1` | Status operacional a incluir | +| `{$NET.IF.IFOPERSTATUS.NOT_MATCHES}` | `^6$` | Exclui interfaces notPresent | +| `{$NET.IF.IFALIAS.MATCHES}` | `.*` | Filtra por alias | +| `{$NET.IF.IFALIAS.NOT_MATCHES}` | `CHANGE_IF_NEEDED` | Desabilitado por padrão | +| `{$NET.IF.IFDESCR.MATCHES}` | `.*` | Filtra por descrição | +| `{$NET.IF.IFDESCR.NOT_MATCHES}` | `CHANGE_IF_NEEDED` | Desabilitado por padrão | +| `{$NET.IF.IFTYPE.MATCHES}` | `.*` | Filtra por tipo de interface | +| `{$NET.IF.IFTYPE.NOT_MATCHES}` | `CHANGE_IF_NEEDED` | Desabilitado por padrão | +| `{$IFCONTROL}` | `1` | Habilita alertas de link down (0 = desabilita) | + +--- + +## Itens Coletados + +### Sistema (via SNMPv2-MIB) + +| Item | OID | Intervalo | Retenção | +|------|-----|-----------|---------| +| System Contact | `SNMPv2-MIB::sysContact.0` | 60 min | 90 dias | +| System Description | `SNMPv2-MIB::sysDescr.0` | 60 min | 2 semanas | +| System Location | `SNMPv2-MIB::sysLocation.0` | 60 min | 7 dias | +| System Name | `SNMPv2-MIB::sysName.0` | 60 min | 2 semanas | +| System Object ID | `1.3.6.1.2.1.1.2.0` | 15 min | — | +| System Uptime | `1.3.6.1.2.1.1.3.0` | 60 min | 7 dias | +| SNMP Agent Availability | Interno Zabbix | — | 7 dias | + +### Disponibilidade (ICMP) + +| Item | Chave | Intervalo | Retenção | +|------|-------|-----------|---------| +| ICMP Ping | `icmpping` | padrão | 90 dias | +| ICMP Loss | `icmppingloss` | padrão | 90 dias | +| ICMP Response Time | `icmppingsec` | padrão | 90 dias | + +### Traps SNMP + +| Item | Chave | Descrição | +|------|-------|-----------| +| SNMP Traps (fallback) | `snmptrap.fallback` | Coleta todos os traps SNMP sem mapeamento específico | + +--- + +## Regras de Descoberta (LLD) + +### 1. SNMP Discovery — Network Interfaces + +**Chave:** `net.if.discovery` +**Tipo:** SNMP Agent (IF-MIB) +**Intervalo:** 1 hora + +**Variáveis descobertas:** + +| Macro | Descrição | +|-------|-----------| +| `{#IFNAME}` | Nome da interface | +| `{#IFALIAS}` | Alias/descrição da interface | +| `{#IFDESCR}` | Descrição do IF-MIB | +| `{#IFOPERSTATUS}` | Status operacional | +| `{#IFADMINSTATUS}` | Status administrativo | +| `{#IFTYPE}` | Tipo de interface | +| `{#SNMPINDEX}` | Índice SNMP | + +**Itens criados por interface:** + +| Item | OID | Intervalo | Unidade | +|------|-----|-----------|---------| +| Bits recebidos | `ifHCInOctets` | 3 min | bps | +| Bits enviados | `ifHCOutOctets` | 3 min | bps | +| Pacotes recebidos descartados | `ifInDiscards` | 3 min | — | +| Pacotes recebidos com erros | `ifInErrors` | 3 min | — | +| Pacotes enviados descartados | `ifOutDiscards` | 3 min | — | +| Pacotes enviados com erros | `ifOutErrors` | 3 min | — | +| Velocidade da interface | `ifHighSpeed` | 5 min | bps | +| Status operacional | `ifOperStatus` | — | — | +| Tipo de interface | `ifType` | 1 hora | — | + +**Gráfico:** `Interface {#IFNAME}({#IFALIAS}): Network traffic` + +--- + +### 2. SNMP Discovery — CPU Core + +**Chave:** `snmp.discovery.cpu.core` +**Tipo:** SNMP Agent (`DMOS-SYSMON-MIB::cpuCoreFiveSecondsActive`) +**Intervalo:** 60 min + +**Itens criados por core (1 e 5 minutos):** + +| Item | MIB | Unidade | +|------|-----|---------| +| Active CPU core | `cpuCoreOneMinuteActive` / `cpuCoreFiveMinutesActive` | % | +| Interrupt CPU core | `cpuCoreOneMinuteInterrupt` / `cpuCoreFiveMinutesInterrupt` | % | +| Nice CPU core | `cpuCoreOneMinuteNice` / `cpuCoreFiveMinutesNIce` | % | +| Softirq CPU core | `cpuCoreOneMinuteSoftirq` / `cpuCoreFiveMinutesSoftirq` | % | +| System CPU core | `cpuCoreOneMinuteSystem` / `cpuCoreFiveMinutesSystem` | % | +| User CPU core | `cpuCoreOneMinuteUser` / `cpuCoreFiveMinutesUser` | % | +| Wait CPU core | `cpuCoreOneMinuteWait` / `cpuCoreFiveMinutesWait` | % | + +**Gráficos:** `CPU Core {#SNMPINDEX} Last 1 Minute` e `CPU Core {#SNMPINDEX} Last 5 Minutes` + +--- + +### 3. SNMP Discovery — CPU Load + +**Chave:** `snmp.discovery.cpu.load` +**Tipo:** SNMP Agent (`DMOS-SYSMON-MIB::cpuLoadFiveSecondsActive`) +**Intervalo:** 60 min + +**Itens criados:** + +| Item | MIB | Intervalo | Unidade | +|------|-----|-----------|---------| +| Active CPU load last 1 minute | `cpuLoadOneMinuteActive` | padrão | % | +| Active CPU load last 5 minutes | `cpuLoadFiveMinutesActive` | 5 min | % | + +**Gráficos:** `CPU Load {#SNMPINDEX} Last 1 Minute` e `CPU Load {#SNMPINDEX} Last 5 Minutes` + +--- + +### 4. SNMP Discovery — Memory + +**Chave:** `snmp.discovery.memory` +**Tipo:** SNMP Agent (`DMOS-SYSMON-MIB::memoryFiveSecondsTotal`) +**Intervalo:** 60 min + +**Itens criados:** + +| Item | MIB | Retenção | +|------|-----|---------| +| Available memory | `memoryOneMinuteAvailable` | 7 dias | +| Buffered memory | `memoryOneMinuteBuffered` | 7 dias | +| Cached memory | `memoryOneMinuteCached` | 7 dias | +| Free memory | `memoryOneMinuteFree` | 7 dias | +| Slab Reclaimed | `memoryOneMinuteSlabRecl` | 7 dias | +| Slab Unreclaimed | `memoryOneMinuteSlabUnrecl` | 7 dias | +| Total memory | `memoryOneMinuteTotal` | 7 dias | +| Used memory | `memoryOneMinuteUsed` | 7 dias | + +**Gráfico:** `Memory Status {#SNMPINDEX} Last 1 minute` + +--- + +### 5. SNMP Discovery — Fan + +**Chave:** `snmp.discovery.fan` +**Tipo:** SNMP Agent (`DMOS-HW-MONITOR-MIB::fanDescription`) +**Intervalo:** 60 min + +**Itens criados:** + +| Item | MIB | Unidade | +|------|-----|---------| +| FAN Description | `fanDescription` | — | +| FAN Speed | `fanSpeed` | RPM | +| FAN Status | `fanSpeedStatus` | — | +| FAN Read Error | `fanSpeedReadError` | — | + +**Gráfico:** `FAN {#SNMPVALUE} Speed` + +--- + +### 6. SNMP Discovery — Temperature Sensor + +**Chave:** `snmp.discovery.temp.sensor` +**Tipo:** SNMP Agent (`DMOS-HW-MONITOR-MIB::temperatureSensorDescription`) +**Intervalo:** 60 min + +**Itens criados:** + +| Item | MIB | Unidade | Pré-processamento | +|------|-----|---------|------------------| +| Current Temperature | `temperatureSensorCurrentTemperature` | ºC | × 0,1 | +| Description | `temperatureSensorDescription` | — | — | +| Hysteresis Temperature | `temperatureSensorHysteresis` | ºC | × 0,1 | +| Max Temperature | `temperatureSensorMaxTemperature` | ºC | × 0,1 | +| Min Temperature | `temperatureSensorMinTemperature` | ºC | × 0,1 | + +--- + +### 7. SNMP Discovery — PSU + +**Chave:** `dmos_hardware_monitor_mib_psu.py["{HOST.CONN}", "{$SNMP_COMMUNITY}"]` +**Tipo:** External Check (script Python) +**Intervalo:** 60 min + +> ⚠️ **Requer** o script `dmos_hardware_monitor_mib_psu.py` instalado no diretório de scripts externos do Zabbix. + +**Variáveis descobertas:** + +| Macro | Descrição | +|-------|-----------| +| `{#PSU_SLOT_NAME}` | Nome do slot da PSU (ex.: `1/PSU1`) | +| `{#PSU_SLOT_NAME_LEN}` | Comprimento do nome em formato decimal | +| `{#PSU_SLOT_NAME_DEC}` | Nome em decimal para uso no OID SNMP (ex.: `49.47.80.83.85.49`) | + +**Itens criados:** + +| Item | OID | Intervalo | +|------|-----|-----------| +| `{#PSU_SLOT_NAME}` Status | `DMOS-HW-MONITOR-MIB::psuStatus.{#PSU_SLOT_NAME_LEN}.{#PSU_SLOT_NAME_DEC}` | 5 min | + +--- + +## Triggers + +### Triggers Fixas + +| Nome | Severidade | Condição | +|------|-----------|---------| +| Unavailable by ICMP ping | 🔴 High | 3 polls consecutivos sem resposta ICMP | +| No SNMP data collection | 🟡 Warning | SNMP indisponível por `{$SNMP.TIMEOUT}` (padrão: 5 min) | +| Host has been restarted | 🟡 Warning | Uptime < 10 minutos | +| High ICMP ping loss | 🟡 Warning | Perda > `{$ICMP_LOSS_WARN}`% (padrão: 20%) por 5 min | +| High ICMP ping response time | 🟡 Warning | Tempo médio > `{$ICMP_RESPONSE_TIME_WARN}`s (padrão: 0.15s) por 5 min | +| System name has changed | 🔵 Info | Nome SNMP alterado | + +### Trigger Prototypes (LLD) + +| Nome | Severidade | Condição | +|------|-----------|---------| +| Interface `{#IFNAME}`: Link down | 🟠 Average | Status operacional = down (controlado por `{$IFCONTROL}`) | +| Interface `{#IFNAME}`: High bandwidth usage | 🟡 Warning | Utilização > `{$IF.UTIL.MAX}`% (padrão: 90%) por 15 min | +| Interface `{#IFNAME}`: High error rate | 🟡 Warning | Taxa de erros > `{$IF.ERRORS.WARN}` pps (padrão: 2) por 5 min | +| Interface `{#IFNAME}`: Ethernet has changed to lower speed | 🔵 Info | Velocidade caiu abaixo do máximo conhecido | +| CPU Load High Usage > `{$CPU.UTIL.CRIT}`% | 🟡 Warning | Uso de CPU ativo > 80% (padrão) por 5 min | +| Memory Available Low < 100MB | 🔴 High | Memória disponível < 100.000.000 bytes | +| FAN `{#SNMPVALUE}` Status Error | 🔴 High | Status do FAN diferente de OK (0) | +| FAN `{#SNMPVALUE}` Read Error | 🔴 High | Erro de leitura de velocidade do FAN | +| PSU Status Failed: `{#PSU_SLOT_NAME}` | 🔴 High | Status PSU ≠ OK e diferente da leitura anterior | + +--- + +## Macros do Template + +| Macro | Valor padrão | Descrição | +|-------|-------------|-----------| +| `{$SNMP_COMMUNITY}` | `public` | Community SNMP | +| `{$SNMP.TIMEOUT}` | `5m` | Timeout para trigger de SNMP indisponível | +| `{$CPU.UTIL.CRIT}` | `80` | Limiar crítico de uso de CPU (%) | +| `{$MEMORY.UTIL.MAX}` | `90` | Limiar máximo de uso de memória (%) | +| `{$ICMP_LOSS_WARN}` | `20` | Limiar de aviso de perda de pacotes ICMP (%) | +| `{$ICMP_RESPONSE_TIME_WARN}` | `0.15` | Limiar de aviso de tempo de resposta ICMP (s) | +| `{$IF.UTIL.MAX}` | `90` | Utilização máxima de interface (%) | +| `{$IF.ERRORS.WARN}` | `2` | Taxa de erro mínima para disparo de alerta (pps) | +| `{$IFCONTROL}` | `1` | Controle de alertas de link down (0 = desabilita) | +| `{$FAN_CRIT_STATUS}` | `2` | Código de status crítico para FANs | +| `{$TEMP_WARN}` | `50` | Temperatura de aviso (ºC) | +| `{$TEMP_CRIT}` | `60` | Temperatura crítica (ºC) | +| `{$TEMP_CRIT_LOW}` | `5` | Temperatura crítica mínima (ºC) | +| `{$NET.IF.IFNAME.NOT_MATCHES}` | `(loopback\|null\|lo\|docker...)` | Interfaces excluídas da descoberta | +| `{$NET.IF.IFADMINSTATUS.NOT_MATCHES}` | `^2$` | Exclui interfaces administrativamente down | +| `{$NET.IF.IFOPERSTATUS.NOT_MATCHES}` | `^6$` | Exclui interfaces notPresent | + +--- + +## Dashboards + +| Nome | Conteúdo | +|------|---------| +| Network interfaces | Gráfico em grade com tráfego de todas as interfaces descobertas | + +--- + +## Gráficos + +| Nome | Itens | +|------|-------| +| Uptime | `system.uptime[sysUpTime.0]` | +| Interface `{#IFNAME}({#IFALIAS})`: Network traffic | Bits in/out, discards in/out | +| CPU Core `{#SNMPINDEX}` Last 1 Minute | Active/Interrupt/Nice/Softirq/System/User/Wait | +| CPU Core `{#SNMPINDEX}` Last 5 Minutes | Active/Interrupt/Nice/Softirq/System/User/Wait | +| CPU Load `{#SNMPINDEX}` Last 1 Minute | cpuLoadOneMinuteActive | +| CPU Load `{#SNMPINDEX}` Last 5 Minutes | cpuLoadFiveMinutesActive | +| Memory Status `{#SNMPINDEX}` Last 1 minute | Available/Buffered/Cached/Free/SlabRecl/SlabUnrecl/Total/Used | +| FAN `{#SNMPVALUE}` Speed | fanSpeed | +| Temperature Sensor `{#SNMPVALUE}` | Current/Max/Min/Hysteresis | + +--- + +## Value Maps + +| Nome | Uso | +|------|-----| +| `Service state` | ICMP Ping (0=Down, 1=Up) | +| `zabbix.host.available` | SNMP Agent Availability (0/1/2) | +| `IF-MIB::ifOperStatus` | Status operacional de interfaces | +| `IF-MIB::ifType` | Tipo de interface (290+ mapeamentos) | +| `DmOS-HW-MONITOR-MIB PSU Status` | Status das fontes de alimentação | +| `DmOS-HW-MONITOR Environment Sensor Status` | Status dos FANs | +| `DmOS-HW-MONITOR Read Error` | Erro de leitura de sensor | + +--- + +## Inventário de Host + +Os seguintes campos de inventário são preenchidos automaticamente: + +| Campo | Item | +|-------|------| +| `CONTACT` | System Contact | +| `HARDWARE` | System Description | +| `LOCATION` | System Location | +| `NAME` | System Name | + +--- + +## Instalação + +1. Importe o arquivo `zbx_export_templates.xml` no Zabbix via **Data collection → Templates → Import**. +2. Copie as MIBs DmOS para o servidor Zabbix e reinicie o `snmpd` ou o Zabbix Server conforme necessário. +3. Copie `dmos_hardware_monitor_mib_psu.py` para `/usr/lib/zabbix/externalscripts/` e dê permissão de execução. +4. Crie ou edite o host do equipamento Datacom no Zabbix: + - Adicione interface SNMP apontando para o IP do equipamento. + - Defina a macro `{$SNMP_COMMUNITY}` com a community correta. + - Vincule o template **IPv0 - Template Datacom DmOS**. +5. Aguarde o próximo ciclo de polling para confirmar os dados coletados. + +--- + +## Grupos de Template + +- **Templates Datacom** +- **Templates IPv0** + +--- + +## Autor + +Teccnia — IPv0 +Template derivado das MIBs proprietárias Datacom DmOS com base nos templates oficiais do repositório [datacom-teracom/dmos-zabbix-template](https://github.com/datacom-teracom/dmos-zabbix-template). \ No newline at end of file diff --git a/datacom/datacom_dmos/Template_Datacom_DmOS.xml b/datacom/datacom_dmos/Template_Datacom_DmOS.xml new file mode 100644 index 0000000..7bd2def --- /dev/null +++ b/datacom/datacom_dmos/Template_Datacom_DmOS.xml @@ -0,0 +1,3403 @@ + + + 7.2 + + + 792ac9730c4a468ebc50c88c7c6be996 + Templates Datacom + + + b01bb96a1ed547e1a8770677a646aa3c + Templates IPv0 + + + + + + + + af057492d8b14ce1bc5d972a38b30100 + Uptime + NO + NO + + + 00BB00 + + IPv0 - Template Datacom DmOS + system.uptime[sysUpTime.0] + + + + + + diff --git a/datacom/datacom_dmos/dmos_hardware_monitor_mib_psu.py b/datacom/datacom_dmos/dmos_hardware_monitor_mib_psu.py new file mode 100644 index 0000000..238afc3 --- /dev/null +++ b/datacom/datacom_dmos/dmos_hardware_monitor_mib_psu.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 + +""" Script to discovery DmOS PSU objects in Zabbix """ + +from subprocess import run +from json import dumps +from sys import argv +from re import search, I + + +def snmp_discovery_info(host, community, oid): + """ Return SNMP discovery info """ + + cmd = f"snmpbulkwalk -v 2c -c {community} {host} {oid}" + process = run(cmd, shell=True, capture_output=True, text=True, timeout=30) + + snmp_info = [] + snmp_error = '' + while True: + return_code = process.returncode + if return_code is not None: + for output in process.stdout.rstrip().split('\n'): + if search(r'no such', output, I): + snmp_error = output.strip() + break + else: + snmp_error = process.stderr.strip() + snmp_info.append(output.strip()) + break + + return snmp_info, snmp_error + +def convert_snmp_value_string_to_decimal(snmp_value): + """ Return object size and dotted decimal for use in SNMP get """ + + snmp_value_dec = '' + + snmp_value_size = len(snmp_value) + + for index in range(snmp_value_size): + char_decimal = int(''.join(str(ord(snmp_value[index])))) + + if index == snmp_value_size-1: + snmp_value_dec += str(char_decimal) + else: + snmp_value_dec += str(char_decimal) + '.' + + return snmp_value_size, snmp_value_dec + +def main(): + """ Main function """ + + host = argv[1] + community = argv[2] + + oid = 'DMOS-HW-MONITOR-MIB::psuStatus' + snmp_info = snmp_discovery_info(host, community, oid) + + number_snmp_info = len(snmp_info[0]) + json_data = [] + + ret_error = snmp_info[1] + snmp_info = snmp_info[0] + + if ret_error != '': + print(ret_error) + exit(1) + + for i in range(number_snmp_info): + object = {} + + regex = r'%s\.\'\.([a-zA-Z0-9\/]{1,50})\'\s.*\s(.*)$' % oid + output_regex = search(regex, snmp_info[i]) + + object['{#PSU_SLOT_NAME}'] = output_regex.group(1) + + snmp_value_decimal = convert_snmp_value_string_to_decimal(output_regex.group(1)) + object['{#PSU_SLOT_NAME_LEN}'] = snmp_value_decimal[0] + object['{#PSU_SLOT_NAME_DEC}'] = snmp_value_decimal[1] + + json_data.append(object) + + print(dumps({"data": json_data}, indent=4)) + + +main()