r3906 merge another set of tested changes from maintenance
authorDenis Ovsienko <infrastation@yandex.ru>
Tue, 13 Jul 2010 10:17:34 +0000 (10:17 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Tue, 13 Jul 2010 10:17:34 +0000 (10:17 +0000)
ChangeLog
inc/database.php
inc/gateways.php
inc/interface.php

index affa597..7e46282 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
 0.18.4
        bugfix: a race condition could be triggered in permissions editor
        new feature: "any mode" of user port in VLAN switch template
+       new feature: LLDP support for VRP 5.50 software
        update: improved error handling code
        update: fixes in 802.1Q
 0.18.3 2010-06-15
index 0e6abb7..90bf310 100644 (file)
@@ -3853,4 +3853,20 @@ function getIPv4Network8021QBindings ($ipv4net_id)
        return $prepared->fetchAll (PDO::FETCH_ASSOC);
 }
 
+// Return entity ID, if its 'name' column equals to provided string, or NULL otherwise (nothing
+// found or more, than one row returned by query due to some odd reason).
+function lookupEntityByString ($realm, $value, $column = 'name')
+{
+       global $SQLSchema;
+       if (!isset ($SQLSchema[$realm]))
+               throw new InvalidArgException ('realm', $realm);
+       $SQLinfo = $SQLSchema[$realm];
+       $query = "SELECT ${SQLinfo['keycolumn']} AS id FROM ${SQLinfo['table']} WHERE ${SQLinfo['table']}.${column}=? LIMIT 2";
+       $result = usePreparedSelectBlade ($query, array ($value));
+       $rows = $result->fetchAll (PDO::FETCH_ASSOC);   
+       if (count ($rows) != 1)
+               return NULL;
+       return $rows[0]['id'];
+}
+
 ?>
index 68afed7..2d8c09a 100644 (file)
@@ -24,6 +24,7 @@ $gwrxlator['getlldpstatus'] = array
 (
        'xos12' => 'xos12ReadLLDPStatus',
        'vrp53' => 'vrp53ReadLLDPStatus',
+       'vrp55' => 'vrp55ReadLLDPStatus',
 );
 $gwrxlator['get8021q'] = array
 (
@@ -230,13 +231,18 @@ function gwSendFile ($endpoint, $handlername, $filetext = array())
                }
                $command .= " ${name}";
        }
-       $outputlines = queryGateway
-       (
-               'sendfile',
-               array ($command)
-       );
-       foreach ($tmpnames as $name)
-               unlink ($name);
+       try
+       {
+               queryGateway ('sendfile', array ($command));
+               foreach ($tmpnames as $name)
+                       unlink ($name);
+       }
+       catch (RTGatewayError $e)
+       {
+               foreach ($tmpnames as $name)
+                       unlink ($name);
+               throw $e;
+       }
 }
 
 // Query something through a gateway and get some text in return. Return that text.
@@ -245,17 +251,19 @@ function gwRecvFile ($endpoint, $handlername, &$output)
        global $remote_username;
        $tmpfilename = tempnam ('', 'RackTables-sendfile-');
        $endpoint = str_replace (' ', '\ ', $endpoint); // the gateway dispatcher uses read (1) to assign arguments
-       $outputlines = queryGateway
-       (
-               'sendfile',
-               array ("submit ${remote_username} ${endpoint} ${handlername} ${tmpfilename}")
-       );
-       $output = file_get_contents ($tmpfilename);
-       unlink ($tmpfilename);
+       try
+       {
+               queryGateway ('sendfile', array ("submit ${remote_username} ${endpoint} ${handlername} ${tmpfilename}"));
+               $output = file_get_contents ($tmpfilename);
+               unlink ($tmpfilename);
+       }
+       catch (RTGatewayError $e)
+       {
+               unlink ($tmpfilename);
+               throw $e;
+       }
        if ($output === FALSE)
                throw new RTGatewayError ('failed to read temporary file');
-       // Being here means having 'OK!' in the response.
-       return oneLiner (66, array ($handlername)); // ignore provided "Ok" text
 }
 
 function gwSendFileToObject ($object_id = 0, $handlername, $filetext = '')
@@ -281,7 +289,7 @@ function gwRecvFileFromObject ($object_id = 0, $handlername, &$output)
        if (count ($endpoints) > 1)
                return oneLiner (162); // can't pick an address
        $endpoint = str_replace (' ', '+', $endpoints[0]);
-       return gwRecvFile ($endpoint, $handlername, $output);
+       gwRecvFile ($endpoint, $handlername, $output);
 }
 
 function detectDeviceBreed ($object_id)
@@ -339,13 +347,17 @@ function gwRetrieveDeviceConfig ($object_id, $command)
                throw new RTGatewayError ('cannot pick management address');
        $endpoint = str_replace (' ', '\ ', str_replace (' ', '+', $endpoints[0]));
        $tmpfilename = tempnam ('', 'RackTables-deviceconfig-');
-       $outputlines = queryGateway
-       (
-               'deviceconfig',
-               array ("${command} ${endpoint} ${breed} ${tmpfilename}")
-       );
-       $configtext = file_get_contents ($tmpfilename);
-       unlink ($tmpfilename);
+       try
+       {
+               queryGateway ('deviceconfig', array ("${command} ${endpoint} ${breed} ${tmpfilename}"));
+               $configtext = file_get_contents ($tmpfilename);
+               unlink ($tmpfilename);
+       }
+       catch (RTGatewayError $e)
+       {
+               unlink ($tmpfilename);
+               throw $e;
+       }
        if ($configtext === FALSE)
                throw new RTGatewayError ('failed to read temporary file');
        // Being here means it was alright.
@@ -369,12 +381,16 @@ function gwDeployDeviceConfig ($object_id, $breed, $text)
                unlink ($tmpfilename);
                throw new RTGatewayError ('failed to write to temporary file');
        }
-       $outputlines = queryGateway
-       (
-               'deviceconfig',
-               array ("deploy ${endpoint} ${breed} ${tmpfilename}")
-       );
-       unlink ($tmpfilename);
+       try
+       {
+               queryGateway ('deviceconfig', array ("deploy ${endpoint} ${breed} ${tmpfilename}"));
+               unlink ($tmpfilename);
+       }
+       catch (RTGatewayError $e)
+       {
+               unlink ($tmpfilename);
+               throw $e;
+       }
 }
 
 // Read provided output of "show cdp neighbors detail" command and
@@ -479,6 +495,46 @@ function vrp53ReadLLDPStatus ($input)
        return $ret;
 }
 
+function vrp55ReadLLDPStatus ($input)
+{
+       $ret = array();
+       foreach (explode ("\n", $input) as $line)
+       {
+               $matches = array();
+               switch (TRUE)
+               {
+               case preg_match ('/^(.+) has 1 neighbors:$/', $line, $matches):
+                       $ret['current']['local_port'] = ios12ShortenIfName ($matches[1]);
+                       break;
+               case preg_match ('/^Port ID type   :([^ ]+)/', $line, $matches):
+                       $ret['current']['PortIdSubtype'] = $matches[1];
+                       break;
+               case preg_match ('/^Port ID        :(.+)$/', $line, $matches):
+                       $ret['current']['PortId'] = $matches[1];
+                       break;
+               case preg_match ('/^System name         :(.+)$/', $line, $matches):
+                       if
+                       (
+                               array_key_exists ('current', $ret) and
+                               array_key_exists ('PortIdSubtype', $ret['current']) and
+                               ($ret['current']['PortIdSubtype'] == 'interfaceAlias' or $ret['current']['PortIdSubtype'] == 'interfaceName') and
+                               array_key_exists ('PortId', $ret['current']) and
+                               array_key_exists ('local_port', $ret['current'])
+                       )
+                               $ret[$ret['current']['local_port']] = array
+                               (
+                                       'device' => $matches[1],
+                                       'port' => ios12ShortenIfName ($ret['current']['PortId']),
+                               );
+                       unset ($ret['current']);
+                       break;
+               default:
+               }
+       }
+       unset ($ret['current']);
+       return $ret;
+}
+
 function vrp53ReadHNDPStatus ($input)
 {
        $ret = array();
@@ -547,17 +603,9 @@ function ios12PickSwitchportCommand (&$work, $line)
        if ($line[0] != ' ') // end of interface section
        {
                // save work, if it makes sense
-               switch (TRUE)
+               switch ($work['current']['mode'])
                {
-               case $work['current']['ignore']:
-                       $work['portdata'][$work['current']['port_name']] = array
-                       (
-                               'mode' => 'none',
-                               'allowed' => array(),
-                               'native' => 0,
-                       );
-                       break;
-               case 'access' == $work['current']['mode']:
+               case 'access':
                        if (!array_key_exists ('access vlan', $work['current']))
                                $work['current']['access vlan'] = 1;
                        $work['portdata'][$work['current']['port_name']] = array
@@ -567,7 +615,7 @@ function ios12PickSwitchportCommand (&$work, $line)
                                'native' => $work['current']['access vlan'],
                        );
                        break;
-               case 'trunk' == $work['current']['mode']:
+               case 'trunk':
                        if (!array_key_exists ('trunk native vlan', $work['current']))
                                $work['current']['trunk native vlan'] = 1;
                        if (!array_key_exists ('trunk allowed vlan', $work['current']))
@@ -586,6 +634,9 @@ function ios12PickSwitchportCommand (&$work, $line)
                                'native' => $effective_native,
                        );
                        break;
+               case 'SKIP':
+                       break;
+               case 'IP':
                default:
                        // dot1q-tunnel, dynamic, private-vlan or even none --
                        // show in returned config and let user decide, if they
@@ -627,9 +678,11 @@ function ios12PickSwitchportCommand (&$work, $line)
                break;
        case preg_match ('@^ channel-group @', $line):
        // port-channel subinterface config follows that of the master interface
+               $work['current']['mode'] = 'SKIP';
+               break;
        case preg_match ('@^ ip address @', $line):
        // L3 interface does no switchport functions
-               $work['current']['ignore'] = TRUE;
+               $work['current']['mode'] = 'IP';
                break;
        default: // suppress warning on irrelevant config clause
        }
index faaf838..9248921 100644 (file)
@@ -6925,20 +6925,25 @@ function renderObject8021QPorts ($object_id)
        if (!array_key_exists ($req_port_name, $desired_config))
        {
                echo '<td>';
-               startPortlet ('port duplicator');
-               echo '<table border=0 align=center>';
-               printOpFormIntro ('save8021QConfig', array ('mutex_rev' => $vswitch['mutex_rev'], 'form_mode' => 'duplicate'));
                $port_options = array();
                foreach ($desired_config as $pn => $portinfo)
                        if (editable8021QPort ($portinfo))
                                $port_options[$pn] = same8021QConfigs ($desired_config[$pn], $cached_config[$pn]) ?
                                        $pn : "${pn} (*)";
-               echo '<tr><td>' . getSelect ($port_options, array ('name' => 'from_port')) . '</td></tr>';
-               echo '<tr><td>&darr; &darr; &darr;</td></tr>';
-               echo '<tr><td>' . getSelect ($port_options, array ('name' => 'to_ports[]', 'size' => getConfigVar ('MAXSELSIZE'), 'multiple' => 1)) . '</td></tr>';
-               echo '<tr><td>' . getImageHREF ('COPY', 'duplicate', TRUE) . '</td></tr>';
-               echo '</form></table>';
-               finishPortlet();
+               if (count ($port_options) < 2)
+                       echo '&nbsp;';
+               else
+               {
+                       startPortlet ('port duplicator');
+                       echo '<table border=0 align=center>';
+                       printOpFormIntro ('save8021QConfig', array ('mutex_rev' => $vswitch['mutex_rev'], 'form_mode' => 'duplicate'));
+                       echo '<tr><td>' . getSelect ($port_options, array ('name' => 'from_port')) . '</td></tr>';
+                       echo '<tr><td>&darr; &darr; &darr;</td></tr>';
+                       echo '<tr><td>' . getSelect ($port_options, array ('name' => 'to_ports[]', 'size' => getConfigVar ('MAXSELSIZE'), 'multiple' => 1)) . '</td></tr>';
+                       echo '<tr><td>' . getImageHREF ('COPY', 'duplicate', TRUE) . '</td></tr>';
+                       echo '</form></table>';
+                       finishPortlet();
+               }
                echo '</td>';
        }
        else
@@ -6966,6 +6971,18 @@ function getAccessPortControlCode ($req_port_name, $vdom, $port_name, $port, &$n
        )
                return formatVLANName ($vdom['vlanlist'][$port['native']], 'label');
 
+       static $vlanpermissions = array();
+       if (!array_key_exists ($port['native'], $vlanpermissions))
+       {
+               $vlanpermissions[$port['native']] = array();
+               foreach (array_keys ($vdom['vlanlist']) as $to)
+                       if
+                       (
+                               permitted (NULL, NULL, 'save8021QConfig', array (array ('tag' => '$fromvlan_' . $port['native']))) and
+                               permitted (NULL, NULL, 'save8021QConfig', array (array ('tag' => '$tovlan_' . $to)))
+                       )
+                               $vlanpermissions[$port['native']][] = $to;
+       }
        $ret = "<input type=hidden name=pn_${nports} value=${port_name}>";
        $ret .= "<input type=hidden name=pm_${nports} value=access>";
        $options = array();
@@ -6979,6 +6996,7 @@ function getAccessPortControlCode ($req_port_name, $vdom, $port_name, $port, &$n
                (
                        ($vlan_id != $port['native'] or $port['mode'] == 'trunk') and
                        $vlan_info['vlan_type'] != 'alien' and
+                       in_array ($vlan_id, $vlanpermissions[$port['native']]) and
                        matchVLANFilter ($vlan_id, $port['wrt_vlans'])
                )
                        $options[$vlan_id] = formatVLANName ($vlan_info, 'option');
@@ -7748,7 +7766,10 @@ function renderDiscoveredNeighbors ($object_id)
                if
                (
                        !array_key_exists ($local_port, $myports) or
-                       NULL === $remote_id = searchByMgmtHostname ($remote['device']) or
+                       (
+                               NULL === $remote_id = searchByMgmtHostname ($remote['device']) and
+                               NULL === $remote_id = lookupEntityByString ('object', $remote['device'])
+                       ) or
                        !count ($remote_port_ids = getPortIDs ($remote_id, $remote['port']))
                )
                {