new feature: patch cables accounting
authorDenis Ovsienko <infrastation@yandex.ru>
Sun, 25 May 2014 09:05:06 +0000 (13:05 +0400)
committerDenis Ovsienko <infrastation@yandex.ru>
Tue, 3 Jun 2014 10:57:30 +0000 (14:57 +0400)
This commit implements basic management of patch cables stock. It allows
for generic types of cables and connectors and comes preconfigured for
common assemblies like fiber optics, twisted pair and such. There is a
configuration page for further customization.

The user can consume/replenish an arbitrary amount of patch cables on
the cable heaps page or consume 1 cable on the port linker pop-up
through a new SELECT that suggests only the patch cable heaps compatible
with the current port type. There is a minimalistic event log for
changes in the amount.

Implementing this data model takes 6 new SQL tables with a foreign key
to the recently introduced PortOuterInterface.

* getPatchCableConnectorList(): new function
* getPatchCableTypeList(): new function
* getPatchCableConnectorOptions(): new function
* getPatchCableTypeOptions(): new function
* getPatchCableHeapSummary(): new function
* getPatchCableHeapOptionsForOIF(): new function
* getPatchCableConnectorCompat(): new function
* getPatchCableOIFCompat(): new function
* commitModifyPatchCableAmount(): new function
* commitSetPatchCableAmount(): new function
* getPatchCableHeapLogEntries(): new function
* addPatchCableHeapLogEntry(): new function
* genericAssertion(): update for "decimal" assertion type
* formatPatchCableHeapAsPlainText(): new function
* install.php: add the new SQL tables w/data
* upgrade.php: idem
* getPatchCableHeapCursorCode(): new function
* renderPatchCableHeapSummary(): new function
* renderPatchCableHeapEditor(): new function
* renderPatchCableHeapAmount(): new function
* renderSimpleTableWithOriginViewer(): new function
* renderSimpleTableWithOriginEditor(): new function
* renderPatchCableConfiguration(): new function
* renderPatchCableConnectorEditor(): new function
* renderPatchCableTypeEditor(): new function
* renderPatchCableConnectorCompatEditor(): new function
* renderPatchCableOIFCompatEditor(): new function
* navigation.php: update $indexlayout and add two new pages
* consumePatchCable(): new function
* replenishPatchCable(): new function
* setPatchCableAmount(): new function
* handlePopupPortLink(): update
* renderPopupPortSelector(): update
* triggerPatchCableHeapsConfigured(): new function

12 files changed:
ChangeLog
wwwroot/inc/database.php
wwwroot/inc/functions.php
wwwroot/inc/install.php
wwwroot/inc/interface-lib.php
wwwroot/inc/interface.php
wwwroot/inc/navigation.php
wwwroot/inc/ophandlers.php
wwwroot/inc/popup.php
wwwroot/inc/triggers.php
wwwroot/inc/upgrade.php
wwwroot/pix/patch_cables.png [new file with mode: 0644]

index 004363eb8cacaf91070288181980c002e28a35fd..fce2862b781b44c3c39e2b4c9e4d396b8e6ac301 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,7 @@
        bugfix: LLDP neighbors was empty for some Juniper devices
        update: allow connecting to a non-standard LDAP port (by Michał Sochoń)
        update: move port outer interfaces from the dictionary
+       new feature: patch cables accounting
 0.20.7 2014-03-03
        bugfix: IP tree expansion button was broken when MAX_UNFILTERED_ENTITIES was set
        bugfix: fix URL detection bug introduced in bugfix to #1023 (#1103)
index 1461e93ab7093affc7343e140c8ef65186f19531..a18b1bb97df986fe2f3d4aaa775ec7e6796e2d48 100644 (file)
@@ -5560,4 +5560,135 @@ function getEntitiesCount ($realm)
        return $result->fetch (PDO::FETCH_COLUMN, 0);
 }
 
+function getPatchCableConnectorList()
+{
+       $result = usePreparedSelectBlade ('SELECT id, origin, connector FROM PatchCableConnector ORDER BY connector');
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+function getPatchCableConnectorOptions()
+{
+       $ret = array();
+       foreach (getPatchCableConnectorList() as $item)
+               $ret[$item['id']] = $item['connector'] . ($item['origin'] == 'custom' ? ' (custom)' : '');
+       return $ret;
+}
+
+function getPatchCableTypeList()
+{
+       $result = usePreparedSelectBlade ('SELECT id, origin, pctype FROM PatchCableType ORDER BY pctype');
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+function getPatchCableTypeOptions()
+{
+       $ret = array();
+       foreach (getPatchCableTypeList() as $item)
+               $ret[$item['id']] = $item['pctype'] . ($item['origin'] == 'custom' ? ' (custom)' : '');
+       return $ret;
+}
+
+function getPatchCableHeapSummary()
+{
+       $result = usePreparedSelectBlade
+       (
+               'SELECT PCH.id, end1_conn_id, PCC1.connector AS end1_connector, pctype_id, pctype, ' .
+               'end2_conn_id, PCC2.connector AS end2_connector, amount, length, description, ' .
+               'COUNT(PCHL.id) AS logc FROM PatchCableHeap AS PCH ' .
+               'INNER JOIN PatchCableType AS PCT ON PCH.pctype_id = PCT.id ' .
+               'INNER JOIN PatchCableConnector AS PCC1 ON end1_conn_id = PCC1.id ' .
+               'INNER JOIN PatchCableConnector AS PCC2 ON end2_conn_id = PCC2.id ' .
+               'LEFT JOIN PatchCableHeapLog AS PCHL ON PCH.id = PCHL.heap_id ' .
+               'GROUP BY PCH.id ' .
+               'ORDER BY pctype, end1_connector, end2_connector, description, id '
+       );
+       return reindexByID ($result->fetchAll (PDO::FETCH_ASSOC));
+}
+
+function getPatchCableHeapOptionsForOIF ($oif_id)
+{
+       $result = usePreparedSelectBlade ('SELECT pctype_id FROM PatchCableOIFCompat WHERE oif_id = ?', array ($oif_id));
+       $pctypes = reduceSubarraysToColumn ($result->fetchAll (PDO::FETCH_ASSOC), 'pctype_id');
+       unset ($result);
+       $ret = array();
+       foreach (getPatchCableHeapSummary() as $item)
+               if ($item['amount'] > 0 && in_array ($item['pctype_id'], $pctypes))
+                       $ret[$item['id']] = formatPatchCableHeapAsPlainText ($item);
+       return $ret;
+}
+
+function getPatchCableConnectorCompat()
+{
+       $result = usePreparedSelectBlade
+       (
+               'SELECT pctype_id, pctype, connector_id, connector FROM PatchCableConnectorCompat ' .
+               'INNER JOIN PatchCableType AS PCT ON pctype_id = PCT.id ' .
+               'INNER JOIN PatchCableConnector AS PCC ON connector_id = PCC.id ' .
+               'ORDER BY pctype, connector'
+       );
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+function getPatchCableOIFCompat()
+{
+       $result = usePreparedSelectBlade
+       (
+               'SELECT pctype_id, pctype, oif_id, oif_name FROM PatchCableOIFCompat ' .
+               'INNER JOIN PatchCableType AS PCT ON pctype_id = PCT.id ' .
+               'INNER JOIN PortOuterInterface AS POI ON oif_id = POI.id ' .
+               'ORDER BY pctype, oif_name'
+       );
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+function commitModifyPatchCableAmount ($heap_id, $by_amount)
+{
+       global $dbxlink;
+       $dbxlink->beginTransaction();
+       usePreparedExecuteBlade
+       (
+               'UPDATE PatchCableHeap SET amount = amount + ? WHERE id = ? AND amount + ? >= 0',
+               array ($by_amount, $heap_id, $by_amount)
+       );
+       addPatchCableHeapLogEntry ($heap_id, "amount adjusted by ${by_amount}");
+       return $dbxlink->commit();
+}
+
+function commitSetPatchCableAmount ($heap_id, $new_amount)
+{
+       global $dbxlink;
+       $dbxlink->beginTransaction();
+       usePreparedUpdateBlade
+       (
+               'PatchCableHeap',
+               array ('amount' => $new_amount),
+               array ('id' => $heap_id)
+       );
+       addPatchCableHeapLogEntry ($heap_id, "amount set to ${new_amount}");
+       return $dbxlink->commit();
+}
+
+function getPatchCableHeapLogEntries ($heap_id)
+{
+       $result = usePreparedSelectBlade
+       (
+               'SELECT date, user, message FROM PatchCableHeapLog WHERE heap_id = ? ORDER BY date DESC',
+               array ($heap_id)
+       );
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+function addPatchCableHeapLogEntry ($heap_id, $message)
+{
+       global $disable_logging;
+       if (isset ($disable_logging) && $disable_logging)
+               return;
+       global $remote_username;
+       usePreparedExecuteBlade
+       (
+               "INSERT INTO PatchCableHeapLog (heap_id, date, user, message) VALUES (?, NOW(), ?, ?)",
+               array ($heap_id, $remote_username, $message)
+       );
+}
+
 ?>
index 74aa611678bc11268f08dd4f29f4bb1513082b5c..2db0a4b13e1b7f38c42b6fbdcfc76d34ac8c75e9 100644 (file)
@@ -277,6 +277,10 @@ function genericAssertion ($argname, $argtype)
                return assertUIntArg ($argname);
        case 'uint0':
                return assertUIntArg ($argname, TRUE);
+       case 'decimal':
+               if (! preg_match ('/^\d+(\.\d+)?$/', assertStringArg ($argname)))
+                       throw new InvalidRequestArgException ($argname, $sic[$argname], 'format error');
+               return $sic[$argname];
        case 'inet':
                return assertIPArg ($argname);
        case 'inet4':
@@ -6157,4 +6161,12 @@ function getLastCreatedId ($realm)
                        return $item['id'];
 }
 
+function formatPatchCableHeapAsPlainText ($heap)
+{
+       $text = "${heap['amount']} pcs: [${heap['end1_connector']}] ${heap['pctype']} [${heap['end2_connector']}]";
+       if ($heap['description'] != '')
+               $text .=  " (${heap['description']})";
+       return niftyString ($text, 512);
+}
+
 ?>
index 8f67aad008badf85d33952a4c26bc02f267ff488..1b4242b5f8f7e0626fd2c07f2d761a3269973e88 100644 (file)
@@ -854,6 +854,66 @@ function get_pseudo_file ($name)
   UNIQUE KEY `parent_child` (`parent_objtype_id`,`child_objtype_id`)
 ) ENGINE=InnoDB";
 
+               $query[] = "CREATE TABLE `PatchCableConnector` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `origin` enum('default','custom') NOT NULL DEFAULT 'custom',
+  `connector` char(32) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `connector_per_origin` (`connector`,`origin`)
+) ENGINE=InnoDB";
+
+               $query[] = "CREATE TABLE `PatchCableConnectorCompat` (
+  `pctype_id` int(10) unsigned NOT NULL,
+  `connector_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`pctype_id`,`connector_id`),
+  KEY `connector_id` (`connector_id`),
+  CONSTRAINT `PatchCableConnectorCompat-FK-connector_id` FOREIGN KEY (`connector_id`) REFERENCES `PatchCableConnector` (`id`),
+  CONSTRAINT `PatchCableConnectorCompat-FK-pctype_id` FOREIGN KEY (`pctype_id`) REFERENCES `PatchCableType` (`id`)
+) ENGINE=InnoDB";
+
+               $query[] = "CREATE TABLE `PatchCableHeap` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `pctype_id` int(10) unsigned NOT NULL,
+  `end1_conn_id` int(10) unsigned NOT NULL,
+  `end2_conn_id` int(10) unsigned NOT NULL,
+  `amount` smallint(5) unsigned NOT NULL DEFAULT '0',
+  `length` decimal(5,2) unsigned NOT NULL DEFAULT '1.00',
+  `description` char(255) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `compat1` (`pctype_id`,`end1_conn_id`),
+  KEY `compat2` (`pctype_id`,`end2_conn_id`),
+  CONSTRAINT `PatchCableHeap-FK-compat1` FOREIGN KEY (`pctype_id`, `end1_conn_id`) REFERENCES `PatchCableConnectorCompat` (`pctype_id`, `connector_id`),
+  CONSTRAINT `PatchCableHeap-FK-compat2` FOREIGN KEY (`pctype_id`, `end2_conn_id`) REFERENCES `PatchCableConnectorCompat` (`pctype_id`, `connector_id`)
+) ENGINE=InnoDB";
+
+               $query[] = "CREATE TABLE `PatchCableHeapLog` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `heap_id` int(10) unsigned NOT NULL,
+  `date` datetime NOT NULL,
+  `user` char(64) NOT NULL,
+  `message` char(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `heap_id-date` (`heap_id`,`date`),
+  CONSTRAINT `PatchCableHeapLog-FK-heap_id` FOREIGN KEY (`heap_id`) REFERENCES `PatchCableHeap` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB";
+
+               $query[] = "CREATE TABLE `PatchCableOIFCompat` (
+  `pctype_id` int(10) unsigned NOT NULL,
+  `oif_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`pctype_id`,`oif_id`),
+  KEY `oif_id` (`oif_id`),
+  CONSTRAINT `PatchCableOIFCompat-FK-oif_id` FOREIGN KEY (`oif_id`) REFERENCES `PortOuterInterface` (`id`),
+  CONSTRAINT `PatchCableOIFCompat-FK-pctype_id` FOREIGN KEY (`pctype_id`) REFERENCES `PatchCableType` (`id`)
+) ENGINE=InnoDB";
+
+               $query[] = "CREATE TABLE `PatchCableType` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `origin` enum('default','custom') NOT NULL DEFAULT 'custom',
+  `pctype` char(64) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `pctype_per_origin` (`pctype`,`origin`)
+) ENGINE=InnoDB";
+
                $query[] = "CREATE TABLE `Port` (
   `id` int(10) unsigned NOT NULL auto_increment,
   `object_id` int(10) unsigned NOT NULL default '0',
@@ -1546,6 +1606,66 @@ WHERE O.objtype_id = 1562";
 (1787,14,NULL,'no'),
 (1787,30,38,'yes')";
 
+               $query[] = "INSERT INTO PatchCableConnector (id, origin, connector) VALUES
+(1,'default','FC/PC'),(2,'default','FC/APC'),
+(3,'default','LC/PC'),(4,'default','LC/APC'),
+(5,'default','MPO-12/PC'),(6,'default','MPO-12/APC'),
+(7,'default','MPO-24/PC'),(8,'default','MPO-24/APC'),
+(9,'default','SC/PC'),(10,'default','SC/APC'),
+(11,'default','ST/PC'),(12,'default','ST/APC'),
+(13,'default','T568/8P8C/RJ45'),
+(14,'default','SFP-1000'),
+(15,'default','SFP+'),
+(999,'default','CX4/SFF-8470')";
+
+               $query[] = "INSERT INTO PatchCableType (id, origin, pctype) VALUES
+(1,'default','duplex OM1'),
+(2,'default','duplex OM2'),
+(3,'default','duplex OM3'),
+(4,'default','duplex OM4'),
+(5,'default','duplex OS1'),
+(6,'default','duplex OS2'),
+(7,'default','simplex OM1'),
+(8,'default','simplex OM2'),
+(9,'default','simplex OM3'),
+(10,'default','simplex OM4'),
+(11,'default','simplex OS1'),
+(12,'default','simplex OS2'),
+(13,'default','Cat.5 TP'),
+(14,'default','Cat.6 TP'),
+(15,'default','Cat.6a TP'),
+(16,'default','Cat.7 TP'),
+(17,'default','Cat.7a TP'),
+(18,'default','12-fiber OM3'),
+(19,'default','12-fiber OM4'),
+(20,'default','10Gb/s CX4 coax'),
+(21,'default','24-fiber OM3'),
+(22,'default','24-fiber OM4'),
+(23,'default','1Gb/s 50cm shielded'),
+(24,'default','10Gb/s 24AWG twinax'),
+(25,'default','10Gb/s 26AWG twinax'),
+(26,'default','10Gb/s 28AWG twinax'),
+(27,'default','10Gb/s 30AWG twinax'),
+(999,'default','Cat.3 TP')";
+
+               $query[] = "INSERT INTO PatchCableConnectorCompat (pctype_id, connector_id) VALUES
+(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1), -- FC/PC
+(1,2),(2,2),(3,2),(4,2),(5,2),(6,2),(7,2),(8,2),(9,2),(10,2),(11,2),(12,2), -- FC/APC
+(1,3),(2,3),(3,3),(4,3),(5,3),(6,3),(7,3),(8,3),(9,3),(10,3),(11,3),(12,3), -- LC/PC
+(1,4),(2,4),(3,4),(4,4),(5,4),(6,4),(7,4),(8,4),(9,4),(10,4),(11,4),(12,4), -- LC/APC
+(1,9),(2,9),(3,9),(4,9),(5,9),(6,9),(7,9),(8,9),(9,9),(10,9),(11,9),(12,9), -- SC/PC
+(1,10),(2,10),(3,10),(4,10),(5,10),(6,10),(7,10),(8,10),(9,10),(10,10),(11,10),(12,10), -- SC/APC
+(1,11),(2,11),(3,11),(4,11),(5,11),(6,11),(7,11),(8,11),(9,11),(10,11),(11,11),(12,11), -- ST/PC
+(1,12),(2,12),(3,12),(4,12),(5,12),(6,12),(7,12),(8,12),(9,12),(10,12),(11,12),(12,12), -- ST/APC
+(13,13),(14,13),(15,13),(16,13),(17,13),(999,13), -- T568
+(18,5),(19,5), -- MPO-12/PC
+(18,6),(19,6), -- MPO-12/APC
+(20,999), -- CX4
+(21,7),(22,7), -- MPO-24/PC
+(21,8),(22,8), -- MPO-24/APC
+(23,14), -- SFP-1000
+(24,15),(25,15),(26,15),(27,15) -- SFP+";
+
                $query[] = "INSERT INTO `PortInnerInterface` VALUES
 (1,'hardwired'),
 (2,'SFP-100'),
@@ -1766,6 +1886,41 @@ WHERE O.objtype_id = 1562";
 // Add new outer interface types with id < 2000. Values 2000 and up are for
 // users' local types.
 
+               $query[] = "INSERT INTO PatchCableOIFCompat (pctype_id, oif_id) VALUES
+(13,18),(14,18),(15,18),(16,18),(17,18),(999,18), -- 10Base-T: Cat.3+ TP
+(11,1198),(12,1198),(11,1199),(12,1199),          -- 100Base-BX10: 1xSMF
+(5,1197),(6,1197),                                -- 100Base-LX10: 2xSMF
+(5,1200),(6,1200),                                -- 100Base-EX: 2xSMF
+(5,1201),(6,1201),                                -- 100Base-ZX: 2xSMF
+(1,1195),(2,1195),(3,1195),(4,1195),              -- 100Base-FX: 2xMMF
+(1,1196),(2,1196),(3,1196),(4,1196),              -- 100Base-SX: 2xMMF
+(13,19),(14,19),(15,19),(16,19),(17,19),          -- 100Base-TX: Cat.5+ TP
+(11,1206),(12,1206),(11,1207),(12,1207),          -- 1000Base-BX10: 1xSMF
+(5,1204),(6,1204),                                -- 1000Base-LX: 2xSMF
+(5,1205),(6,1205),                                -- 1000Base-LX10: 2xSMF
+(1,1202),(2,1202),(3,1202),(4,1202),              -- 1000Base-SX: 2xMMF
+(1,1203),(2,1203),(3,1203),(4,1203),              -- 1000Base-SX+: 2xMMF
+(13,24),(14,24),(15,24),(16,24),(17,24),          -- 1000Base-T: Cat.5+ TP
+(5,34),(6,34),                                    -- 1000Base-ZX: 2xSMF
+(23,1077),                                        -- 1000Base direct attach: shielded
+(1,30),(2,30),(3,30),(4,30),                      -- 10GBase-SR: 2xMMF
+(5,36),(6,36),                                    -- 10GBase-LR: 2xSMF
+(5,35),(6,35),                                    -- 10GBase-ER: 2xSMF
+(5,38),(6,38),                                    -- 10GBase-ZR: 2xSMF
+(1,39),(2,39),(3,39),(4,39),(5,39),(6,39),        -- 10GBase-LX4: 2xMMF/2xSMF
+(1,37),(2,37),(3,37),(4,37),                      -- 10GBase-LRM: 2xMMF
+(14,1642),(15,1642),(16,1642),(17,1642),          -- 10GBase-T: Cat.6+ TP
+(20,40),                                          -- 10GBase-CX4: coax
+(24,1084),(25,1084),(26,1084),(27,1084),          -- 10GBase direct attach: twinax
+(18,1663),(19,1663),                              -- 40GBase-SR4: 8xMMF
+(5,1664),(6,1664),                                -- 40GBase-LR4: 2xSMF
+(5,1662),(6,1662),                                -- 40GBase-ER4: 2xSMF
+(5,1660),(6,1660),                                -- 40GBase-FR: 2xSMF
+(21,1669),(22,1669),                              -- 100GBase-SR10: 20xMMF
+(18,1672),(19,1672),                              -- 100GBase-SR4: 8xMMF
+(5,1670),(6,1670),                                -- 100GBase-LR4: 2xSMF
+(5,1671),(6,1671)                                 -- 100GBase-ER4: 2xSMF";
+
                $query[] = "INSERT INTO `ObjectParentCompat` VALUES
 (3,13),
 (4,1504),
index ca92b03c5289e9ac8f0d65ce5bce66ec9e2243c9..d60da7cd69ba2693bf17eb9d99d7a4ab97b072be 100644 (file)
@@ -42,6 +42,9 @@ $image['objectlog']['height'] = 200;
 $image['virtual']['path'] = 'pix/virtualresources.png';
 $image['virtual']['width'] = 218;
 $image['virtual']['height'] = 200;
+$image['cables']['path'] = 'pix/patch_cables.png';
+$image['cables']['width'] = 218;
+$image['cables']['height'] = 200;
 $image['download']['path'] = 'pix/download.png';
 $image['download']['width'] = 16;
 $image['download']['height'] = 16;
index b94338aa9f9ea1e073f55fd4814b3d3a6c274656..1db3063f9acc518a00aaa46a9350363b96056d8c 100644 (file)
@@ -9872,4 +9872,372 @@ function renderUserProperties ($user_id)
        echo '</th></tr></table></form>';
 }
 
+function getPatchCableHeapCursorCode ($heap, $zoom_heap_id)
+{
+       global $pageno, $tabno;
+       if ($heap['logc'] == 0)
+               return '&nbsp;';
+       $linkparams = array
+       (
+               'page' => $pageno,
+               'tab' => $tabno,
+       );
+       if ($heap['id'] == $zoom_heap_id)
+       {
+               $imagename = 'Zooming';
+               $imagetext = 'zoom out';
+       }
+       else
+       {
+               $imagename = 'Zoom';
+               $imagetext = 'zoom in';
+               $linkparams['zoom_heap_id'] = $heap['id'];
+       }
+       return '<a href="' . makeHref ($linkparams) . '">'  . getImageHREF ($imagename, $imagetext) . '</a>';
+}
+
+function renderPatchCableHeapSummary()
+{
+       $summary = getPatchCableHeapSummary();
+       if (! count ($summary))
+               return;
+       startPortlet ('Heaps');
+       global $nextorder;
+       echo '<br><table class=cooltable align=center border=0 cellpadding=5 cellspacing=0>';
+       echo '<tr><th>Amount</th><th>End 1</th><th>Cable type</th><th>End 2</th><th>Length</th><th>Description</th><th>&nbsp;</th></tr>';
+       $order = 'odd';
+       $zoom_heap_id = array_key_exists ('zoom_heap_id', $_REQUEST) ? genericAssertion ('zoom_heap_id', 'uint') : NULL;
+       foreach ($summary as $heap)
+       {
+               echo "<tr class=row_${order}>";
+               echo "<td class=tdright>${heap['amount']}</td>";
+               echo "<td class=tdleft>${heap['end1_connector']}</td>";
+               echo "<td class=tdleft>${heap['pctype']}</td>";
+               echo "<td class=tdleft>${heap['end2_connector']}</td>";
+               echo "<td class=tdright>${heap['length']}</td>";
+               echo "<td class=tdleft>${heap['description']}</td>";
+               echo '<td>' . getPatchCableHeapCursorCode ($heap, $zoom_heap_id) . '</td>';
+               echo '</tr>';
+               $order = $nextorder[$order];
+       }
+       echo '</table>';
+       finishPortlet();
+
+       if ($zoom_heap_id === NULL)
+               return;
+       if (! count ($eventlog = getPatchCableHeapLogEntries ($zoom_heap_id)))
+               return;
+       startPortlet ('Event log');
+       echo '<br><table class=cooltable align=center border=0 cellpadding=5 cellspacing=0>';
+       echo '<tr><th>Date</th><th>User</th><th>Message</th></tr>';
+       $order = 'odd';
+       foreach ($eventlog as $event)
+       {
+               echo "<tr class=row_${order}>";
+               echo "<td class=tdleft>${event['date']}</td>";
+               echo '<td class=tdleft>' . niftyString ($event['user'], 255) . '</td>';
+               echo '<td class=tdleft>' . niftyString ($event['message'], 255) . '</td>';
+               echo '</tr>';
+               $order = $nextorder[$order];
+       }
+       echo '</table>';
+       finishPortlet();
+}
+
+function renderPatchCableHeapEditor()
+{
+       function printNewitemTR()
+       {
+               printOpFormIntro ('add');
+               echo '<tr>';
+               echo '<td class=tdleft>' . getImageHREF ('create', 'create new', TRUE, 200) . '</td>';
+               echo "<td>&nbsp;</td>";
+               echo '<td>' . getSelect (getPatchCableConnectorOptions(), array ('name' => 'end1_conn_id', 'tabindex' => 110)) . '</td>';
+               echo '<td>' . getSelect (getPatchCableTypeOptions(), array ('name' => 'pctype_id', 'tabindex' => 120)) . '</td>';
+               echo '<td>' . getSelect (getPatchCableConnectorOptions(), array ('name' => 'end2_conn_id', 'tabindex' => 130)) . '</td>';
+               echo '<td><input type=text size=6 name=length value="1.00" tabindex=140></td>';
+               echo '<td><input type=text size=48 name=description tabindex=150></td>';
+               echo '<td class=tdleft>' . getImageHREF ('create', 'create new', TRUE, 200) . '</td>';
+               echo '</tr></form>';
+       }
+       echo '<table class=widetable border=0 cellpadding=5 cellspacing=0 align=center>';
+       echo '<tr><th>&nbsp;</th><th>Amount</th><th>End 1</th><th>Cable type</th><th>End 2</th><th>Length</th><th>Description</th><th>&nbsp;</th></tr>';
+       if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
+               printNewitemTR();
+       foreach (getPatchCableHeapSummary() as $heap)
+       {
+               printOpFormIntro ('upd', array ('id' => $heap['id']));
+               echo '<tr>';
+               echo '<td>' . getOpLink (array ('op' => 'del', 'id' => $heap['id']), '', 'destroy', 'remove') . '</td>';
+               echo "<td class=tdright>${heap['amount']}</td>";
+               echo '<td>' . getSelect (getPatchCableConnectorOptions(), array ('name' => 'end1_conn_id'), $heap['end1_conn_id']) . '</td>';
+               echo '<td>' . getSelect (getPatchCableTypeOptions(), array ('name' => 'pctype_id'), $heap['pctype_id']) . '</td>';
+               echo '<td>' . getSelect (getPatchCableConnectorOptions(), array ('name' => 'end2_conn_id'), $heap['end2_conn_id']) . '</td>';
+               echo "<td><input type=text size=6 name=length value='${heap['length']}'></td>";
+               echo '<td><input type=text size=48 name=description value="' . niftyString ($heap['description'], 255) . '"></td>';
+               echo '<td>' . getImageHREF ('save', 'Save changes', TRUE) . '</td>';
+               echo '</tr>';
+               echo '</form>';
+       }
+       if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
+               printNewitemTR();
+       echo '</table>';
+}
+
+function renderPatchCableHeapAmount()
+{
+       echo '<table class=widetable border=0 cellpadding=5 cellspacing=0 align=center>';
+       echo '<tr><th colspan=3>Amount</th><th>End 1</th><th>Cable type</th><th>End 2</th><th>Length</th><th>Description</th><th>&nbsp;</th></tr>';
+       foreach (getPatchCableHeapSummary() as $heap)
+       {
+               printOpFormIntro ('set', array ('id' => $heap['id']));
+               echo '<tr>';
+               echo '<td>';
+               if ($heap['amount'] > 0)
+                       echo getOpLink (array ('op' => 'dec', 'id' => $heap['id']), '', 'delete', 'consume');
+               else
+                       echo getImageHREF ('nodelete');
+               echo '</td>';
+               echo "<td><input type=text size=7 name=amount value='${heap['amount']}'></td>";
+               echo '<td>' . getOpLink (array ('op' => 'inc', 'id' => $heap['id']), '', 'add', 'replenish') . '</td>';
+               echo '<td>' . niftyString ($heap['end1_connector'], 32) . '</td>';
+               echo '<td>' . niftyString ($heap['pctype'], 255) . '</td>';
+               echo '<td>' . niftyString ($heap['end2_connector'], 32) . '</td>';
+               echo "<td class=tdright>${heap['length']}</td>";
+               echo '<td>' . niftyString ($heap['description'], 255) . '</td>';
+               echo '<td>' . getImageHREF ('save', 'Save changes', TRUE) . '</td>';
+               echo '</tr></form>';
+       }
+       echo '</table>';
+}
+
+function renderSimpleTableWithOriginViewer ($rows, $column)
+{
+       echo '<table class=widetable border=0 cellpadding=5 cellspacing=0 align=center>';
+       echo "<tr><th>Origin</th><th>Key</th><th>${column['header']}</th></tr>";
+       foreach ($rows as $row)
+       {
+               echo '<tr>';
+               echo '<td>';
+               if ($row['origin'] == 'default')
+                       echo getImageHREF ('computer', 'default');
+               else
+                       echo getImageHREF ('favorite', 'custom');
+               echo '</td>';
+               echo "<td class=tdright>${row[$column['key']]}</td>";
+               echo '<td class=tdleft>' . niftyString ($row[$column['value']], $column['width']) . '</td>';
+               echo '</tr>';
+       }
+       echo '</table>';
+}
+
+function renderSimpleTableWithOriginEditor ($rows, $column)
+{
+       function printNewitemTR ($column)
+       {
+               printOpFormIntro ('add');
+               echo '<tr>';
+               echo '<td>&nbsp;</td>';
+               echo '<td class=tdleft>' . getImageHREF ('create', 'create new', TRUE, 200) . '</td>';
+               echo "<td><input type=text size=${column['width']} name=${column['value']} tabindex=100></td>";
+               echo '<td class=tdleft>' . getImageHREF ('create', 'create new', TRUE, 200) . '</td>';
+               echo '</tr></form>';
+       }
+       echo '<table class=widetable border=0 cellpadding=5 cellspacing=0 align=center>';
+       echo "<tr><th>Origin</th><th>&nbsp;</th><th>${column['header']}</th><th>&nbsp;</th></tr>";
+       if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
+               printNewitemTR ($column);
+       foreach ($rows as $row)
+       {
+               echo '<tr>';
+               if ($row['origin'] == 'default')
+               {
+                       echo '<td>' . getImageHREF ('computer', 'default') . '</td>';
+                       echo '<td>&nbsp;</td>';
+                       echo '<td>' . niftyString ($row[$column['value']], $column['width']) . '</td>';
+                       echo '<td>&nbsp;</td>';
+               }
+               else
+               {
+                       printOpFormIntro ('upd', array ($column['key'] => $row[$column['key']]));
+                       echo '<td>' . getImageHREF ('favorite', 'custom') . '</td>';
+                       echo '<td>' . getOpLink (array ('op' => 'del', $column['key'] => $row[$column['key']]), '', 'destroy', 'remove') . '</td>';
+                       echo "<td><input type=text size=${column['width']} name=${column['value']} value='" . niftyString ($row[$column['value']], $column['width']) . "'></td>";
+                       echo '<td>' . getImageHREF ('save', 'Save changes', TRUE) . '</td>';
+                       echo '</form>';
+               }
+               echo '</tr>';
+       }
+       if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
+               printNewitemTR ($column);
+       echo '</table>';
+}
+
+function renderPatchCableConfiguration()
+{
+       global $nextorder;
+
+       echo '<table class=objview border=0 width="100%"><tr><td class=pcleft>';
+
+       startPortlet ('Connectors');
+       renderSimpleTableWithOriginViewer
+       (
+               getPatchCableConnectorList(),
+               array
+               (
+                       'header' => 'Connector',
+                       'key' => 'id',
+                       'value' => 'connector',
+                       'width' => 32,
+               )
+       );
+       finishPortlet();
+
+       startPortlet ('Connector compatibility');
+       renderTwoColumnCompatTableViewer
+       (
+               getPatchCableConnectorCompat(),
+               array
+               (
+                       'header' => 'Cable type',
+                       'key' => 'pctype_id',
+                       'value' => 'pctype',
+                       'width' => 64,
+               ),
+               array
+               (
+                       'header' => 'Connector',
+                       'key' => 'connector_id',
+                       'value' => 'connector',
+                       'width' => 32,
+               )
+       );
+       finishPortlet();
+
+       echo '</td><td class=pcright>';
+
+       startPortlet ('Cable types');
+       renderSimpleTableWithOriginViewer
+       (
+               getPatchCableTypeList(),
+               array
+               (
+                       'header' => 'Cable type',
+                       'key' => 'id',
+                       'value' => 'pctype',
+                       'width' => 64,
+               )
+       );
+       finishPortlet();
+
+       startPortlet ('Cable types and port outer interfaces');
+       renderTwoColumnCompatTableViewer
+       (
+               getPatchCableOIFCompat(),
+               array
+               (
+                       'header' => 'Cable type',
+                       'key' => 'pctype_id',
+                       'value' => 'pctype',
+                       'width' => 64,
+               ),
+               array
+               (
+                       'header' => 'Outer interface',
+                       'key' => 'oif_id',
+                       'value' => 'oif_name',
+                       'width' => 48,
+               )
+       );
+       finishPortlet();
+
+       echo '</td></tr></table>';
+}
+
+function renderPatchCableConnectorEditor()
+{
+       echo '<br>';
+       renderSimpleTableWithOriginEditor
+       (
+               getPatchCableConnectorList(),
+               array
+               (
+                       'header' => 'Connector',
+                       'key' => 'id',
+                       'value' => 'connector',
+                       'width' => 32,
+               )
+       );
+       echo '<br>';
+}
+
+function renderPatchCableTypeEditor()
+{
+       echo '<br>';
+       renderSimpleTableWithOriginEditor
+       (
+               getPatchCableTypeList(),
+               array
+               (
+                       'header' => 'Cable type',
+                       'key' => 'id',
+                       'value' => 'pctype',
+                       'width' => 64,
+               )
+       );
+       echo '<br>';
+}
+
+function renderPatchCableConnectorCompatEditor()
+{
+       echo '<br>';
+       renderTwoColumnCompatTableEditor
+       (
+               getPatchCableConnectorCompat(),
+               array
+               (
+                       'header' => 'Cable type',
+                       'key' => 'pctype_id',
+                       'value' => 'pctype',
+                       'width' => 64,
+                       'options' => getPatchCableTypeOptions(),
+               ),
+               array
+               (
+                       'header' => 'Connector',
+                       'key' => 'connector_id',
+                       'value' => 'connector',
+                       'width' => 32,
+                       'options' => getPatchCableConnectorOptions()
+               )
+       );
+       echo '<br>';
+}
+
+function renderPatchCableOIFCompatEditor()
+{
+       echo '<br>';
+       renderTwoColumnCompatTableEditor
+       (
+               getPatchCableOIFCompat(),
+               array
+               (
+                       'header' => 'Cable type',
+                       'key' => 'pctype_id',
+                       'value' => 'pctype',
+                       'width' => 64,
+                       'options' => getPatchCableTypeOptions(),
+               ),
+               array
+               (
+                       'header' => 'Outer interface',
+                       'key' => 'oif_id',
+                       'value' => 'oif_name',
+                       'width' => 48,
+                       'options' => getPortOIFOptions()
+               )
+       );
+       echo '<br>';
+}
+
 ?>
index 8a4e9b601a462975d201de6f88c5480ae8eef616..dbf8a629b7d47caf9c48d69ae450a83b0e539f43 100644 (file)
@@ -39,7 +39,7 @@ $indexlayout = array
 (
        array ('rackspace', 'depot', 'ipv4space', 'ipv6space'),
        array ('files', 'reports', 'ipv4slb', '8021q'),
-       array ('config', 'objectlog', 'virtual'),
+       array ('config', 'objectlog', 'virtual', 'cables'),
 );
 
 $page['index']['title'] = 'Main page';
@@ -661,6 +661,29 @@ $ophandler['munin']['servers']['add'] = 'tableHandler';
 $ophandler['munin']['servers']['del'] = 'tableHandler';
 $ophandler['munin']['servers']['upd'] = 'tableHandler';
 
+$page['cableconf']['title'] = 'Patch cables';
+$page['cableconf']['parent'] = 'config';
+$tab['cableconf']['default'] = 'View';
+$tab['cableconf']['connectors'] = 'Edit connectors';
+$tab['cableconf']['cabletypes'] = 'Edit cable types';
+$tab['cableconf']['conncompat'] = 'Connector compatibility';
+$tab['cableconf']['oifcompat'] = 'Outer interface compatibility';
+$tabhandler['cableconf']['default'] = 'renderPatchCableConfiguration';
+$tabhandler['cableconf']['connectors'] = 'renderPatchCableConnectorEditor';
+$tabhandler['cableconf']['cabletypes'] = 'renderPatchCableTypeEditor';
+$tabhandler['cableconf']['conncompat'] = 'renderPatchCableConnectorCompatEditor';
+$tabhandler['cableconf']['oifcompat'] = 'renderPatchCableOIFCompatEditor';
+$ophandler['cableconf']['connectors']['add'] = 'tableHandler';
+$ophandler['cableconf']['connectors']['del'] = 'tableHandler';
+$ophandler['cableconf']['connectors']['upd'] = 'tableHandler';
+$ophandler['cableconf']['cabletypes']['add'] = 'tableHandler';
+$ophandler['cableconf']['cabletypes']['del'] = 'tableHandler';
+$ophandler['cableconf']['cabletypes']['upd'] = 'tableHandler';
+$ophandler['cableconf']['conncompat']['add'] = 'tableHandler';
+$ophandler['cableconf']['conncompat']['del'] = 'tableHandler';
+$ophandler['cableconf']['oifcompat']['add'] = 'tableHandler';
+$ophandler['cableconf']['oifcompat']['del'] = 'tableHandler';
+
 $page['reports']['title'] = 'Reports';
 $page['reports']['parent'] = 'index';
 $tab['reports']['default'] = 'System';
@@ -807,6 +830,22 @@ $page['virtual']['parent'] = 'index';
 $tab['virtual']['default'] = 'Summary';
 $tabhandler['virtual']['default'] = 'renderVirtualResourcesSummary';
 
+$page['cables']['title'] = 'Patch cables';
+$page['cables']['parent'] = 'index';
+$tab['cables']['default'] = 'View';
+$tab['cables']['amount'] = 'Consume/replenish';
+$tab['cables']['heaps'] = 'Configure heaps';
+$trigger['cables']['amount'] = 'triggerPatchCableHeapsConfigured';
+$tabhandler['cables']['default'] = 'renderPatchCableHeapSummary';
+$tabhandler['cables']['amount'] = 'renderPatchCableHeapAmount';
+$tabhandler['cables']['heaps'] = 'renderPatchCableHeapEditor';
+$ophandler['cables']['heaps']['add'] = 'tableHandler';
+$ophandler['cables']['heaps']['del'] = 'tableHandler';
+$ophandler['cables']['heaps']['upd'] = 'tableHandler';
+$ophandler['cables']['amount']['dec'] = 'consumePatchCable';
+$ophandler['cables']['amount']['inc'] = 'replenishPatchCable';
+$ophandler['cables']['amount']['set'] = 'setPatchCableAmount';
+
 $ajaxhandler['get-tag-select'] = 'getTagSelectAJAX';
 $ajaxhandler['get-location-select'] = 'getLocationSelectAJAX';
 $ajaxhandler['verifyCode'] = 'verifyCodeAJAX';
index 40c364df5c2e86601610f35b31156ea96deeeeb7..186593ff2dedad74535fc058ad0ee9b5c6dd0fe3 100644 (file)
@@ -595,6 +595,155 @@ $opspec_list['munin-servers-upd'] = array
                array ('url_argname' => 'id', 'assertion' => 'uint'),
        ),
 );
+$opspec_list['cables-heaps-add'] = array
+(
+       'table' => 'PatchCableHeap',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'end1_conn_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'end2_conn_id', 'assertion' => 'uint'),
+               array ('fix_argname' => 'amount', 'fix_argvalue' => 0),
+               array ('url_argname' => 'length', 'assertion' => 'decimal'),
+               array ('url_argname' => 'description', 'assertion' => 'string0'),
+       ),
+);
+$opspec_list['cables-heaps-del'] = array
+(
+       'table' => 'PatchCableHeap',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['cables-heaps-upd'] = array
+(
+       'table' => 'PatchCableHeap',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'end1_conn_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'end2_conn_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'amount', 'assertion' => 'uint0'),
+               array ('url_argname' => 'length', 'assertion' => 'decimal'),
+               array ('url_argname' => 'description', 'assertion' => 'string0'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['cableconf-connectors-add'] = array
+(
+       'table' => 'PatchCableConnector',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'connector', 'assertion' => 'string'),
+               array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
+       ),
+);
+$opspec_list['cableconf-connectors-del'] = array
+(
+       'table' => 'PatchCableConnector',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint'),
+               array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
+       ),
+);
+$opspec_list['cableconf-connectors-upd'] = array
+(
+       'table' => 'PatchCableConnector',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'connector', 'assertion' => 'string'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint'),
+               array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
+       ),
+);
+$opspec_list['cableconf-cabletypes-add'] = array
+(
+       'table' => 'PatchCableType',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'pctype', 'assertion' => 'string'),
+               array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
+       ),
+);
+$opspec_list['cableconf-cabletypes-del'] = array
+(
+       'table' => 'PatchCableType',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint'),
+               array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
+       ),
+);
+$opspec_list['cableconf-cabletypes-upd'] = array
+(
+       'table' => 'PatchCableType',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'pctype', 'assertion' => 'string'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint'),
+               array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
+       ),
+);
+$opspec_list['cableconf-conncompat-add'] = array
+(
+       'table' => 'PatchCableConnectorCompat',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'connector_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['cableconf-conncompat-del'] = array
+(
+       'table' => 'PatchCableConnectorCompat',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'connector_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['cableconf-oifcompat-add'] = array
+(
+       'table' => 'PatchCableOIFCompat',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'oif_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['cableconf-oifcompat-del'] = array
+(
+       'table' => 'PatchCableOIFCompat',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'oif_id', 'assertion' => 'uint'),
+       ),
+);
 
 $msgcode['addPortForwarding']['OK'] = 48;
 function addPortForwarding ()
@@ -3587,4 +3736,27 @@ function renameObjectPorts()
                showNotice ("Nothing renamed");
 }
 
+function consumePatchCable()
+{
+       if (commitModifyPatchCableAmount (genericAssertion ('id', 'uint'), -1))
+               showSuccess ('consumed OK');
+       else
+               showError ('could not consume');
+}
+
+function replenishPatchCable()
+{
+       if (commitModifyPatchCableAmount (genericAssertion ('id', 'uint'), 1))
+               showSuccess ('replenished OK');
+       else
+               showError ('could not replenish');
+}
+
+$msgcode['setPatchCableAmount']['OK'] = 51;
+function setPatchCableAmount()
+{
+       commitSetPatchCableAmount (genericAssertion ('id', 'uint'), genericAssertion ('amount', 'uint0'));
+       showFuncMessage (__FUNCTION__, 'OK');
+}
+
 ?>
index 69677d1abafb0f5ecaa73842c765861e2ab5eb59..82e90dce2d4a3a1b19920de1c5a2903de0ebd005 100644 (file)
@@ -278,6 +278,19 @@ function handlePopupPortLink()
                if ($remote_port_info['oif_id'] != $type_remote)
                        commitUpdatePortOIF ($remote_port_info['id'], $type_remote);
                linkPorts ($port_info['id'], $remote_port_info['id'], $_REQUEST['cable']);
+               // patch cable?
+               if (array_key_exists ('heap_id', $_REQUEST))
+               {
+                       // Leave the compatibility constraints check up to the foreign keys.
+                       if (0 != $heap_id = genericAssertion ('heap_id', 'uint0'))
+                       {
+                               $heaps = getPatchCableHeapSummary();
+                               if (commitModifyPatchCableAmount ($heap_id, -1))
+                                       showSuccess ('consumed a patch cable from ' . formatPatchCableHeapAsPlainText ($heaps[$heap_id]));
+                               else
+                                       showError ('failed to consume a patch cable');
+                       }
+               }
                showOneLiner 
                (
                        8, 
@@ -439,6 +452,11 @@ function renderPopupPortSelector()
        {
                echo getSelect ($spare_ports, array ('name' => 'remote_port', 'size' => getConfigVar ('MAXSELSIZE')), NULL, FALSE);
                echo "<p>Cable ID: <input type=text id=cable name=cable>";
+               // suggest patch cables where it makes sense
+               $heaps = getPatchCableHeapOptionsForOIF ($port_info['oif_id']);
+               if (count ($heaps))
+                       // Use + instead of array_merge() to avoid renumbering the keys.
+                       echo '<p>Patch cable: ' . getSelect (array (0 => 'none') + $heaps, array ('name' => 'heap_id'));
                echo "<p><input type='submit' value='Link' name='do_link'>";
        }
        finishPortlet();
index f414f4c5016a129158b591381315e880fe8b395f..4df20851b380b0a3a198da273ee2c54614b5e61e 100644 (file)
@@ -334,4 +334,9 @@ function trigger_ucs()
        ) ? 'std' : '';
 }
 
+function triggerPatchCableHeapsConfigured()
+{
+       return count (getPatchCableHeapSummary()) ? 'std' : '';
+}
+
 ?>
index 947cdc20f920192c7477f4430ece8177521bb99b..7b127f1521a2e127d2e0b016af0a2c3c6e531a48 100644 (file)
@@ -1657,6 +1657,158 @@ CREATE TABLE `PortOuterInterface` (
                        $query[] = "INSERT INTO PortOuterInterface (id, oif_name) VALUES (42, '1000Base-EX')";
                        $query[] = "INSERT INTO PortCompat (type1, type2) VALUES (42, 42)";
                        $query[] = "INSERT INTO PortInterfaceCompat (iif_id, oif_id) VALUES (3, 42), (4,42)";
+                       // patch cables
+               $query[] = "
+CREATE TABLE `PatchCableConnector` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `origin` enum('default','custom') NOT NULL DEFAULT 'custom',
+  `connector` char(32) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `connector_per_origin` (`connector`,`origin`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+               $query[] = "
+CREATE TABLE `PatchCableType` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `origin` enum('default','custom') NOT NULL DEFAULT 'custom',
+  `pctype` char(64) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `pctype_per_origin` (`pctype`,`origin`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+               $query[] = "
+CREATE TABLE `PatchCableConnectorCompat` (
+  `pctype_id` int(10) unsigned NOT NULL,
+  `connector_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`pctype_id`,`connector_id`),
+  KEY `connector_id` (`connector_id`),
+  CONSTRAINT `PatchCableConnectorCompat-FK-connector_id` FOREIGN KEY (`connector_id`) REFERENCES `PatchCableConnector` (`id`),
+  CONSTRAINT `PatchCableConnectorCompat-FK-pctype_id` FOREIGN KEY (`pctype_id`) REFERENCES `PatchCableType` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+               $query[] = "
+CREATE TABLE `PatchCableHeap` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `pctype_id` int(10) unsigned NOT NULL,
+  `end1_conn_id` int(10) unsigned NOT NULL,
+  `end2_conn_id` int(10) unsigned NOT NULL,
+  `amount` smallint(5) unsigned NOT NULL DEFAULT '0',
+  `length` decimal(5,2) unsigned NOT NULL DEFAULT '1.00',
+  `description` char(255) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `compat1` (`pctype_id`,`end1_conn_id`),
+  KEY `compat2` (`pctype_id`,`end2_conn_id`),
+  CONSTRAINT `PatchCableHeap-FK-compat1` FOREIGN KEY (`pctype_id`, `end1_conn_id`) REFERENCES `PatchCableConnectorCompat` (`pctype_id`, `connector_id`),
+  CONSTRAINT `PatchCableHeap-FK-compat2` FOREIGN KEY (`pctype_id`, `end2_conn_id`) REFERENCES `PatchCableConnectorCompat` (`pctype_id`, `connector_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+               $query[] = "
+CREATE TABLE `PatchCableHeapLog` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `heap_id` int(10) unsigned NOT NULL,
+  `date` datetime NOT NULL,
+  `user` char(64) NOT NULL,
+  `message` char(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `heap_id-date` (`heap_id`,`date`),
+  CONSTRAINT `PatchCableHeapLog-FK-heap_id` FOREIGN KEY (`heap_id`) REFERENCES `PatchCableHeap` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+               $query[] = "
+CREATE TABLE `PatchCableOIFCompat` (
+  `pctype_id` int(10) unsigned NOT NULL,
+  `oif_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`pctype_id`,`oif_id`),
+  KEY `oif_id` (`oif_id`),
+  CONSTRAINT `PatchCableOIFCompat-FK-oif_id` FOREIGN KEY (`oif_id`) REFERENCES `PortOuterInterface` (`id`),
+  CONSTRAINT `PatchCableOIFCompat-FK-pctype_id` FOREIGN KEY (`pctype_id`) REFERENCES `PatchCableType` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+               $query[] = "INSERT INTO PatchCableConnector (id, origin, connector) VALUES
+(1,'default','FC/PC'),(2,'default','FC/APC'),
+(3,'default','LC/PC'),(4,'default','LC/APC'),
+(5,'default','MPO-12/PC'),(6,'default','MPO-12/APC'),
+(7,'default','MPO-24/PC'),(8,'default','MPO-24/APC'),
+(9,'default','SC/PC'),(10,'default','SC/APC'),
+(11,'default','ST/PC'),(12,'default','ST/APC'),
+(13,'default','T568/8P8C/RJ45'),
+(14,'default','SFP-1000'),
+(15,'default','SFP+'),
+(999,'default','CX4/SFF-8470')";
+               $query[] = "INSERT INTO PatchCableType (id, origin, pctype) VALUES
+(1,'default','duplex OM1'),
+(2,'default','duplex OM2'),
+(3,'default','duplex OM3'),
+(4,'default','duplex OM4'),
+(5,'default','duplex OS1'),
+(6,'default','duplex OS2'),
+(7,'default','simplex OM1'),
+(8,'default','simplex OM2'),
+(9,'default','simplex OM3'),
+(10,'default','simplex OM4'),
+(11,'default','simplex OS1'),
+(12,'default','simplex OS2'),
+(13,'default','Cat.5 TP'),
+(14,'default','Cat.6 TP'),
+(15,'default','Cat.6a TP'),
+(16,'default','Cat.7 TP'),
+(17,'default','Cat.7a TP'),
+(18,'default','12-fiber OM3'),
+(19,'default','12-fiber OM4'),
+(20,'default','10Gb/s CX4 coax'),
+(21,'default','24-fiber OM3'),
+(22,'default','24-fiber OM4'),
+(23,'default','1Gb/s 50cm shielded'),
+(24,'default','10Gb/s 24AWG twinax'),
+(25,'default','10Gb/s 26AWG twinax'),
+(26,'default','10Gb/s 28AWG twinax'),
+(27,'default','10Gb/s 30AWG twinax'),
+(999,'default','Cat.3 TP')";
+               $query[] = "INSERT INTO PatchCableOIFCompat (pctype_id, oif_id) VALUES
+(13,18),(14,18),(15,18),(16,18),(17,18),(999,18), -- 10Base-T: Cat.3+ TP
+(11,1198),(12,1198),(11,1199),(12,1199),          -- 100Base-BX10: 1xSMF
+(5,1197),(6,1197),                                -- 100Base-LX10: 2xSMF
+(5,1200),(6,1200),                                -- 100Base-EX: 2xSMF
+(5,1201),(6,1201),                                -- 100Base-ZX: 2xSMF
+(1,1195),(2,1195),(3,1195),(4,1195),              -- 100Base-FX: 2xMMF
+(1,1196),(2,1196),(3,1196),(4,1196),              -- 100Base-SX: 2xMMF
+(13,19),(14,19),(15,19),(16,19),(17,19),          -- 100Base-TX: Cat.5+ TP
+(11,1206),(12,1206),(11,1207),(12,1207),          -- 1000Base-BX10: 1xSMF
+(5,1204),(6,1204),                                -- 1000Base-LX: 2xSMF
+(5,1205),(6,1205),                                -- 1000Base-LX10: 2xSMF
+(1,1202),(2,1202),(3,1202),(4,1202),              -- 1000Base-SX: 2xMMF
+(1,1203),(2,1203),(3,1203),(4,1203),              -- 1000Base-SX+: 2xMMF
+(13,24),(14,24),(15,24),(16,24),(17,24),          -- 1000Base-T: Cat.5+ TP
+(5,34),(6,34),                                    -- 1000Base-ZX: 2xSMF
+(23,1077),                                        -- 1000Base direct attach: shielded
+(1,30),(2,30),(3,30),(4,30),                      -- 10GBase-SR: 2xMMF
+(5,36),(6,36),                                    -- 10GBase-LR: 2xSMF
+(5,35),(6,35),                                    -- 10GBase-ER: 2xSMF
+(5,38),(6,38),                                    -- 10GBase-ZR: 2xSMF
+(1,39),(2,39),(3,39),(4,39),(5,39),(6,39),        -- 10GBase-LX4: 2xMMF/2xSMF
+(1,37),(2,37),(3,37),(4,37),                      -- 10GBase-LRM: 2xMMF
+(14,1642),(15,1642),(16,1642),(17,1642),          -- 10GBase-T: Cat.6+ TP
+(20,40),                                          -- 10GBase-CX4: coax
+(24,1084),(25,1084),(26,1084),(27,1084),          -- 10GBase direct attach: twinax
+(18,1663),(19,1663),                              -- 40GBase-SR4: 8xMMF
+(5,1664),(6,1664),                                -- 40GBase-LR4: 2xSMF
+(5,1662),(6,1662),                                -- 40GBase-ER4: 2xSMF
+(5,1660),(6,1660),                                -- 40GBase-FR: 2xSMF
+(21,1669),(22,1669),                              -- 100GBase-SR10: 20xMMF
+(18,1672),(19,1672),                              -- 100GBase-SR4: 8xMMF
+(5,1670),(6,1670),                                -- 100GBase-LR4: 2xSMF
+(5,1671),(6,1671)                                 -- 100GBase-ER4: 2xSMF";
+               $query[] = "INSERT INTO PatchCableConnectorCompat (pctype_id, connector_id) VALUES
+(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1), -- FC/PC
+(1,2),(2,2),(3,2),(4,2),(5,2),(6,2),(7,2),(8,2),(9,2),(10,2),(11,2),(12,2), -- FC/APC
+(1,3),(2,3),(3,3),(4,3),(5,3),(6,3),(7,3),(8,3),(9,3),(10,3),(11,3),(12,3), -- LC/PC
+(1,4),(2,4),(3,4),(4,4),(5,4),(6,4),(7,4),(8,4),(9,4),(10,4),(11,4),(12,4), -- LC/APC
+(1,9),(2,9),(3,9),(4,9),(5,9),(6,9),(7,9),(8,9),(9,9),(10,9),(11,9),(12,9), -- SC/PC
+(1,10),(2,10),(3,10),(4,10),(5,10),(6,10),(7,10),(8,10),(9,10),(10,10),(11,10),(12,10), -- SC/APC
+(1,11),(2,11),(3,11),(4,11),(5,11),(6,11),(7,11),(8,11),(9,11),(10,11),(11,11),(12,11), -- ST/PC
+(1,12),(2,12),(3,12),(4,12),(5,12),(6,12),(7,12),(8,12),(9,12),(10,12),(11,12),(12,12), -- ST/APC
+(13,13),(14,13),(15,13),(16,13),(17,13),(999,13), -- T568
+(18,5),(19,5), -- MPO-12/PC
+(18,6),(19,6), -- MPO-12/APC
+(20,999), -- CX4
+(21,7),(22,7), -- MPO-24/PC
+(21,8),(22,8), -- MPO-24/APC
+(23,14), -- SFP-1000
+(24,15),(25,15),(26,15),(27,15) -- SFP+";
                        $query[] = "UPDATE Config SET varvalue = '0.20.8' WHERE varname = 'DB_VERSION'";
                        break;
                case '0.21.0':
diff --git a/wwwroot/pix/patch_cables.png b/wwwroot/pix/patch_cables.png
new file mode 100644 (file)
index 0000000..ba59a11
Binary files /dev/null and b/wwwroot/pix/patch_cables.png differ