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