r4910 APCPowerSwitch::getPorts () - change snmpwalk call to snmpwalkoid, fixes #504
[racktables] / wwwroot / inc / ophandlers.php
index 5f7f334..bf09c69 100644 (file)
@@ -105,7 +105,7 @@ $opspec_list['object-log-del'] = array
        'action' => 'DELETE',
        'arglist' => array
        (
-               array ('url_argname' => 'logid', 'table_colname' => 'id', 'assertion' => 'uint'),
+               array ('url_argname' => 'log_id', 'table_colname' => 'id', 'assertion' => 'uint'),
                array ('url_argname' => 'object_id', 'assertion' => 'uint'),
        ),
 );
@@ -132,7 +132,7 @@ $opspec_list['object-editrspvs-updLB'] = array
        (
                array ('url_argname' => 'vsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
                array ('url_argname' => 'rsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
-               array ('url_argname' => 'prio', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
+               array ('url_argname' => 'prio', 'assertion' => 'string0', 'if_empty' => 'NULL'),
        ),
        'where_arglist' => array
        (
@@ -141,6 +141,27 @@ $opspec_list['object-editrspvs-updLB'] = array
                array ('url_argname' => 'vs_id', 'assertion' => 'uint'),
        ),
 );
+$opspec_list['object-cacti-add'] = array
+(
+       'table' => 'CactiGraph',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'object_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'graph_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'caption', 'assertion' => 'string0'),
+       ),
+);
+$opspec_list['object-cacti-del'] = array
+(
+       'table' => 'CactiGraph',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'object_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'graph_id', 'assertion' => 'uint'),
+       ),
+);
 $opspec_list['ipv4net-properties-editRange'] = array
 (
        'table' => 'IPv4Network',
@@ -413,6 +434,7 @@ $opspec_list['vlandomain-vlanlist-del'] = array
                array ('url_argname' => 'vlan_id', 'assertion' => 'vlan'),
        ),
 );
+$opspec_list['vlan-edit-upd'] = // both locations are using the same tableHandler op
 $opspec_list['vlandomain-vlanlist-upd'] = array
 (
        'table' => 'VLANDescription',
@@ -429,27 +451,6 @@ $opspec_list['vlandomain-vlanlist-upd'] = array
        ),
 );
 
-function buildRedirectURL ($nextpage = NULL, $nexttab = NULL, $moreArgs = array())
-{
-       global $page, $pageno, $tabno;
-       if ($nextpage === NULL)
-               $nextpage = $pageno;
-       if ($nexttab === NULL)
-               $nexttab = $tabno;
-       $url = "index.php?page=${nextpage}&tab=${nexttab}";
-       if (isset ($page[$nextpage]['bypass']))
-               $url .= '&' . $page[$nextpage]['bypass'] . '=' . $_REQUEST[$page[$nextpage]['bypass']];
-
-       if (count ($moreArgs) > 0)
-               foreach ($moreArgs as $arg => $value)
-                       if (is_array ($value))
-                               foreach ($value as $v)
-                                       $url .= '&' . urlencode ($arg . '[]') . '=' . urlencode ($v);
-                       elseif ($arg != 'module')
-                               $url .= '&' . urlencode ($arg) . '=' . urlencode ($value);
-       return $url;
-}
-
 $msgcode['addPortForwarding']['OK'] = 48;
 function addPortForwarding ()
 {
@@ -550,6 +551,8 @@ function editPortForObject ()
        genericAssertion ('l2address', 'l2address0');
        genericAssertion ('name', 'string');
        commitUpdatePort ($sic['object_id'], $sic['port_id'], $sic['name'], $sic['port_type_id'], $sic['label'], $sic['l2address'], $sic['reservation_comment']);
+       if (array_key_exists ('cable', $_REQUEST))
+               commitUpdatePortLink ($sic['port_id'], $sic['cable']);
        return showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['name']));
 }
 
@@ -808,50 +811,76 @@ function addIPv6Allocation ()
        return showFuncMessage (__FUNCTION__, 'OK');
 }
 
-$msgcode['addIPv4Prefix']['OK'] = 48;
 function addIPv4Prefix ()
 {
        assertStringArg ('range');
        assertStringArg ('name', TRUE);
-       genericAssertion ('vlan_ck', 'string');
 
-       $is_bcast = isset ($_REQUEST['is_bcast']) ? $_REQUEST['is_bcast'] : 'off';
        $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
+       $is_connected = isset ($_REQUEST['is_connected']) ? $_REQUEST['is_connected'] : 'off';
        global $sic;
-       $vlan_ck = $sic['vlan_ck'] == '0-0' ? NULL : $sic['vlan_ck'];
-       createIPv4Prefix ($_REQUEST['range'], $sic['name'], $is_bcast == 'on', $taglist, $vlan_ck);
-       return showFuncMessage (__FUNCTION__, 'OK');
+       $vlan_ck = empty ($sic['vlan_ck']) ? NULL : $sic['vlan_ck'];
+       $net_id = createIPv4Prefix ($_REQUEST['range'], $sic['name'], $is_connected == 'on', $taglist, $vlan_ck);
+       showSuccess
+       (
+               'IP network <a href="' .
+               makeHref (array ('page' => 'ipv4net', 'tab' => 'default', 'id' => $net_id)) .
+               '">' . $_REQUEST['range'] . '</a> has been created'
+       );
 }
 
-$msgcode['addIPv6Prefix']['OK'] = 48;
 function addIPv6Prefix ()
 {
        assertStringArg ('range');
        assertStringArg ('name', TRUE);
-       genericAssertion ('vlan_ck', 'string');
 
        $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
        $is_connected = isset ($_REQUEST['is_connected']) ? ($_REQUEST['is_connected'] == 'on') : FALSE;
        global $sic;
-       $vlan_ck = $sic['vlan_ck'] == '0-0' ? NULL : $sic['vlan_ck'];
-       createIPv6Prefix ($_REQUEST['range'], $sic['name'], $is_connected, $taglist, $vlan_ck);
-       return showFuncMessage (__FUNCTION__, 'OK');
+       $vlan_ck = empty ($sic['vlan_ck']) ? NULL : $sic['vlan_ck'];
+       $net_id = createIPv6Prefix ($_REQUEST['range'], $sic['name'], $is_connected, $taglist, $vlan_ck);
+       showSuccess
+       (
+               'IP network <a href="' .
+               makeHref (array ('page' => 'ipv6net', 'tab' => 'default', 'id' => $net_id)) .
+               '">' . $_REQUEST['range'] . '</a> has been created'
+       );
 }
 
 $msgcode['delIPv4Prefix']['OK'] = 49;
 function delIPv4Prefix ()
 {
        assertUIntArg ('id');
+       $netinfo = spotEntity ('ipv4net', $_REQUEST['id']);
+       loadIPv4AddrList ($netinfo);
+       if (! isIPNetworkEmpty ($netinfo))
+               return showError ("There are allocations within prefix, delete forbidden");
+       if (array_key_exists ($netinfo['db_first'], $netinfo['addrlist']))
+               updateAddress ($netinfo['addrlist'][$netinfo['db_first']]['ip'], '', 'no');
+       if (array_key_exists ($netinfo['db_last'], $netinfo['addrlist']))
+               updateAddress ($netinfo['addrlist'][$netinfo['db_last']]['ip'], '', 'no');
        destroyIPv4Prefix ($_REQUEST['id']);
-       return showFuncMessage (__FUNCTION__, 'OK');
+       showFuncMessage (__FUNCTION__, 'OK');
+       global $pageno;
+       if ($pageno == 'ipv4net')
+               return buildRedirectURL ('index', 'default');
 }
 
 $msgcode['delIPv6Prefix']['OK'] = 49;
 function delIPv6Prefix ()
 {
        assertUIntArg ('id');
+       $netinfo = spotEntity ('ipv6net', $_REQUEST['id']);
+       loadIPv6AddrList ($netinfo);
+       if (! isIPNetworkEmpty ($netinfo))
+               return showError ("There are allocations within prefix, delete forbidden");
+       if (array_key_exists ($netinfo['db_first']->getBin(), $netinfo['addrlist']))
+               updateAddress ($netinfo['db_first'], '', 'no');
        destroyIPv6Prefix ($_REQUEST['id']);
-       return showFuncMessage (__FUNCTION__, 'OK');
+       showFuncMessage (__FUNCTION__, 'OK');
+       global $pageno;
+       if ($pageno == 'ipv6net')
+               return buildRedirectURL ('index', 'default');
 }
 
 $msgcode['editAddress']['OK'] = 51;
@@ -937,16 +966,17 @@ function updateChapter ()
 {
        assertUIntArg ('chapter_no');
        assertStringArg ('chapter_name');
+       global $sic;
        usePreparedUpdateBlade
        (
                'Chapter',
                array
                (
-                       'name' => $chapter_name,
+                       'name' => $sic['chapter_name'],
                ),
                array
                (
-                       'id' => $chapter_no,
+                       'id' => $sic['chapter_no'],
                        'sticky' => 'no', // note this constant, it protects system chapters
                )
        );
@@ -1200,7 +1230,6 @@ function addMultipleObjects()
                                $taglist
                        );
                        $info = spotEntity ('object', $object_id);
-                       // FIXME: employ amplifyCell() instead of calling loader functions directly
                        amplifyCell ($info);
                        showSuccess ("added object " . formatPortLink ($info['id'], $info['dname'], NULL, NULL));
                }
@@ -1250,7 +1279,7 @@ function addLotOfObjects()
        }
 }
 
-$msgcode['deleteObject']['OK'] = 6;
+$msgcode['deleteObject']['OK'] = 7;
 function deleteObject ()
 {
        assertUIntArg ('object_id');
@@ -1403,6 +1432,13 @@ function resetUIConfig()
        setConfigVar ('FILTER_RACKLIST_BY_TAGS', 'yes');
        setConfigVar ('SSH_OBJS_LISTSRC', 'none');
        setConfigVar ('TELNET_OBJS_LISTSRC', 'none');
+       setConfigVar ('SYNC_802Q_LISTSRC', '');
+       setConfigVar ('QUICK_LINK_PAGES', '');
+       setConfigVar ('CACTI_LISTSRC', 'false');
+       setConfigVar ('CACTI_URL', '');
+       setConfigVar ('CACTI_USERNAME', '');
+       setConfigVar ('CACTI_USERPASS', '');
+       setConfigVar ('VIRTUAL_OBJ_LISTSRC', '1504,1505,1506,1507');
        return showFuncMessage (__FUNCTION__, 'OK');
 }
 
@@ -1410,16 +1446,19 @@ $msgcode['addRealServer']['OK'] = 48;
 // Add single record.
 function addRealServer ()
 {
-       assertIPv4Arg ('remoteip');
+       global $sic;
+       assertIPv4Arg ('rsip');
        assertStringArg ('rsport', TRUE);
        assertStringArg ('rsconfig', TRUE);
+       assertStringArg ('comment', TRUE);
        addRStoRSPool
        (
                getBypassValue(),
-               $_REQUEST['remoteip'],
+               $_REQUEST['rsip'],
                $_REQUEST['rsport'],
-               getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'),
-               $_REQUEST['rsconfig']
+               (isset ($_REQUEST['inservice']) and $_REQUEST['inservice'] == 'on') ? 'yes' : 'no',
+               $sic['rsconfig'],
+               $sic['comment']
        );
        return showFuncMessage (__FUNCTION__, 'OK');
 }
@@ -1432,7 +1471,6 @@ function addRealServers ()
        assertStringArg ('format');
        assertStringArg ('rawtext');
        $ngood = 0;
-       $rsconfig = '';
        // Keep in mind, that the text will have HTML entities (namely '>') escaped.
        foreach (explode ("\n", dos2unix ($_REQUEST['rawtext'])) as $line)
        {
@@ -1472,23 +1510,30 @@ function addRealServers ()
 $msgcode['addVService']['OK'] = 48;
 function addVService ()
 {
+       global $sic;
        assertIPv4Arg ('vip');
-       assertUIntArg ('vport');
        genericAssertion ('proto', 'enum/ipproto');
        assertStringArg ('name', TRUE);
        assertStringArg ('vsconfig', TRUE);
        assertStringArg ('rsconfig', TRUE);
+       if ($_REQUEST['proto'] == 'MARK')
+               $vport = NULL;
+       else
+       {
+               assertUIntArg ('vport');
+               $vport = $_REQUEST['vport'];
+       }
        usePreparedExecuteBlade
        (
                'INSERT INTO IPv4VS (vip, vport, proto, name, vsconfig, rsconfig) VALUES (INET_ATON(?), ?, ?, ?, ?, ?)',
                array
                (
                        $_REQUEST['vip'],
-                       $_REQUEST['vport'],
+                       $vport,
                        $_REQUEST['proto'],
                        !mb_strlen ($_REQUEST['name']) ? NULL : $_REQUEST['name'],
-                       !strlen ($_REQUEST['vsconfig']) ? NULL : $_REQUEST['vsconfig'],
-                       !strlen ($_REQUEST['rsconfig']) ? NULL : $_REQUEST['rsconfig'],
+                       !strlen ($sic['vsconfig']) ? NULL : $sic['vsconfig'],
+                       !strlen ($sic['rsconfig']) ? NULL : $sic['rsconfig'],
                )
        );
        produceTagsForLastRecord ('ipv4vs', isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array());
@@ -1506,12 +1551,13 @@ function deleteVService ()
 $msgcode['updateSLBDefConfig']['OK'] = 43;
 function updateSLBDefConfig ()
 {
+       global $sic;
        commitUpdateSLBDefConf
        (
                array
                (
-                       'vs' => $_REQUEST['vsconfig'],
-                       'rs' => $_REQUEST['rsconfig'],
+                       'vs' => $sic['vsconfig'],
+                       'rs' => $sic['rsconfig'],
                )
        );
        return showFuncMessage (__FUNCTION__, 'OK');
@@ -1520,15 +1566,19 @@ function updateSLBDefConfig ()
 $msgcode['updateRealServer']['OK'] = 51;
 function updateRealServer ()
 {
+       global $sic;
        assertUIntArg ('rs_id');
        assertIPv4Arg ('rsip');
        assertStringArg ('rsport', TRUE);
        assertStringArg ('rsconfig', TRUE);
+       assertStringArg ('comment', TRUE);
        commitUpdateRS (
                $_REQUEST['rs_id'],
                $_REQUEST['rsip'],
                $_REQUEST['rsport'],
-               $_REQUEST['rsconfig']
+               (isset ($_REQUEST['inservice']) and $_REQUEST['inservice'] == 'on') ? 'yes' : 'no',
+               $sic['rsconfig'],
+               $sic['comment']
        );
        return showFuncMessage (__FUNCTION__, 'OK');
 }
@@ -1536,6 +1586,7 @@ function updateRealServer ()
 $msgcode['updateVService']['OK'] = 51;
 function updateVService ()
 {
+       global $sic;
        assertUIntArg ('vs_id');
        assertIPv4Arg ('vip');
        assertUIntArg ('vport');
@@ -1549,8 +1600,8 @@ function updateVService ()
                $_REQUEST['vport'],
                $_REQUEST['proto'],
                $_REQUEST['name'],
-               $_REQUEST['vsconfig'],
-               $_REQUEST['rsconfig']
+               $sic['vsconfig'],
+               $sic['rsconfig']
        );
        return showFuncMessage (__FUNCTION__, 'OK');
 }
@@ -1558,20 +1609,20 @@ function updateVService ()
 $msgcode['addLoadBalancer']['OK'] = 48;
 function addLoadBalancer ()
 {
+       global $sic;
        assertUIntArg ('pool_id');
        assertUIntArg ('object_id');
        assertUIntArg ('vs_id');
        assertStringArg ('vsconfig', TRUE);
        assertStringArg ('rsconfig', TRUE);
-       if (! empty($_REQUEST['prio']))
-               assertUIntArg('prio', TRUE);
+       assertStringArg ('prio', TRUE);
 
        addLBtoRSPool (
                $_REQUEST['pool_id'],
                $_REQUEST['object_id'],
                $_REQUEST['vs_id'],
-               $_REQUEST['vsconfig'],
-               $_REQUEST['rsconfig'],
+               $sic['vsconfig'],
+               $sic['rsconfig'],
                $_REQUEST['prio']
        );
        return showFuncMessage (__FUNCTION__, 'OK');
@@ -1580,14 +1631,15 @@ function addLoadBalancer ()
 $msgcode['addRSPool']['OK'] = 48;
 function addRSPool ()
 {
+       global $sic;
        assertStringArg ('name');
        assertStringArg ('vsconfig', TRUE);
        assertStringArg ('rsconfig', TRUE);
        commitCreateRSPool
        (
                $_REQUEST['name'],
-               $_REQUEST['vsconfig'],
-               $_REQUEST['rsconfig'],
+               $sic['vsconfig'],
+               $sic['rsconfig'],
                isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array()
        );
        return showFuncMessage (__FUNCTION__, 'OK');
@@ -1601,29 +1653,6 @@ function deleteRSPool ()
        return showFuncMessage (__FUNCTION__, 'OK');
 }
 
-$msgcode['updateRSInService']['OK'] = 26;
-function updateRSInService ()
-{
-       assertUIntArg ('rscount');
-       $orig = spotEntity ('ipv4rspool', getBypassValue());
-       amplifyCell ($orig);
-       $ngood = 0;
-       for ($i = 1; $i <= $_REQUEST['rscount']; $i++)
-       {
-               $rs_id = $_REQUEST["rsid_${i}"];
-               if (isset ($_REQUEST["inservice_${i}"]) and $_REQUEST["inservice_${i}"] == 'on')
-                       $newval = 'yes';
-               else
-                       $newval = 'no';
-               if ($newval != $orig['rslist'][$rs_id]['inservice'])
-               {
-                       commitSetInService ($rs_id, $newval);
-                       $ngood++;
-               }
-       }
-       return showFuncMessage (__FUNCTION__, 'OK', array ($ngood));
-}
-
 $msgcode['importPTRData']['OK'] = 26;
 $msgcode['importPTRData']['ERR'] = 141;
 // FIXME: check, that each submitted address belongs to the prefix we
@@ -1960,13 +1989,16 @@ function updateRackProblems ()
 
 function querySNMPData ()
 {
-       assertStringArg ('community', TRUE);
-
+       genericAssertion ('ver', 'uint');
        $snmpsetup = array ();
-       if ($_REQUEST['community'] != '')
-               $snmpsetup['community'] = $_REQUEST['community'];
-       else
+       switch ($_REQUEST['ver'])
        {
+       case 1:
+       case 2:
+               genericAssertion ('community', 'string');
+               $snmpsetup['community'] = $_REQUEST['community'];
+               break;
+       case 3:
                assertStringArg ('sec_name');
                assertStringArg ('sec_level');
                assertStringArg ('auth_protocol');
@@ -1980,7 +2012,11 @@ function querySNMPData ()
                $snmpsetup['auth_passphrase'] = $_REQUEST['auth_passphrase'];
                $snmpsetup['priv_protocol'] = $_REQUEST['priv_protocol'];
                $snmpsetup['priv_passphrase'] = $_REQUEST['priv_passphrase'];
+               break;
+       default:
+               throw new InvalidRequestArgException ('ver', $_REQUEST['ver']);
        }
+       $snmpsetup['version'] = $_REQUEST['ver'];
        doSNMPmining (getBypassValue(), $snmpsetup); // shows message by itself
 }
 
@@ -2286,124 +2322,70 @@ function destroyVLANDomain ()
        return showFuncMessage (__FUNCTION__, 'OK');
 }
 
-$msgcode['save8021QPorts']['OK1'] = 63;
-$msgcode['save8021QPorts']['OK2'] = 41;
-$msgcode['save8021QPorts']['ERR2'] = 109;
 function save8021QPorts ()
 {
-       global $sic, $dbxlink;
+       global $sic;
        assertUIntArg ('mutex_rev', TRUE); // counts from 0
        assertStringArg ('form_mode');
        if ($sic['form_mode'] != 'save' and $sic['form_mode'] != 'duplicate')
                throw new InvalidRequestArgException ('form_mode', $sic['form_mode']);
        $extra = array();
-       $dbxlink->beginTransaction();
-       try
+
+       // prepare the $changes array
+       $changes = array();
+       switch ($sic['form_mode'])
        {
-               if (NULL === $vswitch = getVLANSwitchInfo ($sic['object_id'], 'FOR UPDATE'))
-                       throw new InvalidArgException ('object_id', $object_id, 'VLAN domain is not set for this object');
-               if ($vswitch['mutex_rev'] != $sic['mutex_rev'])
-                       throw new InvalidRequestArgException ('mutex_rev', $sic['mutex_rev'], 'expired form data');
-               $after = $before = apply8021QOrder ($vswitch['template_id'], getStored8021QConfig ($sic['object_id'], 'desired'));
-               $changes = array();
-               switch ($sic['form_mode'])
+       case 'save':
+               assertUIntArg ('nports');
+               if ($sic['nports'] == 1)
                {
-               case 'save':
-                       assertUIntArg ('nports');
-                       if ($sic['nports'] == 1)
-                       {
-                               assertStringArg ('pn_0');
-                               $extra = array ('port_name' => $sic['pn_0']);
-                       }
-                       for ($i = 0; $i < $sic['nports']; $i++)
+                       assertStringArg ('pn_0');
+                       $extra = array ('port_name' => $sic['pn_0']);
+               }
+               for ($i = 0; $i < $sic['nports']; $i++)
+               {
+                       assertStringArg ('pn_' . $i);
+                       assertStringArg ('pm_' . $i);
+                       // An access port only generates form input for its native VLAN,
+                       // which we derive allowed VLAN list from.
+                       $native = isset ($sic['pnv_' . $i]) ? $sic['pnv_' . $i] : 0;
+                       switch ($sic["pm_${i}"])
                        {
-                               assertStringArg ('pn_' . $i);
-                               assertStringArg ('pm_' . $i);
-                               // An access port only generates form input for its native VLAN,
-                               // which we derive allowed VLAN list from.
-                               $native = isset ($sic['pnv_' . $i]) ? $sic['pnv_' . $i] : 0;
-                               switch ($sic["pm_${i}"])
-                               {
-                               case 'trunk':
+                       case 'trunk':
 #                              assertArrayArg ('pav_' . $i);
-                                       $allowed = isset ($sic['pav_' . $i]) ? $sic['pav_' . $i] : array();
-                                       break;
-                               case 'access':
-                                       if ($native == 'same')
-                                               continue 2;
-                                       assertUIntArg ('pnv_' . $i);
-                                       $allowed = array ($native);
-                                       break;
-                               default:
-                                       throw new InvalidRequestArgException ("pm_${i}", $_REQUEST["pm_${i}"], 'unknown port mode');
-                               }
-                               $changes[$sic['pn_' . $i]] = array
-                               (
-                                       'mode' => $sic['pm_' . $i],
-                                       'allowed' => $allowed,
-                                       'native' => $native,
-                               );
+                               $allowed = isset ($sic['pav_' . $i]) ? $sic['pav_' . $i] : array();
+                               break;
+                       case 'access':
+                               if ($native == 'same')
+                                       continue 2;
+                               assertUIntArg ('pnv_' . $i);
+                               $allowed = array ($native);
+                               break;
+                       default:
+                               throw new InvalidRequestArgException ("pm_${i}", $_REQUEST["pm_${i}"], 'unknown port mode');
                        }
-                       break;
-               case 'duplicate':
-                       assertStringArg ('from_port');
-#                      assertArrayArg ('to_ports');
-                       if (!array_key_exists ($sic['from_port'], $before))
-                               throw new InvalidArgException ('from_port', $sic['from_port'], 'this port does not exist');
-                       foreach ($sic['to_ports'] as $tpn)
-                               if (!array_key_exists ($tpn, $before))
-                                       throw new InvalidArgException ('to_ports[]', $tpn, 'this port does not exist');
-                               elseif ($tpn != $sic['from_port'])
-                                       $changes[$tpn] = $before[$sic['from_port']];
-                       break;
-               }
-               $domain_vlanlist = getDomainVLANs ($vswitch['domain_id']);
-               $changes = filter8021QChangeRequests
-               (
-                       $domain_vlanlist,
-                       $before,
-                       apply8021QOrder ($vswitch['template_id'], $changes)
-               );
-               $changes = authorize8021QChangeRequests ($before, $changes);
-               foreach ($changes as $port_name => $port)
-                       $after[$port_name] = $port;
-               $new_uplinks = filter8021QChangeRequests ($domain_vlanlist, $after, produceUplinkPorts ($domain_vlanlist, $after, $vswitch['object_id']));
-               $npulled = replace8021QPorts ('desired', $vswitch['object_id'], $before, $changes);
-               $nsaved_uplinks = replace8021QPorts ('desired', $vswitch['object_id'], $before, $new_uplinks);
-       }
-       catch (Exception $e)
-       {
-               $dbxlink->rollBack();
-               showFuncMessage (__FUNCTION__, 'ERR2');
-               return buildRedirectURL (NULL, NULL, $extra);
-       }
-       if ($npulled + $nsaved_uplinks)
-               usePreparedExecuteBlade
-               (
-                       'UPDATE VLANSwitch SET mutex_rev=mutex_rev+1, last_change=NOW(), out_of_sync="yes" WHERE object_id=?',
-                       array ($sic['object_id'])
-               );
-       $dbxlink->commit();
-       showOneLiner (63, array ($npulled + $nsaved_uplinks));
-       if ($nsaved_uplinks)
-       {
-               initiateUplinksReverb ($vswitch['object_id'], $new_uplinks);
-               showOneLiner (41);
-       }
-       if ($npulled + $nsaved_uplinks > 0 and getConfigVar ('8021Q_INSTANT_DEPLOY') == 'yes')
-       {
-               try
-               {
-                       if (FALSE === $done = exec8021QDeploy ($sic['object_id'], TRUE))
-                               showOneLiner (191);
-                       else
-                               showOneLiner (63, array ($done));
-               }
-               catch (Exception $e)
-               {
-                       showOneLiner (109);
+                       $changes[$sic['pn_' . $i]] = array
+                       (
+                               'mode' => $sic['pm_' . $i],
+                               'allowed' => $allowed,
+                               'native' => $native,
+                       );
                }
+               break;
+       case 'duplicate':
+               assertStringArg ('from_port');
+#                      assertArrayArg ('to_ports');
+               $before = getStored8021QConfig ($sic['object_id'], 'desired');
+               if (!array_key_exists ($sic['from_port'], $before))
+                       throw new InvalidArgException ('from_port', $sic['from_port'], 'this port does not exist');
+               foreach ($sic['to_ports'] as $tpn)
+                       if (!array_key_exists ($tpn, $before))
+                               throw new InvalidArgException ('to_ports[]', $tpn, 'this port does not exist');
+                       elseif ($tpn != $sic['from_port'])
+                               $changes[$tpn] = $before[$sic['from_port']];
+               break;
        }
+       apply8021qChangeRequest ($sic['object_id'], $changes, TRUE, $sic['mutex_rev']);
        return buildRedirectURL (NULL, NULL, $extra);
 }
 
@@ -2635,7 +2617,10 @@ function updVSTRule()
        {
                // Every case, which is soft-processed in process.php, will have the working copy available for a retry.
                if ($e instanceof InvalidRequestArgException or $e instanceof RTDatabaseError)
+               {
+                       @session_start();
                        $_SESSION['vst_edited'] = $data;
+               }
                throw $e;
        }
        return showFuncMessage (__FUNCTION__, 'OK');
@@ -2723,6 +2708,16 @@ function addObjectlog ()
        showSuccess ('Log entry added');
 }
 
+function saveQuickLinks()
+{
+       genericAssertion ('page_list', 'array');
+       if (is_array ($_REQUEST['page_list']))
+       {
+               setUserConfigVar ('QUICK_LINK_PAGES', implode(',', $_REQUEST['page_list']));    
+               showSuccess ('Quick links list is saved');
+       }
+}
+
 function getOpspec()
 {
        global $pageno, $tabno, $op, $opspec_list;
@@ -2746,6 +2741,59 @@ function unlinkPort ()
        showSuccess ("Port unlinked successfully");
 }
 
+function clearVlan()
+{
+       assertStringArg ('vlan_ck');
+       list ($vdom_id, $vlan_id) = decodeVLANCK ($_REQUEST['vlan_ck']);
+       
+       $n_cleared = 0;
+       foreach (getVLANConfiguredPorts ($_REQUEST['vlan_ck']) as $object_id => $portnames)
+       {
+               $D = getStored8021QConfig ($object_id);
+               $changes = array();
+               foreach ($portnames as $pn)
+               {
+                       $conf = $D[$pn];
+                       $conf['allowed'] = array_diff ($conf['allowed'], array ($vlan_id));
+                       if ($conf['mode'] == 'access')
+                               $conf['mode'] = 'trunk';
+                       if ($conf['native'] == $vlan_id)
+                               $conf['native'] = 0;
+                       $changes[$pn] = $conf;
+               }
+               $n_cleared += apply8021qChangeRequest ($object_id, $changes, FALSE);
+       }
+       if ($n_cleared > 0)
+               showSuccess ("VLAN $vlan_id removed from $n_cleared ports");
+}
+
+function deleteVlan()
+{
+       assertStringArg ('vlan_ck');
+       $confports = getVLANConfiguredPorts ($_REQUEST['vlan_ck']);
+       if (! empty ($confports))
+               throw new RackTablesError ("You can not delete vlan which has assosiated ports");
+       list ($vdom_id, $vlan_id) = decodeVLANCK ($_REQUEST['vlan_ck']);
+       usePreparedDeleteBlade ('VLANDescription', array ('domain_id' => $vdom_id, 'vlan_id' => $vlan_id));
+       showSuccess ("VLAN $vlan_id has been deleted");
+       return buildRedirectURL ('vlandomain', 'default', array ('vdom_id' => $vdom_id));
+}
+
+function cloneRSPool()
+{
+       assertUIntArg ('pool_id');
+       $pool = spotEntity ('ipv4rspool', $_REQUEST['pool_id']);
+       $rs_list = getRSListInPool ($pool['id']);
+       $tagidlist = array();
+       foreach ($pool['etags'] as $taginfo)
+               $tagidlist[] = $taginfo['id'];
+       $new_id = commitCreateRSPool ($pool['name'] . ' (copy)', $pool['vsconfig'], $pool['rsconfig'], $tagidlist);
+       foreach ($rs_list as $rs)
+               addRStoRSPool ($new_id, $rs['rsip'], $rs['rsport'], $rs['inservice'], $rs['rsconfig'], $rs['comment']);
+       showSuccess ("Created a copy of pool <a href='" . makeHref (array ('page' => 'ipv4rspool', 'tab' => 'default', 'pool_id' => $pool['id'])) . "'>${pool['name']}</a>");
+       return buildRedirectURL ('ipv4rspool', 'default', array ('pool_id' => $new_id));
+}
+
 function tableHandler()
 {
        $opspec = getOpspec();