root/trunk/RackTables/upgrade.php

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