diff --git a/files/enoc_pdu_snmp2node_exporter.py b/files/enoc_pdu_snmp2node_exporter.py new file mode 100644 index 0000000000000000000000000000000000000000..601dbc203f192164bc8456fee64e122a0030016b --- /dev/null +++ b/files/enoc_pdu_snmp2node_exporter.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +import ast +import os +import subprocess +from pathlib import Path + + +def process_kv(k, v): + if v.startswith('"') and v.endswith('"'): + return k, ast.literal_eval(v) + elif 'Current' in k or 'Energy' in k: + # The energy and current values received from the PDUs are multiplied by 10 + return k, int(v)/10 + return k, int(v) + + +def walk(agent): + p = subprocess.run( + [ + 'snmpwalk', '-O', 'Q', + '-r', '1', + '-t', '1', + '-m', 'IPPDU-MIB', + '-v', '1', + '-c', 'public', + agent, + '1.3.6.1.4.1.30966.10.3' + ], + stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, encoding='utf-8' + ) + data = [process_kv(*line.split(' = ', 1)) for line in p.stdout.strip().splitlines() if '=' in line] + return {k: v for k, v in data} + + +def get_metrics(agent): + d = walk(agent) + + lines = [] + + for phase in ['A', 'B', 'C']: + labels = {'phase': phase, 'agent': agent} + labels_str = '{' + ','.join(f'{k}="{v}"' for k, v in labels.items()) + '}' + + try: + voltage = d[f'IPPDU-MIB::mVoltage{phase}.0'] + lines.append(f'pdu_voltage{labels_str} {voltage}') + except KeyError: + pass + + try: + current = d[f'IPPDU-MIB::mCurrent{phase}.0'] + lines.append(f'pdu_current{labels_str} {current}') + except KeyError: + pass + + try: + # convert KWh to Joules, the preferred unit in prometheus + energy = d[f'IPPDU-MIB::mEnergy{phase}.0'] * 3_600_000 + lines.append(f'pdu_joules_total{labels_str} {energy}') + except KeyError: + pass + + return lines + + +def main(): + with open('/usr/local/etc/enoc_pdu_snmp2node_exporter.hosts', 'r') as f: + hosts = f.read().strip().splitlines() + + tmp_file = Path(f'/var/lib/prometheus-dropzone/pdu.prom.{os.getpid()}') + + with tmp_file.open('w') as f: + for h in hosts: + f.write('\n'.join(get_metrics(h)) + '\n') + + tmp_file.rename(tmp_file.with_name('pdu.prom')) + + +if __name__ == '__main__': + main() diff --git a/files/ip2017.MIB b/files/ip2017.MIB new file mode 100644 index 0000000000000000000000000000000000000000..623391b978cb3e38b491a6c82f14c928a923fc6c --- /dev/null +++ b/files/ip2017.MIB @@ -0,0 +1,454 @@ +IPPDU-MIB DEFINITIONS ::= BEGIN + +IMPORTS + enterprises, Counter, + TimeTicks, Gauge FROM RFC1155-SMI + OBJECT-TYPE FROM RFC-1212 + sysUpTime, DisplayString FROM RFC1213-MIB +TRAP-TYPE FROM RFC-1215; + +clever OBJECT IDENTIFIER ::= { enterprises 30966 } +ip-PDU OBJECT IDENTIFIER ::= { clever 10 } +ipPDU OBJECT IDENTIFIER ::= { ip-PDU 3 } +deviceInfo OBJECT IDENTIFIER ::= { ipPDU 1 } +statusInfo OBJECT IDENTIFIER ::= { ipPDU 2 } + +DeviceName OBJECT-TYPE + SYNTAX DisplayString (SIZE (255)) + ACCESS read-write + STATUS optional + DESCRIPTION + "device name." + ::= { deviceInfo 1 } + +mVoltageA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 1 total votage." + ::= { statusInfo 1 } + +mVoltageB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 2 total votage." + ::= { statusInfo 2 } + +mVoltageC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 3 total votage." + ::= { statusInfo 3 } + +mCurrentA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 1 total current.Magnified 10 times." + ::= { statusInfo 4 } + +mCurrentB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 2 total current.Magnified 10 times." + ::= { statusInfo 5 } + +mCurrentC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 3 total current.Magnified 10 times." + ::= { statusInfo 6 } + +mEnergyA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 1 energy .Magnified 10 times." + ::= { statusInfo 7 } +mEnergyB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 2 energy .Magnified 10 times." + ::= { statusInfo 8 } +mEnergyC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Line 3 energy .Magnified 10 times." + ::= { statusInfo 9 } +mTemperature OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Temperature" + ::= { statusInfo 10 } +mHumidity OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "Master Humidity" + ::= { statusInfo 11 } + + +sOneVoltageA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 1 total votage." + ::= { statusInfo 12 } + +sOneVoltageB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 2 total votage." + ::= { statusInfo 13 } + +sOneVoltageC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 3 total votage." + ::= { statusInfo 14 } + +sOneCurrentA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 1 total current.Magnified 10 times." + ::= { statusInfo 15 } + +sOneCurrentB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 2 total current.Magnified 10 times." + ::= { statusInfo 16 } + +sOneCurrentC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 3 total current.Magnified 10 times." + ::= { statusInfo 17 } + +sOneEnergyA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 1 energy .Magnified 10 times." + ::= { statusInfo 18 } +sOneEnergyB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 2 energy .Magnified 10 times." + ::= { statusInfo 19 } +sOneEnergyC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Line 3 energy .Magnified 10 times." + ::= { statusInfo 20 } +sOneTem OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Temperature" + ::= { statusInfo 21 } +sOneHum OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveOne Humidity" + ::= { statusInfo 22 } + + +sTwoVoltageA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 1 total votage." + ::= { statusInfo 23 } + +sTwoVoltageB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 2 total votage." + ::= { statusInfo 24 } + +sTwoVoltageC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 3 total votage." + ::= { statusInfo 25 } + +sTwoCurrentA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 1 total current.Magnified 10 times." + ::= { statusInfo 26 } + +sTwoCurrentB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 2 total current.Magnified 10 times." + ::= { statusInfo 27 } + +sTwoCurrentC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 3 total current.Magnified 10 times." + ::= { statusInfo 28 } + +sTwoEnergyA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 1 energy .Magnified 10 times." + ::= { statusInfo 29 } +sTwoEnergyB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 2 energy .Magnified 10 times." + ::= { statusInfo 30 } +sTwoEnergyC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Line 3 energy .Magnified 10 times." + ::= { statusInfo 31 } +sTwoTem OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Temperature" + ::= { statusInfo 32 } +sTwoHum OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveTwo Humidity" + ::= { statusInfo 33 } + + + +sThreeVoltageA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 1 total votage." + ::= { statusInfo 34 } + +sThreeVoltageB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 2 total votage." + ::= { statusInfo 35 } + +sThreeVoltageC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 3 total votage." + ::= { statusInfo 36 } + +sThreeCurrentA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 1 total current.Magnified 10 times." + ::= { statusInfo 37 } + +sThreeCurrentB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 2 total current.Magnified 10 times." + ::= { statusInfo 38 } + +sThreeCurrentC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 3 total current.Magnified 10 times." + ::= { statusInfo 39 } + +sThreeEnergyA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 1 energy .Magnified 10 times." + ::= { statusInfo 40 } +sThreeEnergyB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 2 energy .Magnified 10 times." + ::= { statusInfo 41 } +sThreeEnergyC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Line 3 energy .Magnified 10 times." + ::= { statusInfo 42 } +sThreeTem OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Temperature" + ::= { statusInfo 43 } +sThreeHum OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveThree Humidity" + ::= { statusInfo 44 } + + +sFourVoltageA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 1 total votage." + ::= { statusInfo 45 } + +sFourVoltageB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 2 total votage." + ::= { statusInfo 46 } + +sFourVoltageC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 3 total votage." + ::= { statusInfo 47 } + +sFourCurrentA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 1 total current.Magnified 10 times." + ::= { statusInfo 48 } + +sFourCurrentB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 2 total current.Magnified 10 times." + ::= { statusInfo 49 } + +sFourCurrentC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 3 total current.Magnified 10 times." + ::= { statusInfo 50 } + +sFourEnergyA OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 1 energy .Magnified 10 times." + ::= { statusInfo 51 } +sFourEnergyB OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 2 energy .Magnified 10 times." + ::= { statusInfo 52 } +sFourEnergyC OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Line 3 energy .Magnified 10 times." + ::= { statusInfo 53 } +sFourTem OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Temperature" + ::= { statusInfo 54 } +sFourHum OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS optional + DESCRIPTION + "SlaveFour Humidity" + ::= { statusInfo 55 } + + + + + + +END diff --git a/manifests/init.pp b/manifests/init.pp index 234351bce17e046b09ad0880b47ca260b93e92a1..c709e88f9535f9692fba25636fb58c8c35050efd 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -32,4 +32,81 @@ class orwell { user => 'root', minute => '*/2', } + + include orwell::enoc_pdu_snmp +} + +class orwell::enoc_pdu_snmp { + package { 'net-snmp-utils': + ensure => installed, + } + package { 'python3': + ensure => installed, + } + + file { '/root/.snmp/': + ensure => directory, + } + -> file { '/root/.snmp/mibs/': + ensure => directory, + } + -> file { '/root/.snmp/mibs/ip2017.MIB': + ensure => file, + source => 'puppet:///modules/orwell/ip2017.MIB', + } + + file { '/usr/local/sbin/enoc_pdu_snmp2node_exporter.py': + ensure => file, + source => 'puppet:///modules/orwell/enoc_pdu_snmp2node_exporter.py', + mode => '500', + } + + $hosts = [ + 'pdu-r1-1.mgmt', + 'pdu-r1-2.mgmt', + 'pdu-r2-1.mgmt', + 'pdu-r2-2.mgmt', + 'pdu-r3-1.mgmt', + 'pdu-r3-2.mgmt', + 'pdu-r4-1.mgmt', + 'pdu-r4-2.mgmt', + 'pdu-r5-1.mgmt', + 'pdu-r5-2.mgmt', + 'pdu-r6-1.mgmt', + 'pdu-r6-2.mgmt', + 'pdu-r7-1.mgmt', + 'pdu-r7-2.mgmt', + 'pdu-r8-1.mgmt', + 'pdu-r8-2.mgmt', + 'pdu-r9-1.mgmt', + 'pdu-r9-2.mgmt', + 'pdu-r10-1.mgmt', + 'pdu-r10-2.mgmt', + 'pdu-r11-1.mgmt', + 'pdu-r11-2.mgmt', + ] + + file { '/usr/local/etc/enoc_pdu_snmp2node_exporter.hosts': + ensure => file, + content => ($hosts + ['']).join("\n") + } + + $timer_content = @(EOS) +[Timer] +OnCalendar=*:*:0/10 +EOS + + $service_content = @(EOS) +[Service] +User=root +Type=oneshot +ExecStart=/usr/local/sbin/enoc_pdu_snmp2node_exporter.py +EOS + + systemd::timer { 'enoc_pdu_snmp2node_exporter.timer': + active => true, + enable => true, + timer_content => $timer_content, + service_content => $service_content, + } }