r3339 This seems to be the first two-way implementation of 802.1Q.
authorDenis Ovsienko <infrastation@yandex.ru>
Wed, 10 Mar 2010 13:53:04 +0000 (13:53 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Wed, 10 Mar 2010 13:53:04 +0000 (13:53 +0000)
detectDeviceBreed(): new function to hold common code
setDevice8021QConfig(): new function, counterpart to getDevice8021QConfig()
gwDeployDeviceConfig(): new function, counterpart to gwRetrieveDeviceConfig()
unix2dos(): new function, counterpart to dos2unix()
exportSwitch8021QConfig(): new function, transactional wrapper for setDevice8021QConfig()
processVLANSyncRequest(): collect data for and call exportSwitch8021QConfig()

inc/database.php
inc/functions.php
inc/gateways.php
inc/ophandlers.php

index e979862..134a577 100644 (file)
@@ -3826,4 +3826,26 @@ function setSwitchVLANConfig ($object_id, $form_mutex_rev, $work)
        return TRUE;
 }
 
+function exportSwitch8021QConfig ($object_id, $mutex_rev, $which_ports)
+{
+       global $dbxlink;
+       $dbxlink->beginTransaction();
+       $prepared = $dbxlink->prepare ('SELECT mutex_rev FROM VLANSwitch WHERE object_id = ? LOCK IN SHARE MODE');
+       $prepared->execute (array ($object_id));
+       if (!$row = $prepared->fetch (PDO::FETCH_ASSOC))
+       {
+               $dbxlink->rollBack();
+               throw new InvalidArgException ('object_id', $object_id, 'VLAN domain is not set for this object');
+       }
+       $db_mutex_rev = $row['mutex_rev'];
+       unset ($prepared);
+       if ($db_mutex_rev != $mutex_rev)
+       {
+               $dbxlink->rollBack();
+               throw new RuntimeException ('expired data detected');
+       }
+       setDevice8021QConfig ($object_id, computeSwitchPushRequest ($object_id, $which_ports));
+       $dbxlink->commit();
+}
+
 ?>
index fc251f9..4763da3 100644 (file)
@@ -1971,6 +1971,11 @@ function dos2unix ($text)
        return str_replace ("\r\n", "\n", $text);
 }
 
+function unix2dos ($text)
+{
+       return str_replace ("\n", "\r\n", $text);
+}
+
 function buildPredicateTable ($parsetree)
 {
        $ret = array();
index ba5a268..ac6a93f 100644 (file)
@@ -275,9 +275,8 @@ function gwRecvFileFromObject ($object_id = 0, $handlername, &$output)
        return gwRecvFile ($endpoint, $handlername, $output);
 }
 
-function getDevice8021QConfig ($object_id)
+function detectDeviceBreed ($object_id)
 {
-       $breed = '';
        foreach (getAttrValues ($object_id) as $record)
        {
                if
@@ -286,22 +285,21 @@ function getDevice8021QConfig ($object_id)
                        strlen ($record['o_value']) &&
                        preg_match ('/^Cisco IOS 12\./', execGMarker ($record['o_value']))
                )
-               {
-                       $breed = 'ios12';
-                       break;
-               }
+                       return 'ios12';
                if
                (
                        $record['name'] == 'HW type' &&
                        strlen ($record['o_value']) &&
                        preg_match ('/^Foundry FastIron GS /', execGMarker ($record['o_value']))
                )
-               {
-                       $breed = 'fdry5';
-                       break;
-               }
+                       return 'fdry5';
        }
-       if ($breed == '')
+       return '';
+}
+
+function getDevice8021QConfig ($object_id)
+{
+       if ('' == $breed = detectDeviceBreed ($object_id))
                throw new RuntimeException ('cannot pick handler for this device');
        $reader = array
        (
@@ -311,6 +309,18 @@ function getDevice8021QConfig ($object_id)
        return $reader[$breed] (dos2unix (gwRetrieveDeviceConfig ($object_id, $breed)));
 }
 
+function setDevice8021QConfig ($object_id, $pseudocode)
+{
+       if ('' == $breed = detectDeviceBreed ($object_id))
+               throw new RuntimeException ('cannot pick handler for this device');
+       $xlator = array
+       (
+               'ios12' => 'ios12TranslatePushQueue',
+               'fdry5' => 'fdry5TranslatePushQueue',
+       );
+       return gwDeployDeviceConfig ($object_id, $breed, unix2dos ($xlator[$breed] ($pseudocode)));
+}
+
 function gwRetrieveDeviceConfig ($object_id, $breed)
 {
        $objectInfo = spotEntity ('object', $object_id);
@@ -338,4 +348,30 @@ function gwRetrieveDeviceConfig ($object_id, $breed)
        return $configtext;
 }
 
+function gwDeployDeviceConfig ($object_id, $breed, $text)
+{
+       $objectInfo = spotEntity ('object', $object_id);
+       $endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
+       if (count ($endpoints) == 0)
+               throw new RuntimeException ('endpoint not found');
+       if (count ($endpoints) > 1)
+               throw new RuntimeException ('cannot pick endpoint');
+       $endpoint = str_replace (' ', '\ ', str_replace (' ', '+', $endpoints[0]));
+       $tmpfilename = tempnam ('', 'RackTables-deviceconfig-');
+       if (FALSE === file_put_contents ($tmpfilename, $text))
+               throw new RuntimeException ('failed to write to temporary file');
+       $outputlines = queryGateway
+       (
+               'deviceconfig',
+               array ("deploy ${endpoint} ${breed} ${tmpfilename}")
+       );
+       unlink ($tmpfilename);
+       if ($outputlines == NULL)
+               throw new RuntimeException ('unknown gateway failure');
+       if (count ($outputlines) != 1)
+               throw new RuntimeException ('gateway protocol violation');
+       if (strpos ($outputlines[0], 'OK!') !== 0)
+               throw new RuntimeException ("gateway failure: ${outputlines[0]}");
+}
+
 ?>
index 878e601..aba2aad 100644 (file)
@@ -2224,8 +2224,8 @@ function processVLANSyncRequest ()
        // left (produce and send commands to switch)
        // asis (ignore)
        // right (fetch config from switch and save into database)
-       $desired_config = getDesired8021QConfig ($sic['object_id']);
        $from_running = array();
+       $to_running = array();
        for ($i = 1; $i <= $sic['nrows']; $i++)
        {
                if (!array_key_exists ("i_${i}", $sic))
@@ -2234,7 +2234,7 @@ function processVLANSyncRequest ()
                switch ($sic["i_${i}"])
                {
                case 'left':
-                       // FIXME: queue sub-task of DB->switch request
+                       $to_running[] = $sic["pn_${i}"];
                        break;
                case 'right':
                        $from_running[$sic["pn_${i}"]] = array
@@ -2249,6 +2249,8 @@ function processVLANSyncRequest ()
        }
        try
        {
+               // either way it wouldn't work, because the latter increments mutex_rev
+               exportSwitch8021QConfig ($sic['object_id'], $sic['mutex_rev'], $to_running);
                setSwitchVLANConfig ($sic['object_id'], $sic['mutex_rev'], $from_running);
        }
        catch (Exception $e)