r1208 + now we can detect an old database and upgrade it ourselves
[racktables] / upgrade.php
CommitLineData
fbbb74fb
DO
1<?
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.
9function getDBUpgradePath ($v1, $v2)
10{
11 $versionhistory = array ('0.14.4', '0.14.5', '0.14.6');
12 if (!in_array ($v1, $versionhistory) || !in_array ($v2, $versionhistory))
13 {
14 showError ("An upgrade path has been requested for versions '${v1}' and '${v2}', " .
15 "and at least one of those isn't known to me.");
16 die;
17 }
18 $skip = TRUE;
19 $path = array();
20 // Now collect all versions > $v1 and <= $v2
21 foreach ($versionhistory as $v)
22 {
23 if ($v == $v1)
24 {
25 $skip = FALSE;
26 continue;
27 }
28 if ($skip)
29 continue;
30 $path[] = $v;
31 if ($v == $v2)
32 break;
33 }
34 return $path;
35}
36
37// Upgrade batches are name exactly as the release where they first appear.
38// That simple, but seems sufficient for beginning.
39function executeUpgradeBatch ($batchid)
40{
41 $query = array();
42 switch ($batchid)
43 {
44 case '0.14.5':
45 // We can't realiably distinguish between 0.14.4 and 0.14.5, but
46 // luckily the SQL statements below can be safely executed for both.
47
48
49 // This has to be checked once more to be sure IPAddress allocation
50 // conventions are correct.
51 $query[] = "delete from IPAddress where name = '' and reserved = 'no'";
52
53 // In the 0.14.4 release we had AUTO_INCREMENT low in the dictionary and auth
54 // data tables, thus causing new user's data to take primary keys equal to
55 // the values of shipped data in future releases. Let's shift user's data
56 // up and keep DB consistent.
57 $query[] = "alter table Attribute AUTO_INCREMENT = 10000";
58 $query[] = "alter table Chapter AUTO_INCREMENT = 10000";
59 $query[] = "alter table Dictionary AUTO_INCREMENT = 10000";
60 $query[] = "alter table UserAccount AUTO_INCREMENT = 10000";
61 $query[] = "update UserAccount set user_id = user_id + 10000 where user_id between 2 and 10000";
62 $query[] = "update UserPermission set user_id = user_id + 10000 where user_id between 2 and 10000";
63 $query[] = "update Attribute set attr_id = attr_id + 10000 where attr_id between 25 and 10000";
64 $query[] = "update AttributeMap set attr_id = attr_id + 10000 where attr_id between 25 and 10000";
65 $query[] = "update Chapter set chapter_no = chapter_no + 10000 where chapter_no between 21 and 10000";
66 $query[] = "update AttributeMap set chapter_no = chapter_no + 10000 where chapter_no between 21 and 10000";
67 break; // --------------------------------------------
68 case '0.14.6':
69 // This version features new dictionary entries, the correction above should allow us
70 // inject them w/o a problem.
71 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,25,'FreeBSD 1.x')";
72 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,26,'FreeBSD 2.x')";
73 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,27,'FreeBSD 3.x')";
74 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,28,'FreeBSD 4.x')";
75 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,29,'FreeBSD 5.x')";
76 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,30,'FreeBSD 6.x')";
77 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,31,'RHFC8')";
78 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,32,'ALTLinux Master 4.0')";
79 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (20,20)";
80 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (21,21)";
81 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (22,22)";
82 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (23,23)";
83 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (24,24)";
84 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (25,25)";
85 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (26,26)";
86 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (27,27)";
87 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (28,28)";
88 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,20,'KVM')";
89 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,21,'1000Base-ZX')";
90 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,22,'10GBase-ER')";
91 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,23,'10GBase-LR')";
92 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,24,'10GBase-LRM')";
93 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,25,'10GBase-ZR')";
94 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,26,'10GBase-LX4')";
95 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,27,'10GBase-CX4')";
96 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,28,'10GBase-Kx')";
97 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (12,114,'Cisco Catalyst 2970G-24T')";
98 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (12,115,'Cisco Catalyst 2970G-24TS')";
99 $query[] = "INSERT INTO `UserPermission` (`user_id`, `page`, `tab`, `access`) VALUES (0,'help','%','yes')";
100 // And 0.14.6 is the first release, which features Config table. Let's create
101 // and fill it with default values.
102 $query[] = "
103CREATE TABLE `Config` (
104 `varname` char(32) NOT NULL,
105 `varvalue` char(64) NOT NULL,
106 `vartype` enum('string','uint') NOT NULL default 'string',
107 `emptyok` enum('yes','no') NOT NULL default 'no',
108 `is_hidden` enum('yes','no') NOT NULL default 'yes',
109 `description` text,
110 PRIMARY KEY (`varname`)
111) ENGINE=MyISAM DEFAULT CHARSET=latin1
112 ";
113 $query[] = "INSERT INTO `Config` VALUES ('rtwidth_0','9','uint','no','yes','')";
114 $query[] = "INSERT INTO `Config` VALUES ('rtwidth_1','21','uint','no','yes','')";
115 $query[] = "INSERT INTO `Config` VALUES ('rtwidth_2','9','uint','no','yes','')";
116 $query[] = "INSERT INTO `Config` VALUES ('color_F','8fbfbf','string','no','no','HSV: 180-25-75. Free atoms, they are available for allocation to objects.')";
117 $query[] = "INSERT INTO `Config` VALUES ('color_A','bfbfbf','string','no','no','HSV: 0-0-75. Absent atoms.')";
118 $query[] = "INSERT INTO `Config` VALUES ('color_U','bf8f8f','string','no','no','HSV: 0-25-75. Unusable atoms. Some problems keep them from being free.')";
119 $query[] = "INSERT INTO `Config` VALUES ('color_T','408080','string','no','no','HSV: 180-50-50. Taken atoms, object_id should be set for such.')";
120 $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.')";
121 $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.')";
122 $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.')";
123 $query[] = "INSERT INTO `Config` VALUES ('default_port_type','11','uint','no','no','Default value for port type selects.')";
124 $query[] = "INSERT INTO `Config` VALUES ('MASSCOUNT','15','uint','no','no','Number of lines in object mass-adding form.')";
125 $query[] = "INSERT INTO `Config` VALUES ('MAXSELSIZE','30','uint','no','no','Maximum size of a SELECT HTML element.')";
126 $query[] = "INSERT INTO `Config` VALUES ('enterprise','MyCompanyName','string','no','no','Fit to your needs.')";
127 $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.')";
128 $query[] = "INSERT INTO `Config` VALUES ('ROW_SCALE','2','uint','no','no','Row-scope picture scale factor.')";
129 $query[] = "INSERT INTO `Config` VALUES ('PORTS_PER_ROW','12','uint','no','yes','Max switch port per one row on the switchvlans dynamic tab.')";
130 $query[] = "INSERT INTO `Config` VALUES ('DB_VERSION','0.14.6','string','no','yes','Database version.')";
131 break; // --------------------------------------------
132 default:
133 showError ("executeUpgradeBatch () failed, because batch '${batchid}' isn't defined");
134 die;
135 break;
136 }
137 global $dbxlink;
138 $failures = array();
139 echo "<pre>Executing database upgrade batch '${batchid}: ";
140 foreach ($query as $q)
141 {
142 $result = $dbxlink->query ($q);
143 if ($result != NULL)
144 {
145 echo '.';
146 continue;
147 }
148 echo '!';
149 $errorInfo = $dbxlink->errorInfo();
150 $failures[] = array ($q, $errorInfo[2]);
151 }
152 echo '<br>';
153 if (!count ($failures))
154 echo "No errors!\n";
155 else
156 {
157 echo "The following queries failed:\n";
158 foreach ($failures as $f)
159 {
160 list ($q, $i) = $f;
161 echo "${q} // ${i}\n";
162 }
163 }
164 echo '</pre>';
165}
166
167// ******************************************************************
168//
169// Execution starts here
170//
171// ******************************************************************
172
173$root = (empty($_SERVER['HTTPS'])?'http':'https').
174 '://'.
175 (isset($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:($_SERVER['SERVER_NAME'].($_SERVER['SERVER_PORT']=='80'?'':$_SERVER['SERVER_PORT']))).
176 dirname($_SERVER['PHP_SELF']).'/';
177
178// The below will be necessary as long as we rely on showError()
179require_once 'inc/interface.php';
180
181require_once 'inc/config.php';
182require_once 'inc/database.php';
183if (file_exists ('inc/secret.php'))
184 require_once 'inc/secret.php';
185else
186 die ("Database connection parameters are read from inc/secret.php file, " .
187 "which cannot be found.\nCopy provided inc/secret-sample.php to " .
188 "inc/secret.php and modify to your setup.\n\nThen reload the page.");
189
190try
191{
192 $dbxlink = new PDO ($pdo_dsn, $db_username, $db_password);
193}
194catch (PDOException $e)
195{
196 die ("Database connection failed:\n\n" . $e->getMessage());
197}
198
199if (isset ($_SERVER['PHP_AUTH_USER']))
200 $_SERVER['PHP_AUTH_USER'] = escapeString ($_SERVER['PHP_AUTH_USER']);
201if (isset ($_SERVER['PHP_AUTH_PW']))
202 $_SERVER['PHP_AUTH_PW'] = escapeString ($_SERVER['PHP_AUTH_PW']);
203
204// Now we need to be sure that the current user is the administrator.
205// The rest doesn't matter within this context.
206// We still continue to use the current authenticator though, but this will
207// last only till the UserAccounts remains the same. After that this file
208// will have to dig into the DB for the user accounts.
209require_once 'inc/auth.php';
210
211// This will not fail sanely, because getUserAccounts() depends on showError()
212$accounts = getUserAccounts();
213
214// Auth prompt risk being a little broken here due to config cache absence.
215$configCache = array();
216authenticate();
217if ($accounts[$_SERVER['PHP_AUTH_USER']]['user_id'] != 1)
218 die ('You are not allowed to upgrade the database. Ask your RackTables administrator to do this.');
219
220$dbver = getDatabaseVersion();
221echo 'Code version == ' . CODE_VERSION;
222echo '<br>Database version == ' . $dbver;
223if ($dbver == CODE_VERSION)
224 die ("<p align=justify>Your database seems to be up-to-date. " .
225 "Now the best thing to do would be to follow to the <a href='${root}'>main page</a> " .
226 "and explore your data. Have a nice day.</p>");
227
228foreach (getDBUpgradePath ($dbver, CODE_VERSION) as $batchid)
229 executeUpgradeBatch ($batchid);
230
231echo '<br>Database version == ' . getDatabaseVersion();
232echo "<p align=justify>Your database seems to be up-to-date. " .
233 "Now the best thing to do would be to follow to the <a href='${root}'>main page</a> " .
234 "and explore your data. Have a nice day.</p>";
235
236?>