r2232 - last mods before RackTables 0.16.3
[racktables] / upgrade.php
index c04a852..282c614 100644 (file)
@@ -24,6 +24,7 @@ function getDBUpgradePath ($v1, $v2)
                '0.16.0',
                '0.16.1',
                '0.16.2',
+               '0.16.3',
        );
        if (!in_array ($v1, $versionhistory) || !in_array ($v2, $versionhistory))
        {
@@ -62,19 +63,11 @@ function printReleaseNotes ($batchid)
                        echo '(and the first allows everything to you, the administrator). The whole config can ';
                        echo "be reviewed on the Permissions page (under Configuration). Sorry for the inconvenience.<br><br>\n";
                        break;
-               case '0.16.1':
+               case '0.16.3':
                        echo "<font color=red><strong>Release notes for ${batchid}</strong></font><br>";
-                       echo 'This release fixes a missing UNIQUE key in the database. However, this fix may sometimes fail, ';
-                       echo 'if the table contains duplicate records. If the 0.16.0-0.16.1 upgrade batch completed without errors, ';
-                       echo 'no action needs to be taken. If you see a failed ADD UNIQUE query during upgrade, the only solution is to delete the duplicates manually. ';
-                       echo 'To do this, open a MySQL console and issue the failed query again:<br><br>';
-                       echo 'mysql&gt; alter table IPVirtualService ADD UNIQUE endpoint (vip, vport, proto);<br><br>';
-                       echo 'The IP address of the duplicate VS will be known from the &quot;Duplicate entry&quot; message. For example,';
-                       echo " to decode &quot;Duplicate entry '180879877-80-TCP' for key 2&quot; error message, issue:<br><br>";
-                       echo 'mysql&gt; select inet_ntoa(180879877);<br><br>';
-                       echo 'Then go to "virtual services" web-interface page and adjust the data as ';
-                       echo 'necessary. You would need to get rid of the duplicates accurately one by one, repeating the ADD UNIQUE ';
-                       echo 'query until it succeeds.<br><br>';
+                       echo 'This release fixes a missing UNIQUE KEY in a table. The upgrade script may find it necessary first to transform some records.<br>';
+                       echo 'Because of this it is normal to see several "update TagStorage ... Duplicate entry" failed queries during the upgrade.<br>';
+                       echo 'Additionally, it is normal to see " Can\'t DROP \'endpoint\'" message during upgrade<br>';
                        break;
                default:
                        break;
@@ -1305,7 +1298,7 @@ CREATE TABLE `TagTree` (
                                die ('<b>Cannot upgrade due to multibyte extension not present. See the README for details.</b>');
                        }
                        $query[] = 'alter table TagStorage modify column tag_id int(10) unsigned not null;';
-                       $query[] = "alter table TagStorage modify column target_realm enum('object','ipv4net','rack','ipv4vs','ipv4rspool','user');";
+                       $query[] = "alter table TagStorage modify column target_realm enum('object','ipv4net','rack','ipv4vs','ipv4rspool','user') NOT NULL default 'object'";
                        $query[] = "create table Script (script_name char(64) not null primary key, script_text text)";
                        // Do the same getUserPermissions() does, but without the function.
                        // We need to generate more specific rules first, otherwise they will
@@ -1370,7 +1363,6 @@ CREATE TABLE `TagTree` (
                        break;
                case '0.16.1':
                        $query[] = 'alter table Script modify column script_text longtext';
-                       $query[] = 'alter table IPVirtualService ADD UNIQUE endpoint (vip, vport, proto)';
                        $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('SHOW_LAST_TAB','no','string','yes','no','Remember last tab shown for each page')";
                        $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('COOKIE_TTL','1209600','uint','yes','no','Cookies lifetime in seconds')";
                        $query[] = "update Config set varvalue = '0.16.1' where varname = 'DB_VERSION'";
@@ -1378,9 +1370,51 @@ CREATE TABLE `TagTree` (
                case '0.16.2':
                        $query[] = "alter table IPBonds modify column type enum('regular','shared','virtual','router')";
                        $query[] = "update Dictionary set dict_value = 'spacer' where dict_key = 11";
-                       $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('DECODE_IPV4_ADDR','yes','string','no','no','Display parent network info for IPv4 addresses')";
+                       $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('EXT_IPV4_VIEW','yes','string','no','no','Display parent network info for IPv4 addresses')";
+                       $query[] = "ALTER TABLE RackSpace ADD KEY `RackSpace_object_id` (`object_id`)";
                        $query[] = "update Config set varvalue = '0.16.2' where varname = 'DB_VERSION'";
                        break;
+               case '0.16.3':
+                       // The network table list used to allow duplicate "prefix-masklen" pairs, which was a bad idea.
+                       // The code, which verified each new network to be "unique", didn't work for "upper" IPv4 space.
+                       // To enable the relevant index now, it is necessary to process all ghost networks, which could
+                       // be accumulated over the time, and move all tags assigned to them to the "master" record, which
+                       // we recognize to be the one with the lowest ID.
+                       $q = 'select ip, mask, count(*) as c from IPRanges group by ip, mask having c > 1';
+                       $r = $dbxlink->query ($q);
+                       // Let's hope there's not many dupes, cause sub-queries won't work.
+                       $dupes = $r->fetchAll (PDO::FETCH_ASSOC);
+                       unset ($r);
+                       foreach ($dupes as $d)
+                       {
+                               $firstid = 0;
+                               $q = "select id from IPRanges where ip = ${d['ip']} and mask = ${d['mask']} order by id";
+                               $r = $dbxlink->query ($q);
+                               while ($row = $r->fetch (PDO::FETCH_ASSOC))
+                               {
+                                       if (!$firstid)
+                                       {
+                                               $firstid = $row['id'];
+                                               continue;
+                                       }
+                                       // Rewrite tags, but don't rebuild the chains. Let regular code sort it out.
+                                       // One of the next two queries will fail.
+                                       $query[] = "update TagStorage set target_id = ${firstid} where target_id = ${row['id']} and target_realm = 'ipv4net'";
+                                       $query[] = "delete from TagStorage where target_id = ${row['id']} and target_realm = 'ipv4net'";
+                                       $query[] = "delete from IPRanges where id = ${row['id']}";
+                               }
+                               unset ($r);
+                       }
+                       $query[] = 'alter table IPRanges add unique `base-len` (`ip`, `mask`)';
+                       $query[] = 'alter table IPVirtualService drop key `endpoint`';
+                       // fix the default value (only seen when upgrading from pre-0.16.0 to pre-0.16.3)
+                       $query[] = "alter table TagStorage modify column target_realm enum('object','ipv4net','rack','ipv4vs','ipv4rspool','user') NOT NULL default 'object'";
+                       $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('TREE_THRESHOLD','25','uint','yes','no','Tree view auto-collapse threshold')";
+                       $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('IPV4_JAYWALK','no','string','no','no','Enable IPv4 address allocations w/o covering network')";
+                       $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('ADDNEW_AT_TOP','yes','string','no','no','Render \"add new\" line at top of the list')";
+                       $query[] = "update Config set description = 'Extended IPv4 view' where varname = 'EXT_IPV4_VIEW'";
+                       $query[] = "update Config set varvalue = '0.16.3' where varname = 'DB_VERSION'";
+                       break;
                default:
                        showError ("executeUpgradeBatch () failed, because batch '${batchid}' isn't defined", __FILE__);
                        die;