r3334 A session of work to replace port_id with object_id+port_name, which
authorDenis Ovsienko <infrastation@yandex.ru>
Tue, 9 Mar 2010 18:55:29 +0000 (18:55 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Tue, 9 Mar 2010 18:55:29 +0000 (18:55 +0000)
seems to be helpful for 802.1Q implementation.

PortAllowedVLAN: schema update
PortNativeVLAN: idem
setSwitchVLANConfig(): accept args in a new style
savePortVLANConfig(): follow spec change
processVLANSyncRequest(): rewrite
renderObjectVLANPorts(): make use of getDesired8021QConfig()
renderPortVLANConfig(): change spec, use port_name instead of port_id
renderVLANIPv4(): switch to port_name
renderObjectVLANSync(): rewrite
usePreparedDeleteBlade(): fixed bugs from last commit
getAllowedVLANsForObjectPorts(): sayonara
getNativeVLANsForObjectPorts(): sayonara
getDesired8021QConfig(): new function instead
setPortVLANConfig(): change spec, rewrite
getVLANConfiguredPorts(): follow schema change, return port_name only
setSwitchVLANConfig(): make use of getDesired8021QConfig(), fix bugs, update
computeSwitchPushRequest(): rewrite

inc/database.php
inc/functions.php
inc/interface.php
inc/ophandlers.php
install/init-structure.sql

index 3c81543..e979862 100644 (file)
@@ -2246,11 +2246,11 @@ function usePreparedDeleteBlade ($tablename, $columns, $conjunction = 'AND')
        $query = "DELETE FROM ${tablename} WHERE ";
        foreach ($columns as $colname => $colvalue)
        {
-               $query .= "${conj} ${colname} = ?";
+               $query .= " ${conj} ${colname}=?";
                $conj = $conjunction;
        }
        $prepared = $dbxlink->prepare ($query);
-       if (!$prepared->execute (array ($columns)))
+       if (!$prepared->execute (array_values ($columns)))
                return FALSE;
        return $prepared->rowCount(); // FALSE !== 0
 }
@@ -3654,40 +3654,42 @@ function getVLANSwitchInfo ($object_id)
        return NULL;
 }
 
-// Return a list of object's ports, which can run 802.1Q, each with a list
-// of VLANs enabled for that port. Even when a port has no VLANs enabled,
-// it is still shown on the list.
-function getAllowedVLANsForObjectPorts ($object_id)
+// Return the "should-be" version of 802.1Q ports, which includes
+// all current 802.1Q-eligible device ports plus the ports found
+// in the database. This means, if we have once saved configuration
+// for a port named "gi0/1" and it's not on the device's port list
+// any more, it will be present on the returned list anyway (until
+// the 802.1Q configuration is reset for that port).
+function getDesired8021QConfig ($object_id)
 {
-       global $dbxlink;
-       $query = 'SELECT id AS port_id, vlan_id ' .
-               'FROM Port LEFT JOIN PortAllowedVLAN ON Port.id = PortAllowedVLAN.port_id ' .
-               'WHERE object_id = ? AND type IN (SELECT oif_id FROM VLANEligibleOIF) ' .
-               'ORDER BY port_id, vlan_id';
-       $prepared = $dbxlink->prepare ($query);
-       $prepared->execute (array ($object_id));
        $ret = array();
-       while ($row = $prepared->fetch (PDO::FETCH_ASSOC))
+       // currently valid ports are always included in the result
+       $query = 'SELECT name FROM Port WHERE object_id = ? AND type IN (SELECT oif_id FROM VLANEligibleOIF) AND name <> ""';
+       $result = usePreparedSelectBlade ($query, array ($object_id));
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               $ret[$row['name']] = array
+               (
+                       'allowed' => array(),
+                       'native' => 0,
+               );
+       unset ($result);
+       $query = 'SELECT port_name, vlan_id FROM PortAllowedVLAN WHERE object_id = ?';
+       $result = usePreparedSelectBlade ($query, array ($object_id));
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
        {
-               if (!array_key_exists ($row['port_id'], $ret))
-                       $ret[$row['port_id']] = array();
-               if ($row['vlan_id'] !== NULL)
-                       $ret[$row['port_id']][] = $row['vlan_id'];
+               if (!array_key_exists ($row['port_name'], $ret))
+                       $ret[$row['port_name']] = array
+                       (
+                               'allowed' => array(),
+                               'native' => 0,
+                       );
+               $ret[$row['port_name']]['allowed'][] = $row['vlan_id'];
        }
-       return $ret;
-}
-
-function getNativeVLANsForObjectPorts ($object_id)
-{
-       global $dbxlink;
-       $query = 'SELECT port_id, vlan_id FROM ' .
-               'PortNativeVLAN INNER JOIN Port ON Port.id = PortNativeVLAN.port_id ' .
-               'WHERE object_id = ? ORDER BY port_id';
-       $prepared = $dbxlink->prepare ($query);
-       $prepared->execute (array ($object_id));
-       $ret = array();
-       while ($row = $prepared->fetch (PDO::FETCH_ASSOC))
-               $ret[$row['port_id']] = $row['vlan_id']; // port_id is unique in this table
+       unset ($result);
+       $query = 'SELECT port_name, vlan_id FROM PortNativeVLAN WHERE object_id = ?';
+       $result = usePreparedSelectBlade ($query, array ($object_id));
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               $ret[$row['port_name']]['native'] = $row['vlan_id'];
        return $ret;
 }
 
@@ -3696,24 +3698,21 @@ function getNativeVLANsForObjectPorts ($object_id)
 // INSERT query, which would always trigger an FK exception.
 // This function indicates an error, but doesn't revert it, so it is
 // assummed, that the calling function performs necessary transaction wrapping.
-function setPortVLANConfig ($port_id, $allowed, $native)
+function setPortVLANConfig ($object_id, $port_name, $allowed, $native)
 {
        global $dbxlink;
-       if
-       (
-               FALSE === usePreparedDeleteBlade ('PortAllowedVLAN', array ('port_id' => $port_id)) or
-               FALSE === usePreparedDeleteBlade ('PortNativeVLAN', array ('port_id' => $port_id))
-       )
+       // rely on ON DELETE CASCADE for PortNativeVLAN
+       if (FALSE === usePreparedDeleteBlade ('PortAllowedVLAN', array ('object_id' => $object_id, 'port_name' => $port_name)))
                return FALSE;
        foreach ($allowed as $vlan_id)
-               if (!usePreparedInsertBlade ('PortAllowedVLAN', array ('port_id' => $port_id, 'vlan_id' => $vlan_id)))
+               if (!usePreparedInsertBlade ('PortAllowedVLAN', array ('object_id' => $object_id, 'port_name' => $port_name, 'vlan_id' => $vlan_id)))
                        return FALSE;
        // When the new native VLAN ID is 0, only delete the old row (if it exists).
        if
        (
                $native and
                in_array ($native, $allowed) and
-               !usePreparedInsertBlade ('PortNativeVLAN', array ('port_id' => $port_id, 'vlan_id' => $native))
+               !usePreparedInsertBlade ('PortNativeVLAN', array ('object_id' => $object_id, 'port_name' => $port_name, 'vlan_id' => $native))
        )
                return FALSE;
        return TRUE;
@@ -3768,16 +3767,16 @@ function commitReduceVLANIPv4 ($vlan_ck, $ipv4net_id)
 function getVLANConfiguredPorts ($vlan_ck)
 {
        global $dbxlink;
-       $query = 'SELECT Port.object_id, port_id, name AS port_name ' .
-               'FROM PortAllowedVLAN AS PAV INNER JOIN Port ON PAV.port_id = Port.id ' .
-               'INNER JOIN VLANSwitch AS VS ON Port.object_id = VS.object_id ' .
+       $query = 'SELECT PAV.object_id, PAV.port_name ' .
+               'FROM PortAllowedVLAN AS PAV ' .
+               'INNER JOIN VLANSwitch AS VS ON PAV.object_id = VS.object_id ' .
                'WHERE domain_id = ? AND vlan_id = ? ' .
-               'ORDER BY Port.object_id, port_id';
+               'ORDER BY PAV.object_id, PAV.port_name';
        $prepared = $dbxlink->prepare ($query);
        $prepared->execute (decodeVLANCK ($vlan_ck));
        $ret = array();
        while ($row = $prepared->fetch (PDO::FETCH_ASSOC))
-               $ret[$row['object_id']][$row['port_id']] = $row['port_name'];
+               $ret[$row['object_id']][] = $row['port_name'];
        return $ret;
 }
 
@@ -3794,21 +3793,16 @@ function setSwitchVLANConfig ($object_id, $form_mutex_rev, $work)
        }
        $db_mutex_rev = $row['mutex_rev'];
        unset ($prepared);
-       $allowed = getAllowedVLANsForObjectPorts ($object_id);
-       $native = getNativeVLANsForObjectPorts ($object_id);
+       $desired_config = getDesired8021QConfig ($object_id);
        $changed = FALSE;
-       foreach ($work as $item)
+       foreach ($work as $port_name => $item)
        {
-               if (!array_key_exists ($item['port_id'], $allowed))
-               {
-                       $dbxlink->rollBack();
-                       throw new InvalidArgException ('port_id', $item['port_id'], 'the requested port does not belong to current object');
-               }
                // Only consider touching database, when there are changes for the current port.
                if
                (
-                       count (array_intersect ($item['allowed'], $allowed[$item['port_id']])) == count ($item['allowed']) and
-                       $item['native'] == $native[$item['port_id']]
+                       !count (array_diff ($item['allowed'], $desired_config[$port_name]['allowed'])) and
+                       !count (array_diff ($desired_config[$port_name]['allowed'], $item['allowed'])) and
+                       $item['native'] == $desired_config[$port_name]['native']
                )
                        continue; // data already meets the request
                $changed = TRUE;
@@ -3817,7 +3811,7 @@ function setSwitchVLANConfig ($object_id, $form_mutex_rev, $work)
                        $dbxlink->rollBack();
                        throw new RuntimeException();
                }
-               if (!setPortVLANConfig ($item['port_id'], $item['allowed'], $item['native']))
+               if (!setPortVLANConfig ($object_id, $port_name, $item['allowed'], $item['native']))
                {
                        $dbxlink->rollBack();
                        throw new RuntimeException();
index d58faa3..cf945ae 100644 (file)
@@ -2610,47 +2610,25 @@ function computeSwitchPushRequest ($object_id, $which_ports)
                        $old_managed_vlans[] = $vlan_id;
        $object = spotEntity ('object', $object_id);
        amplifyCell ($object);
-       $db_allowed = getAllowedVLANsForObjectPorts ($object_id);
-       $db_native = getNativeVLANsForObjectPorts ($object_id);
-       $db_config = array();
-       foreach ($db_allowed as $port_id => $vlans)
-               $db_config[$port_id] = array
-               (
-                       'allowed' => $vlans,
-                       'native' => 0,
-               );
-       foreach ($db_native as $port_id => $vlan_id)
-               $db_config[$port_id]['native'] = $vlan_id;
+       $db_config = getDesired8021QConfig ($object_id);
        $ports_to_do = array();
-       foreach ($which_ports as $req_port_id)
+       foreach ($which_ports as $req_port_name)
        {
-               if (!array_key_exists ($req_port_id, $db_allowed))
-                       continue;
-               if (NULL === $db_pkey = scanArrayForItem ($object['ports'], 'id', $req_port_id))
-                       continue;
-               if ('' == $port_name = $object['ports'][$db_pkey]['name'])
-                       continue;
-               if (NULL === $dev_pkey = scanArrayForItem ($device_config['portdata'], 'port_name', $port_name))
-                       continue;
-               if
-               (
-                       count ($db_config[$req_port_id]['allowed']) == 0 and
-                       $db_config[$req_port_id]['native'] == 0
-               )
+               if (!array_key_exists ($req_port_name, $db_config))
                        continue;
                if
                (
-                       count ($device_config[$req_port_id]['allowed']) == 0 and
-                       $device_config[$req_port_id]['native'] == 0
+                       count ($db_config[$req_port_name]['allowed']) == 0 and
+                       $db_config[$req_port_name]['native'] == 0
                )
                        continue;
-               $ports_to_do[] = $req_port_id;
+               $ports_to_do[] = $req_port_name;
        }
        $new_managed_vlans = array();
        foreach ($vdomain['vlanlist'] as $vlan_id => $vlan)
                if ($vlan['type'] == 'mandatory')
                        $new_managed_vlans[] = $vlan_id;
-       foreach ($db_allowed as $vlanlist)
+       foreach ($db_config as $vlanlist)
                foreach ($vlanlist as $vlan_id)
                        if (!in_array ($vlan_id, $new_managed_vlans))
                                $new_managed_vlans[] = $vlan_id;
index be5c96a..1bf47ea 100644 (file)
@@ -6628,62 +6628,50 @@ function renderVLANDomainVLANList ($vdom_id)
 function renderObjectVLANPorts ($object_id)
 {
        global $pageno, $tabno, $sic;
-       $allowed = getAllowedVLANsForObjectPorts ($object_id);
-       $native = getNativeVLANsForObjectPorts ($object_id);
-       $object = spotEntity ('object', $object_id);
-       amplifyCell ($object);
-       $port_id = array_key_exists ('port_id', $sic) ? $sic['port_id'] : 0;
+       $req_port_name = array_key_exists ('port_name', $sic) ? $sic['port_name'] : '';
+       $desired_config = getDesired8021QConfig ($object_id);
        echo '<table border=0 width="100%"><tr valign=top><td class=tdleft width="30%">';
        // port list
        echo '<table cellspacing=0 cellpadding=5 align=center class=widetable>';
        echo '<tr><th>port name</th><th>current config</th></tr>';
-       foreach ($object['ports'] as $port)
-               if (array_key_exists ($port['id'], $allowed)) // eligible for 802.1Q
-               {
-                       $tdclass = $port['id'] == $port_id ? 'seltagbox' : 'tagbox';
-                       echo "<tr><td class=${tdclass}><a href='" . makeHref
-                       (
-                               array
-                               (
-                                       'page' => $pageno,
-                                       'tab' => $tabno,
-                                       'object_id' => $object_id,
-                                       'port_id' => $port['id'],
-                               )
-                       );
-                       echo "'>${port['name']}</a></td><td class=${tdclass}>";
-                       echo serializeVLANPack
+       foreach ($desired_config as $port_name => $port)
+       {
+               $tdclass = $port_name == $req_port_name ? 'seltagbox' : 'tagbox';
+               echo "<tr><td class=${tdclass}><a href='" . makeHref
+               (
+                       array
                        (
-                               array_key_exists ($port['id'], $native) ? $native[$port['id']] : 0,
-                               array_key_exists ($port['id'], $allowed) ? $allowed[$port['id']] : array()
-                       );
-                       echo '</td></tr>';
-               }
+                               'page' => $pageno,
+                               'tab' => $tabno,
+                               'object_id' => $object_id,
+                               'port_name' => $port_name,
+                       )
+               );
+               echo "'>${port_name}</a></td><td class=${tdclass}>";
+               echo serializeVLANPack
+               (
+                       $port['native'],
+                       $port['allowed']
+               );
+               echo '</td></tr>';
+       }
        echo '</table>';
        echo '</td>';
        // configuration of currently selected port, if any
-       if (!$port_id)
+       if (!array_key_exists ($req_port_name, $desired_config))
                echo '<td colspan=2>&nbsp;</td>';
        else
-       {
-               $portinfo = getPortInfo ($port_id);
-               if ($portinfo['object_id'] != $object_id)
-               {
-                       showError ('Invalid port_id', __FUNCTION__);
-                       return;
-               }
                renderPortVLANConfig
                (
-                       $port_id,
                        $object_id,
-                       array_key_exists ($port_id, $allowed) ? $allowed[$port_id] : array(),
-                       array_key_exists ($port_id, $native) ? $native[$port_id] : 0
+                       $req_port_name,
+                       $desired_config[$req_port_name]['allowed'],
+                       $desired_config[$req_port_name]['native']
                );
-       }
        echo '</tr></table>';
 }
 
-function renderPortVLANConfig ($port_id, $object_id, $allowed, $native)
+function renderPortVLANConfig ($object_id, $port_name, $allowed, $native)
 {
        $vswitch = getVLANSwitchInfo ($object_id);
        $vdom = getVLANDomain ($vswitch['domain_id']);
@@ -6692,7 +6680,7 @@ function renderPortVLANConfig ($port_id, $object_id, $allowed, $native)
                echo '<td colspan=2>(configured VLAN domain is empty)</td>';
                return;
        }
-       printOpFormIntro ('savePortVLANConfig', array ('port_id' => $port_id, 'mutex_rev' => $vswitch['mutex_rev']));
+       printOpFormIntro ('savePortVLANConfig', array ('port_name' => $port_name, 'mutex_rev' => $vswitch['mutex_rev']));
        echo '<td width="35%">';
        echo '<table border=0 cellspacing=0 cellpadding=3 align=center>';
        echo '<tr><th colspan=2>allowed</th></tr>';
@@ -6748,7 +6736,7 @@ function renderPortVLANConfig ($port_id, $object_id, $allowed, $native)
                printImageHREF ('CLEAR gray');
        else
        {
-               printOpFormIntro ('savePortVLANConfig', array ('port_id' => $port_id, 'mutex_rev' => $vswitch['mutex_rev']));
+               printOpFormIntro ('savePortVLANConfig', array ('port_name' => $port_name, 'mutex_rev' => $vswitch['mutex_rev']));
                printImageHREF ('CLEAR', 'Unassign all VLANs', TRUE);
                echo '</form>';
        }
@@ -6814,7 +6802,7 @@ function renderVLANInfo ($vlan_ck)
                        echo "<tr class=row_${order} valign=top><td>";
                        renderCell (spotEntity ('object', $switch_id));
                        echo '</td><td class=tdleft><ul>';
-                       foreach ($portlist as $port_id => $port_name)
+                       foreach ($portlist as $port_name)
                                echo "<li>${port_name}</li>";
                        echo '</ul></td></tr>';
                        $order = $nextorder[$order];
@@ -6873,33 +6861,40 @@ function renderObjectVLANSync ($object_id)
                showWarning ('Could not retrieve running-config of this device with the following error:<br>' . $re->getMessage(), __FUNCTION__);
                return;
        }
-       $allowed = getAllowedVLANsForObjectPorts ($object_id);
-       $native = getNativeVLANsForObjectPorts ($object_id);
-       $object = spotEntity ('object', $object_id);
-       amplifyCell ($object);
+       $desired_config = getDesired8021QConfig ($object_id);
+       $running_config = getDevice8021QConfig ($object_id);
        $formports = array();
-       // Iterate over object's ports table, which is already sorted in
-       // a particular way, and pick items from "allowed" list, which
-       // comes sorted in some other way.
-       foreach ($object['ports'] as $oport)
-               if (array_key_exists ($oport['id'], $allowed) and mb_strlen ($oport['name']))
-                       $formports[$oport['id']] = array
-                       (
-                               'port_name' => $oport['name'],
-                               'desired_allowed' => $allowed[$oport['id']],
-                               'desired_native' => array_key_exists ($oport['id'], $native) ? $native[$oport['id']] : 0,
-                               'running_allowed' => array(),
-                               'running_native' => 0,
-                       );
-       foreach ($deviceconfig['portdata'] as $item)
+       // The form is based on the "desired" list, which has every
+       // 802.1Q-eligible port of the object plus any port names
+       // already stored in the database. This list may be further
+       // extended by the "running" list of the actual device.
+       foreach ($desired_config as $port_name => $port)
+               $formports[] = array
+               (
+                       'port_name' => $port_name,
+                       'desired_allowed' => $port['allowed'],
+                       'desired_native' => $port['native'],
+                       'running_allowed' => array(),
+                       'running_native' => 0,
+               );
+       foreach ($running_config['portdata'] as $item)
                if (NULL !== $tmpkey = scanArrayForItem ($formports, 'port_name', $item['port_name']))
                {
                        $formports[$tmpkey]['running_allowed'] = $item['allowed'];
                        $formports[$tmpkey]['running_native'] = $item['native'];
                }
+               else
+                       $formports[] = array
+                       (
+                               'port_name' => $item['port_name'],
+                               'desired_allowed' => array(),
+                               'desired_native' => 0,
+                               'running_allowed' => $item['allowed'],
+                               'running_native' => $item['native'],
+                       );
        $vswitch = getVLANSwitchInfo ($object_id);
        $domvlans = array_keys (getDomainVLANs ($vswitch['domain_id']));
-       printOpFormIntro ('sync', array ('mutex_rev' => $vswitch['mutex_rev']));
+       printOpFormIntro ('sync', array ('mutex_rev' => $vswitch['mutex_rev'], 'nrows' => count ($formports)));
        $nrows = count ($formports);
        echo '<table cellspacing=0 cellpadding=5 align=center class=widetable>';
        echo '<tr><th rowspan=2>port name</th><th rowspan=2>desired config</th><th colspan=3>wins</th>';
@@ -6910,7 +6905,7 @@ function renderObjectVLANSync ($object_id)
        echo '</tr>';
        $order = 'odd';
        $rownum = 1;
-       foreach ($formports as $port_id => $port)
+       foreach ($formports as $port)
        {
                $desired_cfgstring = serializeVLANPack ($port['desired_native'], $port['desired_allowed']);
                $running_cfgstring = serializeVLANPack ($port['running_native'], $port['running_allowed']);
@@ -6937,14 +6932,15 @@ function renderObjectVLANSync ($object_id)
                        else
                                // For JS event handler radio input names are indexed from 1
                                // onwards, but for sumbit handler they are based on port id.
-                               echo "<input id=i_${rownum}_${pos} name=i_${port_id} type=radio value=${pos}" . $checked[$pos] . ">";
+                               echo "<input id=i_${rownum}_${pos} name=i_${rownum} type=radio value=${pos}" . $checked[$pos] . ">";
                        echo '</td>';
                }
                echo "<td><label for=i_${rownum}_right>${running_cfgstring}</label></td>";
                echo '</tr>';
-               echo "<input type=hidden name=rn_${port_id} value=${port['running_native']}>";
+               echo "<input type=hidden name=rn_${rownum} value=${port['running_native']}>";
                foreach ($port['running_allowed'] as $a)
-                       echo "<input type=hidden name=ra_${port_id}[] value=${a}>";
+                       echo "<input type=hidden name=ra_${rownum}[] value=${a}>";
+               echo "<input type=hidden name=pn_${rownum} value='" . htmlspecialchars ($port['port_name']) . "'>";
                $order = $nextorder[$order];
                $rownum++;
        }
index 778fa85..878e601 100644 (file)
@@ -2176,25 +2176,21 @@ $msgcode['savePortVLANConfig']['ERR1'] = 160;
 $msgcode['savePortVLANConfig']['ERR2'] = 109;
 function savePortVLANConfig ()
 {
-       assertUIntArg ('port_id');
+       assertStringArg ('port_name');
        assertUIntArg ('mutex_rev');
        global $sic;
-       $portinfo = getPortInfo ($sic['port_id']);
-       if ($portinfo['object_id'] != $sic['object_id'])
-               // should we throw instead?
-               return buildRedirectURL (__FUNCTION__, 'ERR1', array(), NULL, NULL, array ('port_id' => $sic['port_id']));
        try
        {
                $allowed = isset ($sic['allowed_id']) ? $sic['allowed_id'] : array();
                $native = isset ($sic['native_id']) ? $sic['native_id'] : 0; // 0 means "reset"
-               $work = array (array ('port_id' => $sic['port_id'], 'allowed' => $allowed, 'native' => $native));
+               $work = array ($sic['port_name'] => array ('allowed' => $allowed, 'native' => $native));
                setSwitchVLANConfig ($sic['object_id'], $sic['mutex_rev'], $work);
        }
        catch (Exception $e)
        {
-               return buildRedirectURL (__FUNCTION__, 'ERR2', array(), NULL, NULL, array ('port_id' => $sic['port_id']));
+               return buildRedirectURL (__FUNCTION__, 'ERR2', array(), NULL, NULL, array ('port_name' => $sic['port_name']));
        }
-       return buildRedirectURL (__FUNCTION__, 'OK', array(), NULL, NULL, array ('port_id' => $sic['port_id']));
+       return buildRedirectURL (__FUNCTION__, 'OK', array(), NULL, NULL, array ('port_name' => $sic['port_name']));
 }
 
 $msgcode['bindVLANtoIPv4']['OK'] = 48;
@@ -2223,28 +2219,28 @@ function processVLANSyncRequest ()
 {
        global $sic;
        assertUIntArg ('mutex_rev');
-       // Divide submitted radio buttons into 4 groups:
+       assertUIntArg ('nrows');
+       // Divide submitted radio buttons into 3 groups:
        // left (produce and send commands to switch)
        // asis (ignore)
        // right (fetch config from switch and save into database)
-       $object = spotEntity ('object', $_REQUEST['object_id']);
-       $allowed = getAllowedVLANsForObjectPorts ($sic['object_id']);
+       $desired_config = getDesired8021QConfig ($sic['object_id']);
        $from_running = array();
-       foreach ($allowed as $port_id => $vlanlist)
+       for ($i = 1; $i <= $sic['nrows']; $i++)
        {
-               if (!array_key_exists ("i_${port_id}", $sic))
+               if (!array_key_exists ("i_${i}", $sic))
                        continue;
-               switch ($sic["i_${port_id}"])
+               // let's hope other inputs are in place
+               switch ($sic["i_${i}"])
                {
                case 'left':
                        // FIXME: queue sub-task of DB->switch request
                        break;
                case 'right':
-                       $from_running[] = array
+                       $from_running[$sic["pn_${i}"]] = array
                        (
-                               'port_id' => $port_id,
-                               'allowed' => $sic["ra_${port_id}"],
-                               'native' => $sic["rn_${port_id}"],
+                               'allowed' => $sic["ra_${i}"],
+                               'native' => $sic["rn_${i}"],
                        );
                        break;
                default:
index 424e775..1362fb2 100644 (file)
@@ -411,19 +411,21 @@ CREATE TABLE `VLANSwitch` (
 ) ENGINE=InnoDB;
 
 CREATE TABLE `PortAllowedVLAN` (
-  `port_id` int(10) unsigned NOT NULL default '0',
+  `object_id` int(10) unsigned NOT NULL,
+  `port_name` char(255) NOT NULL,
   `vlan_id` int(10) unsigned NOT NULL default '0',
-  PRIMARY KEY  (`port_id`,`vlan_id`),
+  PRIMARY KEY  (`object_id`,`port_name`,`vlan_id`),
   KEY `vlan_id` (`vlan_id`),
-  CONSTRAINT `PortAllowedVLAN-FK-port_id` FOREIGN KEY (`port_id`) REFERENCES `Port` (`id`) ON DELETE CASCADE,
+  CONSTRAINT `PortAllowedVLAN-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE,
   CONSTRAINT `PortAllowedVLAN-FK-vlan_id` FOREIGN KEY (`vlan_id`) REFERENCES `VLANValidID` (`vlan_id`)
 ) ENGINE=InnoDB;
 
 CREATE TABLE `PortNativeVLAN` (
-  `port_id` int(10) unsigned NOT NULL default '0',
+  `object_id` int(10) unsigned NOT NULL,
+  `port_name` char(255) NOT NULL,
   `vlan_id` int(10) unsigned NOT NULL default '0',
-  PRIMARY KEY  (`port_id`,`vlan_id`),
-  UNIQUE KEY `port_id` (`port_id`),
-  CONSTRAINT `PortNativeVLAN-FK-compound` FOREIGN KEY (`port_id`, `vlan_id`) REFERENCES `PortAllowedVLAN` (`port_id`, `vlan_id`) ON DELETE CASCADE
+  PRIMARY KEY  (`object_id`,`port_name`,`vlan_id`),
+  UNIQUE KEY `port_id` (`object_id`,`port_name`),
+  CONSTRAINT `PortNativeVLAN-FK-compound` FOREIGN KEY (`object_id`, `port_name`, `vlan_id`) REFERENCES `PortAllowedVLAN` (`object_id`, `port_name`, `vlan_id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;