root/tags/RackTables-0.15.1/upgrade.php

Revision 1945, 99.1 kB (checked in by pilot, 7 months ago)

+ fit the next 0.15.1 release better

Line 
1 <?php
2
3 // At the moment we assume, that for any two releases we can
4 // sequentally execute all batches, that separate them, and
5 // nothing will break. If this changes one day, the function
6 // below will have to generate smarter upgrade paths, while
7 // the upper layer will remain the same.
8 // Returning an empty array means that no upgrade is necessary.
9 function getDBUpgradePath ($v1, $v2)
10 {
11     $versionhistory = array
12     (
13         '0.14.4',
14         '0.14.5',
15         '0.14.6',
16         '0.14.7',
17         '0.14.8',
18         '0.14.9',
19         '0.14.10',
20         '0.14.11',
21         '0.14.12',
22         '0.15.0',
23         '0.15.1'
24     );
25     if (!in_array ($v1, $versionhistory) || !in_array ($v2, $versionhistory))
26     {
27         showError ("An upgrade path has been requested for versions '${v1}' and '${v2}', " .
28           "and at least one of those isn't known to me.");
29         die;
30     }
31     $skip = TRUE;
32     $path = array();
33     // Now collect all versions > $v1 and <= $v2
34     foreach ($versionhistory as $v)
35     {
36         if ($v == $v1)
37         {
38             $skip = FALSE;
39             continue;
40         }
41         if ($skip)
42             continue;
43         $path[] = $v;
44         if ($v == $v2)
45             break;
46     }
47     return $path;
48 }
49
50 // Upgrade batches are name exactly as the release where they first appear.
51 // That simple, but seems sufficient for beginning.
52 function executeUpgradeBatch ($batchid)
53 {
54     $query = array();
55     global $dbxlink;
56     switch ($batchid)
57     {
58         case '0.14.5':
59             // We can't realiably distinguish between 0.14.4 and 0.14.5, but
60             // luckily the SQL statements below can be safely executed for both.
61
62
63             // This has to be checked once more to be sure IPAddress allocation
64             // conventions are correct.
65             $query[] = "delete from IPAddress where name = '' and reserved = 'no'";
66
67             // In the 0.14.4 release we had AUTO_INCREMENT low in the dictionary and auth
68             // data tables, thus causing new user's data to take primary keys equal to
69             // the values of shipped data in future releases. Let's shift user's data
70             // up and keep DB consistent.
71             $query[] = "alter table Attribute AUTO_INCREMENT = 10000";
72             $query[] = "alter table Chapter AUTO_INCREMENT = 10000";
73             $query[] = "alter table Dictionary AUTO_INCREMENT = 10000";
74             $query[] = "alter table UserAccount AUTO_INCREMENT = 10000";
75             $query[] = "update UserAccount set user_id = user_id + 10000 where user_id between 2 and 10000";
76             $query[] = "update UserPermission set user_id = user_id + 10000 where user_id between 2 and 10000";
77             $query[] = "update Attribute set attr_id = attr_id + 10000 where attr_id between 25 and 10000";
78             $query[] = "update AttributeMap set attr_id = attr_id + 10000 where attr_id between 25 and 10000";
79             $query[] = "update Chapter set chapter_no = chapter_no + 10000 where chapter_no between 21 and 10000";
80             $query[] = "update AttributeMap set chapter_no = chapter_no + 10000 where chapter_no between 21 and 10000";
81             break; // --------------------------------------------
82         case '0.14.6':
83             // This version features new dictionary entries, the correction above should allow us
84             // inject them w/o a problem.
85             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,25,'FreeBSD 1.x')";
86             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,26,'FreeBSD 2.x')";
87             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,27,'FreeBSD 3.x')";
88             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,28,'FreeBSD 4.x')";
89             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,29,'FreeBSD 5.x')";
90             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,30,'FreeBSD 6.x')";
91             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,31,'RHFC8')";
92             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,32,'ALTLinux Master 4.0')";
93             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (20,20)";
94             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (21,21)";
95             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (22,22)";
96             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (23,23)";
97             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (24,24)";
98             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (25,25)";
99             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (26,26)";
100             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (27,27)";
101             $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (28,28)";
102             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,20,'KVM')";
103             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,21,'1000Base-ZX')";
104             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,22,'10GBase-ER')";
105             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,23,'10GBase-LR')";
106             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,24,'10GBase-LRM')";
107             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,25,'10GBase-ZR')";
108             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,26,'10GBase-LX4')";
109             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,27,'10GBase-CX4')";
110             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,28,'10GBase-Kx')";
111             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (12,114,'Cisco Catalyst 2970G-24T')";
112             $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (12,115,'Cisco Catalyst 2970G-24TS')";
113             $query[] = "INSERT INTO `UserPermission` (`user_id`, `page`, `tab`, `access`) VALUES (0,'help','%','yes')";
114             // And 0.14.6 is the first release, which features Config table. Let's create
115             // and fill it with default values.
116             $query[] = "
117 CREATE TABLE `Config` (
118   `varname` char(32) NOT NULL,
119   `varvalue` char(64) NOT NULL,
120   `vartype` enum('string','uint') NOT NULL default 'string',
121   `emptyok` enum('yes','no') NOT NULL default 'no',
122   `is_hidden` enum('yes','no') NOT NULL default 'yes',
123   `description` text,
124   PRIMARY KEY  (`varname`)
125 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
126             ";
127             $query[] = "INSERT INTO `Config` VALUES ('rtwidth_0','9','uint','no','yes','')";
128             $query[] = "INSERT INTO `Config` VALUES ('rtwidth_1','21','uint','no','yes','')";
129             $query[] = "INSERT INTO `Config` VALUES ('rtwidth_2','9','uint','no','yes','')";
130             $query[] = "INSERT INTO `Config` VALUES ('color_F','8fbfbf','string','no','no','HSV: 180-25-75. Free atoms, they are available for allocation to objects.')";
131             $query[] = "INSERT INTO `Config` VALUES ('color_A','bfbfbf','string','no','no','HSV: 0-0-75. Absent atoms.')";
132             $query[] = "INSERT INTO `Config` VALUES ('color_U','bf8f8f','string','no','no','HSV: 0-25-75. Unusable atoms. Some problems keep them from being free.')";
133             $query[] = "INSERT INTO `Config` VALUES ('color_T','408080','string','no','no','HSV: 180-50-50. Taken atoms, object_id should be set for such.')";
134             $query[] = "INSERT INTO `Config` VALUES ('color_Th','80ffff','string','no','no','HSV: 180-50-100. Taken atoms with highlight. They are not stored in the database and are only used for highlighting.')";
135             $query[] = "INSERT INTO `Config` VALUES ('color_Tw','804040','string','no','no','HSV: 0-50-50. Taken atoms with object problem. This is detected at runtime.')";
136             $query[] = "INSERT INTO `Config` VALUES ('color_Thw','ff8080','string','no','no','HSV: 0-50-100. An object can be both current and problematic. We run highlightObject() first and markupObjectProblems() second.')";
137             $query[] = "INSERT INTO `Config` VALUES ('default_port_type','11','uint','no','no','Default value for port type selects.')";
138             $query[] = "INSERT INTO `Config` VALUES ('MASSCOUNT','15','uint','no','no','Number of lines in object mass-adding form.')";
139             $query[] = "INSERT INTO `Config` VALUES ('MAXSELSIZE','30','uint','no','no','Maximum size of a SELECT HTML element.')";
140             $query[] = "INSERT INTO `Config` VALUES ('enterprise','MyCompanyName','string','no','no','Fit to your needs.')";
141             $query[] = "INSERT INTO `Config` VALUES ('NAMEFUL_OBJTYPES','4,7,8','string','yes','no','These are the object types, which assume a common name to be normally configured. If a name is absent for an object of one of such types, HTML output is corrected to accent this misconfiguration.')";
142             $query[] = "INSERT INTO `Config` VALUES ('ROW_SCALE','2','uint','no','no','Row-scope picture scale factor.')";
143             $query[] = "INSERT INTO `Config` VALUES ('PORTS_PER_ROW','12','uint','no','yes','Max switch port per one row on the switchvlans dynamic tab.')";
144             $query[] = "INSERT INTO `Config` VALUES ('DB_VERSION','0.14.6','string','no','yes','Database version.')";
145             break; // --------------------------------------------
146         case '0.14.7':
147             // IPAddress is hopefully fixed now finally.
148             $query[] = "delete from IPAddress where name = '' and reserved != 'yes'";
149
150             // Now rebuild the dictionary into a new table with the same data,
151             // but proper indexing. We are going to convert compound index
152             // into 1-field one to employ AUTO_INCREMENT properly. This means
153             // renumbering lots of records in Dictionary and adjusting records
154             // in related tables. After that we can safely swap the tables.
155             $query[] = "
156 CREATE TABLE `Dictionary_0_14_7_new` (
157   `chapter_no` int(10) unsigned NOT NULL,
158   `dict_key` int(10) unsigned NOT NULL auto_increment,
159   `dict_value` char(128) default NULL,
160   PRIMARY KEY  (`dict_key`),
161   UNIQUE KEY `chap_to_key` (`chapter_no`,`dict_key`),
162   UNIQUE KEY `chap_to_val` (`chapter_no`,`dict_value`)
163 ) TYPE=MyISAM AUTO_INCREMENT=50000
164 ";
165
166 echo '<pre>';
167             // Find all chapter numbers, which will require AttributeValue adjustment.
168             $q2 = 'select distinct chapter_no from AttributeMap where chapter_no != 0';
169             $r2 = $dbxlink->query ($q2);
170             $chaplist = array();
171             while ($row = $r2->fetch (PDO::FETCH_NUM))
172                 $chaplist[] = $row[0];
173             $r2->closeCursor();
174             unset ($r2);
175
176             $stock = array();
177             // Below I list the records, which are known to be the stock
178             // dictionary records of 0.14.6 release.
179             $stock[1] = array
180             (
181                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16
182             );
183             $stock[2] = array
184             (
185                 3, 4, 5, 6, 7, 8, 9,
186                 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
187                 20, 21, 22, 23, 24, 25, 26, 27, 28
188             );
189             $stock[11] = array
190             (
191                 1, 3, 4, 5, 6, 7, 8, 9,
192                 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
193                 21, 22, 24, 25, 26, 27, 28, 29,
194                 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
195                 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
196                 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
197                 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
198                 70, 71, 72, 73, 74, 75, 76
199             );
200             $stock[12] = array
201             (
202                 1, 11, 13, 14, 15, 16, 17, 18, 19, 20, 26, 29,
203                 31, 32, 33, 34, 35, 36, 37, 38, 39,
204                 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
205                 50, 51,    52, 53, 54, 55, 56, 57, 58, 59,
206                 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
207                 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
208                 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
209                 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
210                 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
211                 110, 111, 112, 113, 114, 115
212             );
213             $stock[13] = array
214             (
215                 1, 2, 3, 4, 5, 6, 7, 8, 9,
216                 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
217                 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
218                 30, 31, 32
219             );
220             $stock[14] = array
221             (
222                 1, 2, 9, 11, 13, 15, 19, 20, 21, 22
223             );
224             $stock[16] = array
225             (
226                 1, 2, 3, 4, 5, 6, 7, 8
227             );
228             $stock[17] = array
229             (
230                 1, 2, 3, 4, 5, 6, 7, 8, 9,
231                 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
232                 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
233                 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
234                 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
235                 50
236             );
237             $stock[18] = array
238             (
239                 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
240             );
241             $stock[19] = array
242             (
243                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
244             );
245             $stock[20] = array
246             (
247                 1, 2
248             );
249
250             // Load dictionary and transform into two tree structures for
251             // stock and user record sets.
252             $dict = array();
253             $q3 = 'select chapter_no, dict_key, dict_value from Dictionary order by chapter_no, dict_key';
254             $r3 = $dbxlink->query ($q3);
255
256             while ($row = $r3->fetch (PDO::FETCH_ASSOC))
257             {
258                 $tree = 'user';
259                 $dict_key = $row['dict_key'];
260                 $chapter_no = $row['chapter_no'];
261                 switch ($chapter_no)
262                 {
263                     case 1: // RackObjectType
264                     case 2: // PortType
265                     case 11: // server models
266                     case 12: // network switch models
267                     case 13: // server OS type
268                     case 14: // network switch OS type
269                     case 16: // router OS type
270                     case 17: // router models
271                     case 18: // disk array models
272                     case 19: // tape library models
273                     case 20: // Protocols
274                         if (in_array ($dict_key, $stock[$chapter_no]))
275                             $tree = 'stock';
276                         break;
277                 }
278                 $dict[$tree][$chapter_no][$dict_key] = array ('value' => $row['dict_value']);
279             }
280             $r3->closeCursor();
281             unset ($r3);
282
283
284             // Now we store stock dataset first, bump up key value and store
285             // user's data. After that we will know the new dict_key for all
286             // records.
287             // The result of both datasets processing is saved in $new_dict.
288             // Save on calling LAST_ISERT_ID() each time by keeping own key.
289             $newkey = 1;
290             $new_dict = array();
291             foreach ($dict['stock'] as $chapter_no => $words)
292             {
293                 $new_dict[$chapter_no] = array();
294                 foreach ($words as $dict_key => $entry)
295                 {
296                     $query[] = "insert into Dictionary_0_14_7_new (chapter_no, dict_key, dict_value) " .
297                         "values (${chapter_no}, ${newkey}, '${entry['value']}')";
298                     $new_dict[$chapter_no][$dict_key] = $entry;
299                     $new_dict[$chapter_no][$dict_key]['newkey'] = $newkey;
300                     $newkey++;
301                 }
302             }
303             $newkey = 50000;
304             foreach ($dict['user'] as $chapter_no => $words)
305             {
306                 // Some chapters may appear on the user dataset only.
307                 if (!isset ($new_dict[$chapter_no]))
308                     $new_dict[$chapter_no] = array();
309                 foreach ($words as $dict_key => $entry)
310                 {
311                     $query[] = "insert into Dictionary_0_14_7_new " .
312                         "values (${chapter_no}, ${newkey}, '${entry['value']}')";
313                     $new_dict[$chapter_no][$dict_key] = $entry;
314                     $new_dict[$chapter_no][$dict_key]['newkey'] = $newkey;
315                     $newkey++;
316                 }
317             }
318             // The new table should now have adequate AUTO_INCREMENT w/o our care.
319             // Install the new data.
320             $query[] = 'drop table Dictionary';
321             $query[] = 'alter table Dictionary_0_14_7_new rename to Dictionary';
322
323             // Now we iterate over the joint dataset, picking some chapters and
324             // performing additional processing:
325             // 1 (RackObjectType) --- adjust RackObject and regenerate AttributeMap
326             // 2 (PortType) --- adjust Port and regenerate PortCompat (at a latter point)
327             // 3 (RackRow) --- adjust Rack
328             // 20 (Protocols) --- adjust PortForwarding
329             // All other chapters listed in $chaplist --- adjust AttributeValue
330             
331             $query[] = "delete from AttributeMap";
332             foreach ($new_dict as $chapter_no => $words)
333             {
334                 foreach ($words as $oldkey => $data)
335                 {
336                     $value = $data['value'];
337                     $newkey = $data['newkey'];
338                     // Even if the key doesn't change, go on to have
339                     // AttributeMap regenerated completely.
340                     if ($chapter_no == 1)
341                     {
342                         $q4 = "select id from RackObject where objtype_id = ${oldkey}";
343                         $r4 = $dbxlink->query ($q4);
344                         while ($row = $r4->fetch (PDO::FETCH_ASSOC))
345                             $query[] = "update RackObject set objtype_id = ${newkey} where id = ${row['id']} limit 1";
346                         $r4->closeCursor();
347                         unset ($r4);
348
349                         $q5 = "select attr_id, chapter_no from AttributeMap where objtype_id = ${oldkey}";
350                         $r5 = $dbxlink->query ($q5);
351                         while ($row = $r5->fetch (PDO::FETCH_ASSOC))
352                             $query[] = "insert into AttributeMap (objtype_id, attr_id, chapter_no) values (${newkey}, ${row['attr_id']}, ${row['chapter_no']})";
353                         $r5->closeCursor();
354                         unset ($r5);
355                     }
356                     elseif ($chapter_no == 2)
357                     {
358                         $q46 = "select id from Port where type = ${oldkey}";
359                         $r46 = $dbxlink->query ($q46);
360                         if ($r46 == NULL)
361                             echo 'ERROR';
362                         while ($row = $r46->fetch (PDO::FETCH_ASSOC))
363                             $query[] = "update Port set type = ${newkey} where id = ${row['id']} limit 1";
364                         $r46->closeCursor();
365                         unset ($r46);
366                     }
367                     elseif ($chapter_no == 3)
368                     {
369                         $q7 = "select id from Rack where row_id = ${oldkey}";
370                         $r7 = $dbxlink->query ($q7);
371                         while ($row = $r7->fetch (PDO::FETCH_ASSOC))
372                             $query[] = "update Rack set row_id = ${newkey} where id = ${row['id']} limit 1";
373                         $r7->closeCursor();
374                         unset ($r7);
375                     }
376                     elseif ($chapter_no == 20)
377                     {
378                         $q8 = "select object_id, localip, localport, remoteip, remoteport from PortForwarding where proto = ${oldkey}";
379                         $r8 = $dbxlink->query ($q8);
380                         while ($row = $r8->fetch (PDO::FETCH_ASSOC))
381                             $query[] = "update PortForwarding set proto = ${newkey} where " .
382                             "object_id = ${row['object_id']} and localip = ${row['localip']} and " .
383                             "localport = ${row['localport']} and remoteip = ${row['remoteip']} and " .
384                             "remoteport = ${row['remoteport']} and proto = ${oldkey} limit 1";
385                         $r8->closeCursor();
386                         unset ($r8);
387                     }
388                     elseif (in_array ($chapter_no, $chaplist))
389                     {
390                         $q81 = "select object_id, AttributeValue.attr_id from " .
391                         "AttributeValue natural join Attribute natural join AttributeMap " .
392                         "inner join RackObject on RackObject.id = object_id and RackObject.objtype_id = AttributeMap.objtype_id " .
393                         "where attr_type = 'dict' and chapter_no = ${chapter_no} and uint_value = ${oldkey}";
394                         $r81 = $dbxlink->query ($q81);
395                         while ($row = $r81->fetch (PDO::FETCH_ASSOC))
396                             $query[] = "update AttributeValue set uint_value = ${newkey} " .
397                             "where object_id = ${row['object_id']} and attr_id = ${row['attr_id']}";
398                         $r81->closeCursor();
399                         unset ($r81);
400                     }
40