printf 'term len 0\nshow run\n! END OF CONFIG\nshow vlan brief\n! END OF VLAN LIST\n' >> "$SESSION"
outfile="$WORKFILE"
;;
+getcdpstatus)
+ printf 'term len 0\nshow cdp neighbors detail\n' >> "$SESSION"
+ outfile="$WORKFILE"
+ ;;
deploy)
cat "$WORKFILE" >> "$SESSION"
outfile=/dev/null
echo 'ERR!too few arguments to connect'
return
fi
+ if [ "$command" = "getcdpstatus" and "$handler" != "ios12" ]; then
+ echo 'ERR!getcdpstatus only works for ios12'
+ return
+ fi
[ -x "$MYDIR/$handler.connector" ] || {
echo "ERR!Handler '$handler' is not available"
exit 1
while read cmd args; do
case $cmd in
- retrieve|deploy)
+ retrieve|deploy|getcdpstatus)
do_work $cmd $args
;;
*)
}
// This function returns either port ID or NULL for specified arguments.
-// This function returns either port ID or NULL for specified arguments.
-function getPortID ($object_id, $port_name)
+function getPortIDs ($object_id, $port_name)
{
- $query = "select id from Port where object_id=${object_id} and name='${port_name}' limit 2";
- $result = useSelectBlade ($query);
+ $ret = array();
+ $result = usePreparedSelectBlade ('SELECT id FROM Port WHERE object_id = ? AND name = ?', array ($object_id, $port_name));
+ while ($row = $result->fetch (PDO::FETCH_ASSOC))
+ $ret[] = $row['id'];
+ return $ret;
+}
+
+// Search in "FQDN" attribute only, and return object ID, when there is exactly
+// one result found (and NULL in any other case).
+function searchByMgmtHostname ($string)
+{
+ $result = usePreparedSelectBlade ('SELECT object_id FROM AttributeValue WHERE attr_id = 3 AND string_value = ? LIMIT 2', array ($string));
$rows = $result->fetchAll (PDO::FETCH_NUM);
if (count ($rows) != 1)
return NULL;
- $ret = $rows[0][0];
- $result->closeCursor();
- return $ret;
+ return $rows[0][0];
}
function commitCreateUserAccount ($username, $realname, $password)
return $ret;
}
+// map interface name
+function ios12ShortenIfName ($ifname)
+{
+ $ifname = preg_replace ('@^Ethernet(.+)$@', 'et\\1', $ifname);
+ $ifname = preg_replace ('@^FastEthernet(.+)$@', 'fa\\1', $ifname);
+ $ifname = preg_replace ('@^GigabitEthernet(.+)$@', 'gi\\1', $ifname);
+ $ifname = preg_replace ('@^TenGigabitEthernet(.+)$@', 'te\\1', $ifname);
+ $ifname = preg_replace ('@^Port-channel(.+)$@', 'po\\1', $ifname);
+ return $ifname;
+}
+
function ios12ScanTopLevel (&$work, $line)
{
$matches = array();
switch (TRUE)
{
case (preg_match ('@^interface ((Ethernet|FastEthernet|GigabitEthernet|TenGigabitEthernet|Port-channel)[[:digit:]]+(/[[:digit:]]+)*)$@', $line, $matches)):
- // map interface name
- $matches[1] = preg_replace ('@^Ethernet(.+)$@', 'et\\1', $matches[1]);
- $matches[1] = preg_replace ('@^FastEthernet(.+)$@', 'fa\\1', $matches[1]);
- $matches[1] = preg_replace ('@^GigabitEthernet(.+)$@', 'gi\\1', $matches[1]);
- $matches[1] = preg_replace ('@^TenGigabitEthernet(.+)$@', 'te\\1', $matches[1]);
- $matches[1] = preg_replace ('@^Port-channel(.+)$@', 'po\\1', $matches[1]);
- $work['current'] = array ('port_name' => $matches[1]);
+ $work['current'] = array ('port_name' => ios12ShortenIfName ($matches[1]));
return 'ios12PickSwitchportCommand'; // switch to interface block reading
case (preg_match ('/^VLAN Name Status Ports$/', $line, $matches)):
return 'ios12PickVLANCommand';
return $ret;
}
+// Read provided output of "show cdp neighbors detail" command and
+// return a list of records with (translated) local port name,
+// remote device name and (translated) remote port name.
+function ios12ReadCDPStatus ($input)
+{
+ $ret = array();
+ $procfunc = 'ios12ScanCDPTopLevel';
+ foreach (explode ("\n", $input) as $line)
+ $procfunc = $procfunc ($ret, $line);
+ unset ($ret['current']);
+ return $ret;
+}
+
+function ios12ScanCDPTopLevel (&$work, $line)
+{
+ $matches = array();
+ switch (TRUE)
+ {
+ case preg_match ('/^Device ID: (.+)$/', $line, $matches):
+ $work['current'] = array ('remote_device' => $matches[1]);
+ return 'ios12ScanCDPEntry';
+ default:
+ return __FUNCTION__; // continue scan
+ }
+}
+
+function ios12ScanCDPEntry (&$work, $line)
+{
+ if (preg_match ('/^-+$/', $line))
+ {
+ if
+ (
+ array_key_exists ('local_port', $work['current']) and
+ array_key_exists ('remote_port', $work['current'])
+ )
+ $work[$work['current']['local_port']] = array
+ (
+ 'device' => $work['current']['remote_device'],
+ 'port' => $work['current']['remote_port'],
+ );
+ unset ($work['current']);
+ return 'ios12ScanCDPTopLevel';
+ }
+ $matches = array();
+ switch (TRUE)
+ {
+ case preg_match ('/^Interface: (.+), Port ID \(outgoing port\): (.+)$/', $line, $matches):
+ $work['current']['local_port'] = ios12ShortenIfName ($matches[1]);
+ $work['current']['remote_port'] = ios12ShortenIfName ($matches[2]);
+ break;
+ default:
+ }
+ return __FUNCTION__;
+}
+
// Return TRUE, if every value of A1 is present in A2 and vice versa,
// regardless of each array's sort order and indexing.
function array_values_same ($a1, $a2)
return $ret;
}
+function formatPortIIFOIF ($port)
+{
+ $ret = '';
+ if ($port['iif_id'] != 1)
+ $ret .= $port['iif_name'] . '/';
+ $ret .= $port['oif_name'];
+ return $ret;
+}
+
?>
'vrp53' => 'vrp53ReadVLANConfig',
'nxos4' => 'nxos4Read8021QConfig',
);
- $ret = $reader[$breed] (dos2unix (gwRetrieveDeviceConfig ($object_id, $breed)));
+ $ret = $reader[$breed] (dos2unix (gwRetrieveDeviceConfig ($object_id, $breed, 'retrieve')));
// Once there is no default VLAN in the parsed data, it means
// something else was parsed instead of config text.
if (!in_array (VLAN_DFL_ID, $ret['vlanlist']))
return $ret;
}
+function getRunningCDPStatus ($object_id)
+{
+ if ('' == $breed = detectDeviceBreed ($object_id))
+ throw new RuntimeException ('cannot pick handler for this device');
+ return ios12ReadCDPStatus (dos2unix (gwRetrieveDeviceConfig ($object_id, $breed, 'getcdpstatus')));
+}
+
function setDevice8021QConfig ($object_id, $pseudocode)
{
if ('' == $breed = detectDeviceBreed ($object_id))
gwDeployDeviceConfig ($object_id, $breed, unix2dos ($xlator[$breed] ($pseudocode)));
}
-function gwRetrieveDeviceConfig ($object_id, $breed)
+function gwRetrieveDeviceConfig ($object_id, $breed, $command = 'retrieve')
{
$objectInfo = spotEntity ('object', $object_id);
$endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
$outputlines = queryGateway
(
'deviceconfig',
- array ("retrieve ${endpoint} ${breed} ${tmpfilename}")
+ array ("${command} ${endpoint} ${breed} ${tmpfilename}")
);
$configtext = file_get_contents ($tmpfilename);
unlink ($tmpfilename);
if ($hl_port_id == $port['id'])
echo ' class=port_highlight';
echo "><td class=tdleft>${port['name']}</td><td class=tdleft>${port['label']}</td><td class=tdleft>";
- if ($port['iif_id'] != 1)
- echo $port['iif_name'] . '/';
- echo $port['oif_name'] . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
+ echo formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
if ($port['remote_object_id'])
{
$remote_object = spotEntity ('object', $port['remote_object_id']);
else
{
echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
- if ($port['iif_id'] != 1)
- echo $port['iif_name'] . '/';
- echo "${port['oif_name']}</td>\n";
+ echo formatPortIIFOIF ($port) . '</td>';
}
// 18 is enough to fit 6-byte MAC address in its longest form,
// while 24 should be Ok for WWN
foreach ($object['ports'] as $port)
if (mb_strlen ($port['name']) and array_key_exists ($port['name'], $desired_config))
{
- $socket = array ('interface' => ($port['iif_id'] == 1 ? '' : $port['iif_name'] . '/') . $port['oif_name']);
+ $socket = array ('interface' => formatPortIIFOIF ($port));
if ($port['remote_object_id'])
{
$remote_object = spotEntity ('object', $port['remote_object_id']);
echo '</table>';
}
+function renderLiveCDP ($object_id)
+{
+ $CDP_status = getRunningCDPStatus ($object_id);
+ uksort ($CDP_status, 'sortTokenize');
+ $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;
+ unset ($mydevice);
+ printOpFormIntro ('importCDPData');
+ echo '<br><table cellspacing=0 cellpadding=5 align=center class=widetable>';
+ echo '<tr><th colspan=2>local port</th><th>remote device</th><th colspan=2>remote port</th><th> </th></tr>';
+ $inputno = 0;
+ foreach ($CDP_status as $local_port => $remote)
+ {
+ if
+ (
+ !array_key_exists ($local_port, $myports) or
+ NULL === $remote_id = searchByMgmtHostname ($remote['device']) or
+ !count ($remote_port_ids = getPortIDs ($remote_id, $remote['port']))
+ )
+ {
+ echo "<tr class=trerror><td>${local_port}</td><td> </td>";
+ echo "<td>${remote['device']}</td>";
+ echo "<td>${remote['port']}</td><td> </td>";
+ echo "<td> </td></tr>";
+ continue;
+ }
+ // Link already installed?
+ foreach ($myports[$local_port] as $socket)
+ if (in_array ($socket['remote_id'], $remote_port_ids))
+ {
+ echo "<tr class=trok><td>${local_port}</td><td>";
+ echo formatPortIIFOIF ($socket) . "</td>";
+ echo "<td>${remote['device']}</td>";
+ echo "<td>${remote['port']}</td><td>";
+ echo formatPortIIFOIF (getPortInfo ($socket['remote_id'])) . "</td>";
+ echo "<td> </td></tr>";
+ continue 2;
+ }
+ $local_options = $remote_options = array();
+ foreach ($myports[$local_port] as $port)
+ $local_options[$port['id']] = formatPortIIFOIF ($port);
+ foreach ($remote_port_ids as $remote_port_id)
+ $remote_options[$remote_port_id] = formatPortIIFOIF (getPortInfo ($remote_port_id));
+ echo "<tr class=trwarning><td>${local_port}</td><td>";
+ printSelect ($local_options, array ('name' => "pid2_${inputno}"));
+ echo "</td><td>${remote['device']}</td>";
+ echo "<td>${remote['port']}</td><td>";
+ printSelect ($remote_options, array ('name' => "pid2_${inputno}"));
+ echo "</td><td><input type=checkbox name=do_${inputno}></td></tr>";
+ $inputno++;
+ }
+ if ($inputno)
+ {
+ echo "<input type=hidden name=nports value=${inputno}>";
+ echo '<tr><td colspan=6 align=center>' . getImageHREF ('CREATE', 'import selected', TRUE) . '</td></tr>';
+ }
+ echo '</table></form>';
+}
+
?>
$tab['object']['ipv4'] = 'IPv4';
$tab['object']['nat4'] = 'NATv4';
$tab['object']['livevlans'] = 'Live VLANs';
+$tab['object']['livecdp'] = '[Live CDP]';
$tab['object']['snmpportfinder'] = 'SNMP sync';
$tab['object']['editrspvs'] = 'RS pools';
$tab['object']['lvsconfig'] = 'keepalived.conf';
$tabhandler['object']['ipv4'] = 'renderIPv4ForObject';
$tabhandler['object']['nat4'] = 'renderNATv4ForObject';
$tabhandler['object']['livevlans'] = 'renderVLANMembership';
+$tabhandler['object']['livecdp'] = 'renderLiveCDP';
$tabhandler['object']['snmpportfinder'] = 'renderSNMPPortFinder';
$tabhandler['object']['lvsconfig'] = 'renderLVSConfig';
$tabhandler['object']['autoports'] = 'renderAutoPortsForm';
$trigger['object']['ipv4'] = 'trigger_ipv4';
$trigger['object']['nat4'] = 'trigger_natv4';
$trigger['object']['livevlans'] = 'trigger_livevlans';
+$trigger['object']['livecdp'] = 'trigger_LiveCDP';
$trigger['object']['snmpportfinder'] = 'trigger_snmpportfinder';
$trigger['object']['editrspvs'] = 'trigger_isloadbalancer';
$trigger['object']['lvsconfig'] = 'trigger_isloadbalancer';
$ophandler['object']['nat4']['delNATv4Rule'] = 'delPortForwarding';
$ophandler['object']['nat4']['updNATv4Rule'] = 'updPortForwarding';
$ophandler['object']['livevlans']['setPortVLAN'] = 'setPortVLAN';
+$ophandler['object']['livecdp']['importCDPData'] = 'importCDPData';
$ophandler['object']['autoports']['generate'] = 'generateAutoPorts';
$ophandler['object']['tags']['saveTags'] = 'saveEntityTags';
$ophandler['object']['files']['addFile'] = 'addFileToEntity';
$added_count = $updated_count = $error_count = 0;
foreach ($ports as $port)
{
- $port_id = getPortID ($object_id, $port['name']);
- if ($port_id === NULL)
+ $port_ids = getPortIDs ($object_id, $port['name']);
+ if (!count ($port_ids))
{
$result = commitAddPort ($object_id, $port['name'], $port_type, $port['label'], $port['l2address']);
if ($result == '')
else
$error_count++;
}
- else
+ elseif (count ($port_ids) == 1) // update only single-socket ports
{
- $result = commitUpdatePort ($object_id, $port_id, $port['name'], $port_type, $port['label'], $port['l2address']);
+ $result = commitUpdatePort ($object_id, $port_ids[0], $port['name'], $port_type, $port['label'], $port['l2address']);
if ($result == '')
$updated_count++;
else
return $vswitch['out_of_sync'] == 'yes' ? 'attn' : 'std';
}
+function trigger_LiveCDP ()
+{
+ return 'ios12' == detectDeviceBreed ($_REQUEST['object_id']) ? 'std' : '';
+}
+
?>