r1823 + now fix URLs...
[racktables] / inc / ophandlers.php
index b12baf2c80ef5528fc0a0235043efbcf3304df2e..9607f991eaa1fb66da23ebc97a9f53982da667aa 100644 (file)
@@ -5,17 +5,98 @@
 *
 */
 
+// This function assures that specified argument was passed
+// and is a number greater than zero.
+function assertUIntArg ($argname, $allow_zero = FALSE)
+{
+       if (!isset ($_REQUEST[$argname]))
+       {
+               showError ("Parameter '${argname}' is missing.", __FUNCTION__);
+               die();
+       }
+       if (!is_numeric ($_REQUEST[$argname]))
+       {
+               showError ("Parameter '${argname}' is not a number.", __FUNCTION__);
+               die();
+       }
+       if ($_REQUEST[$argname] < 0)
+       {
+               showError ("Parameter '${argname}' is less than zero.", __FUNCTION__);
+               die();
+       }
+       if (!$allow_zero and $_REQUEST[$argname] == 0)
+       {
+               showError ("Parameter '${argname}' is equal to zero.", __FUNCTION__);
+               die();
+       }
+}
+
+// This function assures that specified argument was passed
+// and is a non-empty string.
+function assertStringArg ($argname, $ok_if_empty = FALSE)
+{
+       if (!isset ($_REQUEST[$argname]))
+       {
+               showError ("Parameter '${argname}' is missing.", __FUNCTION__);
+               die();
+       }
+       if (!is_string ($_REQUEST[$argname]))
+       {
+               showError ("Parameter '${argname}' is not a string.", __FUNCTION__);
+               die();
+       }
+       if (!$ok_if_empty and empty ($_REQUEST[$argname]))
+       {
+               showError ("Parameter '${argname}' is an empty string.", __FUNCTION__);
+               die();
+       }
+}
+
+function assertBoolArg ($argname, $ok_if_empty = FALSE)
+{
+       if (!isset ($_REQUEST[$argname]))
+       {
+               showError ("Parameter '${argname}' is missing.", __FUNCTION__);
+               die();
+       }
+       if (!is_string ($_REQUEST[$argname]) or $_REQUEST[$argname] != 'on')
+       {
+               showError ("Parameter '${argname}' is not a string.", __FUNCTION__);
+               die();
+       }
+       if (!$ok_if_empty and empty ($_REQUEST[$argname]))
+       {
+               showError ("Parameter '${argname}' is an empty string.", __FUNCTION__);
+               die();
+       }
+}
+
+function assertIPv4Arg ($argname, $ok_if_empty = FALSE)
+{
+       assertStringArg ($argname, $ok_if_empty);
+       if (!empty ($_REQUEST[$argname]) and long2ip (ip2long ($_REQUEST[$argname])) !== $_REQUEST[$argname])
+       {
+               showError ("IPv4 address validation failed for value '" . $_REQUEST[$argname] . "'", __FUNCTION__);
+               die();
+       }
+}
+
 function addPortForwarding ()
 {
        global $root, $pageno, $tabno;
 
+       assertUIntArg ('object_id');
+       assertIPv4Arg ('localip');
+       assertIPv4Arg ('remoteip');
+       assertUIntArg ('localport');
+       assertUIntArg ('proto');
+       assertStringArg ('description', TRUE);
        $object_id = $_REQUEST['object_id'];
        $localip = $_REQUEST['localip'];
        $remoteip = $_REQUEST['remoteip'];
        $localport = $_REQUEST['localport'];
        $remoteport = $_REQUEST['remoteport'];
        $proto = $_REQUEST['proto'];
-       $mode = $_REQUEST['mode'];
        $description = $_REQUEST['description'];
        if (empty ($remoteport))
                $remoteport = $localport;
@@ -44,7 +125,6 @@ function delPortForwarding ()
        $localport = $_REQUEST['localport'];
        $remoteport = $_REQUEST['remoteport'];
        $proto = $_REQUEST['proto'];
-       $mode = $_REQUEST['mode'];
 
        $retpage="${root}?page=${pageno}&tab=${tabno}&object_id=$object_id";
 
@@ -278,6 +358,17 @@ http://www.cisco.com/en/US/products/hw/routers/ps274/products_tech_note09186a008
                                        'label' => "${ifnumber}"
                                );
                                break;
+                       case 'ssv1':
+                               $words = explode (' ', $line);
+                               if (empty ($words[0]) or empty ($words[1]))
+                                       continue;
+                               $ports[] = array
+                               (
+                                       'name' => $words[0],
+                                       'l2address' => $words[1],
+                                       'label' => ''
+                               );
+                               break;
                        default:
                                return
                                        "${root}?page=${pageno}&tab=${tabno}&object_id=${object_id}&error=" .
@@ -483,19 +574,19 @@ function addAddressToObject ()
 {
        global $root, $pageno, $tabno;
 
-       $ip = $_REQUEST['ip'];
+       assertStringArg ('ip');
+       assertUIntArg ('object_id');
+       assertStringArg ('name', TRUE);
+       assertStringArg ('type');
+       // Strip masklen.
+       $ip = ereg_replace ('/[[:digit:]]+$', '', $_REQUEST['ip']);
        $object_id = $_REQUEST['object_id'];
-       $name = $_REQUEST['name'];
-       $type = $_REQUEST['type'];
-       $error = bindIpToObject($ip, $object_id, $name, $type);
+       $error = bindIpToObject($ip, $object_id, $_REQUEST['name'], $_REQUEST['type']);
        if ($error != '')
-       {
-               return "${root}?page=${pageno}&tab=${tabno}&object_id=$object_id&error=".urlencode($error);
-       }
+               return "${root}?page=${pageno}&tab=${tabno}&object_id=${object_id}&error=".urlencode($error);
        else
-       {
-               return "${root}?page=$pageno&tab=${tabno}&object_id=$object_id&message=".urlencode("Interface successfully added");
-       }
+               return "${root}?page=$pageno&tab=${tabno}&object_id=${object_id}&message=".
+                       urlencode("Address ${ip} was added successfully.");
 }
 
 function createUserAccount ()
@@ -858,60 +949,6 @@ function useupPort ()
                return "${root}?page=${pageno}&tab=${tabno}&object_id=${object_id}&error=" . urlencode ("Error removing reservation!");
 }
 
-// This function processes a submit from the VLAN configuration form.
-// It doesn't check any data at the moment, relying on a smart gateway.
-// It doesn't even check if the a port already belongs to the VLAN it
-// is being requested to be put into. This behaviour implies having a
-// smart enough gateway, which unconditionally fetches the current
-// configuration and then filters out 'set' requests. The gateway must
-// validate port names and VLAN numbers as well. Ouch.
-function updateVLANMembership ()
-{
-       global $root, $pageno, $tabno, $remote_username;
-       assertUIntArg ('object_id');
-       assertUIntArg ('portcount');
-       $object_id = $_REQUEST['object_id'];
-       $portcount  = $_REQUEST['portcount'];
-
-       $endpoints = findAllEndpoints ($object_id);
-       if (count ($endpoints) == 0)
-               return "${root}?page=${pageno}&tab=${tabno}&object_id=${object_id}&error=" .
-                       urlencode ('Can\'t find any mean to reach current object. Please either set FQDN attribute or assign an IP address to the object.');
-       elseif (count ($endpoints) > 1)
-               return "${root}?page=${pageno}&tab=${tabno}&object_id=${object_id}&error=" .
-                       urlencode ('More than one IP address is assigned to this object, please configure FQDN attribute.');
-
-// Just convert the input and feed it into the gateway.
-       $questions = array("connect ${endpoints[0]} hwtype swtype ${remote_username}");
-       for ($i = 0; $i < $portcount; $i++)
-       {
-               if (!isset ($_REQUEST["portname_${i}"]))
-                       continue;
-               if (!isset ($_REQUEST["vlanid_${i}"]))
-                       continue;
-               $portname = $_REQUEST["portname_${i}"];
-               $vlanid = $_REQUEST["vlanid_${i}"];
-               $questions[] = "set ${portname} ${vlanid}";
-       }
-       $data = queryGateway
-       (
-               $tabno,
-               $questions
-       );
-       $error_count = $success_count = 0;
-       foreach ($data as $reply)
-               if (strncmp ($reply, 'OK!', 3))
-                       $error_count++;
-               else
-                       $success_count++;
-// Generate a message depending on error counter and redirect.
-       return
-               "${root}?page=${pageno}&tab=${tabno}&object_id=${object_id}&" .
-               ($error_count == 0 ? 'message' : 'error') .
-               "=" . urlencode ("${error_count} failures and ${success_count} successfull changes.");
-
-}
-
 function updateUI ()
 {
        global $root, $pageno, $tabno;
@@ -947,7 +984,7 @@ function updateUI ()
 function resetUIConfig()
 {
        global $root, $pageno, $tabno;
-       setConfigVar ('default_port_type','11');
+       setConfigVar ('default_port_type','24');
        setConfigVar ('MASSCOUNT','15');
        setConfigVar ('MAXSELSIZE','30');
        setConfigVar ('NAMEFUL_OBJTYPES','4,7,8');
@@ -956,22 +993,91 @@ function resetUIConfig()
        setConfigVar ('IPV4_ADDRS_PER_PAGE','256');
        setConfigVar ('DEFAULT_RACK_HEIGHT','42');
        setConfigVar ('REQUIRE_ASSET_TAG_FOR','4,7,8');
+       setConfigVar ('USER_AUTH_SRC','database');
+       setConfigVar ('DEFAULT_SLB_VS_PORT','');
+       setConfigVar ('DEFAULT_SLB_RS_PORT','');
+       setConfigVar ('IPV4_PERFORMERS','1,4,7,8,12,14,445,447');
+       setConfigVar ('NATV4_PERFORMERS','4,7,8');
+       setConfigVar ('DETECT_URLS','no');
+       setConfigVar ('RACK_PRESELECT_THRESHOLD','1');
+       setConfigVar ('DEFAULT_IPV4_RS_INSERVICE','no');
+       setConfigVar ('AUTOPORTS_CONFIG','4 = 1*33*kvm + 2*24*eth%u;15 = 1*446*kvm');
+       setConfigVar ('SHOW_EXPLICIT_TAGS','yes');
+       setConfigVar ('SHOW_IMPLICIT_TAGS','yes');
+       setConfigVar ('SHOW_AUTOMATIC_TAGS','no');
+       setConfigVar ('DEFAULT_OBJECT_TYPE','4');
        return "${root}?page=${pageno}&tab=default&message=" . urlencode ("Reset complete");
 }
 
+// Add single record.
 function addRealServer ()
 {
        global $root, $pageno, $tabno;
 
        assertUIntArg ('id');
-       assertIPv4Arg ('rsip');
+       assertIPv4Arg ('remoteip');
        assertUIntArg ('rsport');
        assertStringArg ('rsconfig', TRUE);
        $pool_id = $_REQUEST['id'];
-       if (!addRStoRSPool ($pool_id, $_REQUEST['rsip'], $_REQUEST['rsport'], $_REQUEST['rsconfig']))
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&error=" . urlencode ('addRStoRSPool() failed');
+       if (!addRStoRSPool ($pool_id, $_REQUEST['remoteip'], $_REQUEST['rsport'], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), $_REQUEST['rsconfig']))
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&error=" . urlencode ('addRStoRSPool() failed');
        else
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&message=" . urlencode ("Real server was successfully added");
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&message=" . urlencode ("Real server was successfully added");
+}
+
+// Parse textarea submitted and try adding a real server for each line.
+function addRealServers ()
+{
+       global $root, $pageno, $tabno;
+
+       assertUIntArg ('id');
+       assertStringArg ('format');
+       assertStringArg ('rawtext');
+       $pool_id = $_REQUEST['id'];
+       $rawtext = str_replace ('\r', '', $_REQUEST['rawtext']);
+       $ngood = $nbad = 0;
+       $rsconfig = '';
+       // Keep in mind, that the text will have HTML entities (namely '>') escaped.
+       foreach (explode ('\n', $rawtext) as $line)
+       {
+               if (empty ($line))
+                       continue;
+               $match = array ();
+               switch ($_REQUEST['format'])
+               {
+                       case 'ipvs_2': // address and port only
+                               if (!preg_match ('/^  -&gt; ([0-9\.]+):([0-9]+) /', $line, $match))
+                                       continue;
+                               if (addRStoRSPool ($pool_id, $match[1], $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), ''))
+                                       $ngood++;
+                               else
+                                       $nbad++;
+                               break;
+                       case 'ipvs_3': // address, port and weight
+                               if (!preg_match ('/^  -&gt; ([0-9\.]+):([0-9]+) +[a-zA-Z]+ +([0-9]+) /', $line, $match))
+                                       continue;
+                               if (addRStoRSPool ($pool_id, $match[1], $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), 'weight ' . $match[3]))
+                                       $ngood++;
+                               else
+                                       $nbad++;
+                               break;
+                       case 'ssv_2': // IP address and port
+                               if (!preg_match ('/^([0-9\.]+) ([0-9]+)$/', $line, $match))
+                                       continue;
+                               if (addRStoRSPool ($pool_id, $match[1], $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), ''))
+                                       $ngood++;
+                               else
+                                       $nbad++;
+                               break;
+                       default:
+                               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&error=" . urlencode (__FUNCTION__ . ': invalid format requested');
+                               break;
+               }
+       }
+       if ($nbad == 0 and $ngood > 0)
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&message=" . urlencode ("Successfully added ${ngood} real servers");
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&error=" . urlencode ("Added ${ngood} real servers and encountered ${nbad} errors");
 }
 
 function addVService ()
@@ -1002,9 +1108,9 @@ function deleteRealServer ()
        assertUIntArg ('id');
        $pool_id = $_REQUEST['pool_id'];
        if (!commitDeleteRS ($_REQUEST['id']))
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&error=" . urlencode ('commitDeleteRS() failed');
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&error=" . urlencode ('commitDeleteRS() failed');
        else
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&message=" . urlencode ("Real server was successfully deleted");
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&message=" . urlencode ("Real server was successfully deleted");
 }
 
 function deleteLoadBalancer ()
@@ -1013,11 +1119,12 @@ function deleteLoadBalancer ()
 
        assertUIntArg ('object_id');
        assertUIntArg ('pool_id');
+       assertUIntArg ('vs_id');
        $pool_id = $_REQUEST['pool_id'];
-       if (!commitDeleteLB ($_REQUEST['object_id'], $pool_id))
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&error=" . urlencode ('commitDeleteLB() failed');
+       if (!commitDeleteLB ($_REQUEST['object_id'], $pool_id, $_REQUEST['vs_id']))
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&error=" . urlencode ('commitDeleteLB() failed');
        else
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&message=" . urlencode ("Load balancer was successfully deleted");
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&message=" . urlencode ("Load balancer was successfully deleted");
 }
 
 function deleteVService ()
@@ -1036,31 +1143,32 @@ function updateRealServer ()
        global $root, $pageno, $tabno;
 
        assertUIntArg ('id');
-       assertUIntArg ('pool_id');
+       assertUIntArg ('rs_id');
        assertIPv4Arg ('rsip');
        assertUIntArg ('rsport');
        assertStringArg ('rsconfig', TRUE);
        // only necessary for generating next URL
-       $pool_id = $_REQUEST['pool_id'];
-       if (!commitUpdateRS ($_REQUEST['id'], $_REQUEST['rsip'], $_REQUEST['rsport'], $_REQUEST['rsconfig']))
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&error=" . urlencode ('commitUpdateRS() failed');
+       $pool_id = $_REQUEST['id'];
+       if (!commitUpdateRS ($_REQUEST['rs_id'], $_REQUEST['rsip'], $_REQUEST['rsport'], $_REQUEST['rsconfig']))
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&error=" . urlencode ('commitUpdateRS() failed');
        else
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&message=" . urlencode ("Real server was successfully updated");
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&message=" . urlencode ("Real server was successfully updated");
 }
 
-function updateLoadbalancer ()
+function updateLoadBalancer ()
 {
        global $root, $pageno, $tabno;
 
        assertUIntArg ('object_id');
        assertUIntArg ('pool_id');
+       assertUIntArg ('vs_id');
        assertStringArg ('vsconfig', TRUE);
        assertStringArg ('rsconfig', TRUE);
        $pool_id = $_REQUEST['pool_id'];
-       if (!commitUpdateLB ($_REQUEST['object_id'], $pool_id, $_REQUEST['vsconfig'], $_REQUEST['rsconfig']))
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&error=" . urlencode ('commitUpdateLB() failed');
+       if (!commitUpdateLB ($_REQUEST['object_id'], $pool_id, $_REQUEST['vs_id'], $_REQUEST['vsconfig'], $_REQUEST['rsconfig']))
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&error=" . urlencode ('commitUpdateLB() failed');
        else
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&message=" . urlencode ("Real server was successfully updated");
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&message=" . urlencode ("Load balancer info was successfully updated");
 }
 
 function updateVService ()
@@ -1086,16 +1194,197 @@ function addLoadBalancer ()
 
        assertUIntArg ('pool_id');
        assertUIntArg ('object_id');
+       assertUIntArg ('vs_id');
        assertStringArg ('vsconfig', TRUE);
        assertStringArg ('rsconfig', TRUE);
        $pool_id = $_REQUEST['pool_id'];
+       if (!addLBtoRSPool ($pool_id, $_REQUEST['object_id'], $_REQUEST['vs_id'], $_REQUEST['vsconfig'], $_REQUEST['rsconfig']))
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&error=" . urlencode ('addLBtoRSPool() failed');
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&message=" . urlencode ("Load balancer was successfully added");
+}
+
+function addRSPool ()
+{
+       global $root, $pageno, $tabno;
+
+       assertStringArg ('name', TRUE);
+       assertStringArg ('vsconfig', TRUE);
+       assertStringArg ('rsconfig', TRUE);
+       if (!commitCreateRSPool ($_REQUEST['name'], $_REQUEST['vsconfig'], $_REQUEST['rsconfig']))
+               return "${root}?page=${pageno}&tab=${tabno}&error=" . urlencode ('commitCreateRSPool() failed');
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&message=" . urlencode ("Real server pool was successfully created");
+}
+
+function deleteRSPool ()
+{
+       global $root, $pageno, $tabno;
+
+       assertUIntArg ('pool_id');
+       if (!commitDeleteRSPool ($_REQUEST['pool_id']))
+               return "${root}?page=${pageno}&tab=${tabno}&error=" . urlencode ('commitDeleteRSPool() failed');
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&message=" . urlencode ("Real server pool was successfully deleted");
+}
+
+function updateRSPool ()
+{
+       global $root, $pageno, $tabno;
+
+       assertUIntArg ('pool_id');
+       assertStringArg ('name', TRUE);
+       assertStringArg ('vsconfig', TRUE);
+       assertStringArg ('rsconfig', TRUE);
+       if (!commitUpdateRSPool ($_REQUEST['pool_id'], $_REQUEST['name'], $_REQUEST['vsconfig'], $_REQUEST['rsconfig']))
+               return "${root}?page=${pageno}&tab=${tabno}&error=" . urlencode ('commitUpdateRSPool() failed');
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&message=" . urlencode ("Real server pool was successfully updated");
+}
+
+function updateRSInService ()
+{
+       global $root, $pageno, $tabno;
+       assertUIntArg ('pool_id');
+       assertUIntArg ('rscount');
+       $pool_id = $_REQUEST['pool_id'];
+       $orig = getRSPoolInfo ($pool_id);
+       $nbad = $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'])
+               {
+                       if (commitSetInService ($rs_id, $newval))
+                               $ngood++;
+                       else
+                               $nbad++;
+               }
+       }
+       if (!$nbad)
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&message=" . urlencode ($ngood . " real server(s) were successfully (de)activated");
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&pool_id=${pool_id}&error=" . urlencode ("Encountered ${nbad} errors, (de)activated ${ngood} real servers");
+}
+
+function importPTRData ()
+{
+       global $root, $pageno, $tabno;
+       assertUIntArg ('id');
+       assertUIntArg ('addrcount');
+       $nbad = $ngood = 0;
+       $id = $_REQUEST['id'];
+       for ($i = 0; $i < $_REQUEST['addrcount']; $i++)
+       {
+               $inputname = "import_${i}";
+               if (!isset ($_REQUEST[$inputname]) or $_REQUEST[$inputname] != 'on')
+                       continue;
+               assertIPv4Arg ("addr_${i}");
+               assertStringArg ("descr_${i}", TRUE);
+               assertStringArg ("rsvd_${i}");
+               // Non-existent addresses will not have this argument set in request.
+               $rsvd = 'no';
+               if ($_REQUEST["rsvd_${i}"] == 'yes')
+                       $rsvd = 'yes';
+               if (updateAddress ($_REQUEST["addr_${i}"], $_REQUEST["descr_${i}"], $rsvd) == '')
+                       $ngood++;
+               else
+                       $nbad++;
+       }
+       if (!$nbad)
+               return "${root}?page=${pageno}&tab=${tabno}&id=${id}&message=" . urlencode ($ngood . " IP address(es) were successfully updated");
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&id=${id}&error=" . urlencode ("Encountered ${nbad} errors, updated ${ngood} IP address(es)");
+}
+
+function generateAutoPorts ()
+{
+       global $root, $pageno, $tabno;
+       assertUIntArg ('object_id');
        $object_id = $_REQUEST['object_id'];
-       $vsconfig = $_REQUEST['vsconfig'];
-       $rsconfig = $_REQUEST['rsconfig'];
-       if (!addLBtoRSPool ($pool_id, $object_id, $vsconfig, $rsconfig))
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&error=" . urlencode ('addLBtoRSPool() failed');
+       $info = getObjectInfo ($object_id);
+       // Navigate away in case of success, stay at the place otherwise.
+       if (executeAutoPorts ($object_id, $info['objtype_id']))
+               return "${root}?page=${pageno}&tab=ports&object_id=${object_id}&message=" . urlencode ('Generation complete');
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&object_id=${object_id}&error=" . urlencode ('executeAutoPorts() failed');
+}
+
+// Filter out implicit tags before storing the new tag set.
+function saveEntityTags ($realm, $bypass)
+{
+       global $root, $pageno, $tabno, $explicit_tags, $implicit_tags;
+       assertUIntArg ($bypass);
+       $entity_id = $_REQUEST[$bypass];
+       // Build a trail from the submitted data, minimize it,
+       // then wipe existing records and store the new set instead.
+       wipeTags ($realm, $entity_id);
+       $newtrail = getExplicitTagsOnly (buildTrailFromIds ($_REQUEST['taglist']));
+       $n_succeeds = $n_errors = 0;
+       foreach ($newtrail as $taginfo)
+       {
+               if (useInsertBlade ('TagStorage', array ('target_realm' => "'${realm}'", 'target_id' => $entity_id, 'tag_id' => $taginfo['id'])))
+                       $n_succeeds++;
+               else
+                       $n_errors++;
+       }
+       if ($n_errors)
+               return "${root}?page=${pageno}&tab=${tabno}&${bypass}=${entity_id}&error=" . urlencode ("Replaced trail with ${n_succeeds} tags, but experienced ${n_errors} errors.");
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&${bypass}=${entity_id}&message=" . urlencode ("New trail is ${n_succeeds} tags long");
+}
+
+function saveObjectTags ()
+{
+       return saveEntityTags ('object', 'object_id');
+}
+
+function saveIPv4PrefixTags ()
+{
+       return saveEntityTags ('ipv4net', 'id');
+}
+
+function saveRackTags ()
+{
+       return saveEntityTags ('rack', 'rack_id');
+}
+
+function saveIPv4VSTags ()
+{
+       return saveEntityTags ('ipv4vs', 'id');
+}
+
+function saveIPv4RSPoolTags ()
+{
+       return saveEntityTags ('ipv4rspool', 'id');
+}
+
+function destroyTag ()
+{
+       global $root, $pageno, $tabno;
+       assertUIntArg ('id');
+       if (($ret = commitDestroyTag ($_REQUEST['id'])) == '')
+               return "${root}?page=${pageno}&tab=${tabno}&message=" . urlencode ("Successfully deleted tag.");
+       else
+               return "${root}?page=${pageno}&tab=${tabno}&error=" . urlencode ("Error deleting tag: '${ret}'");
+}
+
+function createTag ()
+{
+       global $root, $pageno, $tabno;
+       assertStringArg ('tagname');
+       assertUIntArg ('parent_id', TRUE);
+       $tagname = trim ($_REQUEST['tagname']);
+       if (($parent_id = $_REQUEST['parent_id']) <= 0)
+               $parent_id = 'NULL';
+       if (($ret = commitCreateTag ($tagname, $parent_id)) == '')
+               return "${root}?page=${pageno}&tab=${tabno}&message=" . urlencode ("Created tag '${tagname}'.");
        else
-               return "${root}?page=${pageno}&tab=${tabno}&id=${pool_id}&message=" . urlencode ("Load balancer was successfully added");
+               return "${root}?page=${pageno}&tab=${tabno}&error=" . urlencode ("Could not create tag '${tagname}' because of error '${ret}'");
 }
 
 ?>