r2329 - rename IPBonds to IPv4Allocation
[racktables] / upgrade.php
CommitLineData
6dc745d2 1<?php
fbbb74fb 2
90b96ff6
DO
3$relnotes = array
4(
5 '0.17.0' => "<font color=red><strong>Release notes for ${batchid}</strong></font><br>" .
6 "Another change is the addition of support for file uploads. Files are stored<br>" .
7 "in the database. There are several settings in php.ini which you may need to modify:<br>" .
8 " file_uploads - needs to be On<br>" .
9 " upload_max_filesize - max size for uploaded files<br>" .
10 " post_max_size - max size of all form data submitted via POST (including files)<br>",
11);
12
fbbb74fb
DO
13// At the moment we assume, that for any two releases we can
14// sequentally execute all batches, that separate them, and
15// nothing will break. If this changes one day, the function
16// below will have to generate smarter upgrade paths, while
17// the upper layer will remain the same.
18// Returning an empty array means that no upgrade is necessary.
19function getDBUpgradePath ($v1, $v2)
20{
a6f83a72
DO
21 $versionhistory = array
22 (
b3f866fc 23 '0.16.4',
64347dcf 24 '0.16.5',
90b96ff6 25 '0.16.6',
30d0a2a3 26 '0.17.0',
a6f83a72 27 );
fbbb74fb
DO
28 if (!in_array ($v1, $versionhistory) || !in_array ($v2, $versionhistory))
29 {
30 showError ("An upgrade path has been requested for versions '${v1}' and '${v2}', " .
b0348307 31 "and at least one of those isn't known to me.", __FILE__);
fbbb74fb
DO
32 die;
33 }
34 $skip = TRUE;
35 $path = array();
36 // Now collect all versions > $v1 and <= $v2
37 foreach ($versionhistory as $v)
38 {
39 if ($v == $v1)
40 {
41 $skip = FALSE;
42 continue;
43 }
44 if ($skip)
45 continue;
46 $path[] = $v;
47 if ($v == $v2)
48 break;
49 }
50 return $path;
51}
52
90b96ff6
DO
53// Upgrade batches are named exactly as the release where they first appear.
54// That is simple, but seems sufficient for beginning.
fbbb74fb
DO
55function executeUpgradeBatch ($batchid)
56{
57 $query = array();
ce109ff2 58 global $dbxlink;
fbbb74fb
DO
59 switch ($batchid)
60 {
64347dcf
DO
61 case '0.16.5':
62 $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('IPV4_TREE_SHOW_USAGE','yes','string','no','no','Show address usage in IPv4 tree')";
63 $query[] = "update Config set varvalue = '0.16.5' where varname = 'DB_VERSION'";
64 break;
90b96ff6
DO
65 case '0.16.6':
66 $query[] = "update Config set varvalue = '0.16.6' where varname = 'DB_VERSION'";
67 break;
30d0a2a3 68 case '0.17.0':
e1ae3fb4
AD
69 // create tables for storing files (requires InnoDB support)
70 if (!isInnoDBSupported ())
71 {
f3c50166
AD
72 showError ("Cannot upgrade because InnoDB tables are not supported by your MySQL server. See the README for details.", __FILE__);
73 die;
e1ae3fb4 74 }
90b96ff6
DO
75 // Many dictionary changes were made... remove all dictvendor entries and install fresh.
76 // Take care not to erase locally added records. 0.16.x ends with max key 797
77 $query[] = 'DELETE FROM Dictionary WHERE ((chapter_no BETWEEN 11 AND 14) or (chapter_no BETWEEN 16 AND 19) ' .
78 'or (chapter_no BETWEEN 21 AND 24)) and dict_key <= 797';
f3c50166
AD
79 $f = fopen ("install/init-dictvendors.sql", 'r');
80 if ($f === FALSE)
81 {
82 showError ("Failed to open install/init-dictvendors.sql for reading");
83 die;
84 }
85 $longq = '';
86 while (!feof ($f))
87 {
88 $line = fgets ($f);
89 if (ereg ('^--', $line))
90 continue;
91 $longq .= $line;
92 }
93 fclose ($f);
94 foreach (explode (";\n", $longq) as $dict_query)
95 {
96 if (empty ($dict_query))
97 continue;
98 $query[] = $dict_query;
99 }
100
101 // schema changes for file management
e1ae3fb4
AD
102 $query[] = "
103CREATE TABLE `File` (
104 `id` int(10) unsigned NOT NULL auto_increment,
105 `name` char(255) NOT NULL,
106 `type` char(255) NOT NULL,
107 `size` int(10) unsigned NOT NULL,
108 `ctime` datetime NOT NULL,
109 `mtime` datetime NOT NULL,
110 `atime` datetime NOT NULL,
111 `contents` longblob NOT NULL,
112 `comment` text,
113 PRIMARY KEY (`id`)
114) ENGINE=InnoDB";
115 $query[] = "
116CREATE TABLE `FileLink` (
117 `id` int(10) unsigned NOT NULL auto_increment,
118 `file_id` int(10) unsigned NOT NULL,
119 `entity_type` enum('ipv4net','ipv4rspool','ipv4vs','object','rack','user') NOT NULL default 'object',
120 `entity_id` int(10) NOT NULL,
121 PRIMARY KEY (`id`),
122 KEY `FileLink-file_id` (`file_id`),
123 CONSTRAINT `FileLink-File_fkey` FOREIGN KEY (`file_id`) REFERENCES `File` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
124) ENGINE=InnoDB";
125 $query[] = "ALTER TABLE TagStorage MODIFY COLUMN target_realm enum('file','ipv4net','ipv4rspool','ipv4vs','object','rack','user') NOT NULL default 'object'";
f3c50166
AD
126
127 // add network security as an object type
d4739002
AD
128 $query[] = "INSERT INTO `Chapter` (`chapter_no`, `sticky`, `chapter_name`) VALUES (24,'no','network security models')";
129 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,1,0)";
130 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,2,24)";
131 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,3,0)";
132 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,5,0)";
133 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,14,0)";
134 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,16,0)";
135 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,17,0)";
136 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,18,0)";
137 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,20,0)";
138 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,21,0)";
139 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,22,0)";
140 $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_no`) VALUES (798,24,0)";
d4739002 141 $query[] = "UPDATE Dictionary SET dict_value = 'Network switch' WHERE dict_key = 8";
706ce117
DO
142 $query[] = 'alter table IPBonds rename to IPv4Allocation';
143 $query[] = 'alter table PortForwarding rename to IPv4NAT';
144 $query[] = 'alter table IPRanges rename to IPv4Network';
145 $query[] = 'alter table IPAddress rename to IPv4Address';
146 $query[] = 'alter table IPLoadBalancer rename to IPv4LB';
147 $query[] = 'alter table IPRSpool rename to IPv4RSPool';
148 $query[] = 'alter table IPRealServer rename to IPv4RS';
149 $query[] = 'alter table IPVirtualServer rename to IPv4VS';
e1ae3fb4 150 $query[] = "UPDATE Config SET varvalue = '0.17.0' WHERE varname = 'DB_VERSION'";
b3f866fc 151 break;
fbbb74fb 152 default:
b0348307 153 showError ("executeUpgradeBatch () failed, because batch '${batchid}' isn't defined", __FILE__);
fbbb74fb
DO
154 die;
155 break;
156 }
fbbb74fb 157 $failures = array();
ce109ff2 158 $ndots = 0;
22e40283 159 echo "<pre>Executing database upgrade batch '${batchid}':\n";
fbbb74fb
DO
160 foreach ($query as $q)
161 {
162 $result = $dbxlink->query ($q);
163 if ($result != NULL)
fbbb74fb 164 echo '.';
758fe24c
DO
165 else
166 {
167 echo '!';
168 $errorInfo = $dbxlink->errorInfo();
169 $failures[] = array ($q, $errorInfo[2]);
170 }
171 if (++$ndots == 50)
172 {
173 echo "\n";
15a50768 174 flush();
758fe24c 175 $ndots = 0;
fbbb74fb 176 }
fbbb74fb
DO
177 }
178 echo '<br>';
179 if (!count ($failures))
180 echo "No errors!\n";
181 else
182 {
7fc5565c 183 echo "The following queries failed:\n<font color=red>";
fbbb74fb
DO
184 foreach ($failures as $f)
185 {
186 list ($q, $i) = $f;
187 echo "${q} // ${i}\n";
188 }
189 }
7fc5565c 190 echo '</font></pre>';
fbbb74fb
DO
191}
192
193// ******************************************************************
194//
195// Execution starts here
196//
197// ******************************************************************
198
199$root = (empty($_SERVER['HTTPS'])?'http':'https').
200 '://'.
201 (isset($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:($_SERVER['SERVER_NAME'].($_SERVER['SERVER_PORT']=='80'?'':$_SERVER['SERVER_PORT']))).
54c2a7a8
DO
202 dirname($_SERVER['PHP_SELF']);
203if (substr ($root, -1) != '/')
204 $root .= '/';
fbbb74fb
DO
205
206// The below will be necessary as long as we rely on showError()
207require_once 'inc/interface.php';
208
209require_once 'inc/config.php';
210require_once 'inc/database.php';
211if (file_exists ('inc/secret.php'))
212 require_once 'inc/secret.php';
213else
214 die ("Database connection parameters are read from inc/secret.php file, " .
215 "which cannot be found.\nCopy provided inc/secret-sample.php to " .
216 "inc/secret.php and modify to your setup.\n\nThen reload the page.");
217
218try
219{
220 $dbxlink = new PDO ($pdo_dsn, $db_username, $db_password);
221}
222catch (PDOException $e)
223{
224 die ("Database connection failed:\n\n" . $e->getMessage());
225}
226
fbbb74fb
DO
227// Now we need to be sure that the current user is the administrator.
228// The rest doesn't matter within this context.
229// We still continue to use the current authenticator though, but this will
230// last only till the UserAccounts remains the same. After that this file
231// will have to dig into the DB for the user accounts.
232require_once 'inc/auth.php';
233
a1f3710a
DO
234// 1. This didn't fail sanely, because getUserAccounts() depended on showError()
235// 2. getUserAccounts() doesn't work for old DBs since 0.16.0. Let's have own
236// copy until it breaks too.
237
238function getUserAccounts_local ()
239{
240 global $dbxlink;
241 $query = 'select user_id, user_name, user_password_hash from UserAccount order by user_name';
242 if (($result = $dbxlink->query ($query)) == NULL)
243 die ('SQL query failed in ' . __FUNCTION__);
244 $ret = array();
245 while ($row = $result->fetch (PDO::FETCH_ASSOC))
246 foreach (array ('user_id', 'user_name', 'user_password_hash') as $cname)
247 $ret[$row['user_name']][$cname] = $row[$cname];
248 return $ret;
249}
250
251$accounts = getUserAccounts_local();
fbbb74fb 252
d78fdaea
DO
253// Only administrator is always authenticated locally, so reject others
254// for authenticate() to succeed.
99ee5479
DO
255
256if
257(
258 !isset ($_SERVER['PHP_AUTH_USER']) or
259 !isset ($_SERVER['PHP_AUTH_PW']) or
260 $accounts[$_SERVER['PHP_AUTH_USER']]['user_id'] != 1 or
261 !authenticated_via_database (escapeString ($_SERVER['PHP_AUTH_USER']), escapeString ($_SERVER['PHP_AUTH_PW']))
262)
263{
c0142c01
DO
264 header ('WWW-Authenticate: Basic realm="RackTables upgrade"');
265 header ('HTTP/1.0 401 Unauthorized');
b0348307 266 showError ('You must be authenticated as an administrator to complete the upgrade.', __FILE__);
99ee5479
DO
267 die;
268}
fbbb74fb
DO
269
270$dbver = getDatabaseVersion();
5f4027b8
DO
271echo 'Code version: ' . CODE_VERSION . '<br>';
272echo 'Database version: ' . $dbver . '<br>';
fbbb74fb 273if ($dbver == CODE_VERSION)
758fe24c 274{
5f4027b8
DO
275 die ("<p align=justify>No action is necessary. " .
276 "Proceed to the <a href='${root}'>main page</a>, " .
277 "check your data and have a nice day.</p>");
758fe24c 278}
fbbb74fb
DO
279
280foreach (getDBUpgradePath ($dbver, CODE_VERSION) as $batchid)
5f4027b8 281{
fbbb74fb 282 executeUpgradeBatch ($batchid);
90b96ff6
DO
283 if (isset ($relnotes[$batchid]))
284 echo $relnotes[$batchid];
5f4027b8 285}
fbbb74fb
DO
286
287echo '<br>Database version == ' . getDatabaseVersion();
288echo "<p align=justify>Your database seems to be up-to-date. " .
289 "Now the best thing to do would be to follow to the <a href='${root}'>main page</a> " .
290 "and explore your data. Have a nice day.</p>";
291
292?>