r1724 + generateAutoPorts(): welcome new ophandler
[racktables] / inc / database.php
index f037006af8b455c4e00995b0e287b9d3d050b126..4f2fba50782b7e608418801d3e9c7df13b19d2f7 100644 (file)
@@ -5,10 +5,15 @@
 *
 */
 
-function escapeString ($value)
+function escapeString ($value, $do_db_escape = TRUE)
 {
-       global $dbxlink;
-       return substr ($dbxlink->quote (htmlentities ($value)), 1, -1);
+       $ret = htmlentities ($value, ENT_QUOTES);
+       if ($do_db_escape)
+       {
+               global $dbxlink;
+               $ret = substr ($dbxlink->quote ($ret), 1, -1);
+       }
+       return $ret;
 }
 
 // This function returns detailed information about either all or one
@@ -371,6 +376,8 @@ function commitAddObject ($new_name, $new_label, $new_barcode, $new_type_id, $ne
        $row = $result2->fetch (PDO::FETCH_NUM);
        $last_insert_id = $row[0];
        $result2->closeCursor();
+       // Do AutoPorts magic
+       executeAutoPorts ($last_insert_id, $new_type_id);
        return recordHistory ('RackObject', "id = ${last_insert_id}");
 }
 
@@ -465,7 +472,7 @@ function processGridForm (&$rackData, $unchecked_state, $checked_state, $object_
                                "unit_no = ${unit_no} and atom = '${atom}' limit 1";
                        $r = $dbxlink->query ($query);
                        if ($r == NULL)
-                               return array ('code' => 500, 'message' => "${rack_name}: SQL DELETE query failed in processGridForm()");
+                               return array ('code' => 500, 'message' => __FUNCTION__ . ": ${rack_name}: SQL DELETE query failed");
                        if ($newstate != 'F')
                        {
                                $query =
@@ -473,7 +480,7 @@ function processGridForm (&$rackData, $unchecked_state, $checked_state, $object_
                                        "values(${rack_id}, ${unit_no}, '${atom}', '${newstate}') ";
                                $r = $dbxlink->query ($query);
                                if ($r == NULL)
-                                       return array ('code' => 500, 'message' => "${rack_name}: SQL INSERT query failed in processGridForm()");
+                                       return array ('code' => 500, 'message' => __FUNCTION__ . ": ${rack_name}: SQL INSERT query failed");
                        }
                        if ($newstate == 'T' and $object_id != 0)
                        {
@@ -490,7 +497,10 @@ function processGridForm (&$rackData, $unchecked_state, $checked_state, $object_
                }
        }
        if ($rackchanged)
+       {
+               resetThumbCache ($rack_id);
                return array ('code' => 200, 'message' => "${rack_name}: All changes were successfully saved.");
+       }
        else
                return array ('code' => 300, 'message' => "${rack_name}: No changes.");
 }
@@ -594,7 +604,7 @@ function recordHistory ($tableName, $whereClause)
        $result = $dbxlink->query ($query);
        if ($result == NULL or $result->rowCount() != 1)
        {
-               showError ("SQL query failed for table ${tableName}", __FUNCTION__);
+               showError ("SQL query '${query}' failed for table ${tableName}", __FUNCTION__);
                return FALSE;
        }
        return TRUE;
@@ -648,7 +658,7 @@ function getOperationMolecules ($op_id = 0)
        return array ($omid, $nmid);
 }
 
-function getResidentRacksData ($object_id = 0)
+function getResidentRacksData ($object_id = 0, $fetch_rackdata = TRUE)
 {
        if ($object_id <= 0)
        {
@@ -668,6 +678,11 @@ function getResidentRacksData ($object_id = 0)
        $ret = array();
        foreach ($rows as $row)
        {
+               if (!$fetch_rackdata)
+               {
+                       $ret[$row[0]] = $row[0];
+                       continue;
+               }
                $rackData = getRackData ($row[0]);
                if ($rackData == NULL)
                {
@@ -808,9 +823,9 @@ function commitUpdatePort ($port_id, $port_name, $port_label, $port_l2address, $
 function delObjectPort ($port_id)
 {
        if (unlinkPort ($port_id) != '')
-               return 'unlinkPort() failed in delObjectPort()';
+               return __FUNCTION__ . ': unlinkPort() failed';
        if (useDeleteBlade ('Port', 'id', $port_id) != TRUE)
-               return 'useDeleteBlade() failed in delObjectPort()';
+               return __FUNCTION__ . ': useDeleteBlade() failed';
        return '';
 }
 
@@ -1103,11 +1118,11 @@ function updateAddress ($ip=0, $name='', $reserved='no')
 function commitDeleteRange ($id = 0)
 {
        if ($id <= 0)
-               return 'Invalid range ID in commitDeleteRange()';
+               return __FUNCTION__ . ': Invalid range ID';
        if (useDeleteBlade ('IPRanges', 'id', $id))
                return '';
        else
-               return 'SQL query failed in commitDeleteRange';
+               return __FUNCTION__ . ': SQL query failed';
 }
 
 function updateBond ($ip='', $object_id=0, $name='', $type='')
@@ -1352,17 +1367,17 @@ function addPortCompat ($type1 = 0, $type2 = 0)
 function getDict ()
 {
        global $dbxlink;
-       $query =
+       $query1 =
                "select chapter_name, Chapter.chapter_no, dict_key, dict_value, sticky from " .
                "Chapter natural left join Dictionary order by chapter_name, dict_value";
-       $result = $dbxlink->query ($query);
-       if ($result == NULL)
+       $result1 = $dbxlink->query ($query1);
+       if ($result1 == NULL)
        {
-               showError ('SQL query failed', __FUNCTION__);
+               showError ('SQL query #1 failed', __FUNCTION__);
                return NULL;
        }
        $dict = array();
-       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+       while ($row = $result1->fetch (PDO::FETCH_ASSOC))
        {
                $chapter_no = $row['chapter_no'];
                if (!isset ($dict[$chapter_no]))
@@ -1373,15 +1388,37 @@ function getDict ()
                        $dict[$chapter_no]['word'] = array();
                }
                if ($row['dict_key'] != NULL)
+               {
                        $dict[$chapter_no]['word'][$row['dict_key']] = $row['dict_value'];
+                       $dict[$chapter_no]['refcnt'][$row['dict_key']] = 0;
+               }
        }
-       $result->closeCursor();
+       $result1->closeCursor();
+// Find the list of all assigned values of dictionary-addressed attributes, each with
+// chapter/word keyed reference counters. Use the structure to adjust reference counters
+// of the returned disctionary words.
+       $query2 = "select a.attr_id, am.chapter_no, uint_value, count(object_id) as refcnt " .
+               "from Attribute as a inner join AttributeMap as am on a.attr_id = am.attr_id " .
+               "inner join AttributeValue as av on a.attr_id = av.attr_id " .
+               "inner join Dictionary as d on am.chapter_no = d.chapter_no and av.uint_value = d.dict_key " .
+               "where attr_type = 'dict' group by a.attr_id, am.chapter_no, uint_value " .
+               "order by a.attr_id, am.chapter_no, uint_value";
+       $result2 = $dbxlink->query ($query2);
+       if ($result2 == NULL)
+       {
+               showError ('SQL query #2 failed', __FUNCTION__);
+               return NULL;
+       }
+       $refcnt = array();
+       while ($row = $result2->fetch (PDO::FETCH_ASSOC))
+               $dict[$row['chapter_no']]['refcnt'][$row['uint_value']] = $row['refcnt'];
+       $result2->closeCursor();
        return $dict;
 }
 
 function getDictStats ()
 {
-       $stock_chapters = array (1, 2, 3, 11, 12, 13, 14, 16, 17, 18, 19, 20);
+       $stock_chapters = array (1, 2, 3, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23);
        global $dbxlink;
        $query =
                "select Chapter.chapter_no, chapter_name, count(dict_key) as wc from " .
@@ -1433,6 +1470,62 @@ function getDictStats ()
        return $ret;
 }
 
+function getIPv4Stats()
+{
+       global $dbxlink;
+       $ret = array();
+       $subject = array();
+       $subject[] = array ('q' => 'select count(id) from IPRanges', 'txt' => 'Networks');
+       $subject[] = array ('q' => 'select count(ip) from IPAddress', 'txt' => 'Addresses commented/reserved');
+       $subject[] = array ('q' => 'select count(ip) from IPBonds', 'txt' => 'Addresses allocated');
+       $subject[] = array ('q' => 'select count(*) from PortForwarding', 'txt' => 'NAT rules');
+       $subject[] = array ('q' => 'select count(id) from IPVirtualService', 'txt' => 'Virtual services');
+       $subject[] = array ('q' => 'select count(id) from IPRSPool', 'txt' => 'Real server pools');
+       $subject[] = array ('q' => 'select count(id) from IPRealServer', 'txt' => 'Real servers');
+       $subject[] = array ('q' => 'select count(distinct object_id) from IPLoadBalancer', 'txt' => 'Load balancers');
+
+       foreach ($subject as $item)
+       {
+               $result = $dbxlink->query ($item['q']);
+               if ($result == NULL)
+               {
+                       showError ("SQL query '${item['q']}' failed", __FUNCTION__);
+                       return NULL;
+               }
+               $row = $result->fetch (PDO::FETCH_NUM);
+               $ret[$item['txt']] = $row[0];
+               $result->closeCursor();
+               unset ($result);
+       }
+       return $ret;
+}
+
+function getRackspaceStats()
+{
+       global $dbxlink;
+       $ret = array();
+       $subject = array();
+       $subject[] = array ('q' => 'select count(*) from Dictionary where chapter_no = 3', 'txt' => 'Rack rows');
+       $subject[] = array ('q' => 'select count(*) from Rack', 'txt' => 'Racks');
+       $subject[] = array ('q' => 'select avg(height) from Rack', 'txt' => 'Average rack height');
+       $subject[] = array ('q' => 'select sum(height) from Rack', 'txt' => 'Total rack units in field');
+
+       foreach ($subject as $item)
+       {
+               $result = $dbxlink->query ($item['q']);
+               if ($result == NULL)
+               {
+                       showError ("SQL query '${item['q']}' failed", __FUNCTION__);
+                       return NULL;
+               }
+               $row = $result->fetch (PDO::FETCH_NUM);
+               $ret[$item['txt']] = empty ($row[0]) ? 0 : $row[0];
+               $result->closeCursor();
+               unset ($result);
+       }
+       return $ret;
+}
+
 function commitUpdateDictionary ($chapter_no = 0, $dict_key = 0, $dict_value = '')
 {
        if ($chapter_no <= 0 or $dict_key <= 0 or empty ($dict_value))
@@ -1956,13 +2049,13 @@ function getDatabaseVersion ()
                $errorInfo = $dbxlink->errorInfo();
                if ($errorInfo[0] == '42S02') // ER_NO_SUCH_TABLE
                        return '0.14.4';
-               die ('SQL query #1 failed in getDatabaseVersion() with error ' . $errorInfo[2]);
+               die (__FUNCTION__ . ': SQL query #1 failed with error ' . $errorInfo[2]);
        }
        $rows = $result->fetchAll (PDO::FETCH_NUM);
        if (count ($rows) != 1 || empty ($rows[0][0]))
        {
                $result->closeCursor();
-               die ('Cannot guess database version. Config table is present, but DB_VERSION is missing or invalid. Giving up.');
+               die (__FUNCTION__ . ': Cannot guess database version. Config table is present, but DB_VERSION is missing or invalid. Giving up.');
        }
        $ret = $rows[0][0];
        $result->closeCursor();
@@ -1974,12 +2067,12 @@ function getDatabaseVersion ()
 function getSLBSummary ()
 {
        global $dbxlink;
-       $query = 'select vs.id as vsid, inet_ntoa(vip) as vip, vport, proto, ' .
-               'vs.name, rsp.id as pool_id, rsp.name as pool_name, object_id, count(rs.id) as rscount from ' .
-               'IPVirtualService as vs inner join IPRSPool as rsp on vs.id = rsp.vs_id ' .
-               'inner join IPRealServer as rs on rs.rspool_id = rsp.id ' .
-               'inner join IPLoadBalancer as lb on rsp.id = lb.rspool_id ' .
-               'group by rsp.id, object_id order by vip, object_id';
+       $query = 'select vs.id as vsid, inet_ntoa(vip) as vip, vport, proto, vs.name, object_id, ' .
+               'lb.rspool_id, pool.name as pool_name, count(rs.id) as rscount ' .
+               'from IPVirtualService as vs inner join IPLoadBalancer as lb on vs.id = lb.vs_id ' .
+               'inner join IPRSPool as pool on lb.rspool_id = pool.id ' .
+               'left join IPRealServer as rs on rs.rspool_id = lb.rspool_id ' .
+               'group by vs.id, object_id order by vs.vip, object_id';
        $result = $dbxlink->query ($query);
        if ($result == NULL)
        {
@@ -1999,7 +2092,13 @@ function getSLBSummary ()
                                $ret[$vsid][$cname] = $row[$cname];
                        $ret[$vsid]['lblist'] = array();
                }
-               $ret[$vsid]['lblist'][$row['object_id']][$row['pool_id']] = array ('size' => $row['rscount'], 'name' => $row['pool_name']);
+               // There's only one assigned RS pool possible for each LB-VS combination.
+               $ret[$vsid]['lblist'][$row['object_id']] = array
+               (
+                       'id' => $row['rspool_id'],
+                       'size' => $row['rscount'],
+                       'name' => $row['pool_name']
+               );
        }
        $result->closeCursor();
        return $ret;
@@ -2061,13 +2160,13 @@ function getVServiceInfo ($vsid = 0)
 // Collect and return the following info about the given real server pool:
 // basic information
 // parent virtual service information
-// load balancers list
+// load balancers list (each with a list of VSes)
 // real servers list
 
 function getRSPoolInfo ($id = 0)
 {
        global $dbxlink;
-       $query1 = "select ${id} as id, vs_id, name, vsconfig, rsconfig from " .
+       $query1 = "select id, name, vsconfig, rsconfig from " .
                "IPRSPool where id = ${id}";
        $result1 = $dbxlink->query ($query1);
        if ($result1 == NULL)
@@ -2079,12 +2178,12 @@ function getRSPoolInfo ($id = 0)
        $row = $result1->fetch (PDO::FETCH_ASSOC);
        if (!$row)
                return NULL;
-       foreach (array ('id', 'name', 'vsconfig', 'rsconfig', 'vs_id') as $c)
+       foreach (array ('id', 'name', 'vsconfig', 'rsconfig') as $c)
                $ret[$c] = $row[$c];
        $result1->closeCursor();
        $ret['lblist'] = array();
        $ret['rslist'] = array();
-       $query2 = "select object_id, vsconfig, rsconfig from IPLoadBalancer where rspool_id = ${id} order by object_id";
+       $query2 = "select object_id, vs_id, vsconfig, rsconfig from IPLoadBalancer where rspool_id = ${id} order by object_id";
        $result2 = $dbxlink->query ($query2);
        if ($result2 == NULL)
        {
@@ -2093,9 +2192,10 @@ function getRSPoolInfo ($id = 0)
        }
        while ($row = $result2->fetch (PDO::FETCH_ASSOC))
                foreach (array ('vsconfig', 'rsconfig') as $c)
-                       $ret['lblist'][$row['object_id']][$c] = $row[$c];
+                       $ret['lblist'][$row['object_id']][$row['vs_id']][$c] = $row[$c];
        $result2->closeCursor();
-       $query3 = "select id, inet_ntoa(rsip) as rsip, rsport, rsconfig from IPRealServer where rspool_id = ${id} order by rsip, rsport";
+       $query3 = "select id, inservice, inet_ntoa(rsip) as rsip, rsport, rsconfig from " .
+               "IPRealServer where rspool_id = ${id} order by IPRealServer.rsip, rsport";
        $result3 = $dbxlink->query ($query3);
        if ($result3 == NULL)
        {
@@ -2103,24 +2203,19 @@ function getRSPoolInfo ($id = 0)
                return NULL;
        }
        while ($row = $result3->fetch (PDO::FETCH_ASSOC))
-               foreach (array ('rsip', 'rsport', 'rsconfig') as $c)
+               foreach (array ('inservice', 'rsip', 'rsport', 'rsconfig') as $c)
                        $ret['rslist'][$row['id']][$c] = $row[$c];
        $result3->closeCursor();
        return $ret;
 }
 
-function addRStoRSPool ($pool_id = 0, $rsip = '', $rsport = 0, $rsconfig = '')
+function addRStoRSPool ($pool_id = 0, $rsip = '', $rsport = 0, $inservice = 'no', $rsconfig = '')
 {
        if ($pool_id <= 0 or $rsport <= 0)
        {
                showError ('Invalid arguments', __FUNCTION__);
                die;
        }
-       if (long2ip (ip2long ($rsip)) !== $rsip)
-       {
-               showError ("Invalid IP address '${rsip}'", __FUNCTION__);
-               die;
-       }
        return useInsertBlade
        (
                'IPRealServer',
@@ -2129,7 +2224,52 @@ function addRStoRSPool ($pool_id = 0, $rsip = '', $rsport = 0, $rsconfig = '')
                        'rsip' => "inet_aton('${rsip}')",
                        'rsport' => $rsport,
                        'rspool_id' => $pool_id,
-                       'rsconfig' => (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'"))
+                       'inservice' => ($inservice == 'yes' ? "'yes'" : "'no'"),
+                       'rsconfig' => (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'")
+               )
+       );
+}
+
+function commitCreateVS ($vip = '', $vport = 0, $proto = '', $name = '', $vsconfig, $rsconfig)
+{
+       if (empty ($vip) or $vport <= 0 or empty ($proto))
+       {
+               showError ('Invalid arguments', __FUNCTION__);
+               die;
+       }
+       return useInsertBlade
+       (
+               'IPVirtualService',
+               array
+               (
+                       'vip' => "inet_aton('${vip}')",
+                       'vport' => $vport,
+                       'proto' => "'${proto}'",
+                       'name' => (empty ($name) ? 'NULL' : "'${name}'"),
+                       'vsconfig' => (empty ($vsconfig) ? 'NULL' : "'${vsconfig}'"),
+                       'rsconfig' => (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'")
+               )
+       );
+}
+
+function addLBtoRSPool ($pool_id = 0, $object_id = 0, $vs_id = 0, $vsconfig = '', $rsconfig = '')
+{
+       if ($pool_id <= 0 or $object_id <= 0 or $vs_id <= 0)
+       {
+               showError ('Invalid arguments', __FUNCTION__);
+               die;
+       }
+       return useInsertBlade
+       (
+               'IPLoadBalancer',
+               array
+               (
+                       'object_id' => $object_id,
+                       'rspool_id' => $pool_id,
+                       'vs_id' => $vs_id,
+                       'vsconfig' => (empty ($vsconfig) ? 'NULL' : "'${vsconfig}'"),
+                       'rsconfig' => (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'")
+               )
        );
 }
 
@@ -2140,6 +2280,29 @@ function commitDeleteRS ($id = 0)
        return useDeleteBlade ('IPRealServer', 'id', $id);
 }
 
+function commitDeleteVS ($id = 0)
+{
+       if ($id <= 0)
+               return FALSE;
+       return useDeleteBlade ('IPVirtualService', 'id', $id);
+}
+
+function commitDeleteLB ($object_id = 0, $pool_id = 0, $vs_id = 0)
+{
+       global $dbxlink;
+       if ($object_id <= 0 or $pool_id <= 0 or $vs_id <= 0)
+               return FALSE;
+       $query = "delete from IPLoadBalancer where object_id = ${object_id} and " .
+               "rspool_id = ${pool_id} and vs_id = ${vs_id} limit 1";
+       $result = $dbxlink->exec ($query);
+       if ($result === NULL)
+               return FALSE;
+       elseif ($result != 1)
+               return FALSE;
+       else
+               return TRUE;
+}
+
 function commitUpdateRS ($rsid = 0, $rsip = '', $rsport = 0, $rsconfig = '')
 {
        if ($rsid <= 0 or $rsport <= 0)
@@ -2155,7 +2318,7 @@ function commitUpdateRS ($rsid = 0, $rsip = '', $rsport = 0, $rsconfig = '')
        global $dbxlink;
        $query =
                "update IPRealServer set rsip = inet_aton('${rsip}'), rsport = ${rsport}, rsconfig = " .
-               (empty ($rsconfig) ? 'NULL' : "'#{rsconfig}'") .
+               (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'") .
                " where id = ${rsid} limit 1";
        $result = $dbxlink->query ($query);
        if ($result == NULL)
@@ -2166,4 +2329,333 @@ function commitUpdateRS ($rsid = 0, $rsip = '', $rsport = 0, $rsconfig = '')
        return TRUE;
 }
 
+function commitUpdateLB ($object_id = 0, $pool_id = 0, $vs_id = 0, $vsconfig = '', $rsconfig = '')
+{
+       if ($object_id <= 0 or $pool_id <= 0 or $vs_id <= 0)
+       {
+               showError ('Invalid args', __FUNCTION__);
+               die;
+       }
+       global $dbxlink;
+       $query =
+               "update IPLoadBalancer set vsconfig = " .
+               (empty ($vsconfig) ? 'NULL' : "'${vsconfig}'") .
+               ', rsconfig = ' .
+               (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'") .
+               " where object_id = ${object_id} and rspool_id = ${pool_id} " .
+               "and vs_id = ${vs_id} limit 1";
+       $result = $dbxlink->exec ($query);
+       if ($result === NULL)
+               return FALSE;
+       else
+               return TRUE;
+}
+
+function commitUpdateVS ($vsid = 0, $vip = '', $vport = 0, $proto = '', $name = '', $vsconfig = '', $rsconfig = '')
+{
+       if ($vsid <= 0 or empty ($vip) or $vport <= 0 or empty ($proto))
+       {
+               showError ('Invalid args', __FUNCTION__);
+               die;
+       }
+       global $dbxlink;
+       $query = "update IPVirtualService set " .
+               "vip = inet_aton('${vip}'), " .
+               "vport = ${vport}, " .
+               "proto = '${proto}', " .
+               'name = ' . (empty ($name) ? 'NULL,' : "'${name}', ") .
+               'vsconfig = ' . (empty ($vsconfig) ? 'NULL,' : "'${vsconfig}', ") .
+               'rsconfig = ' . (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'") .
+               " where id = ${vsid} limit 1";
+       $result = $dbxlink->exec ($query);
+       if ($result === NULL)
+               return FALSE;
+       else
+               return TRUE;
+}
+
+// Return the list of virtual services, indexed by vs_id.
+// Each record will be shown with its basic info plus RS pools counter.
+function getVSList ()
+{
+       global $dbxlink;
+       $query = "select vs.id, inet_ntoa(vip) as vip, vport, proto, vs.name, vs.vsconfig, vs.rsconfig, count(rspool_id) as poolcount " .
+               "from IPVirtualService as vs left join IPLoadBalancer as lb on vs.id = lb.vs_id " .
+               "group by vs.id order by vs.vip, proto, vport";
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               showError ('SQL query failed', __FUNCTION__);
+               return NULL;
+       }
+       $ret = array ();
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               foreach (array ('vip', 'vport', 'proto', 'name', 'vsconfig', 'rsconfig', 'poolcount') as $cname)
+                       $ret[$row['id']][$cname] = $row[$cname];
+       $result->closeCursor();
+       return $ret;
+}
+
+// Return the list of RS pool, indexed by pool id.
+function getRSPoolList ()
+{
+       global $dbxlink;
+       $query = "select pool.id, pool.name, count(rspool_id) as refcnt, pool.vsconfig, pool.rsconfig " .
+               "from IPRSPool as pool left join IPLoadBalancer as lb on pool.id = lb.rspool_id " .
+               "group by pool.id order by pool.id, name";
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               showError ('SQL query failed', __FUNCTION__);
+               return NULL;
+       }
+       $ret = array ();
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               foreach (array ('name', 'refcnt', 'vsconfig', 'rsconfig') as $cname)
+                       $ret[$row['id']][$cname] = $row[$cname];
+       $result->closeCursor();
+       return $ret;
+}
+
+function loadThumbCache ($rack_id = 0)
+{
+       global $dbxlink;
+       $ret = NULL;
+       $query = "select thumb_data from Rack where id = ${rack_id} and thumb_data is not null limit 1";
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               showError ('SQL query failed', __FUNCTION__);
+               return NULL;
+       }
+       $row = $result->fetch (PDO::FETCH_ASSOC);
+       if ($row)
+               $ret = base64_decode ($row['thumb_data']);
+       $result->closeCursor();
+       return $ret;
+}
+
+function saveThumbCache ($rack_id = 0, $cache = NULL)
+{
+       global $dbxlink;
+       if ($rack_id == 0 or $cache == NULL)
+       {
+               showError ('Invalid arguments', __FUNCTION__);
+               return;
+       }
+       $data = base64_encode ($cache);
+       $query = "update Rack set thumb_data = '${data}' where id = ${rack_id} limit 1";
+       $result = $dbxlink->exec ($query);
+}
+
+function resetThumbCache ($rack_id = 0)
+{
+       global $dbxlink;
+       if ($rack_id == 0)
+       {
+               showError ('Invalid argument', __FUNCTION__);
+               return;
+       }
+       $query = "update Rack set thumb_data = NULL where id = ${rack_id} limit 1";
+       $result = $dbxlink->exec ($query);
+}
+
+// Return the list of attached RS pools for the given object. As long as we have
+// the LB-VS UNIQUE in IPLoadBalancer table, it is Ok to key returned records
+// by vs_id, because there will be only one RS pool listed for each VS of the
+// current object.
+function getRSPoolsForObject ($object_id = 0)
+{
+       if ($object_id <= 0)
+       {
+               showError ('Invalid object_id', __FUNCTION__);
+               return NULL;
+       }
+       global $dbxlink;
+       $query = 'select vs_id, inet_ntoa(vip) as vip, vport, proto, vs.name, pool.id as pool_id, ' .
+               'pool.name as pool_name, count(rsip) as rscount, lb.vsconfig, lb.rsconfig from ' .
+               'IPLoadBalancer as lb inner join IPRSPool as pool on lb.rspool_id = pool.id ' .
+               'inner join IPVirtualService as vs on lb.vs_id = vs.id ' .
+               'left join IPRealServer as rs on lb.rspool_id = rs.rspool_id ' .
+               "where lb.object_id = ${object_id} " .
+               'group by lb.rspool_id, lb.vs_id order by vs.vip, vport, proto, pool.name';
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               showError ('SQL query failed', __FUNCTION__);
+               return NULL;
+       }
+       $ret = array ();
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               foreach (array ('vip', 'vport', 'proto', 'name', 'pool_id', 'pool_name', 'rscount', 'vsconfig', 'rsconfig') as $cname)
+                       $ret[$row['vs_id']][$cname] = $row[$cname];
+       $result->closeCursor();
+       return $ret;
+}
+
+function commitCreateRSPool ($name = '', $vsconfig = '', $rsconfig = '')
+{
+       return useInsertBlade
+       (
+               'IPRSPool',
+               array
+               (
+                       'name' => (empty ($name) ? 'NULL' : "'${name}'"),
+                       'vsconfig' => (empty ($vsconfig) ? 'NULL' : "'${vsconfig}'"),
+                       'rsconfig' => (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'")
+               )
+       );
+}
+
+function commitDeleteRSPool ($pool_id = 0)
+{
+       global $dbxlink;
+       if ($pool_id <= 0)
+               return FALSE;
+       $query = "delete from IPRSPool where id = ${pool_id} limit 1";
+       $result = $dbxlink->exec ($query);
+       if ($result === NULL)
+               return FALSE;
+       elseif ($result != 1)
+               return FALSE;
+       else
+               return TRUE;
+}
+
+function commitUpdateRSPool ($pool_id = 0, $name = '', $vsconfig = '', $rsconfig = '')
+{
+       if ($pool_id <= 0)
+       {
+               showError ('Invalid arg', __FUNCTION__);
+               die;
+       }
+       global $dbxlink;
+       $query = "update IPRSPool set " .
+               'name = ' . (empty ($name) ? 'NULL,' : "'${name}', ") .
+               'vsconfig = ' . (empty ($vsconfig) ? 'NULL,' : "'${vsconfig}', ") .
+               'rsconfig = ' . (empty ($rsconfig) ? 'NULL' : "'${rsconfig}'") .
+               " where id = ${pool_id} limit 1";
+       $result = $dbxlink->exec ($query);
+       if ($result === NULL)
+               return FALSE;
+       elseif ($result != 1)
+               return FALSE;
+       else
+               return TRUE;
+}
+
+function getRSList ()
+{
+       global $dbxlink;
+       $query = "select id, inservice, inet_ntoa(rsip) as rsip, rsport, rspool_id, rsconfig " .
+               "from IPRealServer order by rspool_id, IPRealServer.rsip, rsport";
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               showError ('SQL query failed', __FUNCTION__);
+               return NULL;
+       }
+       $ret = array ();
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               foreach (array ('inservice', 'rsip', 'rsport', 'rspool_id', 'rsconfig') as $cname)
+                       $ret[$row['id']][$cname] = $row[$cname];
+       $result->closeCursor();
+       return $ret;
+}
+
+// Return the list of all currently configured load balancers with their pool count.
+function getLBList ()
+{
+       global $dbxlink;
+       $query = "select object_id, count(rspool_id) as poolcount " .
+               "from IPLoadBalancer group by object_id order by object_id";
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               showError ('SQL query failed', __FUNCTION__);
+               return NULL;
+       }
+       $ret = array ();
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               $ret[$row['object_id']] = $row['poolcount'];
+       $result->closeCursor();
+       return $ret;
+}
+
+// For the given object return: it vsconfig/rsconfig; the list of RS pools
+// attached (each with vsconfig/rsconfig in turn), each with the list of
+// virtual services terminating the pool. Each pool also lists all real
+// servers with rsconfig.
+function buildLBConfig ($object_id)
+{
+       if ($object_id <= 0)
+       {
+               showError ('Invalid arg', __FUNCTION__);
+               return NULL;
+       }
+       global $dbxlink;
+       $ret = array();
+       $query = 'select vs_id, inet_ntoa(vip) as vip, vport, proto, vs.name as vs_name, ' .
+               'vs.vsconfig as vs_vsconfig, vs.rsconfig as vs_rsconfig, ' .
+               'lb.vsconfig as lb_vsconfig, lb.rsconfig as lb_rsconfig, pool.id as pool_id, pool.name as pool_name, ' .
+               'pool.vsconfig as pool_vsconfig, pool.rsconfig as pool_rsconfig, ' .
+               'rs.id as rs_id, inet_ntoa(rsip) as rsip, rsport, rs.rsconfig as rs_rsconfig from ' .
+               'IPLoadBalancer as lb inner join IPRSPool as pool on lb.rspool_id = pool.id ' .
+               'inner join IPVirtualService as vs on lb.vs_id = vs.id ' .
+               'inner join IPRealServer as rs on lb.rspool_id = rs.rspool_id ' .
+               "where lb.object_id = ${object_id} and rs.inservice = 'yes' " .
+               "order by vs.vip, vport, proto, pool.name, rs.rsip, rs.rsport";
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               showError ('SQL query failed', __FUNCTION__);
+               return NULL;
+       }
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+       {
+               $vs_id = $row['vs_id'];
+               if (!isset ($ret[$vs_id]))
+               {
+                       foreach (array ('vip', 'vport', 'proto', 'vs_name', 'vs_vsconfig', 'vs_rsconfig', 'lb_vsconfig', 'lb_rsconfig', 'pool_vsconfig', 'pool_rsconfig', 'pool_id', 'pool_name') as $c)
+                               $ret[$vs_id][$c] = $row[$c];
+                       $ret[$vs_id]['rslist'] = array();
+               }
+               foreach (array ('rsip', 'rsport', 'rs_rsconfig') as $c)
+                       $ret[$vs_id]['rslist'][$row['rs_id']][$c] = $row[$c];
+       }
+       $result->closeCursor();
+       return $ret;
+}
+
+function commitSetInService ($rs_id = 0, $inservice = '')
+{
+       if ($rs_id <= 0 or empty ($inservice))
+       {
+               showError ('Invalid args', __FUNCTION__);
+               return NULL;
+       }
+       global $dbxlink;
+       $query = "update IPRealServer set inservice = '${inservice}' where id = ${rs_id} limit 1";
+       $result = $dbxlink->exec ($query);
+       if ($result === NULL)
+               return FALSE;
+       elseif ($result != 1)
+               return FALSE;
+       else
+               return TRUE;
+}
+
+function executeAutoPorts ($object_id = 0, $type_id = 0)
+{
+       if ($object_id == 0 or $type_id == 0)
+       {
+               showError ('Invalid arguments', __FUNCTION__);
+               die;
+       }
+       $ret = TRUE;
+       foreach (getAutoPorts ($type_id) as $autoport)
+               $ret = $ret and '' == commitAddPort ($object_id, $autoport['name'], $autoport['type'], '', '');
+       return $ret;
+}
+
 ?>