r3070 - checkTypeAndAttribute(): new helper function for generic code
authorDenis Ovsienko <infrastation@yandex.ru>
Wed, 26 Aug 2009 14:25:37 +0000 (14:25 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Wed, 26 Aug 2009 14:25:37 +0000 (14:25 +0000)
 - trigger_livevlans(): make use of checkTypeAndAttribute()
 - trigger_APC_SNMP(): new function
 - class SNMPDevice: initial import of Russ Garrett's code
 - class APCPowerSwitch: idem
 - doPDUSNMPmining(): idem
 - commitUpdatePortLabels(): idem
 - renderPortsForObject(): idem

inc/database.php
inc/interface.php
inc/navigation.php
inc/snmp.php
inc/triggers.php

index 910de1d..8ec210d 100644 (file)
@@ -1010,6 +1010,28 @@ function commitUpdatePort ($object_id, $port_id, $port_name, $port_type_id, $por
        return $errorInfo[2];
 }
 
+function commitUpdatePortLabels($object_id = 0, $port_name, $port_type_id, $port_label) {
+       global $dbxlink;
+       $query =
+               "update Port set name='$port_name', label='$port_label'" .
+               "where object_id='$object_id' and name = '$port_name'";
+       $result = $dbxlink->exec ($query);
+       if ($result == 1)
+               return $result;
+       $result = useInsertBlade
+               (
+                'Port',
+                array
+                (
+                 'name' => "'${port_name}'",
+                 'object_id' => "'${object_id}'",
+                 'label' => "'${port_label}'",
+                 'type' => "'${port_type_id}'",
+                )
+               );
+       return $result;
+}
+
 function delObjectPort ($port_id)
 {
        if (unlinkPort ($port_id) != '')
index c7c9bd6..63cafc4 100644 (file)
@@ -1174,6 +1174,29 @@ function renderPortsForObject ($object_id)
        if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
                return;
 
+       $object = getObjectInfo ($object_id);
+       if ($object['objtype_id'] == 2) {
+               startPortlet ('Live Update');
+
+               if (isset ($_REQUEST['do_scan']))
+               {
+                       assertStringArg ('community', __FUNCTION__);
+                       printLog (doPDUSNMPmining ($object_id, $_REQUEST['community']));
+               }
+               echo <<<EOF
+                       <form method=post>
+                       <input type=hidden name=pageno value='${pageno}'>
+                       <input type=hidden name=tabno value='${pageno}'>
+                       <p align=center>
+                       To update the port labels for this power switch, enter the SNMP community:
+                       </p>
+                       <input type=text name=community value='public'>
+                       <input type=submit name='do_scan' value='Go!'>
+                       </form>
+EOF;
+               finishPortlet();
+       }
+
        startPortlet ('Add/update multiple ports');
        printOpFormIntro ('addMultiPorts');
        echo 'Format: <select name=format tabindex=201>';
index a9ab80c..b58c6ff 100644 (file)
@@ -90,6 +90,7 @@ $tab['object']['lvsconfig'] = 'keepalived.conf';
 $tab['object']['autoports'] = 'AutoPorts';
 $tab['object']['tags'] = 'Tags';
 $tab['object']['files'] = 'Files';
+$tab['object']['apcsnmp'] = 'APC SNMP sync';
 $tabhandler['object']['default'] = 'renderRackObject';
 $tabhandler['object']['edit'] = 'renderEditObjectForm';
 $tabhandler['object']['rackspace'] = 'renderRackSpaceForObject';
@@ -103,6 +104,7 @@ $tabhandler['object']['autoports'] = 'renderAutoPortsForm';
 $tabhandler['object']['tags'] = 'renderEntityTags';
 $tabhandler['object']['files'] = 'renderFilesForEntity';
 $tabhandler['object']['editrspvs'] = 'renderObjectSLB';
+$tabhandler['object']['apcsnmp'] = 'renderAPCSNMP';
 $trigger['object']['rackspace'] = 'trigger_rackspace';
 $trigger['object']['ipv4'] = 'trigger_ipv4';
 $trigger['object']['nat4'] = 'trigger_natv4';
index 76e26c9..6dee507 100644 (file)
@@ -650,4 +650,100 @@ function doSNMPmining ($object_id, $community)
        return $log;
 }
 
+// APC SNMP code by Russ Garrett
+
+function doPDUSNMPmining ($object_id, $community)
+{
+       $objectInfo = spotEntity ('object', $object_id);
+       $endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
+       $switch = new APCPowerSwitch($endpoints[0], 'public');
+       $log = array();
+       $sysName = $switch->getName();
+       $error = commitUpdateAttrValue ($object_id, 3, $sysName);
+       if ($error == TRUE)
+               $log[] = array ('code' => 'success', 'message' => 'FQDN set to ' . $sysName);
+       else
+               $log[] = array ('code' => 'error', 'message' => 'Failed settig FQDN: ' . $error);
+       
+       $updated = 0;
+       $ports = $switch->getPorts();
+       foreach ($ports as $name => $port) {
+               if (commitUpdatePortLabels($object_id, $name, 16, $port[0])) {
+                       $updated++;
+               }
+       }
+       if ($updated > 0)
+               $log[] = array ('code' => 'success', 'message' => "Updated ${updated} port(s)");
+
+       return $log;
+}
+
+define('APC_STATUS_ON', 1);
+define('APC_STATUS_OFF', 2);
+define('APC_STATUS_REBOOT', 3);
+
+class SNMPDevice {
+    protected $hostname;
+    protected $community;
+
+    function __construct($hostname, $community) {
+        $this->hostname = $hostname;
+        $this->community = $community;
+    }
+
+    function getName() {
+       return $this->getString('sysName.0');
+    }
+    function getDescription() {
+       return $this->getString('sysDescr.0');
+    }
+
+    protected function snmpSet($oid, $type, $value) {
+        return snmpset($this->hostname, $this->community, $oid, $type, $value);
+    }
+
+    protected function getString($oid) {
+       return trim(str_replace('STRING: ', '', snmpget($this->hostname, $this->community, $oid)), '"');
+    }
+}
+
+class APCPowerSwitch extends SNMPDevice {
+    protected $snmpMib = 'SNMPv2-SMI::enterprises.318';
+
+    function getPorts() {
+        $data = snmpwalk($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.3.3.1.1.2");
+        $status = snmpwalk($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.3.3.1.1.4");
+        $out = array();
+        foreach ($data as $id => $d) {
+            $out[$id + 1] = array(trim(str_replace('STRING: ', '', $d), '"'), str_replace('INTEGER: ', '', $status[$id]));
+        }
+        return $out;
+    }
+    
+    function getPortStatus($id) {
+        return trim(snmpget($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.3.3.1.1.4.$id"), 'INTEGER: ');
+    }
+
+    function getPortName($id) {
+        return trim(str_replace('STRING: ', '', snmpget($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.3.3.1.1.2.$id")), '"');
+    }
+
+    function setPortName($id, $name) {
+        return snmpset($this->hostname, $this->community, "{$this->snmpMib}.1.1.4.5.2.1.3.$id", 's', $name);
+    }
+
+    function portOff($id) {
+        return $this->snmpSet("{$this->snmpMib}.1.1.12.3.3.1.1.4.$id", 'i', APC_STATUS_OFF);
+    }
+
+    function portOn($id) {
+        return $this->snmpSet("{$this->snmpMib}.1.1.12.3.3.1.1.4.$id", 'i', APC_STATUS_ON);
+    }
+
+    function portReboot($id) {
+        return $this->snmpSet("{$this->snmpMib}.1.1.12.3.3.1.1.4.$id", 'i', APC_STATUS_REBOOT);
+    }
+}
+
 ?>
index 7ae5918..cd2f7ab 100644 (file)
 // to decide (the 'bypass' hint of a page), and in some cases,
 // other data can be used.
 
+// Return 'std', if the object belongs to specified type and has
+// specified attribute belonging to the given set of values.
+function checkTypeAndAttribute ($object_id, $type_id, $attr_id, $values)
+{
+       $object = spotEntity ('object', $object_id);
+       if ($object['objtype_id'] != $type_id)
+               return '';
+       foreach (getAttrValues ($object_id) as $record)
+               if ($record['id'] == $attr_id and in_array ($record['key'], $values))
+                       return 'std';
+       return '';
+}
+
 // This trigger filters out everything except switches with known-good
 // software.
-// FIXME: That's a bit of hardcoding at the moment, but
-// let's thinks about fixing it later.
 function trigger_livevlans ()
 {
-       assertUIntArg ('object_id', __FUNCTION__);
-       $object_id = $_REQUEST['object_id'];
-       $object = spotEntity ('object', $object_id, FALSE);
-       if ($object['objtype_id'] != 8)
-               return '';
-       $values = getAttrValues ($object_id);
-       foreach ($values as $record)
-       {
-               if ($record['id'] != 4) // SW type
-                       continue;
+       return checkTypeAndAttribute
+       (
+               $_REQUEST['object_id'],
+               8, // network switch
+               4, // SW type
                // Cisco IOS 12.0
                // Cisco IOS 12.1
                // Cisco IOS 12.2
-               if (in_array ($record['key'], array (244, 251, 252)))
-                       return 'std';
-               else
-                       return '';
-       }
-       return '';
+               array (244, 251, 252)
+       );
+}
+
+function trigger_APC_SNMP ()
+{
+// APC "switched rack PDU" stands for a number of part numbers:
+// http://www.apc.com/products/family/index.cfm?id=70
+       $known_SKUs = array
+       (
+               // 100V input
+               1151 => 'AP7902J',
+               1152 => 'AP7930J',
+               1153 => 'AP7932J',
+               // 120V input
+               1154 => 'AP7900',
+               1155 => 'AP7901',
+               1156 => 'AP7902',
+               1157 => 'AP7930',
+               1158 => 'AP7931',
+               1159 => 'AP7932',
+               // 208V input
+               1160 => 'AP7911',
+               1161 => 'AP7940',
+               1162 => 'AP7941',
+               // 208V 3 phases input
+               1163 => 'AP7960',
+               1164 => 'AP7961',
+               1165 => 'AP7968',
+               1166 => 'AP7990',
+               1167 => 'AP7991',
+               1168 => 'AP7998',
+               // 230V input
+               1137 => 'AP7920',
+               1138 => 'AP7921',
+               1139 => 'AP7922',
+               1140 => 'AP7950',
+               1141 => 'AP7951',
+               1142 => 'AP7952',
+               1143 => 'AP7953',
+               1144 => 'AP7954',
+               // 400V 3 phases input
+               1154 => 'AP7957',
+       );
+       return checkTypeAndAttribute
+       (
+               $_REQUEST['object_id'],
+               2, // PDU
+               2, // SW type
+               $known_SKUs
+       );
 }
 
 // SNMP port finder tab trigger. At the moment we decide on showing it