View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 550 | RackTables | default | public | 2012-04-12 11:46 | 2015-06-11 03:59 |
| Reporter | Assigned To | infrastation | |||
| Priority | normal | Severity | feature | Reproducibility | N/A |
| Status | assigned | Resolution | open | ||
| Summary | 550: tracking cable types | ||||
| Description | Hi, I've discussed this idea with infrastation a while ago. My colleagues want to track which cable types are used for certain connections. I'm willing to write that code, but first I'd like to have a few opinions on my plan: Changes in Database: - Add a field `cable_type_id` UNSIGNED INTEGER to PortCompat which hold a ref to a chapter from which possible cable types for this kind of connection can be selected. ( This can be NULL if you don't want to use this feature for a certain connection ) - Add a field to `cable_type_key` UNSIGNED INTEGER to Link which points to a dictionary entry. ( This is NULL if the cable is not known. ) Changes in Interface: - Extend the Port compatibility config page according to the database changes. - Extend the Object -> Ports tab to show the cable type for connected ports. - Extend the Link-to popup with a drop-down showing the available cable types. Changes to functions: - fetchPortList ( fetch the cable type ) - linkPorts ( optional additional argument ) - commitUpdatePortLink ( idem ) - handlePopupPortLink Still to be considered: - Track cable changes in PortLog? - Interface if you just want to change the cable type but not the linked port. Kind regards Hannes | ||||
| Tags | No tags attached. | ||||
| Attached Files | track_cable_type.patch (31,600 bytes)
diff -rupN '--exclude=.git' '--exclude=secret.php' racktables2/wwwroot/inc/database.php racktables/wwwroot/inc/database.php
--- racktables2/wwwroot/inc/database.php 2012-04-19 12:29:26.749825940 +0200
+++ racktables/wwwroot/inc/database.php 2012-04-19 12:20:06.809828661 +0200
@@ -728,6 +728,7 @@ SELECT
(SELECT PortInnerInterface.iif_name FROM PortInnerInterface WHERE PortInnerInterface.id = Port.iif_id) AS iif_name,
(SELECT Dictionary.dict_value FROM Dictionary WHERE Dictionary.dict_key = Port.type) AS oif_name,
IF(la.porta, la.cable, lb.cable) AS cableid,
+ IF(la.porta, la.cable_dict_key, lb.cable_dict_key) AS cable_dict_key,
IF(la.porta, pa.id, pb.id) AS remote_id,
IF(la.porta, pa.name, pb.name) AS remote_name,
IF(la.porta, pa.object_id, pb.object_id) AS remote_object_id,
@@ -1452,19 +1453,44 @@ function getAllIPv4Allocations ()
return $ret;
}
-function linkPorts ($porta, $portb, $cable = NULL)
+function linkPorts ($porta, $portb, $cable = NULL, $cable_type = NULL, $update = false)
{
if ($porta == $portb)
throw new InvalidArgException ('porta/portb', $porta, "Ports can't be the same");
global $dbxlink;
- $dbxlink->exec ('LOCK TABLES Link WRITE');
+ # the many locks are necessary. otherwise commitUnlinkPort could not access these tables:
+ $dbxlink->exec ('LOCK TABLES Link WRITE, Port AS pa WRITE, Port AS pb WRITE , Object WRITE, RackObject WRITE, PortLog WRITE');
$result = usePreparedSelectBlade
(
- 'SELECT COUNT(*) FROM Link WHERE porta IN (?,?) OR portb IN (?,?)',
+ 'SELECT * FROM Link WHERE porta IN (?,?) OR portb IN (?,?)',
array ($porta, $portb, $porta, $portb)
);
- if ($result->fetchColumn () != 0)
+ if ( $update )
+ {
+ $a = $result->fetch();
+ if( $a ){
+ if( ($a['porta'] == $porta && $a['portb'] == $portb) || ($a['portb'] == $porta && $a['porta'] == $portb) )
+ {
+ // update!
+ $dbxlink->exec ('UNLOCK TABLES');
+ usePreparedUpdateBlade(
+ 'Link',
+ array (
+ 'cable' => ( mb_strlen ($cable) ? $cable : NULL ) ,
+ 'cable_dict_key' => ( mb_strlen ($cable_type) ? intval($cable_type) : NULL )
+ ),
+ array( 'porta' => $a['porta'], 'portb' => $a['portb'] )
+ );
+
+ return ;
+ }else{
+ commitUnlinkPort($porta);
+ commitUnlinkPort($portb);
+ }
+ }
+ }
+ else if ($result->fetch ())
{
$dbxlink->exec ('UNLOCK TABLES');
return "Port ${porta} or ${portb} is already linked";
@@ -1483,7 +1509,8 @@ function linkPorts ($porta, $portb, $cab
(
'porta' => $porta,
'portb' => $portb,
- 'cable' => mb_strlen ($cable) ? $cable : NULL
+ 'cable' => mb_strlen ($cable) ? $cable : NULL,
+ 'cable_dict_key' => mb_strlen ($cable_type) ? intval($cable_type) : NULL
)
);
$dbxlink->exec ('UNLOCK TABLES');
@@ -2812,9 +2839,10 @@ function commitUpdateUserAccount ($id, $
function getPortOIFCompat ()
{
$query =
- "select type1, type2, d1.dict_value as type1name, d2.dict_value as type2name from " .
+ "select type1, type2, d1.dict_value as type1name, d2.dict_value as type2name, cable_chapter_id , c.name as cable_chapter_name from " .
"PortCompat as pc inner join Dictionary as d1 on pc.type1 = d1.dict_key " .
"inner join Dictionary as d2 on pc.type2 = d2.dict_key " .
+ "left join Chapter as c on pc.cable_chapter_id = c.id ".
'ORDER BY type1name, type2name';
$result = usePreparedSelectBlade ($query);
return $result->fetchAll (PDO::FETCH_ASSOC);
diff -rupN '--exclude=.git' '--exclude=secret.php' racktables2/wwwroot/inc/interface.php racktables/wwwroot/inc/interface.php
--- racktables2/wwwroot/inc/interface.php 2012-04-16 09:51:40.040216558 +0200
+++ racktables/wwwroot/inc/interface.php 2012-04-19 12:20:06.813828661 +0200
@@ -1246,7 +1246,24 @@ function renderPortsForObject ($object_i
'object_id'=>$object_id)).
"'>";
printImageHREF ('cut', 'Unlink this port');
- echo "</a></td>";
+ echo "</a>";
+ echo "<span";
+ $helper_args = array
+ (
+ 'port' => $port['id'],
+ );
+ $popup_args = 'height=700, width=400, location=no, menubar=no, '.
+ 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
+ echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
+ echo "\",\"findlink\",\"${popup_args}\");'";
+ // end of onclick=
+ echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
+ echo "\",\"findlink\",\"${popup_args}\");'";
+ // end of onclick=
+ echo '>';
+ // end of <a>
+ printImageHREF ('plug', 'Link this port');
+ echo "</span></td>";
}
elseif (strlen ($port['reservation_comment']))
{
@@ -3418,7 +3435,7 @@ function renderOIFCompatViewer()
$order = 'odd';
$last_left_oif_id = NULL;
echo '<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>';
- echo '<tr><th>From interface</th><th>To interface</th></tr>';
+ echo '<tr><th>From interface</th><th>To interface</th><th>Cable</th></tr>';
foreach (getPortOIFCompat() as $pair)
{
if ($last_left_oif_id != $pair['type1'])
@@ -3426,14 +3443,20 @@ function renderOIFCompatViewer()
$order = $nextorder[$order];
$last_left_oif_id = $pair['type1'];
}
- echo "<tr class=row_${order}><td>${pair['type1name']}</td><td>${pair['type2name']}</td></tr>";
+ echo "<tr class=row_${order}><td>${pair['type1name']}</td><td>${pair['type2name']}</td><td>${pair['cable_chapter_name']}</td></tr>";
}
echo '</table>';
}
function renderOIFCompatEditor()
{
- function printNewitemTR()
+ $raw_chaplist = getChapterList();
+ $chaplist = array();
+ $chaplist[0]='';
+ foreach( $raw_chaplist as $chapter ){
+ $chaplist[$chapter['id']]= htmlspecialchars( $chapter['name'] );
+ }
+ function printNewitemTR($chaplist_local)
{
printOpFormIntro ('add');
echo '<tr><th class=tdleft>';
@@ -3442,6 +3465,10 @@ function renderOIFCompatEditor()
printSelect (readChapter (CHAP_PORTTYPE), array ('name' => 'type1'));
echo '</th><th class=tdleft>';
printSelect (readChapter (CHAP_PORTTYPE), array ('name' => 'type2'));
+ echo '</th><th class=tdleft>';
+ printSelect( $chaplist_local, array( 'name' => 'cable_chapter_id' ) );
+ echo '</th><th>';
+ printImageHREF ('add', 'add pair', TRUE);
echo '</th></tr></form>';
}
@@ -3466,9 +3493,9 @@ function renderOIFCompatEditor()
startPortlet ('interface by interface');
$last_left_oif_id = NULL;
echo '<br><table class=cooltable align=center border=0 cellpadding=5 cellspacing=0>';
- echo '<tr><th> </th><th>From Interface</th><th>To Interface</th></tr>';
+ echo '<tr><th> </th><th>From Interface</th><th>To Interface</th><th>Cable</th><th></th></tr>';
if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
- printNewitemTR();
+ printNewitemTR($chaplist);
foreach (getPortOIFCompat() as $pair)
{
if ($last_left_oif_id != $pair['type1'])
@@ -3476,13 +3503,19 @@ function renderOIFCompatEditor()
$order = $nextorder[$order];
$last_left_oif_id = $pair['type1'];
}
+ printOpFormIntro('upd',array('type1'=>$pair['type1'], 'type2' => $pair['type2']) );
echo "<tr class=row_${order}><td>";
echo '<a href="' . makeHrefProcess (array ('op' => 'del', 'type1' => $pair['type1'], 'type2' => $pair['type2'])) . '">';
printImageHREF ('delete', 'remove pair');
- echo "</a></td><td class=tdleft>${pair['type1name']}</td><td class=tdleft>${pair['type2name']}</td></tr>";
+ echo "</a></td><td class=tdleft>${pair['type1name']}</td><td class=tdleft>${pair['type2name']}</td>";
+ echo '<td>';
+ printSelect($chaplist, array('name'=>'cable_chapter_id'), $pair['cable_chapter_id']);
+ echo '</td><td>';
+ printImageHREF ('save', 'Save changes', TRUE);
+ echo "</td></tr></form>";
}
if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
- printNewitemTR();
+ printNewitemTR($chaplist);
echo '</table>';
finishPortlet();
}
diff -rupN '--exclude=.git' '--exclude=secret.php' racktables2/wwwroot/inc/navigation.php racktables/wwwroot/inc/navigation.php
--- racktables2/wwwroot/inc/navigation.php 2012-04-16 09:51:40.044216558 +0200
+++ racktables/wwwroot/inc/navigation.php 2012-04-19 12:20:06.813828661 +0200
@@ -435,6 +435,7 @@ $tabhandler['portmap']['default'] = 'ren
$tabhandler['portmap']['edit'] = 'renderOIFCompatEditor';
$ophandler['portmap']['edit']['add'] = 'tableHandler';
$ophandler['portmap']['edit']['del'] = 'tableHandler';
+$ophandler['portmap']['edit']['upd'] = 'tableHandler';
$ophandler['portmap']['edit']['addPack'] = 'addOIFCompatPack';
$ophandler['portmap']['edit']['delPack'] = 'delOIFCompatPack';
diff -rupN '--exclude=.git' '--exclude=secret.php' racktables2/wwwroot/inc/ophandlers.php racktables/wwwroot/inc/ophandlers.php
--- racktables2/wwwroot/inc/ophandlers.php 2012-04-19 12:29:26.757825940 +0200
+++ racktables/wwwroot/inc/ophandlers.php 2012-04-19 12:20:06.813828661 +0200
@@ -262,6 +262,21 @@ $opspec_list['portmap-edit-add'] = array
(
array ('url_argname' => 'type1', 'assertion' => 'uint'),
array ('url_argname' => 'type2', 'assertion' => 'uint'),
+ array ('url_argname' => 'cable_chapter_id', 'assertion' => 'uint0', 'if_empty' => 'NULL' )
+ ),
+);
+$opspec_list['portmap-edit-upd'] = array
+(
+ 'table' => 'PortCompat',
+ 'action' => 'UPDATE',
+ 'set_arglist' => array
+ (
+ array ('url_argname' => 'cable_chapter_id', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
+ ),
+ 'where_arglist' => array
+ (
+ array ('url_argname' => 'type1', 'assertion' => 'uint'),
+ array ('url_argname' => 'type2', 'assertion' => 'uint')
),
);
$opspec_list['portmap-edit-del'] = array
diff -rupN '--exclude=.git' '--exclude=secret.php' racktables2/wwwroot/inc/popup.php racktables/wwwroot/inc/popup.php
--- racktables2/wwwroot/inc/popup.php 2012-04-16 09:51:40.044216558 +0200
+++ racktables/wwwroot/inc/popup.php 2012-04-19 12:39:08.649823113 +0200
@@ -34,7 +34,7 @@ function getProximateRacks ($rack_id, $p
return $ret;
}
-function findSparePorts ($port_info, $filter)
+function getSparePorts($port_info, $filter)
{
$qparams = array ();
$query = "
@@ -45,37 +45,34 @@ SELECT
p.iif_id,
p.type as oif_id,
pii.iif_name,
- d.dict_value as oif_name,
p.object_id,
o.name as object_name
FROM Port p
INNER JOIN Object o ON o.id = p.object_id
INNER JOIN PortInnerInterface pii ON p.iif_id = pii.id
-INNER JOIN Dictionary d ON d.dict_key = p.type
";
// porttype filter (non-strict match)
$query .= "
INNER JOIN (
- SELECT Port.id FROM Port
+ SELECT p2.id FROM Port p2
INNER JOIN
(
- SELECT DISTINCT pic2.iif_id
+ SELECT DISTINCT pic2.iif_id, pic2.oif_id
FROM PortInterfaceCompat pic2
INNER JOIN PortCompat pc ON pc.type2 = pic2.oif_id
";
if ($port_info['iif_id'] != 1)
{
- $query .= " INNER JOIN PortInterfaceCompat pic ON pic.oif_id = pc.type1 WHERE pic.iif_id = ? AND ";
+ $query .= " INNER JOIN PortInterfaceCompat pic ON pic.oif_id = pc.type1 WHERE pic.iif_id = ? ";
$qparams[] = $port_info['iif_id'];
}
else
{
- $query .= " WHERE pc.type1 = ? AND ";
+ $query .= " WHERE pc.type1 = ? ";
$qparams[] = $port_info['oif_id'];
}
$query .= "
- pic2.iif_id <> 1
- ) AS sub1 USING (iif_id)
+ ) AS sub1 ON p2.iif_id = sub1.iif_id AND ( p2.iif_id <> 1 OR p2.type = sub1.oif_id )
UNION
SELECT Port.id
FROM Port
@@ -113,42 +110,104 @@ INNER JOIN (
// ordering
$query .= ' ORDER BY o.name';
- $ret = array();
- $result = usePreparedSelectBlade ($query, $qparams);
-
- $rows_by_pn = array();
- $prev_object_id = NULL;
+ return usePreparedSelectBlade ($query, $qparams);
+}
+
+function getLinkPortJavascript($port_info, $ports)
+{
+ $required_oif = array();
+ $required_iif = array();
+ $required_chapter = array();
+ if( count($ports) == 0 ){
+ return '';
+ }
+ $jsports = array();
+ $compat = array();
+ $buffer = array('$(function($){');
+ $buffer[]='var PORT = { id:'.$port_info['id'].', name:"'.addslashes($port_info['name']).'",';
+ $buffer[]=' object_name:"'.addslashes($port_info['object_name']).'",';
+ $buffer[]=' oif_id:'.($port_info['oif_id'] ? $port_info['oif_id'] : 'null').', ';
+ $buffer[]=' iif_id:'.$port_info['iif_id'].', ';
+ $buffer[]=' cable:"'.addslashes($port_info['cableid']).'", ';
+ $buffer[]=' cable_dict_key:'.($port_info['cable_dict_key'] ? $port_info['cable_dict_key'] : 'null' ).', ';
+ $buffer[]=' remote_id:'.($port_info['remote_id'] ? $port_info['remote_id'] : 'null').'};';
+ $buffer[]='var PORTS = [';
- // fetch port rows from the DB
- while (TRUE)
+ $required_iif[$port_info['iif_id']]=true;
+ if( $port_info['oif_id'] ) $required_oif[$port_info['oif_id']]=true;
+ foreach( $ports as $port ){
+ $required_iif[ $port['iif_id'] ]=true;
+ if( $port['oif_id'] ) $required_oif[$port['oif_id']]=true;
+ $buffer[]=' { id:'.$port['id'].', name:"'.addslashes($port['name']).'", object_name:"'.addslashes($port['object_name']).'", oif_id:'.($port['oif_id'] ? $port['oif_id'] : 'null').', iif_id:'.$port['iif_id'].', reservation:"'.addslashes($port['reservation_comment']).'"},';
+ }
+ $buffer[]='];';
+
+ $incom = usePreparedSelectBlade('SELECT * FROM PortInterfaceCompat WHERE iif_id IN ('.questionMarks(count($required_iif)).') ORDER BY iif_id ', array_keys($required_iif));
+ $buffer[]='var INNER_OUTER_COMPATIBILITY = {';
+ $last_iif_id = null;
+ foreach( $incom as $in )
{
- $row = $result->fetch (PDO::FETCH_ASSOC);
- if (isset ($prev_object_id) and (! $row or $row['object_id'] != $prev_object_id))
+ if( $in['iif_id'] != $last_iif_id )
{
- // handle sorted object's portlist
- foreach (sortPortList ($rows_by_pn) as $ports_subarray)
- foreach ($ports_subarray as $port_row)
- {
- $port_description = $port_row['object_name'] . ' -- ' . $port_row['name'];
- if (count ($ports_subarray) > 1)
- {
- $if_type = $port_row['iif_id'] == 1 ? $port_row['oif_name'] : $port_row['iif_name'];
- $port_description .= " ($if_type)";
- }
- if (! empty ($port_row['reservation_comment']))
- $port_description .= ' -- ' . $port_row['reservation_comment'];
- $ret[$port_row['id']] = $port_description;
- }
- $rows_by_pn = array();
+ if( $last_iif_id != null )
+ {
+ $buffer[]=' ],';
+ }
+ $buffer[]=' '.$in['iif_id'].': [';
+ $last_iif_id = $in['iif_id'];
}
- $prev_object_id = $row['object_id'];
- if ($row)
- $rows_by_pn[$row['name']][] = $row;
- else
- break;
+ $required_oif[$in['oif_id']]=true;
+ $buffer[]=' '.$in['oif_id'].',';
}
+ if( $last_iif_id != null )
+ {
+ $buffer[]=' ]';
+ }
+ $buffer[]='};';
- return $ret;
+ $query ='SELECT * FROM PortCompat pc'.
+ ' WHERE type1 IN ('.questionMarks(count($required_oif)).') AND type2 IN ('.questionMarks(count($required_oif)).');';
+ $types = usePreparedSelectBlade($query, array_merge( array_keys($required_oif), array_keys($required_oif) ) );
+ foreach( $types as $type ){
+ @$compat[ $type['type1'] ][ $type['type2'] ] = array( 'cable_chapter_id'=> ($type['cable_chapter_id'] ? intval($type['cable_chapter_id']) : 'null') );
+ if( $type['cable_chapter_id'] ) $required_chapter[intval($type['cable_chapter_id'])] = true;
+ }
+ $buffer[]='var OUTER_COMPATIBILITY = {';
+ foreach( $compat as $a => $sub ){
+ $buffer[]=' '.$a.': { ';
+ foreach( $sub as $b => $info ){
+ $buffer[]=' '.$b.': {cable_chapter_id:'.$info['cable_chapter_id'].'},';
+ }
+ $buffer[]=' },';
+ }
+ $buffer[]='};';
+ if( $required_chapter ){
+ $buffer[]='var CABLES = {';
+ $last_chapter_id = -1;
+ foreach( array_keys($required_chapter) as $chapter_id ){
+ $chapter = cookOptgroups( readChapter( $chapter_id, 'o' ) );
+ $buffer[]= $chapter_id.': [';
+ foreach( $chapter as $group => $entries ){
+ $buffer[]= ' {name: "'.addslashes($group).'", values:[';
+ foreach( $entries as $key => $value ){
+ $buffer[]= ' {key: '.$key.', value: "'.addslashes($value).'"},';
+ }
+ $buffer[]=' ]},';
+ }
+ $buffer[]='],';
+ }
+ $buffer[]='};';
+ }else{
+ $buffer[]='var CABLES = {};';
+ }
+ $oifs = usePreparedSelectBlade('SELECT dict_key,dict_value FROM Dictionary WHERE chapter_id = 2 AND dict_key IN ('.questionMarks(count($required_oif)).');', array_keys($required_oif));
+ $buffer[]='var OIF = {};';
+ foreach( $oifs as $oif ){
+ $buffer[]='OIF['.$oif['dict_key'].']= "'.addslashes($oif['dict_value']).'";';
+ }
+ $buffer[]=' initializeLinkportForm( PORT, PORTS, INNER_OUTER_COMPATIBILITY, OUTER_COMPATIBILITY, CABLES, OIF )';
+ $buffer[]='});';
+ return join("\n",$buffer);
}
// Return a list of all objects which are possible parents
@@ -221,131 +280,66 @@ function renderPopupObjectSelector()
function handlePopupPortLink()
{
+ global $dbxlink;
assertUIntArg ('port');
assertUIntArg ('remote_port');
assertStringArg ('cable', TRUE);
$port_info = getPortInfo ($_REQUEST['port']);
$remote_port_info = getPortInfo ($_REQUEST['remote_port']);
- $POIFC = getPortOIFCompat();
- if (isset ($_REQUEST['port_type']) and isset ($_REQUEST['remote_port_type']))
- {
- $type_local = $_REQUEST['port_type'];
- $type_remote = $_REQUEST['remote_port_type'];
- }
- else
- {
- $type_local = $port_info['oif_id'];
- $type_remote = $remote_port_info['oif_id'];
- }
- $matches = FALSE;
- $js_table = '';
- foreach ($POIFC as $pair)
- if ($pair['type1'] == $type_local && $pair['type2'] == $type_remote)
- {
- $matches = TRUE;
- break;
+ $dbxlink->beginTransaction();
+ try{
+
+ if( $port_info['iif_id'] != 1 ){
+ // updateable
+ assertUIntArg ('local_oif');
+ if( $_POST['local_oif'] != $port_info['oif_id'] ){
+ commitUpdatePortOIF( $port_info['id'], $_POST['local_oif']);
+ $port_info['oif_id'] = intval($_POST['local_oif']);
+ }
}
- else
- $js_table .= "POIFC['${pair['type1']}-${pair['type2']}'] = 1;\n";
-
- if ($matches)
- {
- if ($port_info['oif_id'] != $type_local)
- commitUpdatePortOIF ($port_info['id'], $type_local);
- 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']);
- showOneLiner
- (
- 8,
- array
+ if( $remote_port_info['iif_id'] != 1 ){
+ // updateable
+ assertUIntArg ('remote_oif');
+ if( $_POST['remote_oif'] != $remote_port_info['oif_id'] ){
+ commitUpdatePortOIF( $remote_port_info['id'], $_POST['remote_oif']);
+ $remote_port_info['oif_id'] = intval($_POST['remote_oif']);
+ }
+ }
+ // now check compat
+ $compat = usePreparedSelectBlade('SELECT * FROM PortCompat WHERE ( type1 = ? AND type2 = ? ) OR ( type2 = ? AND type1= ? ) ',
+ array( $port_info['oif_id'],$remote_port_info['oif_id'],$port_info['oif_id'],$remote_port_info['oif_id']) )->fetchAll();
+ if( !$compat ){
+ throw new InvalidRequestArgException('oif_id', '', 'Ports are not compatible');
+ }else{
+ // :)
+ $cable_type = null;
+ if( $compat[0]['cable_chapter_id'] && $_POST['cable_type'] ){
+ assertUIntArg('cable_type',true);
+ $cable_type = $_POST['cable_type'];
+ }
+ linkPorts( $port_info['id'], $remote_port_info['id'], $_POST['cable'], $cable_type, true );
+ $dbxlink->commit();
+ showOneLiner
(
- formatPortLink ($port_info['id'], $port_info['name'], NULL, NULL),
- formatPort ($remote_port_info),
- )
- );
- addJS (<<<END
-window.opener.location.reload(true);
-window.close();
+ 8,
+ array
+ (
+ formatPortLink ($port_info['id'], $port_info['name'], NULL, NULL),
+ formatPort ($remote_port_info),
+ )
+ );
+ addJS (<<<END
+ window.opener.location.reload(true);
+ window.close();
END
- , TRUE);
- }
- else
- {
- // JS code to display port compatibility hint
- addJS (<<<END
-POIFC = {};
-$js_table
-$(document).ready(function () {
- $('select.porttype').change(onPortTypeChange);
- onPortTypeChange();
-});
-function onPortTypeChange() {
- var key = $('*[name=port_type]')[0].value + '-' + $('*[name=remote_port_type]')[0].value;
- if (POIFC[key] == 1)
- {
- $('#hint-not-compat').hide();
- $('#hint-compat').show();
- }
- else
- {
- $('#hint-compat').hide();
- $('#hint-not-compat').show();
- }
-}
-END
- , TRUE);
- addCSS (<<<END
-.compat-hint {
- display: none;
- font-size: 125%;
-}
-.compat-hint#hint-compat {
- color: green;
-}
-.compat-hint#hint-not-compat {
- color: #804040;
-}
-END
- , TRUE);
- // render port type editor form
- echo '<form method=GET>';
- echo '<input type=hidden name="module" value="popup">';
- echo '<input type=hidden name="helper" value="portlist">';
- echo '<input type=hidden name="port" value="' . $port_info['id'] . '">';
- echo '<input type=hidden name="remote_port" value="' . $remote_port_info['id'] . '">';
- echo '<input type=hidden name="cable" value="' . htmlspecialchars ($_REQUEST['cable'], ENT_QUOTES) . '">';
- echo '<p>The ports you have selected are not compatible. Please select a compatible transceiver pair.';
- echo '<p>';
- echo formatPort ($port_info) . ' ';
- if ($port_info['iif_id'] == 1)
- {
- echo formatPortIIFOIF ($port_info);
- echo '<input type=hidden name="port_type" value="' . $port_info['oif_id'] . '">';
- }
- else
- {
- echo '<label>' . $port_info['iif_name'] . ' ';
- printSelect (getExistingPortTypeOptions ($port_info['id']), array ('class' => 'porttype', 'name' => 'port_type'), $type_local);
- echo '</label>';
+ , true);
+ return;
}
- echo ' — ';
- if ($remote_port_info['iif_id'] == 1)
- {
- echo formatPortIIFOIF ($remote_port_info);
- echo '<input type=hidden name="remote_port_type" value="' . $remote_port_info['oif_id'] . '">';
- }
- else
- {
- echo '<label>' . $remote_port_info['iif_name'] . ' ';
- printSelect (getExistingPortTypeOptions ($remote_port_info['id']), array ('class' => 'porttype', 'name' => 'remote_port_type'), $type_remote);
- echo '</label>';
- }
- echo ' ' . formatPort ($remote_port_info);
- echo '<p class="compat-hint" id="hint-not-compat">✕ Not compatible port types</p>';
- echo '<p class="compat-hint" id="hint-compat">✔ Compatible port types</p>';
- echo '<p><input type=submit name="do_link" value="Link">';
+ }catch( Exception $e ){
+ $dbxlink->rollBack();
+ throw $e;
}
+ return renderPopupPortSelector();
}
function renderPopupPortSelector()
@@ -353,6 +347,7 @@ function renderPopupPortSelector()
assertUIntArg ('port');
$port_id = $_REQUEST['port'];
$port_info = getPortInfo ($port_id);
+
$in_rack = isset ($_REQUEST['in_rack']);
// fill port filter structure
@@ -379,11 +374,27 @@ function renderPopupPortSelector()
! empty ($filter['objects']) ||
! empty ($filter['ports'])
)
- $spare_ports = findSparePorts ($port_info, $filter);
-
+ $ports_with_current = $ports = getSparePorts($port_info, $filter)->fetchAll();
+ if( $port_info['remote_id'] ){
+ $current = $ports_with_current[]= getPortInfo($port_info['remote_id']);
+ }
+ addJS('js/link_port_form.js');
+ addJS(getLinkPortJavascript($port_info, $ports_with_current),true);
+ addCSS (<<<'END'
+.reserved {
+ text-decoration: line-through;
+}
+.compatible {
+ background: #afa;
+}
+.incompatible {
+ background: #faa;
+}
+END
+ , TRUE);
// display search form
echo 'Link ' . formatPort ($port_info) . ' to...';
- echo '<form method=GET>';
+ echo '<form method="POST">';
startPortlet ('Port list filter');
echo '<input type=hidden name="module" value="popup">';
echo '<input type=hidden name="helper" value="portlist">';
@@ -391,23 +402,59 @@ function renderPopupPortSelector()
echo '<table align="center" valign="bottom"><tr>';
echo '<td class="tdleft"><label>Object name:<br><input type=text size=8 name="filter-obj" value="' . htmlspecialchars ($filter['objects'], ENT_QUOTES) . '"></label></td>';
echo '<td class="tdleft"><label>Port name:<br><input type=text size=6 name="filter-port" value="' . htmlspecialchars ($filter['ports'], ENT_QUOTES) . '"></label></td>';
+ echo '</tr><tr>';
echo '<td class="tdleft" valign="bottom"><label><input type=checkbox name="in_rack"' . ($in_rack ? ' checked' : '') . '>Nearest racks</label></td>';
echo '<td valign="bottom"><input type=submit value="show ports"></td>';
echo '</tr></table>';
finishPortlet();
// display results
- startPortlet ('Compatible spare ports');
- if (empty ($spare_ports))
- echo '(nothing found)';
- else
- {
- echo getSelect ($spare_ports, array ('name' => 'remote_port', 'size' => getConfigVar ('MAXSELSIZE')), NULL, FALSE);
- echo "<p>Cable ID: <input type=text id=cable name=cable>";
- echo "<p><input type='submit' value='Link' name='do_link'>";
+ startPortlet ('Link port');
+ if( $ports_with_current ){
+ echo '<div style="float: left;width:40%">';
+ echo '<select name="remote_port" id="remote_port" size="',getConfigVar ('MAXSELSIZE'),'" style="width:100%">';
+ if( $current ){
+ echo '<optgroup label="current">';
+ echo '<optgroup label=" ', htmlspecialchars($current['object_name']), '">';
+ echo '<option value="',$current['id'],'" selected="selected">', htmlspecialchars($current['name'] ),'</option>';
+ echo '</optgroup>';
+ }
+ echo '<optgroup label="search result">';
+ if( !$ports ){
+ echo '<option disabled="disabled" value="">nothing found</option>';
+ }else{
+ $ports_by_object = array();
+ foreach( $ports as $port ){
+ if( !isset($ports_by_object[$port['object_name']]) ) $ports_by_object[$port['object_name']] = array();
+ $ports_by_object[$port['object_name']][] = $port;
+ }
+ ksort( $ports_by_object );
+ foreach( $ports_by_object as $name => $object_ports ){
+ echo '<optgroup label=" ', htmlspecialchars($name), '">';
+ foreach( sortPortList($object_ports, true) as $port ){
+ echo '<option value="', $port['id'],'"',($port['reservation_comment'] ? ' class="reserved"':''),'>', htmlspecialchars($port['name']), '</option>';
+ }
+ echo '</optgroup>';
+ }
+ }
+ echo '</optgroup>';
+ echo '</select>';
+ echo '</div>';
+ echo '<div style="margin-left: 41%">';
+ echo '<p style="display:none">This port is reserved: <span id="reservation"></span></p>';
+ echo '<p style="display:none"><label for="cable_type">Local Transceiver</label></br><select name="local_oif" id="local_oif" style="width:100%"></select></p>';
+ echo '<p style="display:none"><label for="remote_oif">Remote Transceiver</label></br><select name="remote_oif" id="remote_oif" style="width:100%"></select></p>';
+ echo '<p style="display:none"><label for="cable_type">Cable type</label></br><select name="cable_type" id="cable_type" style="width:100%"></select></p>';
+ echo '<p><label for="cable">Cable ID: </label><br /><input type="text" id="cable" name="cable" style="width:100%" value="',htmlspecialchars($port_info['cableid']) ,'"/></p>';
+ echo '<p><input type="submit" value="Link" name="do_link" id="submit"></p>';
+ echo '<br style="clear:both" /></div>';
+ }else{
+ echo 'nothing found';
}
+
finishPortlet();
echo '</form>';
+ echo '<br style="clear:both" />';
}
function renderPopupIPv4Selector()
diff -rupN '--exclude=.git' '--exclude=secret.php' racktables2/wwwroot/js/link_port_form.js racktables/wwwroot/js/link_port_form.js
--- racktables2/wwwroot/js/link_port_form.js 1970-01-01 01:00:00.000000000 +0100
+++ racktables/wwwroot/js/link_port_form.js 2012-04-19 12:20:06.813828661 +0200
@@ -0,0 +1,147 @@
+function initializeLinkportForm( PORT, PORTS, INNER_OUTER_COMPATIBILITY, OUTER_COMPATIBILITY, CABLES, OIF ){
+ var $remote_port = $('#remote_port'),$remote_oif = $('#remote_oif'),$local_oif = $('#local_oif'),$cable_type = $('#cable_type'), $submit = $('#submit'), $reservation = $('#reservation');
+ var compatClass = function(a,b){
+ if( !a || !b ){
+ return '';
+ }else if( !OUTER_COMPATIBILITY[a] || !OUTER_COMPATIBILITY[a][b] ){
+ return 'incompatible';
+ }else{
+ return 'compatible';
+ }
+ }
+ var updateSelects = function(){
+ var rp = $remote_port.val(), ro = $remote_oif.val(), lo = $local_oif.val(), ct = $cable_type.val();
+ if( ro ) ro = parseInt(ro);
+ if( !lo ){
+ lo = PORT.oif_id;
+ }else{
+ lo = parseInt(lo);
+ }
+ if( !rp ){
+ rp = PORT.remote_id;
+ }
+ if( !ct ){
+ ct = PORT.cable_dict_key;
+ }
+ //remote_oif
+ $remote_oif.empty();
+ var remote_port;
+ if( rp ){
+ remote_port = $.grep(PORTS,function(p){ return p.id == rp })[0];
+ if( !ro || remote_port.iif_id == 1 || INNER_OUTER_COMPATIBILITY[ remote_port.iif_id ].indexOf(ro) == -1 ){
+ ro = remote_port.oif_id;
+ }
+ if( remote_port.reservation == "" ){
+ $reservation.closest('p').hide();
+ }else{
+ $reservation.text( remote_port.reservation );
+ $reservation.closest('p').show();
+ }
+ if( remote_port.iif_id != 1 ){
+ $remote_oif.closest('p').show();
+ $remote_oif.attr('disabled',false);
+ }else{
+ $remote_oif.closest('p').hide();
+ $remote_oif.attr('disabled',true);
+ }
+ var rps = INNER_OUTER_COMPATIBILITY[ remote_port.iif_id ];
+ rps.sort(function(a,b){
+ return OIF[a].localeCompare(OIF[b]);
+ }).forEach( function(oif){
+ $('<option>').val(oif).text( OIF[oif] ).addClass( compatClass( oif, lo ) ).appendTo($remote_oif);
+ });
+ $remote_oif.val(ro);
+ }else{
+ $remote_oif.closest('p').hide();
+ $remote_oif.attr('disabled',true);
+ }
+ //local_oif
+ $local_oif.empty();
+ if( PORT.iif_id != 1 ){
+ $local_oif.closest('p').show();
+ $local_oif.attr('disabled',false);
+ }else{
+ $local_oif.closest('p').hide();
+ $local_oif.attr('disabled',true);
+ }
+ var lps = INNER_OUTER_COMPATIBILITY[ PORT.iif_id ];
+ lps.sort(function(a,b){
+ return OIF[a].localeCompare(OIF[b]);
+ }).forEach( function(oif){
+ $('<option>').val(oif).text( OIF[oif] ).addClass( compatClass( oif, ro ) ).appendTo($local_oif);
+ });
+ $local_oif.val(lo);
+ if( rp && lo && ro ){
+ // cables and compat!
+ var comb = OUTER_COMPATIBILITY[ ro ] ? OUTER_COMPATIBILITY[ ro ][ lo ] : null;
+ if( !comb ){
+ $submit.attr('disabled',true);
+ $submit.val('Incompatible transceiver');
+ $cable_type.closest('p').hide();
+ }else{
+ if( comb.cable_chapter_id ){
+ $cable_type.empty();
+ var cables = CABLES[comb.cable_chapter_id];
+ if( cables ){
+ var other;
+ $.each(cables,function(i,group){
+ if( group.name == 'other' ){
+ other = group;
+ return ;
+ }
+ var g = $('<optgroup>').attr('label',group.name).appendTo($cable_type);
+ $.each(group.values, function(j, opt){
+ $('<option>').val(opt.key).text(opt.value).appendTo(g);
+ });
+ });
+ if( other ){
+ $.each(other.values, function(j, opt){
+ $('<option>').val(opt.key).text(opt.value).appendTo($cable_type);
+ });
+ }
+ }
+ $('<option>').val('').text('').appendTo($cable_type);
+ $cable_type.val(ct);
+ $cable_type.closest('p').show();
+ }else{
+ // compatible but no cables
+ $cable_type.closest('p').hide();
+ }
+ $submit.attr('disabled',false);
+ $submit.val('Link');
+ }
+ }else{
+ if( !rp ){
+ $submit.attr('disabled',true);
+ $submit.val('Select a port');
+ }
+ $cable_type.closest('p').hide();
+ }
+ }
+ updateSelects();
+ $remote_port.change(updateSelects);
+ var changeTransceiver = function( $a, $b ){
+ var av = $a.val();
+ var bv = $b.val();
+ if( !OUTER_COMPATIBILITY[av] ){
+ return ;
+ }
+ if( OUTER_COMPATIBILITY[av][bv] ){
+ return;
+ }
+ $b.children('option').each(function(i,o ){
+ if( OUTER_COMPATIBILITY[ av ][ $(o).val() ] ){
+ $b.val( $(o).val() );
+ return false;
+ }
+ });
+ }
+ $local_oif.change(function(){
+ changeTransceiver($local_oif,$remote_oif);
+ updateSelects();
+ });
+ $remote_oif.change(function(){
+ changeTransceiver($remote_oif,$local_oif);
+ updateSelects();
+ });
+}
track_cable_type_0.19.13.diff (31,959 bytes)
diff --git a/wwwroot/inc/database.php b/wwwroot/inc/database.php
index d9f8e2c..1b9dd82 100644
--- a/wwwroot/inc/database.php
+++ b/wwwroot/inc/database.php
@@ -580,9 +580,10 @@ function getObjectPortsAndLinks ($object_id)
{
$portid = $ret[$tmpkey]['id'];
$remote_id = NULL;
- $query = "select porta, portb, cable from Link where porta = ? or portb = ?";
+ $query = "select porta, portb, cable, cable_dict_key from Link where porta = ? or portb = ?";
$result = usePreparedSelectBlade ($query, array ($portid, $portid));
$cable = "CableID n/a";
+ $cable_dict_key = null;
if ($row = $result->fetch (PDO::FETCH_ASSOC))
{
if ($portid != $row['porta'])
@@ -590,6 +591,7 @@ function getObjectPortsAndLinks ($object_id)
elseif ($portid != $row['portb'])
$remote_id = $row['portb'];
$cable = $row['cable'];
+ $cable_dict_key = $row['cable_dict_key'];
}
unset ($result);
if ($remote_id) // there's a remote end here
@@ -601,6 +603,7 @@ function getObjectPortsAndLinks ($object_id)
$ret[$tmpkey]['remote_name'] = $row['name'];
$ret[$tmpkey]['remote_object_id'] = $row['object_id'];
$ret[$tmpkey]['cableid'] = $cable;
+ $ret[$tmpkey]['cable_dict_key'] = $cable_dict_key;
}
$ret[$tmpkey]['remote_id'] = $remote_id;
unset ($result);
@@ -1232,19 +1235,44 @@ function getAllIPv4Allocations ()
return $ret;
}
-function linkPorts ($porta, $portb, $cable = NULL)
+function linkPorts ($porta, $portb, $cable = NULL, $cable_type = NULL, $update = false)
{
if ($porta == $portb)
throw new InvalidArgException ('porta/portb', $porta, "Ports can't be the same");
global $dbxlink;
- $dbxlink->exec ('LOCK TABLES Link WRITE');
+ # the many locks are necessary. otherwise commitUnlinkPort could not access these tables:
+ $dbxlink->exec ('LOCK TABLES Link WRITE, Port AS pa WRITE, Port AS pb WRITE , RackObject WRITE');
$result = usePreparedSelectBlade
(
- 'SELECT COUNT(*) FROM Link WHERE porta IN (?,?) OR portb IN (?,?)',
+ 'SELECT * FROM Link WHERE porta IN (?,?) OR portb IN (?,?)',
array ($porta, $portb, $porta, $portb)
);
- if ($result->fetchColumn () != 0)
+ if ( $update )
+ {
+ $a = $result->fetch();
+ if( $a ){
+ if( ($a['porta'] == $porta && $a['portb'] == $portb) || ($a['portb'] == $porta && $a['porta'] == $portb) )
+ {
+ // update!
+ $dbxlink->exec ('UNLOCK TABLES');
+ usePreparedUpdateBlade(
+ 'Link',
+ array (
+ 'cable' => ( mb_strlen ($cable) ? $cable : NULL ) ,
+ 'cable_dict_key' => ( mb_strlen ($cable_type) ? intval($cable_type) : NULL )
+ ),
+ array( 'porta' => $a['porta'], 'portb' => $a['portb'] )
+ );
+
+ return ;
+ }else{
+ commitUnlinkPort($porta);
+ commitUnlinkPort($portb);
+ }
+ }
+ }
+ else if ($result->fetch ())
{
$dbxlink->exec ('UNLOCK TABLES');
return "Port ${porta} or ${portb} is already linked";
@@ -1263,7 +1291,8 @@ function linkPorts ($porta, $portb, $cable = NULL)
(
'porta' => $porta,
'portb' => $portb,
- 'cable' => mb_strlen ($cable) ? $cable : NULL
+ 'cable' => mb_strlen ($cable) ? $cable : NULL,
+ 'cable_dict_key' => mb_strlen ($cable_type) ? intval($cable_type) : NULL
)
);
$dbxlink->exec ('UNLOCK TABLES');
@@ -2311,9 +2340,10 @@ function commitUpdateUserAccount ($id, $new_username, $new_realname, $new_passwo
function getPortOIFCompat ()
{
$query =
- "select type1, type2, d1.dict_value as type1name, d2.dict_value as type2name from " .
+ "select type1, type2, d1.dict_value as type1name, d2.dict_value as type2name, cable_chapter_id , c.name as cable_chapter_name from " .
"PortCompat as pc inner join Dictionary as d1 on pc.type1 = d1.dict_key " .
"inner join Dictionary as d2 on pc.type2 = d2.dict_key " .
+ "left join Chapter as c on pc.cable_chapter_id = c.id ".
'ORDER BY type1name, type2name';
$result = usePreparedSelectBlade ($query);
return $result->fetchAll (PDO::FETCH_ASSOC);
diff --git a/wwwroot/inc/interface.php b/wwwroot/inc/interface.php
index 3e54e38..85fb28d 100644
--- a/wwwroot/inc/interface.php
+++ b/wwwroot/inc/interface.php
@@ -1164,7 +1164,24 @@ function renderPortsForObject ($object_id)
'object_id'=>$object_id)).
"'>";
printImageHREF ('cut', 'Unlink this port');
- echo "</a></td>";
+ echo "</a>";
+ echo "<span";
+ $helper_args = array
+ (
+ 'port' => $port['id'],
+ );
+ $popup_args = 'height=700, width=400, location=no, menubar=no, '.
+ 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
+ echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
+ echo "\",\"findlink\",\"${popup_args}\");'";
+ // end of onclick=
+ echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
+ echo "\",\"findlink\",\"${popup_args}\");'";
+ // end of onclick=
+ echo '>';
+ // end of <a>
+ printImageHREF ('plug', 'Link this port');
+ echo "</span></td>";
}
elseif (strlen ($port['reservation_comment']))
{
@@ -3928,7 +3945,7 @@ function renderPortOIFCompatViewer()
$order = 'odd';
$last_left_oif_id = NULL;
echo '<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>';
- echo '<tr><th>From interface</th><th>To interface</th></tr>';
+ echo '<tr><th>From interface</th><th>To interface</th><th>Cable</th></tr>';
foreach (getPortOIFCompat() as $pair)
{
if ($last_left_oif_id != $pair['type1'])
@@ -3936,14 +3953,20 @@ function renderPortOIFCompatViewer()
$order = $nextorder[$order];
$last_left_oif_id = $pair['type1'];
}
- echo "<tr class=row_${order}><td>${pair['type1name']}</td><td>${pair['type2name']}</td></tr>";
+ echo "<tr class=row_${order}><td>${pair['type1name']}</td><td>${pair['type2name']}</td><td>${pair['cable_chapter_name']}</td></tr>";
}
echo '</table>';
}
function renderPortOIFCompatEditor()
{
- function printNewitemTR()
+ $raw_chaplist = getChapterList();
+ $chaplist = array();
+ $chaplist[0]='';
+ foreach( $raw_chaplist as $chapter ){
+ $chaplist[$chapter['id']]= htmlspecialchars( $chapter['name'] );
+ }
+ function printNewitemTR($chaplist_local)
{
printOpFormIntro ('add');
echo '<tr><th class=tdleft>';
@@ -3952,6 +3975,10 @@ function renderPortOIFCompatEditor()
printSelect (readChapter (CHAP_PORTTYPE), array ('name' => 'type1'));
echo '</th><th class=tdleft>';
printSelect (readChapter (CHAP_PORTTYPE), array ('name' => 'type2'));
+ echo '</th><th class=tdleft>';
+ printSelect( $chaplist_local, array( 'name' => 'cable_chapter_id' ) );
+ echo '</th><th>';
+ printImageHREF ('add', 'add pair', TRUE);
echo '</th></tr></form>';
}
@@ -3959,9 +3986,9 @@ function renderPortOIFCompatEditor()
$last_left_oif_id = NULL;
$order = 'odd';
echo '<br><table class=cooltable align=center border=0 cellpadding=5 cellspacing=0>';
- echo '<tr><th> </th><th>From Interface</th><th>To Interface</th></tr>';
+ echo '<tr><th> </th><th>From Interface</th><th>To Interface</th><th>Cable</th><th></th></tr>';
if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
- printNewitemTR();
+ printNewitemTR($chaplist);
foreach (getPortOIFCompat() as $pair)
{
if ($last_left_oif_id != $pair['type1'])
@@ -3969,13 +3996,19 @@ function renderPortOIFCompatEditor()
$order = $nextorder[$order];
$last_left_oif_id = $pair['type1'];
}
+ printOpFormIntro('upd',array('type1'=>$pair['type1'], 'type2' => $pair['type2']) );
echo "<tr class=row_${order}><td>";
echo '<a href="' . makeHrefProcess (array ('op' => 'del', 'type1' => $pair['type1'], 'type2' => $pair['type2'])) . '">';
printImageHREF ('delete', 'remove pair');
- echo "</a></td><td class=tdleft>${pair['type1name']}</td><td class=tdleft>${pair['type2name']}</td></tr>";
+ echo "</a></td><td class=tdleft>${pair['type1name']}</td><td class=tdleft>${pair['type2name']}</td>";
+ echo '<td>';
+ printSelect($chaplist, array('name'=>'cable_chapter_id'), $pair['cable_chapter_id']);
+ echo '</td><td>';
+ printImageHREF ('save', 'Save changes', TRUE);
+ echo "</td></tr></form>";
}
if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
- printNewitemTR();
+ printNewitemTR($chaplist);
echo '</table>';
}
diff --git a/wwwroot/inc/navigation.php b/wwwroot/inc/navigation.php
index 7e25ec3..f32fdfc 100644
--- a/wwwroot/inc/navigation.php
+++ b/wwwroot/inc/navigation.php
@@ -453,6 +453,9 @@ $tabhandler['portmap']['default'] = 'renderPortOIFCompatViewer';
$tabhandler['portmap']['edit'] = 'renderPortOIFCompatEditor';
$ophandler['portmap']['edit']['add'] = 'tableHandler';
$ophandler['portmap']['edit']['del'] = 'tableHandler';
+$ophandler['portmap']['edit']['upd'] = 'tableHandler';
+$ophandler['portmap']['edit']['addPack'] = 'addOIFCompatPack';
+$ophandler['portmap']['edit']['delPack'] = 'delOIFCompatPack';
$page['portifcompat']['title'] = 'Enabled port types';
$page['portifcompat']['parent'] = 'config';
diff --git a/wwwroot/inc/ophandlers.php b/wwwroot/inc/ophandlers.php
index 2fad512..3fc2e15 100644
--- a/wwwroot/inc/ophandlers.php
+++ b/wwwroot/inc/ophandlers.php
@@ -272,6 +272,21 @@ $opspec_list['portmap-edit-add'] = array
(
array ('url_argname' => 'type1', 'assertion' => 'uint'),
array ('url_argname' => 'type2', 'assertion' => 'uint'),
+ array ('url_argname' => 'cable_chapter_id', 'assertion' => 'uint0', 'if_empty' => 'NULL' )
+ ),
+);
+$opspec_list['portmap-edit-upd'] = array
+(
+ 'table' => 'PortCompat',
+ 'action' => 'UPDATE',
+ 'set_arglist' => array
+ (
+ array ('url_argname' => 'cable_chapter_id', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
+ ),
+ 'where_arglist' => array
+ (
+ array ('url_argname' => 'type1', 'assertion' => 'uint'),
+ array ('url_argname' => 'type2', 'assertion' => 'uint')
),
);
$opspec_list['portmap-edit-del'] = array
diff --git a/wwwroot/inc/popup.php b/wwwroot/inc/popup.php
index 15244cb..d9bb8a8 100644
--- a/wwwroot/inc/popup.php
+++ b/wwwroot/inc/popup.php
@@ -34,7 +34,7 @@ function getProximateRacks ($rack_id, $proximity = 0)
return $ret;
}
-function findSparePorts ($port_info, $filter)
+function getSparePorts($port_info, $filter)
{
$qparams = array ();
$query = "
@@ -45,37 +45,34 @@ SELECT
p.iif_id,
p.type as oif_id,
pii.iif_name,
- d.dict_value as oif_name,
p.object_id,
o.name as object_name
FROM Port p
INNER JOIN RackObject o ON o.id = p.object_id
INNER JOIN PortInnerInterface pii ON p.iif_id = pii.id
-INNER JOIN Dictionary d ON d.dict_key = p.type
";
// porttype filter (non-strict match)
$query .= "
INNER JOIN (
- SELECT Port.id FROM Port
+ SELECT p2.id FROM Port p2
INNER JOIN
(
- SELECT DISTINCT pic2.iif_id
+ SELECT DISTINCT pic2.iif_id, pic2.oif_id
FROM PortInterfaceCompat pic2
INNER JOIN PortCompat pc ON pc.type2 = pic2.oif_id
";
if ($port_info['iif_id'] != 1)
{
- $query .= " INNER JOIN PortInterfaceCompat pic ON pic.oif_id = pc.type1 WHERE pic.iif_id = ? AND ";
+ $query .= " INNER JOIN PortInterfaceCompat pic ON pic.oif_id = pc.type1 WHERE pic.iif_id = ? ";
$qparams[] = $port_info['iif_id'];
}
else
{
- $query .= " WHERE pc.type1 = ? AND ";
+ $query .= " WHERE pc.type1 = ? ";
$qparams[] = $port_info['oif_id'];
}
$query .= "
- pic2.iif_id <> 1
- ) AS sub1 USING (iif_id)
+ ) AS sub1 ON p2.iif_id = sub1.iif_id AND ( p2.iif_id <> 1 OR p2.type = sub1.oif_id )
UNION
SELECT Port.id
FROM Port
@@ -113,42 +110,104 @@ INNER JOIN (
// ordering
$query .= ' ORDER BY o.name';
- $ret = array();
- $result = usePreparedSelectBlade ($query, $qparams);
-
- $rows_by_pn = array();
- $prev_object_id = NULL;
+ return usePreparedSelectBlade ($query, $qparams);
+}
+
+function getLinkPortJavascript($port_info, $ports)
+{
+ $required_oif = array();
+ $required_iif = array();
+ $required_chapter = array();
+ if( count($ports) == 0 ){
+ return '';
+ }
+ $jsports = array();
+ $compat = array();
+ $buffer = array('$(function($){');
+ $buffer[]='var PORT = { id:'.$port_info['id'].', name:"'.addslashes($port_info['name']).'",';
+ $buffer[]=' object_name:"'.addslashes($port_info['object_name']).'",';
+ $buffer[]=' oif_id:'.($port_info['oif_id'] ? $port_info['oif_id'] : 'null').', ';
+ $buffer[]=' iif_id:'.$port_info['iif_id'].', ';
+ $buffer[]=' cable:"'.addslashes($port_info['cableid']).'", ';
+ $buffer[]=' cable_dict_key:'.($port_info['cable_dict_key'] ? $port_info['cable_dict_key'] : 'null' ).', ';
+ $buffer[]=' remote_id:'.($port_info['remote_id'] ? $port_info['remote_id'] : 'null').'};';
+ $buffer[]='var PORTS = [';
- // fetch port rows from the DB
- while (TRUE)
+ $required_iif[$port_info['iif_id']]=true;
+ if( $port_info['oif_id'] ) $required_oif[$port_info['oif_id']]=true;
+ foreach( $ports as $port ){
+ $required_iif[ $port['iif_id'] ]=true;
+ if( $port['oif_id'] ) $required_oif[$port['oif_id']]=true;
+ $buffer[]=' { id:'.$port['id'].', name:"'.addslashes($port['name']).'", object_name:"'.addslashes($port['object_name']).'", oif_id:'.($port['oif_id'] ? $port['oif_id'] : 'null').', iif_id:'.$port['iif_id'].', reservation:"'.addslashes($port['reservation_comment']).'"},';
+ }
+ $buffer[]='];';
+
+ $incom = usePreparedSelectBlade('SELECT * FROM PortInterfaceCompat WHERE iif_id IN ('.questionMarks(count($required_iif)).') ORDER BY iif_id ', array_keys($required_iif));
+ $buffer[]='var INNER_OUTER_COMPATIBILITY = {';
+ $last_iif_id = null;
+ foreach( $incom as $in )
{
- $row = $result->fetch (PDO::FETCH_ASSOC);
- if (isset ($prev_object_id) and (! $row or $row['object_id'] != $prev_object_id))
+ if( $in['iif_id'] != $last_iif_id )
{
- // handle sorted object's portlist
- foreach (sortPortList ($rows_by_pn) as $ports_subarray)
- foreach ($ports_subarray as $port_row)
- {
- $port_description = $port_row['object_name'] . ' -- ' . $port_row['name'];
- if (count ($ports_subarray) > 1)
- {
- $if_type = $port_row['iif_id'] == 1 ? $port_row['oif_name'] : $port_row['iif_name'];
- $port_description .= " ($if_type)";
- }
- if (! empty ($port_row['reservation_comment']))
- $port_description .= ' -- ' . $port_row['reservation_comment'];
- $ret[$port_row['id']] = $port_description;
- }
- $rows_by_pn = array();
+ if( $last_iif_id != null )
+ {
+ $buffer[]=' ],';
+ }
+ $buffer[]=' '.$in['iif_id'].': [';
+ $last_iif_id = $in['iif_id'];
}
- $prev_object_id = $row['object_id'];
- if ($row)
- $rows_by_pn[$row['name']][] = $row;
- else
- break;
+ $required_oif[$in['oif_id']]=true;
+ $buffer[]=' '.$in['oif_id'].',';
}
+ if( $last_iif_id != null )
+ {
+ $buffer[]=' ]';
+ }
+ $buffer[]='};';
- return $ret;
+ $query ='SELECT * FROM PortCompat pc'.
+ ' WHERE type1 IN ('.questionMarks(count($required_oif)).') AND type2 IN ('.questionMarks(count($required_oif)).');';
+ $types = usePreparedSelectBlade($query, array_merge( array_keys($required_oif), array_keys($required_oif) ) );
+ foreach( $types as $type ){
+ @$compat[ $type['type1'] ][ $type['type2'] ] = array( 'cable_chapter_id'=> ($type['cable_chapter_id'] ? intval($type['cable_chapter_id']) : 'null') );
+ if( $type['cable_chapter_id'] ) $required_chapter[intval($type['cable_chapter_id'])] = true;
+ }
+ $buffer[]='var OUTER_COMPATIBILITY = {';
+ foreach( $compat as $a => $sub ){
+ $buffer[]=' '.$a.': { ';
+ foreach( $sub as $b => $info ){
+ $buffer[]=' '.$b.': {cable_chapter_id:'.$info['cable_chapter_id'].'},';
+ }
+ $buffer[]=' },';
+ }
+ $buffer[]='};';
+ if( $required_chapter ){
+ $buffer[]='var CABLES = {';
+ $last_chapter_id = -1;
+ foreach( array_keys($required_chapter) as $chapter_id ){
+ $chapter = cookOptgroups( readChapter( $chapter_id, 'o' ) );
+ $buffer[]= $chapter_id.': [';
+ foreach( $chapter as $group => $entries ){
+ $buffer[]= ' {name: "'.addslashes($group).'", values:[';
+ foreach( $entries as $key => $value ){
+ $buffer[]= ' {key: '.$key.', value: "'.addslashes($value).'"},';
+ }
+ $buffer[]=' ]},';
+ }
+ $buffer[]='],';
+ }
+ $buffer[]='};';
+ }else{
+ $buffer[]='var CABLES = {};';
+ }
+ $oifs = usePreparedSelectBlade('SELECT dict_key,dict_value FROM Dictionary WHERE chapter_id = 2 AND dict_key IN ('.questionMarks(count($required_oif)).');', array_keys($required_oif));
+ $buffer[]='var OIF = {};';
+ foreach( $oifs as $oif ){
+ $buffer[]='OIF['.$oif['dict_key'].']= "'.addslashes($oif['dict_value']).'";';
+ }
+ $buffer[]=' initializeLinkportForm( PORT, PORTS, INNER_OUTER_COMPATIBILITY, OUTER_COMPATIBILITY, CABLES, OIF )';
+ $buffer[]='});';
+ return join("\n",$buffer);
}
// Return a list of all objects which are possible parents
@@ -221,131 +280,66 @@ function renderPopupObjectSelector()
function handlePopupPortLink()
{
+ global $dbxlink;
assertUIntArg ('port');
assertUIntArg ('remote_port');
assertStringArg ('cable', TRUE);
$port_info = getPortInfo ($_REQUEST['port']);
$remote_port_info = getPortInfo ($_REQUEST['remote_port']);
- $POIFC = getPortOIFCompat();
- if (isset ($_REQUEST['port_type']) and isset ($_REQUEST['remote_port_type']))
- {
- $type_local = $_REQUEST['port_type'];
- $type_remote = $_REQUEST['remote_port_type'];
- }
- else
- {
- $type_local = $port_info['oif_id'];
- $type_remote = $remote_port_info['oif_id'];
- }
- $matches = FALSE;
- $js_table = '';
- foreach ($POIFC as $pair)
- if ($pair['type1'] == $type_local && $pair['type2'] == $type_remote)
- {
- $matches = TRUE;
- break;
+ $dbxlink->beginTransaction();
+ try{
+
+ if( $port_info['iif_id'] != 1 ){
+ // updateable
+ assertUIntArg ('local_oif');
+ if( $_POST['local_oif'] != $port_info['oif_id'] ){
+ commitUpdatePortOIF( $port_info['id'], $_POST['local_oif']);
+ $port_info['oif_id'] = intval($_POST['local_oif']);
+ }
}
- else
- $js_table .= "POIFC['${pair['type1']}-${pair['type2']}'] = 1;\n";
-
- if ($matches)
- {
- if ($port_info['oif_id'] != $type_local)
- commitUpdatePortOIF ($port_info['id'], $type_local);
- 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']);
- showSuccess
- (
- sprintf
+ if( $remote_port_info['iif_id'] != 1 ){
+ // updateable
+ assertUIntArg ('remote_oif');
+ if( $_POST['remote_oif'] != $remote_port_info['oif_id'] ){
+ commitUpdatePortOIF( $remote_port_info['id'], $_POST['remote_oif']);
+ $remote_port_info['oif_id'] = intval($_POST['remote_oif']);
+ }
+ }
+ // now check compat
+ $compat = usePreparedSelectBlade('SELECT * FROM PortCompat WHERE ( type1 = ? AND type2 = ? ) OR ( type2 = ? AND type1= ? ) ',
+ array( $port_info['oif_id'],$remote_port_info['oif_id'],$port_info['oif_id'],$remote_port_info['oif_id']) )->fetchAll();
+ if( !$compat ){
+ throw new InvalidRequestArgException('oif_id', '', 'Ports are not compatible');
+ }else{
+ // :)
+ $cable_type = null;
+ if( $compat[0]['cable_chapter_id'] && $_POST['cable_type'] ){
+ assertUIntArg('cable_type',true);
+ $cable_type = $_POST['cable_type'];
+ }
+ linkPorts( $port_info['id'], $remote_port_info['id'], $_POST['cable'], $cable_type, true );
+ $dbxlink->commit();
+ showSuccess
(
+ sprintf
+ (
'Port %s successfully linked with port %s',
formatPortLink ($port_info['id'], $port_info['name'], NULL, NULL),
formatPort ($remote_port_info)
- )
- );
- addJS (<<<END
-window.opener.location.reload(true);
-window.close();
+ )
+ );
+ addJS (<<<END
+ window.opener.location.reload(true);
+ window.close();
END
- , TRUE);
- }
- else
- {
- // JS code to display port compatibility hint
- addJS (<<<END
-POIFC = {};
-$js_table
-$(document).ready(function () {
- $('select.porttype').change(onPortTypeChange);
- onPortTypeChange();
-});
-function onPortTypeChange() {
- var key = $('*[name=port_type]')[0].value + '-' + $('*[name=remote_port_type]')[0].value;
- if (POIFC[key] == 1)
- {
- $('#hint-not-compat').hide();
- $('#hint-compat').show();
- }
- else
- {
- $('#hint-compat').hide();
- $('#hint-not-compat').show();
- }
-}
-END
- , TRUE);
- addCSS (<<<END
-.compat-hint {
- display: none;
- font-size: 125%;
-}
-.compat-hint#hint-compat {
- color: green;
-}
-.compat-hint#hint-not-compat {
- color: #804040;
-}
-END
- , TRUE);
- // render port type editor form
- echo '<form method=GET>';
- echo '<input type=hidden name="module" value="popup">';
- echo '<input type=hidden name="helper" value="portlist">';
- echo '<input type=hidden name="port" value="' . $port_info['id'] . '">';
- echo '<input type=hidden name="remote_port" value="' . $remote_port_info['id'] . '">';
- echo '<input type=hidden name="cable" value="' . htmlspecialchars ($_REQUEST['cable'], ENT_QUOTES) . '">';
- echo '<p>The ports you have selected are not compatible. Please select a compatible transceiver pair.';
- echo '<p>';
- echo formatPort ($port_info) . ' ';
- if ($port_info['iif_id'] == 1)
- {
- echo formatPortIIFOIF ($port_info);
- echo '<input type=hidden name="port_type" value="' . $port_info['oif_id'] . '">';
- }
- else
- {
- echo '<label>' . $port_info['iif_name'] . ' ';
- printSelect (getExistingPortTypeOptions ($port_info['id']), array ('class' => 'porttype', 'name' => 'port_type'), $type_local);
- echo '</label>';
+ , true);
+ return;
}
- echo ' — ';
- if ($remote_port_info['iif_id'] == 1)
- {
- echo formatPortIIFOIF ($remote_port_info);
- echo '<input type=hidden name="remote_port_type" value="' . $remote_port_info['oif_id'] . '">';
- }
- else
- {
- echo '<label>' . $remote_port_info['iif_name'] . ' ';
- printSelect (getExistingPortTypeOptions ($remote_port_info['id']), array ('class' => 'porttype', 'name' => 'remote_port_type'), $type_remote);
- echo '</label>';
- }
- echo ' ' . formatPort ($remote_port_info);
- echo '<p class="compat-hint" id="hint-not-compat">✕ Not compatible port types</p>';
- echo '<p class="compat-hint" id="hint-compat">✔ Compatible port types</p>';
- echo '<p><input type=submit name="do_link" value="Link">';
+ }catch( Exception $e ){
+ $dbxlink->rollBack();
+ throw $e;
}
+ return renderPopupPortSelector();
}
function renderPopupPortSelector()
@@ -353,6 +347,7 @@ function renderPopupPortSelector()
assertUIntArg ('port');
$port_id = $_REQUEST['port'];
$port_info = getPortInfo ($port_id);
+
$in_rack = isset ($_REQUEST['in_rack']);
// fill port filter structure
@@ -379,11 +374,34 @@ function renderPopupPortSelector()
! empty ($filter['objects']) ||
! empty ($filter['ports'])
)
- $spare_ports = findSparePorts ($port_info, $filter);
+ $ports_with_current = $ports = getSparePorts($port_info, $filter)->fetchAll();
+ if( $port_info['linked'] ){
+ $link = usePreparedSelectBlade('SELECT * FROM Link WHERE porta = ? OR portb = ?', array($port_id, $port_id))->fetch(PDO::FETCH_ASSOC);
+
+ $current = getPortInfo( ($link['porta'] == $port_id) ? $link['portb'] : $link['porta'] );
+ $port_info['cableid'] = $current['cableid'] = $link['cable'];
+ $port_info['cable_dict_key'] = $current['cable_dict_key'] = $link['cable_dict_key'];
+ $port_info['remote_id'] = $current['id'];
+ $ports_with_current[] = $current;
+ }
+ addJS('js/link_port_form.js');
+ addJS(getLinkPortJavascript($port_info, $ports_with_current),true);
+ addCSS (<<<'END'
+.reserved {
+ text-decoration: line-through;
+}
+.compatible {
+ background: #afa;
+}
+.incompatible {
+ background: #faa;
+}
+END
+ , TRUE);
// display search form
echo 'Link ' . formatPort ($port_info) . ' to...';
- echo '<form method=GET>';
+ echo '<form method="POST">';
startPortlet ('Port list filter');
echo '<input type=hidden name="module" value="popup">';
echo '<input type=hidden name="helper" value="portlist">';
@@ -391,23 +409,59 @@ function renderPopupPortSelector()
echo '<table align="center" valign="bottom"><tr>';
echo '<td class="tdleft"><label>Object name:<br><input type=text size=8 name="filter-obj" value="' . htmlspecialchars ($filter['objects'], ENT_QUOTES) . '"></label></td>';
echo '<td class="tdleft"><label>Port name:<br><input type=text size=6 name="filter-port" value="' . htmlspecialchars ($filter['ports'], ENT_QUOTES) . '"></label></td>';
+ echo '</tr><tr>';
echo '<td class="tdleft" valign="bottom"><label><input type=checkbox name="in_rack"' . ($in_rack ? ' checked' : '') . '>Nearest racks</label></td>';
echo '<td valign="bottom"><input type=submit value="show ports"></td>';
echo '</tr></table>';
finishPortlet();
// display results
- startPortlet ('Compatible spare ports');
- if (empty ($spare_ports))
- echo '(nothing found)';
- else
- {
- echo getSelect ($spare_ports, array ('name' => 'remote_port', 'size' => getConfigVar ('MAXSELSIZE')), NULL, FALSE);
- echo "<p>Cable ID: <input type=text id=cable name=cable>";
- echo "<p><input type='submit' value='Link' name='do_link'>";
+ startPortlet ('Link port');
+ if( $ports_with_current ){
+ echo '<div style="float: left;width:40%">';
+ echo '<select name="remote_port" id="remote_port" size="',getConfigVar ('MAXSELSIZE'),'" style="width:100%">';
+ if( $current ){
+ echo '<optgroup label="current">';
+ echo '<optgroup label=" ', htmlspecialchars($current['object_name']), '">';
+ echo '<option value="',$current['id'],'" selected="selected">', htmlspecialchars($current['name'] ),'</option>';
+ echo '</optgroup>';
+ }
+ echo '<optgroup label="search result">';
+ if( !$ports ){
+ echo '<option disabled="disabled" value="">nothing found</option>';
+ }else{
+ $ports_by_object = array();
+ foreach( $ports as $port ){
+ if( !isset($ports_by_object[$port['object_name']]) ) $ports_by_object[$port['object_name']] = array();
+ $ports_by_object[$port['object_name']][] = $port;
+ }
+ ksort( $ports_by_object );
+ foreach( $ports_by_object as $name => $object_ports ){
+ echo '<optgroup label=" ', htmlspecialchars($name), '">';
+ foreach( sortPortList($object_ports, true) as $port ){
+ echo '<option value="', $port['id'],'"',($port['reservation_comment'] ? ' class="reserved"':''),'>', htmlspecialchars($port['name']), '</option>';
+ }
+ echo '</optgroup>';
+ }
+ }
+ echo '</optgroup>';
+ echo '</select>';
+ echo '</div>';
+ echo '<div style="margin-left: 41%">';
+ echo '<p style="display:none">This port is reserved: <span id="reservation"></span></p>';
+ echo '<p style="display:none"><label for="cable_type">Local Transceiver</label></br><select name="local_oif" id="local_oif" style="width:100%"></select></p>';
+ echo '<p style="display:none"><label for="remote_oif">Remote Transceiver</label></br><select name="remote_oif" id="remote_oif" style="width:100%"></select></p>';
+ echo '<p style="display:none"><label for="cable_type">Cable type</label></br><select name="cable_type" id="cable_type" style="width:100%"></select></p>';
+ echo '<p><label for="cable">Cable ID: </label><br /><input type="text" id="cable" name="cable" style="width:100%" value="',htmlspecialchars($port_info['cableid']) ,'"/></p>';
+ echo '<p><input type="submit" value="Link" name="do_link" id="submit"></p>';
+ echo '<br style="clear:both" /></div>';
+ }else{
+ echo 'nothing found';
}
+
finishPortlet();
echo '</form>';
+ echo '<br style="clear:both" />';
}
function renderPopupIPv4Selector()
diff --git a/wwwroot/js/link_port_form.js b/wwwroot/js/link_port_form.js
new file mode 100644
index 0000000..0cf45a2
--- /dev/null
+++ b/wwwroot/js/link_port_form.js
@@ -0,0 +1,147 @@
+function initializeLinkportForm( PORT, PORTS, INNER_OUTER_COMPATIBILITY, OUTER_COMPATIBILITY, CABLES, OIF ){
+ var $remote_port = $('#remote_port'),$remote_oif = $('#remote_oif'),$local_oif = $('#local_oif'),$cable_type = $('#cable_type'), $submit = $('#submit'), $reservation = $('#reservation');
+ var compatClass = function(a,b){
+ if( !a || !b ){
+ return '';
+ }else if( !OUTER_COMPATIBILITY[a] || !OUTER_COMPATIBILITY[a][b] ){
+ return 'incompatible';
+ }else{
+ return 'compatible';
+ }
+ }
+ var updateSelects = function(){
+ var rp = $remote_port.val(), ro = $remote_oif.val(), lo = $local_oif.val(), ct = $cable_type.val();
+ if( ro ) ro = parseInt(ro);
+ if( !lo ){
+ lo = PORT.oif_id;
+ }else{
+ lo = parseInt(lo);
+ }
+ if( !rp ){
+ rp = PORT.remote_id;
+ }
+ if( !ct ){
+ ct = PORT.cable_dict_key;
+ }
+ //remote_oif
+ $remote_oif.empty();
+ var remote_port;
+ if( rp ){
+ remote_port = $.grep(PORTS,function(p){ return p.id == rp })[0];
+ if( !ro || remote_port.iif_id == 1 || INNER_OUTER_COMPATIBILITY[ remote_port.iif_id ].indexOf(ro) == -1 ){
+ ro = remote_port.oif_id;
+ }
+ if( remote_port.reservation == "" ){
+ $reservation.closest('p').hide();
+ }else{
+ $reservation.text( remote_port.reservation );
+ $reservation.closest('p').show();
+ }
+ if( remote_port.iif_id != 1 ){
+ $remote_oif.closest('p').show();
+ $remote_oif.attr('disabled',false);
+ }else{
+ $remote_oif.closest('p').hide();
+ $remote_oif.attr('disabled',true);
+ }
+ var rps = INNER_OUTER_COMPATIBILITY[ remote_port.iif_id ];
+ rps.sort(function(a,b){
+ return OIF[a].localeCompare(OIF[b]);
+ }).forEach( function(oif){
+ $('<option>').val(oif).text( OIF[oif] ).addClass( compatClass( oif, lo ) ).appendTo($remote_oif);
+ });
+ $remote_oif.val(ro);
+ }else{
+ $remote_oif.closest('p').hide();
+ $remote_oif.attr('disabled',true);
+ }
+ //local_oif
+ $local_oif.empty();
+ if( PORT.iif_id != 1 ){
+ $local_oif.closest('p').show();
+ $local_oif.attr('disabled',false);
+ }else{
+ $local_oif.closest('p').hide();
+ $local_oif.attr('disabled',true);
+ }
+ var lps = INNER_OUTER_COMPATIBILITY[ PORT.iif_id ];
+ lps.sort(function(a,b){
+ return OIF[a].localeCompare(OIF[b]);
+ }).forEach( function(oif){
+ $('<option>').val(oif).text( OIF[oif] ).addClass( compatClass( oif, ro ) ).appendTo($local_oif);
+ });
+ $local_oif.val(lo);
+ if( rp && lo && ro ){
+ // cables and compat!
+ var comb = OUTER_COMPATIBILITY[ ro ] ? OUTER_COMPATIBILITY[ ro ][ lo ] : null;
+ if( !comb ){
+ $submit.attr('disabled',true);
+ $submit.val('Incompatible transceiver');
+ $cable_type.closest('p').hide();
+ }else{
+ if( comb.cable_chapter_id ){
+ $cable_type.empty();
+ var cables = CABLES[comb.cable_chapter_id];
+ if( cables ){
+ var other;
+ $.each(cables,function(i,group){
+ if( group.name == 'other' ){
+ other = group;
+ return ;
+ }
+ var g = $('<optgroup>').attr('label',group.name).appendTo($cable_type);
+ $.each(group.values, function(j, opt){
+ $('<option>').val(opt.key).text(opt.value).appendTo(g);
+ });
+ });
+ if( other ){
+ $.each(other.values, function(j, opt){
+ $('<option>').val(opt.key).text(opt.value).appendTo($cable_type);
+ });
+ }
+ }
+ $('<option>').val('').text('').appendTo($cable_type);
+ $cable_type.val(ct);
+ $cable_type.closest('p').show();
+ }else{
+ // compatible but no cables
+ $cable_type.closest('p').hide();
+ }
+ $submit.attr('disabled',false);
+ $submit.val('Link');
+ }
+ }else{
+ if( !rp ){
+ $submit.attr('disabled',true);
+ $submit.val('Select a port');
+ }
+ $cable_type.closest('p').hide();
+ }
+ }
+ updateSelects();
+ $remote_port.change(updateSelects);
+ var changeTransceiver = function( $a, $b ){
+ var av = $a.val();
+ var bv = $b.val();
+ if( !OUTER_COMPATIBILITY[av] ){
+ return ;
+ }
+ if( OUTER_COMPATIBILITY[av][bv] ){
+ return;
+ }
+ $b.children('option').each(function(i,o ){
+ if( OUTER_COMPATIBILITY[ av ][ $(o).val() ] ){
+ $b.val( $(o).val() );
+ return false;
+ }
+ });
+ }
+ $local_oif.change(function(){
+ changeTransceiver($local_oif,$remote_oif);
+ updateSelects();
+ });
+ $remote_oif.change(function(){
+ changeTransceiver($remote_oif,$local_oif);
+ updateSelects();
+ });
+}
track_cable_type_0.19.13.correct.diff (32,223 bytes)
diff --git a/wwwroot/inc/database.php b/wwwroot/inc/database.php
index d9f8e2c..1b9dd82 100644
--- a/wwwroot/inc/database.php
+++ b/wwwroot/inc/database.php
@@ -580,9 +580,10 @@ function getObjectPortsAndLinks ($object_id)
{
$portid = $ret[$tmpkey]['id'];
$remote_id = NULL;
- $query = "select porta, portb, cable from Link where porta = ? or portb = ?";
+ $query = "select porta, portb, cable, cable_dict_key from Link where porta = ? or portb = ?";
$result = usePreparedSelectBlade ($query, array ($portid, $portid));
$cable = "CableID n/a";
+ $cable_dict_key = null;
if ($row = $result->fetch (PDO::FETCH_ASSOC))
{
if ($portid != $row['porta'])
@@ -590,6 +591,7 @@ function getObjectPortsAndLinks ($object_id)
elseif ($portid != $row['portb'])
$remote_id = $row['portb'];
$cable = $row['cable'];
+ $cable_dict_key = $row['cable_dict_key'];
}
unset ($result);
if ($remote_id) // there's a remote end here
@@ -601,6 +603,7 @@ function getObjectPortsAndLinks ($object_id)
$ret[$tmpkey]['remote_name'] = $row['name'];
$ret[$tmpkey]['remote_object_id'] = $row['object_id'];
$ret[$tmpkey]['cableid'] = $cable;
+ $ret[$tmpkey]['cable_dict_key'] = $cable_dict_key;
}
$ret[$tmpkey]['remote_id'] = $remote_id;
unset ($result);
@@ -1232,19 +1235,44 @@ function getAllIPv4Allocations ()
return $ret;
}
-function linkPorts ($porta, $portb, $cable = NULL)
+function linkPorts ($porta, $portb, $cable = NULL, $cable_type = NULL, $update = false)
{
if ($porta == $portb)
throw new InvalidArgException ('porta/portb', $porta, "Ports can't be the same");
global $dbxlink;
- $dbxlink->exec ('LOCK TABLES Link WRITE');
+ # the many locks are necessary. otherwise commitUnlinkPort could not access these tables:
+ $dbxlink->exec ('LOCK TABLES Link WRITE, Port AS pa WRITE, Port AS pb WRITE , RackObject WRITE');
$result = usePreparedSelectBlade
(
- 'SELECT COUNT(*) FROM Link WHERE porta IN (?,?) OR portb IN (?,?)',
+ 'SELECT * FROM Link WHERE porta IN (?,?) OR portb IN (?,?)',
array ($porta, $portb, $porta, $portb)
);
- if ($result->fetchColumn () != 0)
+ if ( $update )
+ {
+ $a = $result->fetch();
+ if( $a ){
+ if( ($a['porta'] == $porta && $a['portb'] == $portb) || ($a['portb'] == $porta && $a['porta'] == $portb) )
+ {
+ // update!
+ $dbxlink->exec ('UNLOCK TABLES');
+ usePreparedUpdateBlade(
+ 'Link',
+ array (
+ 'cable' => ( mb_strlen ($cable) ? $cable : NULL ) ,
+ 'cable_dict_key' => ( mb_strlen ($cable_type) ? intval($cable_type) : NULL )
+ ),
+ array( 'porta' => $a['porta'], 'portb' => $a['portb'] )
+ );
+
+ return ;
+ }else{
+ commitUnlinkPort($porta);
+ commitUnlinkPort($portb);
+ }
+ }
+ }
+ else if ($result->fetch ())
{
$dbxlink->exec ('UNLOCK TABLES');
return "Port ${porta} or ${portb} is already linked";
@@ -1263,7 +1291,8 @@ function linkPorts ($porta, $portb, $cable = NULL)
(
'porta' => $porta,
'portb' => $portb,
- 'cable' => mb_strlen ($cable) ? $cable : NULL
+ 'cable' => mb_strlen ($cable) ? $cable : NULL,
+ 'cable_dict_key' => mb_strlen ($cable_type) ? intval($cable_type) : NULL
)
);
$dbxlink->exec ('UNLOCK TABLES');
@@ -2311,9 +2340,10 @@ function commitUpdateUserAccount ($id, $new_username, $new_realname, $new_passwo
function getPortOIFCompat ()
{
$query =
- "select type1, type2, d1.dict_value as type1name, d2.dict_value as type2name from " .
+ "select type1, type2, d1.dict_value as type1name, d2.dict_value as type2name, cable_chapter_id , c.name as cable_chapter_name from " .
"PortCompat as pc inner join Dictionary as d1 on pc.type1 = d1.dict_key " .
"inner join Dictionary as d2 on pc.type2 = d2.dict_key " .
+ "left join Chapter as c on pc.cable_chapter_id = c.id ".
'ORDER BY type1name, type2name';
$result = usePreparedSelectBlade ($query);
return $result->fetchAll (PDO::FETCH_ASSOC);
diff --git a/wwwroot/inc/interface.php b/wwwroot/inc/interface.php
index 3e54e38..85fb28d 100644
--- a/wwwroot/inc/interface.php
+++ b/wwwroot/inc/interface.php
@@ -1164,7 +1164,24 @@ function renderPortsForObject ($object_id)
'object_id'=>$object_id)).
"'>";
printImageHREF ('cut', 'Unlink this port');
- echo "</a></td>";
+ echo "</a>";
+ echo "<span";
+ $helper_args = array
+ (
+ 'port' => $port['id'],
+ );
+ $popup_args = 'height=700, width=400, location=no, menubar=no, '.
+ 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
+ echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
+ echo "\",\"findlink\",\"${popup_args}\");'";
+ // end of onclick=
+ echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
+ echo "\",\"findlink\",\"${popup_args}\");'";
+ // end of onclick=
+ echo '>';
+ // end of <a>
+ printImageHREF ('plug', 'Link this port');
+ echo "</span></td>";
}
elseif (strlen ($port['reservation_comment']))
{
@@ -3928,7 +3945,7 @@ function renderPortOIFCompatViewer()
$order = 'odd';
$last_left_oif_id = NULL;
echo '<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>';
- echo '<tr><th>From interface</th><th>To interface</th></tr>';
+ echo '<tr><th>From interface</th><th>To interface</th><th>Cable</th></tr>';
foreach (getPortOIFCompat() as $pair)
{
if ($last_left_oif_id != $pair['type1'])
@@ -3936,14 +3953,20 @@ function renderPortOIFCompatViewer()
$order = $nextorder[$order];
$last_left_oif_id = $pair['type1'];
}
- echo "<tr class=row_${order}><td>${pair['type1name']}</td><td>${pair['type2name']}</td></tr>";
+ echo "<tr class=row_${order}><td>${pair['type1name']}</td><td>${pair['type2name']}</td><td>${pair['cable_chapter_name']}</td></tr>";
}
echo '</table>';
}
function renderPortOIFCompatEditor()
{
- function printNewitemTR()
+ $raw_chaplist = getChapterList();
+ $chaplist = array();
+ $chaplist[0]='';
+ foreach( $raw_chaplist as $chapter ){
+ $chaplist[$chapter['id']]= htmlspecialchars( $chapter['name'] );
+ }
+ function printNewitemTR($chaplist_local)
{
printOpFormIntro ('add');
echo '<tr><th class=tdleft>';
@@ -3952,6 +3975,10 @@ function renderPortOIFCompatEditor()
printSelect (readChapter (CHAP_PORTTYPE), array ('name' => 'type1'));
echo '</th><th class=tdleft>';
printSelect (readChapter (CHAP_PORTTYPE), array ('name' => 'type2'));
+ echo '</th><th class=tdleft>';
+ printSelect( $chaplist_local, array( 'name' => 'cable_chapter_id' ) );
+ echo '</th><th>';
+ printImageHREF ('add', 'add pair', TRUE);
echo '</th></tr></form>';
}
@@ -3959,9 +3986,9 @@ function renderPortOIFCompatEditor()
$last_left_oif_id = NULL;
$order = 'odd';
echo '<br><table class=cooltable align=center border=0 cellpadding=5 cellspacing=0>';
- echo '<tr><th> </th><th>From Interface</th><th>To Interface</th></tr>';
+ echo '<tr><th> </th><th>From Interface</th><th>To Interface</th><th>Cable</th><th></th></tr>';
if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
- printNewitemTR();
+ printNewitemTR($chaplist);
foreach (getPortOIFCompat() as $pair)
{
if ($last_left_oif_id != $pair['type1'])
@@ -3969,13 +3996,19 @@ function renderPortOIFCompatEditor()
$order = $nextorder[$order];
$last_left_oif_id = $pair['type1'];
}
+ printOpFormIntro('upd',array('type1'=>$pair['type1'], 'type2' => $pair['type2']) );
echo "<tr class=row_${order}><td>";
echo '<a href="' . makeHrefProcess (array ('op' => 'del', 'type1' => $pair['type1'], 'type2' => $pair['type2'])) . '">';
printImageHREF ('delete', 'remove pair');
- echo "</a></td><td class=tdleft>${pair['type1name']}</td><td class=tdleft>${pair['type2name']}</td></tr>";
+ echo "</a></td><td class=tdleft>${pair['type1name']}</td><td class=tdleft>${pair['type2name']}</td>";
+ echo '<td>';
+ printSelect($chaplist, array('name'=>'cable_chapter_id'), $pair['cable_chapter_id']);
+ echo '</td><td>';
+ printImageHREF ('save', 'Save changes', TRUE);
+ echo "</td></tr></form>";
}
if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
- printNewitemTR();
+ printNewitemTR($chaplist);
echo '</table>';
}
diff --git a/wwwroot/inc/navigation.php b/wwwroot/inc/navigation.php
index 7e25ec3..f32fdfc 100644
--- a/wwwroot/inc/navigation.php
+++ b/wwwroot/inc/navigation.php
@@ -453,6 +453,9 @@ $tabhandler['portmap']['default'] = 'renderPortOIFCompatViewer';
$tabhandler['portmap']['edit'] = 'renderPortOIFCompatEditor';
$ophandler['portmap']['edit']['add'] = 'tableHandler';
$ophandler['portmap']['edit']['del'] = 'tableHandler';
+$ophandler['portmap']['edit']['upd'] = 'tableHandler';
+$ophandler['portmap']['edit']['addPack'] = 'addOIFCompatPack';
+$ophandler['portmap']['edit']['delPack'] = 'delOIFCompatPack';
$page['portifcompat']['title'] = 'Enabled port types';
$page['portifcompat']['parent'] = 'config';
diff --git a/wwwroot/inc/ophandlers.php b/wwwroot/inc/ophandlers.php
index 2fad512..3fc2e15 100644
--- a/wwwroot/inc/ophandlers.php
+++ b/wwwroot/inc/ophandlers.php
@@ -272,6 +272,21 @@ $opspec_list['portmap-edit-add'] = array
(
array ('url_argname' => 'type1', 'assertion' => 'uint'),
array ('url_argname' => 'type2', 'assertion' => 'uint'),
+ array ('url_argname' => 'cable_chapter_id', 'assertion' => 'uint0', 'if_empty' => 'NULL' )
+ ),
+);
+$opspec_list['portmap-edit-upd'] = array
+(
+ 'table' => 'PortCompat',
+ 'action' => 'UPDATE',
+ 'set_arglist' => array
+ (
+ array ('url_argname' => 'cable_chapter_id', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
+ ),
+ 'where_arglist' => array
+ (
+ array ('url_argname' => 'type1', 'assertion' => 'uint'),
+ array ('url_argname' => 'type2', 'assertion' => 'uint')
),
);
$opspec_list['portmap-edit-del'] = array
diff --git a/wwwroot/inc/popup.php b/wwwroot/inc/popup.php
index 15244cb..85cb212 100644
--- a/wwwroot/inc/popup.php
+++ b/wwwroot/inc/popup.php
@@ -34,7 +34,7 @@ function getProximateRacks ($rack_id, $proximity = 0)
return $ret;
}
-function findSparePorts ($port_info, $filter)
+function getSparePorts($port_info, $filter)
{
$qparams = array ();
$query = "
@@ -45,37 +45,34 @@ SELECT
p.iif_id,
p.type as oif_id,
pii.iif_name,
- d.dict_value as oif_name,
p.object_id,
o.name as object_name
FROM Port p
INNER JOIN RackObject o ON o.id = p.object_id
INNER JOIN PortInnerInterface pii ON p.iif_id = pii.id
-INNER JOIN Dictionary d ON d.dict_key = p.type
";
// porttype filter (non-strict match)
$query .= "
INNER JOIN (
- SELECT Port.id FROM Port
+ SELECT p2.id FROM Port p2
INNER JOIN
(
- SELECT DISTINCT pic2.iif_id
+ SELECT DISTINCT pic2.iif_id, pic2.oif_id
FROM PortInterfaceCompat pic2
INNER JOIN PortCompat pc ON pc.type2 = pic2.oif_id
";
if ($port_info['iif_id'] != 1)
{
- $query .= " INNER JOIN PortInterfaceCompat pic ON pic.oif_id = pc.type1 WHERE pic.iif_id = ? AND ";
+ $query .= " INNER JOIN PortInterfaceCompat pic ON pic.oif_id = pc.type1 WHERE pic.iif_id = ? ";
$qparams[] = $port_info['iif_id'];
}
else
{
- $query .= " WHERE pc.type1 = ? AND ";
+ $query .= " WHERE pc.type1 = ? ";
$qparams[] = $port_info['oif_id'];
}
$query .= "
- pic2.iif_id <> 1
- ) AS sub1 USING (iif_id)
+ ) AS sub1 ON p2.iif_id = sub1.iif_id AND ( p2.iif_id <> 1 OR p2.type = sub1.oif_id )
UNION
SELECT Port.id
FROM Port
@@ -113,42 +110,104 @@ INNER JOIN (
// ordering
$query .= ' ORDER BY o.name';
- $ret = array();
- $result = usePreparedSelectBlade ($query, $qparams);
-
- $rows_by_pn = array();
- $prev_object_id = NULL;
+ return usePreparedSelectBlade ($query, $qparams);
+}
+
+function getLinkPortJavascript($port_info, $ports)
+{
+ $required_oif = array();
+ $required_iif = array();
+ $required_chapter = array();
+ if( count($ports) == 0 ){
+ return '';
+ }
+ $jsports = array();
+ $compat = array();
+ $buffer = array('$(function($){');
+ $buffer[]='var PORT = { id:'.$port_info['id'].', name:"'.addslashes($port_info['name']).'",';
+ $buffer[]=' object_name:"'.addslashes($port_info['object_name']).'",';
+ $buffer[]=' oif_id:'.($port_info['oif_id'] ? $port_info['oif_id'] : 'null').', ';
+ $buffer[]=' iif_id:'.$port_info['iif_id'].', ';
+ $buffer[]=' cable:"'.addslashes($port_info['cableid']).'", ';
+ $buffer[]=' cable_dict_key:'.($port_info['cable_dict_key'] ? $port_info['cable_dict_key'] : 'null' ).', ';
+ $buffer[]=' remote_id:'.($port_info['remote_id'] ? $port_info['remote_id'] : 'null').'};';
+ $buffer[]='var PORTS = [';
- // fetch port rows from the DB
- while (TRUE)
+ $required_iif[$port_info['iif_id']]=true;
+ if( $port_info['oif_id'] ) $required_oif[$port_info['oif_id']]=true;
+ foreach( $ports as $port ){
+ $required_iif[ $port['iif_id'] ]=true;
+ if( $port['oif_id'] ) $required_oif[$port['oif_id']]=true;
+ $buffer[]=' { id:'.$port['id'].', name:"'.addslashes($port['name']).'", object_name:"'.addslashes($port['object_name']).'", oif_id:'.($port['oif_id'] ? $port['oif_id'] : 'null').', iif_id:'.$port['iif_id'].', reservation:"'.addslashes($port['reservation_comment']).'"},';
+ }
+ $buffer[]='];';
+
+ $incom = usePreparedSelectBlade('SELECT * FROM PortInterfaceCompat WHERE iif_id IN ('.questionMarks(count($required_iif)).') ORDER BY iif_id ', array_keys($required_iif));
+ $buffer[]='var INNER_OUTER_COMPATIBILITY = {';
+ $last_iif_id = null;
+ foreach( $incom as $in )
{
- $row = $result->fetch (PDO::FETCH_ASSOC);
- if (isset ($prev_object_id) and (! $row or $row['object_id'] != $prev_object_id))
+ if( $in['iif_id'] != $last_iif_id )
{
- // handle sorted object's portlist
- foreach (sortPortList ($rows_by_pn) as $ports_subarray)
- foreach ($ports_subarray as $port_row)
- {
- $port_description = $port_row['object_name'] . ' -- ' . $port_row['name'];
- if (count ($ports_subarray) > 1)
- {
- $if_type = $port_row['iif_id'] == 1 ? $port_row['oif_name'] : $port_row['iif_name'];
- $port_description .= " ($if_type)";
- }
- if (! empty ($port_row['reservation_comment']))
- $port_description .= ' -- ' . $port_row['reservation_comment'];
- $ret[$port_row['id']] = $port_description;
- }
- $rows_by_pn = array();
+ if( $last_iif_id != null )
+ {
+ $buffer[]=' ],';
+ }
+ $buffer[]=' '.$in['iif_id'].': [';
+ $last_iif_id = $in['iif_id'];
}
- $prev_object_id = $row['object_id'];
- if ($row)
- $rows_by_pn[$row['name']][] = $row;
- else
- break;
+ $required_oif[$in['oif_id']]=true;
+ $buffer[]=' '.$in['oif_id'].',';
}
+ if( $last_iif_id != null )
+ {
+ $buffer[]=' ]';
+ }
+ $buffer[]='};';
- return $ret;
+ $query ='SELECT * FROM PortCompat pc'.
+ ' WHERE type1 IN ('.questionMarks(count($required_oif)).') AND type2 IN ('.questionMarks(count($required_oif)).');';
+ $types = usePreparedSelectBlade($query, array_merge( array_keys($required_oif), array_keys($required_oif) ) );
+ foreach( $types as $type ){
+ @$compat[ $type['type1'] ][ $type['type2'] ] = array( 'cable_chapter_id'=> ($type['cable_chapter_id'] ? intval($type['cable_chapter_id']) : 'null') );
+ if( $type['cable_chapter_id'] ) $required_chapter[intval($type['cable_chapter_id'])] = true;
+ }
+ $buffer[]='var OUTER_COMPATIBILITY = {';
+ foreach( $compat as $a => $sub ){
+ $buffer[]=' '.$a.': { ';
+ foreach( $sub as $b => $info ){
+ $buffer[]=' '.$b.': {cable_chapter_id:'.$info['cable_chapter_id'].'},';
+ }
+ $buffer[]=' },';
+ }
+ $buffer[]='};';
+ if( $required_chapter ){
+ $buffer[]='var CABLES = {';
+ $last_chapter_id = -1;
+ foreach( array_keys($required_chapter) as $chapter_id ){
+ $chapter = cookOptgroups( readChapter( $chapter_id, 'o' ) );
+ $buffer[]= $chapter_id.': [';
+ foreach( $chapter as $group => $entries ){
+ $buffer[]= ' {name: "'.addslashes($group).'", values:[';
+ foreach( $entries as $key => $value ){
+ $buffer[]= ' {key: '.$key.', value: "'.addslashes($value).'"},';
+ }
+ $buffer[]=' ]},';
+ }
+ $buffer[]='],';
+ }
+ $buffer[]='};';
+ }else{
+ $buffer[]='var CABLES = {};';
+ }
+ $oifs = usePreparedSelectBlade('SELECT dict_key,dict_value FROM Dictionary WHERE chapter_id = 2 AND dict_key IN ('.questionMarks(count($required_oif)).');', array_keys($required_oif));
+ $buffer[]='var OIF = {};';
+ foreach( $oifs as $oif ){
+ $buffer[]='OIF['.$oif['dict_key'].']= "'.addslashes($oif['dict_value']).'";';
+ }
+ $buffer[]=' initializeLinkportForm( PORT, PORTS, INNER_OUTER_COMPATIBILITY, OUTER_COMPATIBILITY, CABLES, OIF )';
+ $buffer[]='});';
+ return join("\n",$buffer);
}
// Return a list of all objects which are possible parents
@@ -221,131 +280,66 @@ function renderPopupObjectSelector()
function handlePopupPortLink()
{
+ global $dbxlink;
assertUIntArg ('port');
assertUIntArg ('remote_port');
assertStringArg ('cable', TRUE);
$port_info = getPortInfo ($_REQUEST['port']);
$remote_port_info = getPortInfo ($_REQUEST['remote_port']);
- $POIFC = getPortOIFCompat();
- if (isset ($_REQUEST['port_type']) and isset ($_REQUEST['remote_port_type']))
- {
- $type_local = $_REQUEST['port_type'];
- $type_remote = $_REQUEST['remote_port_type'];
- }
- else
- {
- $type_local = $port_info['oif_id'];
- $type_remote = $remote_port_info['oif_id'];
- }
- $matches = FALSE;
- $js_table = '';
- foreach ($POIFC as $pair)
- if ($pair['type1'] == $type_local && $pair['type2'] == $type_remote)
- {
- $matches = TRUE;
- break;
+ $dbxlink->beginTransaction();
+ try{
+
+ if( $port_info['iif_id'] != 1 ){
+ // updateable
+ assertUIntArg ('local_oif');
+ if( $_POST['local_oif'] != $port_info['oif_id'] ){
+ commitUpdatePortOIF( $port_info['id'], $_POST['local_oif']);
+ $port_info['oif_id'] = intval($_POST['local_oif']);
+ }
}
- else
- $js_table .= "POIFC['${pair['type1']}-${pair['type2']}'] = 1;\n";
-
- if ($matches)
- {
- if ($port_info['oif_id'] != $type_local)
- commitUpdatePortOIF ($port_info['id'], $type_local);
- 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']);
- showSuccess
- (
- sprintf
+ if( $remote_port_info['iif_id'] != 1 ){
+ // updateable
+ assertUIntArg ('remote_oif');
+ if( $_POST['remote_oif'] != $remote_port_info['oif_id'] ){
+ commitUpdatePortOIF( $remote_port_info['id'], $_POST['remote_oif']);
+ $remote_port_info['oif_id'] = intval($_POST['remote_oif']);
+ }
+ }
+ // now check compat
+ $compat = usePreparedSelectBlade('SELECT * FROM PortCompat WHERE ( type1 = ? AND type2 = ? ) OR ( type2 = ? AND type1= ? ) ',
+ array( $port_info['oif_id'],$remote_port_info['oif_id'],$port_info['oif_id'],$remote_port_info['oif_id']) )->fetchAll();
+ if( !$compat ){
+ throw new InvalidRequestArgException('oif_id', '', 'Ports are not compatible');
+ }else{
+ // :)
+ $cable_type = null;
+ if( $compat[0]['cable_chapter_id'] && $_POST['cable_type'] ){
+ assertUIntArg('cable_type',true);
+ $cable_type = $_POST['cable_type'];
+ }
+ linkPorts( $port_info['id'], $remote_port_info['id'], $_POST['cable'], $cable_type, true );
+ $dbxlink->commit();
+ showSuccess
(
+ sprintf
+ (
'Port %s successfully linked with port %s',
formatPortLink ($port_info['id'], $port_info['name'], NULL, NULL),
formatPort ($remote_port_info)
- )
- );
- addJS (<<<END
-window.opener.location.reload(true);
-window.close();
+ )
+ );
+ addJS (<<<END
+ window.opener.location.reload(true);
+ window.close();
END
- , TRUE);
- }
- else
- {
- // JS code to display port compatibility hint
- addJS (<<<END
-POIFC = {};
-$js_table
-$(document).ready(function () {
- $('select.porttype').change(onPortTypeChange);
- onPortTypeChange();
-});
-function onPortTypeChange() {
- var key = $('*[name=port_type]')[0].value + '-' + $('*[name=remote_port_type]')[0].value;
- if (POIFC[key] == 1)
- {
- $('#hint-not-compat').hide();
- $('#hint-compat').show();
- }
- else
- {
- $('#hint-compat').hide();
- $('#hint-not-compat').show();
- }
-}
-END
- , TRUE);
- addCSS (<<<END
-.compat-hint {
- display: none;
- font-size: 125%;
-}
-.compat-hint#hint-compat {
- color: green;
-}
-.compat-hint#hint-not-compat {
- color: #804040;
-}
-END
- , TRUE);
- // render port type editor form
- echo '<form method=GET>';
- echo '<input type=hidden name="module" value="popup">';
- echo '<input type=hidden name="helper" value="portlist">';
- echo '<input type=hidden name="port" value="' . $port_info['id'] . '">';
- echo '<input type=hidden name="remote_port" value="' . $remote_port_info['id'] . '">';
- echo '<input type=hidden name="cable" value="' . htmlspecialchars ($_REQUEST['cable'], ENT_QUOTES) . '">';
- echo '<p>The ports you have selected are not compatible. Please select a compatible transceiver pair.';
- echo '<p>';
- echo formatPort ($port_info) . ' ';
- if ($port_info['iif_id'] == 1)
- {
- echo formatPortIIFOIF ($port_info);
- echo '<input type=hidden name="port_type" value="' . $port_info['oif_id'] . '">';
- }
- else
- {
- echo '<label>' . $port_info['iif_name'] . ' ';
- printSelect (getExistingPortTypeOptions ($port_info['id']), array ('class' => 'porttype', 'name' => 'port_type'), $type_local);
- echo '</label>';
+ , true);
+ return;
}
- echo ' — ';
- if ($remote_port_info['iif_id'] == 1)
- {
- echo formatPortIIFOIF ($remote_port_info);
- echo '<input type=hidden name="remote_port_type" value="' . $remote_port_info['oif_id'] . '">';
- }
- else
- {
- echo '<label>' . $remote_port_info['iif_name'] . ' ';
- printSelect (getExistingPortTypeOptions ($remote_port_info['id']), array ('class' => 'porttype', 'name' => 'remote_port_type'), $type_remote);
- echo '</label>';
- }
- echo ' ' . formatPort ($remote_port_info);
- echo '<p class="compat-hint" id="hint-not-compat">✕ Not compatible port types</p>';
- echo '<p class="compat-hint" id="hint-compat">✔ Compatible port types</p>';
- echo '<p><input type=submit name="do_link" value="Link">';
+ }catch( Exception $e ){
+ $dbxlink->rollBack();
+ throw $e;
}
+ return renderPopupPortSelector();
}
function renderPopupPortSelector()
@@ -353,7 +347,8 @@ function renderPopupPortSelector()
assertUIntArg ('port');
$port_id = $_REQUEST['port'];
$port_info = getPortInfo ($port_id);
- $in_rack = isset ($_REQUEST['in_rack']);
+
+ $in_rack = $_REQUEST['in_rack'] != 'off';;
// fill port filter structure
$filter = array
@@ -379,11 +374,34 @@ function renderPopupPortSelector()
! empty ($filter['objects']) ||
! empty ($filter['ports'])
)
- $spare_ports = findSparePorts ($port_info, $filter);
+ $ports_with_current = $ports = getSparePorts($port_info, $filter)->fetchAll();
+ if( $port_info['linked'] ){
+ $link = usePreparedSelectBlade('SELECT * FROM Link WHERE porta = ? OR portb = ?', array($port_id, $port_id))->fetch(PDO::FETCH_ASSOC);
+
+ $current = getPortInfo( ($link['porta'] == $port_id) ? $link['portb'] : $link['porta'] );
+ $port_info['cableid'] = $current['cableid'] = $link['cable'];
+ $port_info['cable_dict_key'] = $current['cable_dict_key'] = $link['cable_dict_key'];
+ $port_info['remote_id'] = $current['id'];
+ $ports_with_current[] = $current;
+ }
+ addJS('js/link_port_form.js');
+ addJS(getLinkPortJavascript($port_info, $ports_with_current),true);
+ addCSS (<<<'END'
+.reserved {
+ text-decoration: line-through;
+}
+.compatible {
+ background: #afa;
+}
+.incompatible {
+ background: #faa;
+}
+END
+ , TRUE);
// display search form
echo 'Link ' . formatPort ($port_info) . ' to...';
- echo '<form method=GET>';
+ echo '<form method="POST">';
startPortlet ('Port list filter');
echo '<input type=hidden name="module" value="popup">';
echo '<input type=hidden name="helper" value="portlist">';
@@ -391,23 +409,59 @@ function renderPopupPortSelector()
echo '<table align="center" valign="bottom"><tr>';
echo '<td class="tdleft"><label>Object name:<br><input type=text size=8 name="filter-obj" value="' . htmlspecialchars ($filter['objects'], ENT_QUOTES) . '"></label></td>';
echo '<td class="tdleft"><label>Port name:<br><input type=text size=6 name="filter-port" value="' . htmlspecialchars ($filter['ports'], ENT_QUOTES) . '"></label></td>';
- echo '<td class="tdleft" valign="bottom"><label><input type=checkbox name="in_rack"' . ($in_rack ? ' checked' : '') . '>Nearest racks</label></td>';
+ echo '</tr><tr>';
+ echo '<td class="tdleft" valign="bottom"><input type="hidden" name="in_rack" value="off" /><label><input type=checkbox name="in_rack"' . ($in_rack ? ' checked' : '') . '>Nearest racks</label></td>';
echo '<td valign="bottom"><input type=submit value="show ports"></td>';
echo '</tr></table>';
finishPortlet();
// display results
- startPortlet ('Compatible spare ports');
- if (empty ($spare_ports))
- echo '(nothing found)';
- else
- {
- echo getSelect ($spare_ports, array ('name' => 'remote_port', 'size' => getConfigVar ('MAXSELSIZE')), NULL, FALSE);
- echo "<p>Cable ID: <input type=text id=cable name=cable>";
- echo "<p><input type='submit' value='Link' name='do_link'>";
+ startPortlet ('Link port');
+ if( $ports_with_current ){
+ echo '<div style="float: left;width:40%">';
+ echo '<select name="remote_port" id="remote_port" size="',getConfigVar ('MAXSELSIZE'),'" style="width:100%">';
+ if( $current ){
+ echo '<optgroup label="current">';
+ echo '<optgroup label=" ', htmlspecialchars($current['object_name']), '">';
+ echo '<option value="',$current['id'],'" selected="selected">', htmlspecialchars($current['name'] ),'</option>';
+ echo '</optgroup>';
+ }
+ echo '<optgroup label="search result">';
+ if( !$ports ){
+ echo '<option disabled="disabled" value="">nothing found</option>';
+ }else{
+ $ports_by_object = array();
+ foreach( $ports as $port ){
+ if( !isset($ports_by_object[$port['object_name']]) ) $ports_by_object[$port['object_name']] = array();
+ $ports_by_object[$port['object_name']][] = $port;
+ }
+ ksort( $ports_by_object );
+ foreach( $ports_by_object as $name => $object_ports ){
+ echo '<optgroup label=" ', htmlspecialchars($name), '">';
+ foreach( sortPortList($object_ports, true) as $port ){
+ echo '<option value="', $port['id'],'"',($port['reservation_comment'] ? ' class="reserved"':''),'>', htmlspecialchars($port['name']), '</option>';
+ }
+ echo '</optgroup>';
+ }
+ }
+ echo '</optgroup>';
+ echo '</select>';
+ echo '</div>';
+ echo '<div style="margin-left: 41%">';
+ echo '<p style="display:none">This port is reserved: <span id="reservation"></span></p>';
+ echo '<p style="display:none"><label for="cable_type">Local Transceiver</label></br><select name="local_oif" id="local_oif" style="width:100%"></select></p>';
+ echo '<p style="display:none"><label for="remote_oif">Remote Transceiver</label></br><select name="remote_oif" id="remote_oif" style="width:100%"></select></p>';
+ echo '<p style="display:none"><label for="cable_type">Cable type</label></br><select name="cable_type" id="cable_type" style="width:100%"></select></p>';
+ echo '<p><label for="cable">Cable ID: </label><br /><input type="text" id="cable" name="cable" style="width:100%" value="',htmlspecialchars($port_info['cableid']) ,'"/></p>';
+ echo '<p><input type="submit" value="Link" name="do_link" id="submit"></p>';
+ echo '<br style="clear:both" /></div>';
+ }else{
+ echo 'nothing found';
}
+
finishPortlet();
echo '</form>';
+ echo '<br style="clear:both" />';
}
function renderPopupIPv4Selector()
diff --git a/wwwroot/js/link_port_form.js b/wwwroot/js/link_port_form.js
new file mode 100644
index 0000000..0cf45a2
--- /dev/null
+++ b/wwwroot/js/link_port_form.js
@@ -0,0 +1,147 @@
+function initializeLinkportForm( PORT, PORTS, INNER_OUTER_COMPATIBILITY, OUTER_COMPATIBILITY, CABLES, OIF ){
+ var $remote_port = $('#remote_port'),$remote_oif = $('#remote_oif'),$local_oif = $('#local_oif'),$cable_type = $('#cable_type'), $submit = $('#submit'), $reservation = $('#reservation');
+ var compatClass = function(a,b){
+ if( !a || !b ){
+ return '';
+ }else if( !OUTER_COMPATIBILITY[a] || !OUTER_COMPATIBILITY[a][b] ){
+ return 'incompatible';
+ }else{
+ return 'compatible';
+ }
+ }
+ var updateSelects = function(){
+ var rp = $remote_port.val(), ro = $remote_oif.val(), lo = $local_oif.val(), ct = $cable_type.val();
+ if( ro ) ro = parseInt(ro);
+ if( !lo ){
+ lo = PORT.oif_id;
+ }else{
+ lo = parseInt(lo);
+ }
+ if( !rp ){
+ rp = PORT.remote_id;
+ }
+ if( !ct ){
+ ct = PORT.cable_dict_key;
+ }
+ //remote_oif
+ $remote_oif.empty();
+ var remote_port;
+ if( rp ){
+ remote_port = $.grep(PORTS,function(p){ return p.id == rp })[0];
+ if( !ro || remote_port.iif_id == 1 || INNER_OUTER_COMPATIBILITY[ remote_port.iif_id ].indexOf(ro) == -1 ){
+ ro = remote_port.oif_id;
+ }
+ if( remote_port.reservation == "" ){
+ $reservation.closest('p').hide();
+ }else{
+ $reservation.text( remote_port.reservation );
+ $reservation.closest('p').show();
+ }
+ if( remote_port.iif_id != 1 ){
+ $remote_oif.closest('p').show();
+ $remote_oif.attr('disabled',false);
+ }else{
+ $remote_oif.closest('p').hide();
+ $remote_oif.attr('disabled',true);
+ }
+ var rps = INNER_OUTER_COMPATIBILITY[ remote_port.iif_id ];
+ rps.sort(function(a,b){
+ return OIF[a].localeCompare(OIF[b]);
+ }).forEach( function(oif){
+ $('<option>').val(oif).text( OIF[oif] ).addClass( compatClass( oif, lo ) ).appendTo($remote_oif);
+ });
+ $remote_oif.val(ro);
+ }else{
+ $remote_oif.closest('p').hide();
+ $remote_oif.attr('disabled',true);
+ }
+ //local_oif
+ $local_oif.empty();
+ if( PORT.iif_id != 1 ){
+ $local_oif.closest('p').show();
+ $local_oif.attr('disabled',false);
+ }else{
+ $local_oif.closest('p').hide();
+ $local_oif.attr('disabled',true);
+ }
+ var lps = INNER_OUTER_COMPATIBILITY[ PORT.iif_id ];
+ lps.sort(function(a,b){
+ return OIF[a].localeCompare(OIF[b]);
+ }).forEach( function(oif){
+ $('<option>').val(oif).text( OIF[oif] ).addClass( compatClass( oif, ro ) ).appendTo($local_oif);
+ });
+ $local_oif.val(lo);
+ if( rp && lo && ro ){
+ // cables and compat!
+ var comb = OUTER_COMPATIBILITY[ ro ] ? OUTER_COMPATIBILITY[ ro ][ lo ] : null;
+ if( !comb ){
+ $submit.attr('disabled',true);
+ $submit.val('Incompatible transceiver');
+ $cable_type.closest('p').hide();
+ }else{
+ if( comb.cable_chapter_id ){
+ $cable_type.empty();
+ var cables = CABLES[comb.cable_chapter_id];
+ if( cables ){
+ var other;
+ $.each(cables,function(i,group){
+ if( group.name == 'other' ){
+ other = group;
+ return ;
+ }
+ var g = $('<optgroup>').attr('label',group.name).appendTo($cable_type);
+ $.each(group.values, function(j, opt){
+ $('<option>').val(opt.key).text(opt.value).appendTo(g);
+ });
+ });
+ if( other ){
+ $.each(other.values, function(j, opt){
+ $('<option>').val(opt.key).text(opt.value).appendTo($cable_type);
+ });
+ }
+ }
+ $('<option>').val('').text('').appendTo($cable_type);
+ $cable_type.val(ct);
+ $cable_type.closest('p').show();
+ }else{
+ // compatible but no cables
+ $cable_type.closest('p').hide();
+ }
+ $submit.attr('disabled',false);
+ $submit.val('Link');
+ }
+ }else{
+ if( !rp ){
+ $submit.attr('disabled',true);
+ $submit.val('Select a port');
+ }
+ $cable_type.closest('p').hide();
+ }
+ }
+ updateSelects();
+ $remote_port.change(updateSelects);
+ var changeTransceiver = function( $a, $b ){
+ var av = $a.val();
+ var bv = $b.val();
+ if( !OUTER_COMPATIBILITY[av] ){
+ return ;
+ }
+ if( OUTER_COMPATIBILITY[av][bv] ){
+ return;
+ }
+ $b.children('option').each(function(i,o ){
+ if( OUTER_COMPATIBILITY[ av ][ $(o).val() ] ){
+ $b.val( $(o).val() );
+ return false;
+ }
+ });
+ }
+ $local_oif.change(function(){
+ changeTransceiver($local_oif,$remote_oif);
+ updateSelects();
+ });
+ $remote_oif.change(function(){
+ changeTransceiver($remote_oif,$local_oif);
+ updateSelects();
+ });
+}
| ||||
|
Hi, I made good progress. The biggest changes happened to the link-port form. This was necessary, to keep the numbers of additional clicks low. Furthermore you can now select transceivers without submitting the form. Cheers! Hannes |
|
| Hannes, I will review the patch and update this issue. | |
| Nice! When you are done, I'll backport this to 0.19.13. | |
|
Hi, I just backported the feature on top of the 0.19.13 release. Cheers! |
|
| Sorry, I forgot to check "nearest rack" by default. Corrected this. | |
| Aaron, these changes would conflict with the patch panels code but there are good points in this work that should be considered. I have reassigned this issue to you. | |
| Re-assigning to infrastation since he added the "Patch cables" feature. | |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2012-04-12 11:46 |
|
New Issue | |
| 2012-04-19 10:40 |
|
File Added: track_cable_type.patch | |
| 2012-04-19 10:51 |
|
File Added: track_cable_type.sql | |
| 2012-04-19 10:55 |
|
Note Added: 0000657 | |
| 2012-04-22 08:10 | infrastation | Note Added: 0000661 | |
| 2012-04-22 08:10 | infrastation | Status | new => acknowledged |
| 2012-04-23 08:16 |
|
Note Added: 0000665 | |
| 2012-07-02 13:32 |
|
File Added: track_cable_type_0.19.13.diff | |
| 2012-07-02 13:33 |
|
Note Added: 0000699 | |
| 2012-07-03 07:12 |
|
File Added: track_cable_type_0.19.13.correct.diff | |
| 2012-07-03 07:12 |
|
Note Added: 0000700 | |
| 2012-08-23 14:34 | infrastation | Assigned To | => infrastation |
| 2012-08-23 14:34 | infrastation | Status | acknowledged => assigned |
| 2013-11-27 13:03 | infrastation | Relationship added | child of 333 |
| 2013-11-27 13:03 | infrastation | Assigned To | infrastation => adoom42 |
| 2013-11-27 13:05 | infrastation | Note Added: 0001989 | |
| 2015-06-11 03:59 | adoom42 | Note Added: 0002853 | |
| 2015-06-11 03:59 | adoom42 | Assigned To | adoom42 => infrastation |