function handlePopupPortLink() { assertPermission('depot', 'default'); 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; } 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']); // patch cable? if (array_key_exists('heap_id', $_REQUEST)) { // Leave the compatibility constraints check up to the foreign keys. if (0 != ($heap_id = genericAssertion('heap_id', 'uint0'))) { $heaps = getPatchCableHeapSummary(); if (commitModifyPatchCableAmount($heap_id, -1)) { showSuccess('consumed a patch cable from ' . formatPatchCableHeapAsPlainText($heaps[$heap_id])); } else { showError('failed to consume a patch cable'); } } } showOneLiner(8, array(formatPortLink($port_info['object_id'], NULL, $port_info['id'], $port_info['name']), formatPort($remote_port_info))); addJS(<<<END window.opener.location.reload(true); window.close(); END , TRUE); backupLogMessages(); } else { // JS code to display port compatibility hint addJS(<<<END POIFC = {}; {$js_table} \$(document).ready(function () { \t\$('select.porttype').change(onPortTypeChange);\t \tonPortTypeChange(); }); function onPortTypeChange() { \tvar key = \$('*[name=port_type]')[0].value + '-' + \$('*[name=remote_port_type]')[0].value; \tif (POIFC[key] == 1) \t{ \t\t\$('#hint-not-compat').hide(); \t\t\$('#hint-compat').show(); \t} \telse \t{ \t\t\$('#hint-compat').hide(); \t\t\$('#hint-not-compat').show(); \t} } END , TRUE); addCSS(<<<END .compat-hint { \tdisplay: none; \tfont-size: 125%; } .compat-hint#hint-compat { \tcolor: green; } .compat-hint#hint-not-compat { \tcolor: #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), array('class' => 'porttype', 'name' => 'port_type'), $type_local); echo '</label>'; } 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), 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">'; } }
function renderDiscoveredNeighbors($object_id) { global $tabno; $opcode_by_tabno = array('livecdp' => 'getcdpstatus', 'livelldp' => 'getlldpstatus'); try { $neighbors = queryDevice($object_id, $opcode_by_tabno[$tabno]); $neighbors = sortPortList($neighbors); } catch (RTGatewayError $e) { showError($e->getMessage()); return; } $mydevice = spotEntity('object', $object_id); amplifyCell($mydevice); // reindex by port name $myports = array(); foreach ($mydevice['ports'] as $port) { if (mb_strlen($port['name'])) { $myports[$port['name']][] = $port; } } // scroll to selected port if (isset($_REQUEST['hl_port_id'])) { assertUIntArg('hl_port_id'); $hl_port_id = intval($_REQUEST['hl_port_id']); addAutoScrollScript("port-{$hl_port_id}"); } switchportInfoJS($object_id); // load JS code to make portnames interactive printOpFormIntro('importDPData'); echo '<br><table cellspacing=0 cellpadding=5 align=center class=widetable>'; echo '<tr><th colspan=2>local port</th><th></th><th>remote device</th><th colspan=2>remote port</th><th><input type="checkbox" checked id="cb-toggle"></th></tr>'; $inputno = 0; foreach ($neighbors as $local_port => $remote_list) { $initial_row = TRUE; // if port has multiple neighbors, the first table row is initial // array of local ports with the name specified by DP $local_ports = isset($myports[$local_port]) ? $myports[$local_port] : array(); foreach ($remote_list as $dp_neighbor) { $error_message = NULL; $link_matches = FALSE; $portinfo_local = NULL; $portinfo_remote = NULL; $variants = array(); do { // once-cyle fake loop used only to break out of it if (!empty($local_ports)) { $portinfo_local = $local_ports[0]; } // find remote object by DP information $dp_remote_object_id = searchByMgmtHostname($dp_neighbor['device']); if (!$dp_remote_object_id) { $dp_remote_object_id = lookupEntityByString('object', $dp_neighbor['device']); } if (!$dp_remote_object_id) { $error_message = "No such neighbor <i>{$dp_neighbor['device']}</i>"; break; } $dp_remote_object = spotEntity('object', $dp_remote_object_id); amplifyCell($dp_remote_object); $dp_neighbor['port'] = shortenIfName($dp_neighbor['port'], NULL, $dp_remote_object['id']); // get list of ports that have name matching CDP portname $remote_ports = array(); // list of remote (by DP info) ports foreach ($dp_remote_object['ports'] as $port) { if ($port['name'] == $dp_neighbor['port']) { $portinfo_remote = $port; $remote_ports[] = $port; } } // check if ports with such names exist on devices if (empty($local_ports)) { $error_message = "No such local port <i>{$local_port}</i>"; break; } if (empty($remote_ports)) { $error_message = "No such port on " . formatPortLink($dp_remote_object['id'], $dp_remote_object['name'], NULL, NULL); break; } // determine match or mismatch of local link foreach ($local_ports as $portinfo_local) { if ($portinfo_local['remote_id']) { if ($portinfo_local['remote_object_id'] == $dp_remote_object_id and $portinfo_local['remote_name'] == $dp_neighbor['port']) { // set $portinfo_remote to corresponding remote port foreach ($remote_ports as $portinfo_remote) { if ($portinfo_remote['id'] == $portinfo_local['remote_id']) { break; } } $link_matches = TRUE; unset($error_message); } elseif ($portinfo_local['remote_object_id'] != $dp_remote_object_id) { $error_message = "Remote device mismatch - port linked to " . formatLinkedPort($portinfo_local); } else { // ($portinfo_local['remote_name'] != $dp_neighbor['port']) $error_message = "Remote port mismatch - port linked to " . formatPortLink($portinfo_local['remote_object_id'], NULL, $portinfo_local['remote_id'], $portinfo_local['remote_name']); } break 2; } } // no local links found, try to search for remote links foreach ($remote_ports as $portinfo_remote) { if ($portinfo_remote['remote_id']) { $remote_link_html = formatLinkedPort($portinfo_remote); $remote_port_html = formatPortLink($portinfo_remote['object_id'], NULL, $portinfo_remote['id'], $portinfo_remote['name']); $error_message = "Remote port {$remote_port_html} is already linked to {$remote_link_html}"; break 2; } } // no links found on both sides, search for a compatible port pair $port_types = array(); foreach (array('left' => $local_ports, 'right' => $remote_ports) as $side => $port_list) { foreach ($port_list as $portinfo) { $tmp_types = $portinfo['iif_id'] == 1 ? array($portinfo['oif_id'] => $portinfo['oif_name']) : getExistingPortTypeOptions($portinfo['id']); foreach ($tmp_types as $oif_id => $oif_name) { $port_types[$side][$oif_id][] = array('id' => $oif_id, 'name' => $oif_name, 'portinfo' => $portinfo); } } } foreach ($port_types['left'] as $left_id => $left) { foreach ($port_types['right'] as $right_id => $right) { if (arePortTypesCompatible($left_id, $right_id)) { foreach ($left as $left_port) { foreach ($right as $right_port) { $variants[] = array('left' => $left_port, 'right' => $right_port); } } } } } if (!count($variants)) { // no compatible ports found $error_message = "Incompatible port types"; } } while (FALSE); // do { $tr_class = $link_matches ? 'trok' : (isset($error_message) ? 'trerror' : 'trwarning'); echo "<tr class=\"{$tr_class}\">"; if ($initial_row) { $count = count($remote_list); $td_class = ''; if (isset($hl_port_id) and $hl_port_id == $portinfo_local['id']) { $td_class = "class='border_highlight'"; } echo "<td rowspan=\"{$count}\" {$td_class} NOWRAP>" . ($portinfo_local ? formatPortLink($mydevice['id'], NULL, $portinfo_local['id'], $portinfo_local['name'], 'interactive-portname port-menu') : "<a class='interactive-portname port-menu nolink'>{$local_port}</a>") . ($count > 1 ? "<br> ({$count} neighbors)" : '') . '</td>'; $initial_row = FALSE; } echo "<td>" . ($portinfo_local ? formatPortIIFOIF($portinfo_local) : ' ') . "</td>"; echo "<td>" . formatIfTypeVariants($variants, "ports_{$inputno}") . "</td>"; echo "<td>{$dp_neighbor['device']}</td>"; echo "<td>" . ($portinfo_remote ? formatPortLink($dp_remote_object_id, NULL, $portinfo_remote['id'], $portinfo_remote['name']) : $dp_neighbor['port']) . "</td>"; echo "<td>" . ($portinfo_remote ? formatPortIIFOIF($portinfo_remote) : ' ') . "</td>"; echo "<td>"; if (!empty($variants)) { echo "<input type=checkbox name=do_{$inputno} class='cb-makelink'>"; $inputno++; } echo "</td>"; if (isset($error_message)) { echo "<td style=\"background-color: white; border-top: none\">{$error_message}</td>"; } echo "</tr>"; } } if ($inputno) { echo "<input type=hidden name=nports value={$inputno}>"; echo '<tr><td colspan=7 align=center>' . getImageHREF('CREATE', 'import selected', TRUE) . '</td></tr>'; } echo '</table></form>'; addJS(<<<END \$(document).ready(function () { \t\$('#cb-toggle').click(function (event) { \t\tvar list = \$('.cb-makelink'); \t\tfor (var i in list) { \t\t\tvar cb = list[i]; \t\t\tcb.checked = event.target.checked; \t\t} \t}).triggerHandler('click'); }); END , TRUE); }