librenms/librenms

View on GitHub
includes/discovery/entity-physical/mrv-od.inc.php

Summary

Maintainability
D
3 days
Test Coverage
<?php
/*
 * LibreNMS entity-physical module for the discovery of components in the MRV® OptiDriver® Optical Transport Platform
 *
 * Copyright (c) 2019 Martijn Schmidt <martijn.schmidt@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.  Please see LICENSE.txt at the top level of
 * the source code distribution for details.
 */

echo "\nCaching OIDs:";

$entity_array = [];
echo ' MRV OptiDriver';
$chassis_array = snmpwalk_cache_multi_oid($device, 'nbsCmmcChassisTable', $chassis_array, 'NBS-CMMC-MIB');
$slot_array = snmpwalk_cache_multi_oid($device, 'nbsCmmcSlotTable', $slot_array, 'NBS-CMMC-MIB');
$port_array = snmpwalk_cache_multi_oid($device, 'nbsCmmcPortTable', $port_array, 'NBS-CMMC-MIB');

// We use the last digit in the OID to define an entPhysicalIndex for Power Supply state sensors
$nbsCmmcChassisPSStatus_array = [
    7 => 'nbsCmmcChassisPS1Status',
    8 => 'nbsCmmcChassisPS2Status',
    9 => 'nbsCmmcChassisPS3Status',
    10 => 'nbsCmmcChassisPS4Status',
];

// We use the last digit in the OID to define an entPhysicalIndex for Fan state sensors
$nbsCmmcChassisFanStatus_array = [
    11 => 'nbsCmmcChassisFan1Status',
    12 => 'nbsCmmcChassisFan2Status',
    13 => 'nbsCmmcChassisFan3Status',
    14 => 'nbsCmmcChassisFan4Status',
    36 => 'nbsCmmcChassisFan5Status',
    37 => 'nbsCmmcChassisFan6Status',
    38 => 'nbsCmmcChassisFan7Status',
    39 => 'nbsCmmcChassisFan8Status',
];

// Define all the types of pluggable port form factors recognized by nbsCmmcPortType in NBS-CMMC-MIB,
// if nbsCmmcPortType returns a value that is not in this array, it should be a built-in port in the card.
$nbsCmmcPortType_array = [
    125 => 'SFP',
    147 => 'GBIC',
    197 => 'XFP',
    219 => 'QSFP+',
    220 => 'CXP',
    221 => 'CFP',
    223 => 'QSFP28',
    224 => 'CFP2',
];

$nbsCmmcPortSensor_array = [
    30 => [
        'objectType' => 'nbsCmmcPortTemperature',
        'skipValue' => '-2147483648',
        'entPhysicalName' => 'Port Temperature',
    ],
    31 => [
        'objectType' => 'nbsCmmcPortTxPower',
        'skipValue' => '-2147483648',
        'entPhysicalName' => 'Port Tx Power',
    ],
    32 => [
        'objectType' => 'nbsCmmcPortRxPower',
        'skipValue' => '-2147483648',
        'entPhysicalName' => 'Port Rx Power',
    ],
    33 => [
        'objectType' => 'nbsCmmcPortBiasAmps',
        'skipValue' => '-1',
        'entPhysicalName' => 'Port Tx Bias Current',
    ],
    34 => [
        'objectType' => 'nbsCmmcPortSupplyVolts',
        'skipValue' => '-1',
        'entPhysicalName' => 'Port Tx Supply Voltage',
    ],
    38 => [
        'objectType' => 'nbsCmmcPortDigitalDiags',
        'skipValue' => '1',
        'entPhysicalName' => 'Port Overall DigiDiags State',
    ],
];

foreach ($chassis_array as $nbsCmmcChassis => $chassis_contents) {
    [$chassisHardwareRev, $chassisFirmwareRev] = explode(', ', $chassis_contents['nbsCmmcChassisHardwareRevision']);
    // Discover the chassis
    $entity_array[] = [
        'entPhysicalIndex' => $chassis_contents['nbsCmmcChassisIfIndex'] . '00',
        'entPhysicalDescr' => "MRV OptiDriver {$chassis_contents['nbsCmmcChassisModel']}",
        'entPhysicalClass' => 'chassis',
        'entPhysicalName' => "Chassis $nbsCmmcChassis",
        'entPhysicalModelName' => $chassis_contents['nbsCmmcChassisModel'],
        'entPhysicalSerialNum' => $chassis_contents['nbsCmmcChassisSerialNum'],
        'entPhysicalContainedIn' => '0',
        'entPhysicalMfgName' => 'MRV Communications',
        'entPhysicalParentRelPos' => $chassis_contents['nbsCmmcChassisIndex'],
        'entPhysicalVendorType' => $chassis_contents['nbsCmmcChassisType'],
        'entPhysicalHardwareRev' => $chassisHardwareRev,
        'entPhysicalFirmwareRev' => $chassisFirmwareRev,
        'entPhysicalIsFRU' => 'true',
        'entPhysicalAlias' => $chassis_contents['nbsCmmcChassisName'],
    ];

    // Discover the chassis temperature sensor
    if (isset($chassis_contents['nbsCmmcChassisTemperature']) && $chassis_contents['nbsCmmcChassisTemperature'] != '-2147483648') {
        $entity_array[] = [
            'entPhysicalIndex' => "{$chassis_contents['nbsCmmcChassisIfIndex']}15",
            'entPhysicalDescr' => 'Chassis Temperature Sensor',
            'entPhysicalClass' => 'sensor',
            'entPhysicalName' => 'Chassis Temperature',
            'entPhysicalContainedIn' => "{$chassis_contents['nbsCmmcChassisIfIndex']}00",
            'entPhysicalMfgName' => 'MRV Communications',
            'entPhysicalParentRelPos' => '-1',
            'entPhysicalIsFRU' => 'false',
        ];
    }

    // Discover the chassis power budget status sensor
    if (isset($chassis_contents['nbsCmmcChassisPowerStatus']) && $chassis_contents['nbsCmmcChassisPowerStatus'] != 'notSupported') {
        $entity_array[] = [
            'entPhysicalIndex' => "{$chassis_contents['nbsCmmcChassisIfIndex']}51",
            'entPhysicalDescr' => 'Chassis Power Budget Status Sensor',
            'entPhysicalClass' => 'sensor',
            'entPhysicalName' => 'Chassis Power Budget Status',
            'entPhysicalContainedIn' => "{$chassis_contents['nbsCmmcChassisIfIndex']}00",
            'entPhysicalMfgName' => 'MRV Communications',
            'entPhysicalParentRelPos' => '-1',
            'entPhysicalIsFRU' => 'false',
        ];
    }

    // Discover the chassis power supplies and state sensors
    foreach ($nbsCmmcChassisPSStatus_array as $index => $item) {
        if (isset($chassis_contents[$item]) && $chassis_contents[$item] != 'notSupported') {
            $position = substr($item, 16, 1);
            $entity_array[] = [
                'entPhysicalIndex' => $chassis_contents['nbsCmmcChassisIfIndex'] . $position,
                'entPhysicalDescr' => 'Power Supply',
                'entPhysicalClass' => 'powerSupply',
                'entPhysicalName' => "Power Supply $position",
                'entPhysicalContainedIn' => "{$chassis_contents['nbsCmmcChassisIfIndex']}00",
                'entPhysicalMfgName' => 'MRV Communications',
                'entPhysicalParentRelPos' => $position,
                'entPhysicalIsFRU' => 'false',
            ];
            $entity_array[] = [
                'entPhysicalIndex' => $chassis_contents['nbsCmmcChassisIfIndex'] . $index,
                'entPhysicalDescr' => 'Power Supply State',
                'entPhysicalClass' => 'sensor',
                'entPhysicalName' => "Power Supply $position",
                'entPhysicalContainedIn' => $chassis_contents['nbsCmmcChassisIfIndex'] . $position,
                'entPhysicalMfgName' => 'MRV Communications',
                'entPhysicalParentRelPos' => '-1',
                'entPhysicalIsFRU' => 'true',
            ];
        }
    }

    // Discover the chassis fan trays and state sensors
    foreach ($nbsCmmcChassisFanStatus_array as $index => $item) {
        if (isset($chassis_contents[$item]) && $chassis_contents[$item] != 'notSupported') {
            $position = substr($item, 17, 1);
            $entity_array[] = [
                'entPhysicalIndex' => "{$chassis_contents['nbsCmmcChassisIfIndex']}0$position",
                'entPhysicalDescr' => 'Fan Tray',
                'entPhysicalClass' => 'fan',
                'entPhysicalName' => "Fan Tray $position",
                'entPhysicalContainedIn' => "{$chassis_contents['nbsCmmcChassisIfIndex']}00",
                'entPhysicalMfgName' => 'MRV Communications',
                'entPhysicalParentRelPos' => $position,
                'entPhysicalIsFRU' => 'false',
            ];
            $entity_array[] = [
                'entPhysicalIndex' => $chassis_contents['nbsCmmcChassisIfIndex'] . $index,
                'entPhysicalDescr' => 'Fan State',
                'entPhysicalClass' => 'sensor',
                'entPhysicalName' => "Fan $position",
                'entPhysicalContainedIn' => "{$chassis_contents['nbsCmmcChassisIfIndex']}0$position",
                'entPhysicalMfgName' => 'MRV Communications',
                'entPhysicalParentRelPos' => '-1',
                'entPhysicalIsFRU' => 'true',
            ];
        }
    }
}

foreach ($slot_array as $nbsCmmcSlot => $slot_contents) {
    // Obtain the nbsCmmcChassisIfIndex of the chassis which houses this slot
    $nbsCmmcChassisIfIndex = $chassis_array[$slot_contents['nbsCmmcSlotChassisIndex']]['nbsCmmcChassisIfIndex'];
    // Calculate the nbsCmmcSlotIfIndex since an empty slot has nbsCmmcSlotIfIndex == -1
    $nbsCmmcSlotIfIndex = $nbsCmmcChassisIfIndex + $slot_contents['nbsCmmcSlotIndex'] * 1000;
    // Discover the slot
    $entity_array[] = [
        'entPhysicalIndex' => $nbsCmmcSlotIfIndex . '00',
        'entPhysicalDescr' => 'MRV OptiDriver Slot',
        'entPhysicalClass' => 'container',
        'entPhysicalName' => "Card Slot $nbsCmmcSlot",
        'entPhysicalContainedIn' => $nbsCmmcChassisIfIndex . '00',
        'entPhysicalMfgName' => 'MRV Communications',
        'entPhysicalParentRelPos' => $slot_contents['nbsCmmcSlotIndex'],
        'entPhysicalIsFRU' => 'false',
    ];
    if (isset($slot_contents['nbsCmmcSlotIfIndex']) && $slot_contents['nbsCmmcSlotIfIndex'] != '-1') {
        [$cardHardwareRev, $cardFirmwareRev, $cardOtherRev] = explode(', ', $slot_contents['nbsCmmcSlotHardwareRevision']);
        // Discover the card
        $entity_array[] = [
            'entPhysicalIndex' => $slot_contents['nbsCmmcSlotIfIndex'] . '01',
            'entPhysicalDescr' => 'MRV ' . ucfirst($slot_contents['nbsCmmcSlotOperationType']) . ' Card',
            'entPhysicalClass' => 'module',
            'entPhysicalName' => "Card $nbsCmmcSlot",
            'entPhysicalModelName' => $slot_contents['nbsCmmcSlotModel'],
            'entPhysicalSerialNum' => $slot_contents['nbsCmmcSlotSerialNum'],
            'entPhysicalContainedIn' => "{$slot_contents['nbsCmmcSlotIfIndex']}00",
            'entPhysicalMfgName' => 'MRV Communications',
            'entPhysicalParentRelPos' => '-1',
            'entPhysicalVendorType' => $slot_contents['nbsCmmcSlotType'],
            'entPhysicalHardwareRev' => "$cardHardwareRev, $cardOtherRev",
            'entPhysicalFirmwareRev' => $cardFirmwareRev,
            'entPhysicalIsFRU' => 'true',
            'entPhysicalAlias' => $slot_contents['nbsCmmcSlotName'],
        ];

        // Discover the module temperature sensor
        if (isset($slot_contents['nbsCmmcSlotTemperature']) && $slot_contents['nbsCmmcSlotTemperature'] != '-2147483648') {
            $entity_array[] = [
                'entPhysicalIndex' => "{$slot_contents['nbsCmmcSlotIfIndex']}34",
                'entPhysicalDescr' => 'Card Temperature Sensor',
                'entPhysicalClass' => 'sensor',
                'entPhysicalName' => 'Card Temperature',
                'entPhysicalContainedIn' => "{$slot_contents['nbsCmmcSlotIfIndex']}01",
                'entPhysicalMfgName' => 'MRV Communications',
                'entPhysicalParentRelPos' => '-1',
                'entPhysicalIsFRU' => 'false',
            ];
        }
    }
}

foreach ($port_array as $nbsCmmcPort => $port_contents) {
    // Obtain the nbsCmmcSlotIfIndex of the slot which houses this port
    $nbsCmmcSlot = $port_contents['nbsCmmcPortChassisIndex'] . '.' . $port_contents['nbsCmmcPortSlotIndex'];
    $nbsCmmcSlotIfIndex = $slot_array[$nbsCmmcSlot]['nbsCmmcSlotIfIndex'];

    // We only need to discover a transceiver container if the port type is pluggable
    if (array_key_exists($port_contents['nbsCmmcPortType'], $nbsCmmcPortType_array)) {
        $nbsCmmcPortType = $nbsCmmcPortType_array[$port_contents['nbsCmmcPortType']];

        // Discover the transceiver container
        $entity_array[] = [
            'entPhysicalIndex' => $port_contents['nbsCmmcPortIfIndex'] . '00',
            'entPhysicalDescr' => "$nbsCmmcPortType Transceiver Container",
            'entPhysicalClass' => 'container',
            'entPhysicalName' => "Transceiver Container $nbsCmmcPort",
            'entPhysicalContainedIn' => $nbsCmmcSlotIfIndex . '01',
            'entPhysicalMfgName' => 'MRV Communications',
            'entPhysicalParentRelPos' => $port_contents['nbsCmmcPortIndex'],
            'entPhysicalIsFRU' => 'false',
        ];
        // Set a few variables for the port discovery
        $nbsCmmcPortContainedIn = $port_contents['nbsCmmcPortIfIndex'] . '00';
        $nbsCmmcPortVendorInfo = $port_contents['nbsCmmcPortVendorInfo'];
        $nbsCmmcPortIsFRU = 'true';
        $nbsCmmcPortParentRelPos = '-1';
        // If one runs a command like "show 1.1.1 | grep Part" on a port with a genuine pluggable transceiver,
        // CLI output like "Part #/Rev: SFP-10GDWZR-22/0001" indicates / is considered to be the string delimiter.
        // However, non-genuine pluggable transceivers may not adhere to this format.
        [$nbsCmmcPortModelName, $nbsCmmcPortHardwareRev] = explode('/', $port_contents['nbsCmmcPortPartRev']);
    } else {
        $nbsCmmcPortType = 'Built-in';

        // Set a few variables for the port discovery
        $nbsCmmcPortContainedIn = $nbsCmmcSlotIfIndex . '01';
        $nbsCmmcPortVendorInfo = 'MRV Communications';
        $nbsCmmcPortIsFRU = 'false';
        $nbsCmmcPortParentRelPos = $port_contents['nbsCmmcPortIndex'];
        $nbsCmmcPortModelName = '';
        $nbsCmmcPortHardwareRev = '';
    }

    if (isset($port_contents['nbsCmmcPortConnector']) && $port_contents['nbsCmmcPortConnector'] != 'removed') {
        // Determine the correct entPhysicalDescr for the port
        if (isset($port_contents['nbsCmmcPortWavelengthX']) && $port_contents['nbsCmmcPortWavelengthX'] != 'N/A') {
            $portEntPhysicalDescr = "$nbsCmmcPortType Port, {$port_contents['nbsCmmcPortWavelengthX']}nm Tx Signal, {$port_contents['nbsCmmcPortConnector']} Connector";
        } elseif (! empty($port_contents['nbsCmmcPortDescription'])) {
            $portEntPhysicalDescr = "$nbsCmmcPortType Port, {$port_contents['nbsCmmcPortDescription']}, {$port_contents['nbsCmmcPortConnector']} Connector";
        } else {
            $portEntPhysicalDescr = "$nbsCmmcPortType Port, {$port_contents['nbsCmmcPortConnector']} Connector";
        }

        // Discover the port
        $entity_array[] = [
            'entPhysicalIndex' => "{$port_contents['nbsCmmcPortIfIndex']}01",
            'entPhysicalDescr' => $portEntPhysicalDescr,
            'entPhysicalClass' => 'port',
            'entPhysicalName' => "Port $nbsCmmcPort",
            'entPhysicalModelName' => $nbsCmmcPortModelName,
            'entPhysicalSerialNum' => $port_contents['nbsCmmcPortSerialNumber'],
            'entPhysicalContainedIn' => $nbsCmmcPortContainedIn,
            'entPhysicalMfgName' => $nbsCmmcPortVendorInfo,
            'entPhysicalParentRelPos' => $nbsCmmcPortParentRelPos,
            'entPhysicalVendorType' => $port_contents['nbsCmmcPortType'],
            'entPhysicalHardwareRev' => $nbsCmmcPortHardwareRev,
            'entPhysicalIsFRU' => $nbsCmmcPortIsFRU,
            'entPhysicalAlias' => $port_contents['nbsCmmcPortName'],
            'ifIndex' => $port_contents['nbsCmmcPortIfIndex'],
        ];

        // Discover the port sensors
        foreach ($nbsCmmcPortSensor_array as $index => $nbsCmmcPortSensor) {
            if (isset($port_contents[$nbsCmmcPortSensor['objectType']]) && $port_contents[$nbsCmmcPortSensor['objectType']] != $nbsCmmcPortSensor['skipValue']) {
                $entity_array[] = [
                    'entPhysicalIndex' => $port_contents['nbsCmmcPortIfIndex'] . $index,
                    'entPhysicalDescr' => "{$nbsCmmcPortSensor['entPhysicalName']} Sensor",
                    'entPhysicalClass' => 'sensor',
                    'entPhysicalName' => $nbsCmmcPortSensor['entPhysicalName'],
                    'entPhysicalContainedIn' => "{$port_contents['nbsCmmcPortIfIndex']}01",
                    'entPhysicalMfgName' => $nbsCmmcPortVendorInfo,
                    'entPhysicalParentRelPos' => '-1',
                    'entPhysicalIsFRU' => 'false',
                ];
            }
        }
    }
}

foreach ($entity_array as $entPhysicalIndex => $entry) {
    $entPhysicalIndex = array_key_exists('entPhysicalIndex', $entry) ? $entry['entPhysicalIndex'] : '';
    $entPhysicalDescr = array_key_exists('entPhysicalDescr', $entry) ? $entry['entPhysicalDescr'] : '';
    $entPhysicalClass = array_key_exists('entPhysicalClass', $entry) ? $entry['entPhysicalClass'] : '';
    $entPhysicalName = array_key_exists('entPhysicalName', $entry) ? $entry['entPhysicalName'] : '';
    $entPhysicalModelName = array_key_exists('entPhysicalModelName', $entry) ? $entry['entPhysicalModelName'] : '';
    $entPhysicalSerialNum = array_key_exists('entPhysicalSerialNum', $entry) ? $entry['entPhysicalSerialNum'] : '';
    $entPhysicalContainedIn = array_key_exists('entPhysicalContainedIn', $entry) ? $entry['entPhysicalContainedIn'] : '';
    $entPhysicalMfgName = array_key_exists('entPhysicalMfgName', $entry) ? $entry['entPhysicalMfgName'] : '';
    $entPhysicalParentRelPos = array_key_exists('entPhysicalParentRelPos', $entry) ? $entry['entPhysicalParentRelPos'] : '';
    $entPhysicalVendorType = array_key_exists('entPhysicalVendorType', $entry) ? $entry['entPhysicalVendorType'] : '';
    $entPhysicalHardwareRev = array_key_exists('entPhysicalHardwareRev', $entry) ? $entry['entPhysicalHardwareRev'] : '';
    $entPhysicalFirmwareRev = array_key_exists('entPhysicalFirmwareRev', $entry) ? $entry['entPhysicalFirmwareRev'] : '';
    $entPhysicalSoftwareRev = array_key_exists('entPhysicalSoftwareRev', $entry) ? $entry['entPhysicalSoftwareRev'] : '';
    $entPhysicalIsFRU = array_key_exists('entPhysicalIsFRU', $entry) ? $entry['entPhysicalIsFRU'] : '';
    $entPhysicalAlias = array_key_exists('entPhysicalAlias', $entry) ? $entry['entPhysicalAlias'] : '';
    $entPhysicalAssetID = array_key_exists('entPhysicalAssetID', $entry) ? $entry['entPhysicalAssetID'] : '';
    $ifIndex = array_key_exists('ifIndex', $entry) ? $entry['ifIndex'] : '';

    discover_entity_physical($valid, $device, $entPhysicalIndex, $entPhysicalDescr, $entPhysicalClass, $entPhysicalName, $entPhysicalModelName, $entPhysicalSerialNum, $entPhysicalContainedIn, $entPhysicalMfgName, $entPhysicalParentRelPos, $entPhysicalVendorType, $entPhysicalHardwareRev, $entPhysicalFirmwareRev, $entPhysicalSoftwareRev, $entPhysicalIsFRU, $entPhysicalAlias, $entPhysicalAssetID, $ifIndex);
}//end foreach

echo "\n";
unset(
    $update_data,
    $insert_data,
    $entry,
    $entity_array
);