r4501 convert racks and rows into objects
authorAaron Dummer <aaron@dummer.info>
Sat, 7 May 2011 20:08:48 +0000 (20:08 +0000)
committerAaron Dummer <aaron@dummer.info>
Sat, 7 May 2011 20:08:48 +0000 (20:08 +0000)
15 files changed:
ChangeLog
README
scripts/init-sample-racks.sql
wwwroot/css/pi.css
wwwroot/inc/config.php
wwwroot/inc/database.php
wwwroot/inc/dictionary.php
wwwroot/inc/functions.php
wwwroot/inc/install.php
wwwroot/inc/interface.php
wwwroot/inc/navigation.php
wwwroot/inc/ophandlers.php
wwwroot/inc/popup.php
wwwroot/inc/solutions.php
wwwroot/inc/upgrade.php

index 1bbad33..2afc97e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,7 @@
        update: 802.1q: config deploy to Cisco IOS switches is no more requiring 'switchport trunk encapsulation dot1q' pre-set
        update: dismiss HNDP support
        update: markup IPv6 subnet-router on request (by Jens Weibler)
+       update: convert racks and rows into objects (by Aaron Dummer)
        new feature: you can obtain who has made tag assignment, object's ports or IPv4 address changes by hovering cursor on these entities
        new feature: ability to open a terminal session to a device by clicking on its FQDN
 0.19.4
diff --git a/README b/README
index eb0a6cf..fee8c37 100644 (file)
--- a/README
+++ b/README
@@ -88,6 +88,12 @@ should be sufficient:
 *                                                     *
 *******************************************************
 
+*** Upgrading to 0.20.0 ***
+
+Racks and Rows are now stored in the database as Objects.  The RackObject table 
+was renamed to Object.  SQL views were created to ease the migration of custom 
+reports and scripts.
+
 *** Upgrading to 0.19.2 ***
 
 This release is different in filesystem layout. The "gateways" directory
index 0762a60..2b66ef9 100644 (file)
@@ -1,6 +1,6 @@
 set names 'utf8';
 
-INSERT INTO `RackObject` (id, name, label, objtype_id, asset_no, has_problems, comment) VALUES 
+INSERT INTO `Object` (id, name, label, objtype_id, asset_no, has_problems, comment) VALUES 
 (905,'london router','bbrtr1',7,'net247','no',''),
 (906,'londonswitch1','',8,NULL,'no',''),
 (907,'New-York router 1','bbrtr2a',7,'net55','no',''),
@@ -58,7 +58,29 @@ INSERT INTO `RackObject` (id, name, label, objtype_id, asset_no, has_problems, c
 (959,'mps4','',4,NULL,'no',NULL),
 (960,'mps5','',4,NULL,'no',NULL),
 (961,'mskswitch','',8,'sw0001','no',NULL),
-(962,'moscow kvm switch','',445,'sw0002','no',NULL);
+(962,'moscow kvm switch','',445,'sw0002','no',NULL),
+(963,'Moscow','',1561,NULL,'no',NULL),
+(964,'Tokyo','',1561,NULL,'no',NULL),
+(965,'New-York','',1561,NULL,'no',NULL),
+(966,'London','',1561,NULL,'no',NULL),
+(967,'L01','',1560,NULL,'no','test'),
+(968,'L02','',1560,NULL,'no','network equipment mini-rack'),
+(969,'L03','',1560,NULL,'no',NULL),
+(970,'NY100','',1560,NULL,'no',NULL),
+(971,'NY101','',1560,NULL,'no','server farm wing A'),
+(972,'M01','',1560,NULL,'no',NULL),
+(973,'NY102','',1560,NULL,'no','server farm wing B'),
+(974,'T01','',1560,NULL,'no',NULL);
+
+INSERT INTO `EntityLink` (`parent_entity_type`, `parent_entity_id`, `child_entity_type`, `child_entity_id`) VALUES
+('object',966,'object',967),
+('object',966,'object',968),
+('object',966,'object',969),
+('object',965,'object',970),
+('object',965,'object',971),
+('object',963,'object',972),
+('object',965,'object',973),
+('object',964,'object',974);
 
 INSERT INTO `AttributeValue` VALUES (905,2,NULL,269,NULL);
 INSERT INTO `AttributeValue` VALUES (906,2,NULL,165,NULL);
@@ -107,11 +129,14 @@ INSERT INTO `AttributeValue` VALUES (960,2,NULL,62,NULL);
 INSERT INTO `AttributeValue` VALUES (960,4,NULL,791,NULL);
 INSERT INTO `AttributeValue` VALUES (961,2,NULL,755,NULL);
 INSERT INTO `AttributeValue` VALUES (962,2,NULL,470,NULL);
-
-INSERT INTO `RackRow` (`id`, `name`) VALUES (50000,'Moscow');
-INSERT INTO `RackRow` (`id`, `name`) VALUES (50001,'Tokyo');
-INSERT INTO `RackRow` (`id`, `name`) VALUES (50002,'New-York');
-INSERT INTO `RackRow` (`id`, `name`) VALUES (50003,'London');
+INSERT INTO `AttributeValue` VALUES (967,27,NULL,42,NULL);
+INSERT INTO `AttributeValue` VALUES (968,27,NULL,12,NULL);
+INSERT INTO `AttributeValue` VALUES (969,27,NULL,42,NULL);
+INSERT INTO `AttributeValue` VALUES (970,27,NULL,16,NULL);
+INSERT INTO `AttributeValue` VALUES (971,27,NULL,42,NULL);
+INSERT INTO `AttributeValue` VALUES (972,27,NULL,42,NULL);
+INSERT INTO `AttributeValue` VALUES (973,27,NULL,42,NULL);
+INSERT INTO `AttributeValue` VALUES (974,27,NULL,16,NULL);
 
 INSERT INTO `IPv4Address` VALUES (180879678,'default gw','no');
 INSERT INTO `IPv4Address` VALUES (180879617,'',NULL);
@@ -427,284 +452,274 @@ INSERT INTO `IPv4NAT` (`object_id`, `proto`, `localip`, `localport`, `remoteip`,
 INSERT INTO `IPv4NAT` (`object_id`, `proto`, `localip`, `localport`, `remoteip`, `remoteport`, `description`) VALUES (915,'TCP',180879677,443,180879686,443,'');
 INSERT INTO `IPv4NAT` (`object_id`, `proto`, `localip`, `localport`, `remoteip`, `remoteport`, `description`) VALUES (915,'TCP',180879677,443,180879687,443,'');
 
-INSERT INTO `Rack` (id, name, row_id, height, comment) VALUES
-(40,'L01',50003,42,'test'),
-(41,'L02',50003,12,'network equipment mini-rack'),
-(42,'L03',50003,42,''),
-(43,'NY100',50002,16,''),
-(44,'NY101',50002,42,'server farm wing A'),
-(45,'M01',50000,42,''),
-(46,'NY102',50002,42,'server farm wing B'),
-(47,'T01',50001,16,'');
-
-INSERT INTO `RackSpace` VALUES (41,9,'interior','T',905);
-INSERT INTO `RackSpace` VALUES (41,9,'front','T',905);
-INSERT INTO `RackSpace` VALUES (41,10,'interior','T',905);
-INSERT INTO `RackSpace` VALUES (41,10,'front','T',905);
-INSERT INTO `RackSpace` VALUES (41,11,'interior','T',905);
-INSERT INTO `RackSpace` VALUES (41,11,'front','T',905);
-INSERT INTO `RackSpace` VALUES (41,7,'front','T',906);
-INSERT INTO `RackSpace` VALUES (41,7,'interior','T',906);
-INSERT INTO `RackSpace` VALUES (43,16,'interior','T',907);
-INSERT INTO `RackSpace` VALUES (43,16,'rear','T',907);
-INSERT INTO `RackSpace` VALUES (43,15,'interior','T',907);
-INSERT INTO `RackSpace` VALUES (43,15,'rear','T',907);
-INSERT INTO `RackSpace` VALUES (43,14,'interior','T',907);
-INSERT INTO `RackSpace` VALUES (43,14,'rear','T',907);
-INSERT INTO `RackSpace` VALUES (47,15,'interior','T',909);
-INSERT INTO `RackSpace` VALUES (47,15,'rear','T',909);
-INSERT INTO `RackSpace` VALUES (47,14,'interior','T',909);
-INSERT INTO `RackSpace` VALUES (47,14,'rear','T',909);
-INSERT INTO `RackSpace` VALUES (47,13,'interior','T',909);
-INSERT INTO `RackSpace` VALUES (47,13,'rear','T',909);
-INSERT INTO `RackSpace` VALUES (45,20,'interior','T',908);
-INSERT INTO `RackSpace` VALUES (45,20,'rear','T',908);
-INSERT INTO `RackSpace` VALUES (45,19,'interior','T',908);
-INSERT INTO `RackSpace` VALUES (45,19,'rear','T',908);
-INSERT INTO `RackSpace` VALUES (45,18,'interior','T',908);
-INSERT INTO `RackSpace` VALUES (45,18,'rear','T',908);
-INSERT INTO `RackSpace` VALUES (40,2,'front','T',910);
-INSERT INTO `RackSpace` VALUES (40,2,'interior','T',910);
-INSERT INTO `RackSpace` VALUES (40,2,'rear','T',910);
-INSERT INTO `RackSpace` VALUES (40,4,'front','T',911);
-INSERT INTO `RackSpace` VALUES (40,4,'interior','T',911);
-INSERT INTO `RackSpace` VALUES (40,4,'rear','T',911);
-INSERT INTO `RackSpace` VALUES (40,6,'front','T',912);
-INSERT INTO `RackSpace` VALUES (40,6,'interior','T',912);
-INSERT INTO `RackSpace` VALUES (40,6,'rear','T',912);
-INSERT INTO `RackSpace` VALUES (40,8,'front','T',913);
-INSERT INTO `RackSpace` VALUES (40,8,'interior','T',913);
-INSERT INTO `RackSpace` VALUES (40,8,'rear','T',913);
-INSERT INTO `RackSpace` VALUES (40,10,'front','T',914);
-INSERT INTO `RackSpace` VALUES (40,10,'interior','T',914);
-INSERT INTO `RackSpace` VALUES (40,10,'rear','T',914);
-INSERT INTO `RackSpace` VALUES (40,23,'rear','T',916);
-INSERT INTO `RackSpace` VALUES (40,23,'interior','T',916);
-INSERT INTO `RackSpace` VALUES (40,23,'front','T',916);
-INSERT INTO `RackSpace` VALUES (41,5,'front','T',915);
-INSERT INTO `RackSpace` VALUES (41,5,'interior','T',915);
-INSERT INTO `RackSpace` VALUES (41,4,'interior','T',915);
-INSERT INTO `RackSpace` VALUES (41,4,'front','T',915);
-INSERT INTO `RackSpace` VALUES (40,22,'front','T',916);
-INSERT INTO `RackSpace` VALUES (40,22,'interior','T',916);
-INSERT INTO `RackSpace` VALUES (40,22,'rear','T',916);
-INSERT INTO `RackSpace` VALUES (42,7,'front','T',918);
-INSERT INTO `RackSpace` VALUES (42,7,'interior','T',918);
-INSERT INTO `RackSpace` VALUES (42,7,'rear','T',918);
-INSERT INTO `RackSpace` VALUES (42,6,'front','T',918);
-INSERT INTO `RackSpace` VALUES (42,6,'interior','T',918);
-INSERT INTO `RackSpace` VALUES (42,6,'rear','T',918);
-INSERT INTO `RackSpace` VALUES (42,5,'front','T',918);
-INSERT INTO `RackSpace` VALUES (42,5,'interior','T',918);
-INSERT INTO `RackSpace` VALUES (42,5,'rear','T',918);
-INSERT INTO `RackSpace` VALUES (42,4,'front','T',918);
-INSERT INTO `RackSpace` VALUES (42,4,'interior','T',918);
-INSERT INTO `RackSpace` VALUES (42,4,'rear','T',918);
-INSERT INTO `RackSpace` VALUES (42,3,'front','T',918);
-INSERT INTO `RackSpace` VALUES (42,3,'interior','T',918);
-INSERT INTO `RackSpace` VALUES (42,3,'rear','T',918);
-INSERT INTO `RackSpace` VALUES (42,13,'front','T',919);
-INSERT INTO `RackSpace` VALUES (42,13,'interior','T',919);
-INSERT INTO `RackSpace` VALUES (42,13,'rear','T',919);
-INSERT INTO `RackSpace` VALUES (42,12,'front','T',919);
-INSERT INTO `RackSpace` VALUES (42,12,'interior','T',919);
-INSERT INTO `RackSpace` VALUES (42,12,'rear','T',919);
-INSERT INTO `RackSpace` VALUES (42,11,'front','T',919);
-INSERT INTO `RackSpace` VALUES (42,11,'interior','T',919);
-INSERT INTO `RackSpace` VALUES (42,11,'rear','T',919);
-INSERT INTO `RackSpace` VALUES (42,10,'front','T',919);
-INSERT INTO `RackSpace` VALUES (42,10,'interior','T',919);
-INSERT INTO `RackSpace` VALUES (42,10,'rear','T',919);
-INSERT INTO `RackSpace` VALUES (42,9,'front','T',919);
-INSERT INTO `RackSpace` VALUES (42,9,'interior','T',919);
-INSERT INTO `RackSpace` VALUES (42,9,'rear','T',919);
-INSERT INTO `RackSpace` VALUES (42,37,'front','T',920);
-INSERT INTO `RackSpace` VALUES (42,37,'interior','T',920);
-INSERT INTO `RackSpace` VALUES (42,37,'rear','T',920);
-INSERT INTO `RackSpace` VALUES (42,36,'front','T',920);
-INSERT INTO `RackSpace` VALUES (42,36,'interior','T',920);
-INSERT INTO `RackSpace` VALUES (42,36,'rear','T',920);
-INSERT INTO `RackSpace` VALUES (42,35,'front','T',920);
-INSERT INTO `RackSpace` VALUES (42,35,'interior','T',920);
-INSERT INTO `RackSpace` VALUES (42,35,'rear','T',920);
-INSERT INTO `RackSpace` VALUES (42,34,'front','T',920);
-INSERT INTO `RackSpace` VALUES (42,34,'interior','T',920);
-INSERT INTO `RackSpace` VALUES (42,34,'rear','T',920);
-INSERT INTO `RackSpace` VALUES (42,33,'front','T',920);
-INSERT INTO `RackSpace` VALUES (42,33,'interior','T',920);
-INSERT INTO `RackSpace` VALUES (42,33,'rear','T',920);
-INSERT INTO `RackSpace` VALUES (42,32,'front','T',920);
-INSERT INTO `RackSpace` VALUES (42,32,'interior','T',920);
-INSERT INTO `RackSpace` VALUES (42,32,'rear','T',920);
-INSERT INTO `RackSpace` VALUES (42,31,'front','T',920);
-INSERT INTO `RackSpace` VALUES (42,31,'interior','T',920);
-INSERT INTO `RackSpace` VALUES (42,31,'rear','T',920);
-INSERT INTO `RackSpace` VALUES (42,30,'front','T',920);
-INSERT INTO `RackSpace` VALUES (42,30,'interior','T',920);
-INSERT INTO `RackSpace` VALUES (42,30,'rear','T',920);
-INSERT INTO `RackSpace` VALUES (42,16,'front','T',921);
-INSERT INTO `RackSpace` VALUES (42,16,'interior','T',921);
-INSERT INTO `RackSpace` VALUES (42,16,'rear','T',921);
-INSERT INTO `RackSpace` VALUES (42,15,'front','T',921);
-INSERT INTO `RackSpace` VALUES (42,15,'interior','T',921);
-INSERT INTO `RackSpace` VALUES (42,15,'rear','T',921);
-INSERT INTO `RackSpace` VALUES (42,18,'front','T',922);
-INSERT INTO `RackSpace` VALUES (42,18,'interior','T',922);
-INSERT INTO `RackSpace` VALUES (42,18,'rear','T',922);
-INSERT INTO `RackSpace` VALUES (42,17,'front','T',922);
-INSERT INTO `RackSpace` VALUES (42,17,'interior','T',922);
-INSERT INTO `RackSpace` VALUES (42,17,'rear','T',922);
-INSERT INTO `RackSpace` VALUES (47,11,'interior','T',926);
-INSERT INTO `RackSpace` VALUES (47,11,'rear','T',926);
-INSERT INTO `RackSpace` VALUES (47,1,'front','T',923);
-INSERT INTO `RackSpace` VALUES (47,1,'interior','T',923);
-INSERT INTO `RackSpace` VALUES (47,1,'rear','T',923);
-INSERT INTO `RackSpace` VALUES (47,3,'front','T',924);
-INSERT INTO `RackSpace` VALUES (47,3,'interior','T',924);
-INSERT INTO `RackSpace` VALUES (47,3,'rear','T',924);
-INSERT INTO `RackSpace` VALUES (47,5,'front','T',925);
-INSERT INTO `RackSpace` VALUES (47,5,'interior','T',925);
-INSERT INTO `RackSpace` VALUES (47,5,'rear','T',925);
-INSERT INTO `RackSpace` VALUES (43,12,'interior','T',927);
-INSERT INTO `RackSpace` VALUES (43,12,'rear','T',927);
-INSERT INTO `RackSpace` VALUES (43,11,'interior','T',927);
-INSERT INTO `RackSpace` VALUES (43,11,'rear','T',927);
-INSERT INTO `RackSpace` VALUES (43,10,'interior','T',927);
-INSERT INTO `RackSpace` VALUES (43,10,'rear','T',927);
-INSERT INTO `RackSpace` VALUES (43,2,'front','T',944);
-INSERT INTO `RackSpace` VALUES (43,2,'interior','T',944);
-INSERT INTO `RackSpace` VALUES (43,2,'rear','T',944);
-INSERT INTO `RackSpace` VALUES (43,1,'front','T',944);
-INSERT INTO `RackSpace` VALUES (43,1,'interior','T',944);
-INSERT INTO `RackSpace` VALUES (43,1,'rear','T',944);
-INSERT INTO `RackSpace` VALUES (44,5,'front','T',942);
-INSERT INTO `RackSpace` VALUES (44,5,'interior','T',942);
-INSERT INTO `RackSpace` VALUES (44,5,'rear','T',942);
-INSERT INTO `RackSpace` VALUES (44,4,'front','T',942);
-INSERT INTO `RackSpace` VALUES (44,4,'interior','T',942);
-INSERT INTO `RackSpace` VALUES (44,4,'rear','T',942);
-INSERT INTO `RackSpace` VALUES (44,3,'front','T',942);
-INSERT INTO `RackSpace` VALUES (44,3,'interior','T',942);
-INSERT INTO `RackSpace` VALUES (44,3,'rear','T',942);
-INSERT INTO `RackSpace` VALUES (44,2,'front','T',942);
-INSERT INTO `RackSpace` VALUES (44,2,'interior','T',942);
-INSERT INTO `RackSpace` VALUES (44,2,'rear','T',942);
-INSERT INTO `RackSpace` VALUES (44,1,'front','T',942);
-INSERT INTO `RackSpace` VALUES (44,1,'interior','T',942);
-INSERT INTO `RackSpace` VALUES (44,1,'rear','T',942);
-INSERT INTO `RackSpace` VALUES (46,5,'front','T',943);
-INSERT INTO `RackSpace` VALUES (46,5,'interior','T',943);
-INSERT INTO `RackSpace` VALUES (46,5,'rear','T',943);
-INSERT INTO `RackSpace` VALUES (46,4,'front','T',943);
-INSERT INTO `RackSpace` VALUES (46,4,'interior','T',943);
-INSERT INTO `RackSpace` VALUES (46,4,'rear','T',943);
-INSERT INTO `RackSpace` VALUES (46,3,'front','T',943);
-INSERT INTO `RackSpace` VALUES (46,3,'interior','T',943);
-INSERT INTO `RackSpace` VALUES (46,3,'rear','T',943);
-INSERT INTO `RackSpace` VALUES (46,2,'front','T',943);
-INSERT INTO `RackSpace` VALUES (46,2,'interior','T',943);
-INSERT INTO `RackSpace` VALUES (46,2,'rear','T',943);
-INSERT INTO `RackSpace` VALUES (46,1,'front','T',943);
-INSERT INTO `RackSpace` VALUES (46,1,'interior','T',943);
-INSERT INTO `RackSpace` VALUES (46,1,'rear','T',943);
-INSERT INTO `RackSpace` VALUES (44,6,'front','U',NULL);
-INSERT INTO `RackSpace` VALUES (44,6,'interior','U',NULL);
-INSERT INTO `RackSpace` VALUES (44,6,'rear','U',NULL);
-INSERT INTO `RackSpace` VALUES (46,6,'front','U',NULL);
-INSERT INTO `RackSpace` VALUES (46,6,'interior','U',NULL);
-INSERT INTO `RackSpace` VALUES (46,6,'rear','U',NULL);
-INSERT INTO `RackSpace` VALUES (46,17,'rear','T',954);
-INSERT INTO `RackSpace` VALUES (45,20,'front','T',953);
-INSERT INTO `RackSpace` VALUES (41,6,'front','T',952);
-INSERT INTO `RackSpace` VALUES (40,1,'rear','T',949);
-INSERT INTO `RackSpace` VALUES (46,37,'rear','T',931);
-INSERT INTO `RackSpace` VALUES (46,37,'interior','T',931);
-INSERT INTO `RackSpace` VALUES (46,40,'rear','T',929);
-INSERT INTO `RackSpace` VALUES (46,40,'interior','T',929);
-INSERT INTO `RackSpace` VALUES (46,15,'rear','T',941);
-INSERT INTO `RackSpace` VALUES (46,15,'interior','T',941);
-INSERT INTO `RackSpace` VALUES (46,15,'front','T',941);
-INSERT INTO `RackSpace` VALUES (46,13,'front','T',939);
-INSERT INTO `RackSpace` VALUES (46,11,'rear','T',937);
-INSERT INTO `RackSpace` VALUES (46,11,'interior','T',937);
-INSERT INTO `RackSpace` VALUES (46,9,'interior','T',935);
-INSERT INTO `RackSpace` VALUES (46,7,'interior','T',933);
-INSERT INTO `RackSpace` VALUES (47,16,'rear','T',946);
-INSERT INTO `RackSpace` VALUES (44,38,'rear','T',930);
-INSERT INTO `RackSpace` VALUES (44,40,'interior','T',928);
-INSERT INTO `RackSpace` VALUES (44,15,'rear','T',940);
-INSERT INTO `RackSpace` VALUES (44,13,'rear','T',938);
-INSERT INTO `RackSpace` VALUES (44,11,'rear','T',936);
-INSERT INTO `RackSpace` VALUES (44,9,'rear','T',934);
-INSERT INTO `RackSpace` VALUES (44,7,'rear','T',932);
-INSERT INTO `RackSpace` VALUES (41,12,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,11,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,10,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,9,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,8,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,7,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,6,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,5,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,4,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,3,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,2,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (41,1,'rear','A',NULL);
-INSERT INTO `RackSpace` VALUES (47,9,'rear','T',955);
-INSERT INTO `RackSpace` VALUES (44,17,'rear','T',951);
-INSERT INTO `RackSpace` VALUES (43,9,'rear','T',948);
-INSERT INTO `RackSpace` VALUES (42,14,'rear','T',950);
-INSERT INTO `RackSpace` VALUES (42,2,'rear','T',947);
-INSERT INTO `RackSpace` VALUES (46,38,'rear','T',931);
-INSERT INTO `RackSpace` VALUES (46,38,'interior','T',931);
-INSERT INTO `RackSpace` VALUES (46,41,'rear','T',929);
-INSERT INTO `RackSpace` VALUES (46,41,'interior','T',929);
-INSERT INTO `RackSpace` VALUES (46,13,'rear','T',939);
-INSERT INTO `RackSpace` VALUES (46,13,'interior','T',939);
-INSERT INTO `RackSpace` VALUES (46,11,'front','T',937);
-INSERT INTO `RackSpace` VALUES (46,9,'rear','T',935);
-INSERT INTO `RackSpace` VALUES (46,9,'front','T',935);
-INSERT INTO `RackSpace` VALUES (46,7,'rear','T',933);
-INSERT INTO `RackSpace` VALUES (46,7,'front','T',933);
-INSERT INTO `RackSpace` VALUES (43,13,'rear','T',945);
-INSERT INTO `RackSpace` VALUES (44,37,'rear','T',930);
-INSERT INTO `RackSpace` VALUES (44,37,'interior','T',930);
-INSERT INTO `RackSpace` VALUES (44,38,'interior','T',930);
-INSERT INTO `RackSpace` VALUES (44,40,'rear','T',928);
-INSERT INTO `RackSpace` VALUES (44,41,'rear','T',928);
-INSERT INTO `RackSpace` VALUES (44,41,'interior','T',928);
-INSERT INTO `RackSpace` VALUES (44,15,'interior','T',940);
-INSERT INTO `RackSpace` VALUES (44,15,'front','T',940);
-INSERT INTO `RackSpace` VALUES (44,13,'interior','T',938);
-INSERT INTO `RackSpace` VALUES (44,13,'front','T',938);
-INSERT INTO `RackSpace` VALUES (44,11,'interior','T',936);
-INSERT INTO `RackSpace` VALUES (44,11,'front','T',936);
-INSERT INTO `RackSpace` VALUES (44,9,'interior','T',934);
-INSERT INTO `RackSpace` VALUES (44,9,'front','T',934);
-INSERT INTO `RackSpace` VALUES (44,7,'interior','T',932);
-INSERT INTO `RackSpace` VALUES (44,7,'front','T',932);
-INSERT INTO `RackSpace` VALUES (41,2,'front','T',917);
-INSERT INTO `RackSpace` VALUES (41,2,'interior','T',917);
-INSERT INTO `RackSpace` VALUES (41,1,'front','T',917);
-INSERT INTO `RackSpace` VALUES (41,1,'interior','T',917);
-INSERT INTO `RackSpace` VALUES (45,2,'front','T',956);
-INSERT INTO `RackSpace` VALUES (45,2,'interior','T',956);
-INSERT INTO `RackSpace` VALUES (45,2,'rear','T',956);
-INSERT INTO `RackSpace` VALUES (45,4,'front','T',957);
-INSERT INTO `RackSpace` VALUES (45,4,'interior','T',957);
-INSERT INTO `RackSpace` VALUES (45,4,'rear','T',957);
-INSERT INTO `RackSpace` VALUES (45,6,'front','T',958);
-INSERT INTO `RackSpace` VALUES (45,6,'interior','T',958);
-INSERT INTO `RackSpace` VALUES (45,6,'rear','T',958);
-INSERT INTO `RackSpace` VALUES (45,8,'front','T',959);
-INSERT INTO `RackSpace` VALUES (45,8,'interior','T',959);
-INSERT INTO `RackSpace` VALUES (45,8,'rear','T',959);
-INSERT INTO `RackSpace` VALUES (45,10,'front','T',960);
-INSERT INTO `RackSpace` VALUES (45,10,'interior','T',960);
-INSERT INTO `RackSpace` VALUES (45,10,'rear','T',960);
-INSERT INTO `RackSpace` VALUES (45,35,'interior','T',961);
-INSERT INTO `RackSpace` VALUES (45,35,'rear','T',961);
-INSERT INTO `RackSpace` VALUES (45,34,'interior','T',962);
-INSERT INTO `RackSpace` VALUES (45,34,'rear','T',962);
+INSERT INTO `RackSpace` VALUES (968,9,'interior','T',905);
+INSERT INTO `RackSpace` VALUES (968,9,'front','T',905);
+INSERT INTO `RackSpace` VALUES (968,10,'interior','T',905);
+INSERT INTO `RackSpace` VALUES (968,10,'front','T',905);
+INSERT INTO `RackSpace` VALUES (968,11,'interior','T',905);
+INSERT INTO `RackSpace` VALUES (968,11,'front','T',905);
+INSERT INTO `RackSpace` VALUES (968,7,'front','T',906);
+INSERT INTO `RackSpace` VALUES (968,7,'interior','T',906);
+INSERT INTO `RackSpace` VALUES (970,16,'interior','T',907);
+INSERT INTO `RackSpace` VALUES (970,16,'rear','T',907);
+INSERT INTO `RackSpace` VALUES (970,15,'interior','T',907);
+INSERT INTO `RackSpace` VALUES (970,15,'rear','T',907);
+INSERT INTO `RackSpace` VALUES (970,14,'interior','T',907);
+INSERT INTO `RackSpace` VALUES (970,14,'rear','T',907);
+INSERT INTO `RackSpace` VALUES (974,15,'interior','T',909);
+INSERT INTO `RackSpace` VALUES (974,15,'rear','T',909);
+INSERT INTO `RackSpace` VALUES (974,14,'interior','T',909);
+INSERT INTO `RackSpace` VALUES (974,14,'rear','T',909);
+INSERT INTO `RackSpace` VALUES (974,13,'interior','T',909);
+INSERT INTO `RackSpace` VALUES (974,13,'rear','T',909);
+INSERT INTO `RackSpace` VALUES (972,20,'interior','T',908);
+INSERT INTO `RackSpace` VALUES (972,20,'rear','T',908);
+INSERT INTO `RackSpace` VALUES (972,19,'interior','T',908);
+INSERT INTO `RackSpace` VALUES (972,19,'rear','T',908);
+INSERT INTO `RackSpace` VALUES (972,18,'interior','T',908);
+INSERT INTO `RackSpace` VALUES (972,18,'rear','T',908);
+INSERT INTO `RackSpace` VALUES (967,2,'front','T',910);
+INSERT INTO `RackSpace` VALUES (967,2,'interior','T',910);
+INSERT INTO `RackSpace` VALUES (967,2,'rear','T',910);
+INSERT INTO `RackSpace` VALUES (967,4,'front','T',911);
+INSERT INTO `RackSpace` VALUES (967,4,'interior','T',911);
+INSERT INTO `RackSpace` VALUES (967,4,'rear','T',911);
+INSERT INTO `RackSpace` VALUES (967,6,'front','T',912);
+INSERT INTO `RackSpace` VALUES (967,6,'interior','T',912);
+INSERT INTO `RackSpace` VALUES (967,6,'rear','T',912);
+INSERT INTO `RackSpace` VALUES (967,8,'front','T',913);
+INSERT INTO `RackSpace` VALUES (967,8,'interior','T',913);
+INSERT INTO `RackSpace` VALUES (967,8,'rear','T',913);
+INSERT INTO `RackSpace` VALUES (967,10,'front','T',914);
+INSERT INTO `RackSpace` VALUES (967,10,'interior','T',914);
+INSERT INTO `RackSpace` VALUES (967,10,'rear','T',914);
+INSERT INTO `RackSpace` VALUES (967,23,'rear','T',916);
+INSERT INTO `RackSpace` VALUES (967,23,'interior','T',916);
+INSERT INTO `RackSpace` VALUES (967,23,'front','T',916);
+INSERT INTO `RackSpace` VALUES (968,5,'front','T',915);
+INSERT INTO `RackSpace` VALUES (968,5,'interior','T',915);
+INSERT INTO `RackSpace` VALUES (968,4,'interior','T',915);
+INSERT INTO `RackSpace` VALUES (968,4,'front','T',915);
+INSERT INTO `RackSpace` VALUES (967,22,'front','T',916);
+INSERT INTO `RackSpace` VALUES (967,22,'interior','T',916);
+INSERT INTO `RackSpace` VALUES (967,22,'rear','T',916);
+INSERT INTO `RackSpace` VALUES (969,7,'front','T',918);
+INSERT INTO `RackSpace` VALUES (969,7,'interior','T',918);
+INSERT INTO `RackSpace` VALUES (969,7,'rear','T',918);
+INSERT INTO `RackSpace` VALUES (969,6,'front','T',918);
+INSERT INTO `RackSpace` VALUES (969,6,'interior','T',918);
+INSERT INTO `RackSpace` VALUES (969,6,'rear','T',918);
+INSERT INTO `RackSpace` VALUES (969,5,'front','T',918);
+INSERT INTO `RackSpace` VALUES (969,5,'interior','T',918);
+INSERT INTO `RackSpace` VALUES (969,5,'rear','T',918);
+INSERT INTO `RackSpace` VALUES (969,4,'front','T',918);
+INSERT INTO `RackSpace` VALUES (969,4,'interior','T',918);
+INSERT INTO `RackSpace` VALUES (969,4,'rear','T',918);
+INSERT INTO `RackSpace` VALUES (969,3,'front','T',918);
+INSERT INTO `RackSpace` VALUES (969,3,'interior','T',918);
+INSERT INTO `RackSpace` VALUES (969,3,'rear','T',918);
+INSERT INTO `RackSpace` VALUES (969,13,'front','T',919);
+INSERT INTO `RackSpace` VALUES (969,13,'interior','T',919);
+INSERT INTO `RackSpace` VALUES (969,13,'rear','T',919);
+INSERT INTO `RackSpace` VALUES (969,12,'front','T',919);
+INSERT INTO `RackSpace` VALUES (969,12,'interior','T',919);
+INSERT INTO `RackSpace` VALUES (969,12,'rear','T',919);
+INSERT INTO `RackSpace` VALUES (969,11,'front','T',919);
+INSERT INTO `RackSpace` VALUES (969,11,'interior','T',919);
+INSERT INTO `RackSpace` VALUES (969,11,'rear','T',919);
+INSERT INTO `RackSpace` VALUES (969,10,'front','T',919);
+INSERT INTO `RackSpace` VALUES (969,10,'interior','T',919);
+INSERT INTO `RackSpace` VALUES (969,10,'rear','T',919);
+INSERT INTO `RackSpace` VALUES (969,9,'front','T',919);
+INSERT INTO `RackSpace` VALUES (969,9,'interior','T',919);
+INSERT INTO `RackSpace` VALUES (969,9,'rear','T',919);
+INSERT INTO `RackSpace` VALUES (969,37,'front','T',920);
+INSERT INTO `RackSpace` VALUES (969,37,'interior','T',920);
+INSERT INTO `RackSpace` VALUES (969,37,'rear','T',920);
+INSERT INTO `RackSpace` VALUES (969,36,'front','T',920);
+INSERT INTO `RackSpace` VALUES (969,36,'interior','T',920);
+INSERT INTO `RackSpace` VALUES (969,36,'rear','T',920);
+INSERT INTO `RackSpace` VALUES (969,35,'front','T',920);
+INSERT INTO `RackSpace` VALUES (969,35,'interior','T',920);
+INSERT INTO `RackSpace` VALUES (969,35,'rear','T',920);
+INSERT INTO `RackSpace` VALUES (969,34,'front','T',920);
+INSERT INTO `RackSpace` VALUES (969,34,'interior','T',920);
+INSERT INTO `RackSpace` VALUES (969,34,'rear','T',920);
+INSERT INTO `RackSpace` VALUES (969,33,'front','T',920);
+INSERT INTO `RackSpace` VALUES (969,33,'interior','T',920);
+INSERT INTO `RackSpace` VALUES (969,33,'rear','T',920);
+INSERT INTO `RackSpace` VALUES (969,32,'front','T',920);
+INSERT INTO `RackSpace` VALUES (969,32,'interior','T',920);
+INSERT INTO `RackSpace` VALUES (969,32,'rear','T',920);
+INSERT INTO `RackSpace` VALUES (969,31,'front','T',920);
+INSERT INTO `RackSpace` VALUES (969,31,'interior','T',920);
+INSERT INTO `RackSpace` VALUES (969,31,'rear','T',920);
+INSERT INTO `RackSpace` VALUES (969,30,'front','T',920);
+INSERT INTO `RackSpace` VALUES (969,30,'interior','T',920);
+INSERT INTO `RackSpace` VALUES (969,30,'rear','T',920);
+INSERT INTO `RackSpace` VALUES (969,16,'front','T',921);
+INSERT INTO `RackSpace` VALUES (969,16,'interior','T',921);
+INSERT INTO `RackSpace` VALUES (969,16,'rear','T',921);
+INSERT INTO `RackSpace` VALUES (969,15,'front','T',921);
+INSERT INTO `RackSpace` VALUES (969,15,'interior','T',921);
+INSERT INTO `RackSpace` VALUES (969,15,'rear','T',921);
+INSERT INTO `RackSpace` VALUES (969,18,'front','T',922);
+INSERT INTO `RackSpace` VALUES (969,18,'interior','T',922);
+INSERT INTO `RackSpace` VALUES (969,18,'rear','T',922);
+INSERT INTO `RackSpace` VALUES (969,17,'front','T',922);
+INSERT INTO `RackSpace` VALUES (969,17,'interior','T',922);
+INSERT INTO `RackSpace` VALUES (969,17,'rear','T',922);
+INSERT INTO `RackSpace` VALUES (974,11,'interior','T',926);
+INSERT INTO `RackSpace` VALUES (974,11,'rear','T',926);
+INSERT INTO `RackSpace` VALUES (974,1,'front','T',923);
+INSERT INTO `RackSpace` VALUES (974,1,'interior','T',923);
+INSERT INTO `RackSpace` VALUES (974,1,'rear','T',923);
+INSERT INTO `RackSpace` VALUES (974,3,'front','T',924);
+INSERT INTO `RackSpace` VALUES (974,3,'interior','T',924);
+INSERT INTO `RackSpace` VALUES (974,3,'rear','T',924);
+INSERT INTO `RackSpace` VALUES (974,5,'front','T',925);
+INSERT INTO `RackSpace` VALUES (974,5,'interior','T',925);
+INSERT INTO `RackSpace` VALUES (974,5,'rear','T',925);
+INSERT INTO `RackSpace` VALUES (970,12,'interior','T',927);
+INSERT INTO `RackSpace` VALUES (970,12,'rear','T',927);
+INSERT INTO `RackSpace` VALUES (970,11,'interior','T',927);
+INSERT INTO `RackSpace` VALUES (970,11,'rear','T',927);
+INSERT INTO `RackSpace` VALUES (970,10,'interior','T',927);
+INSERT INTO `RackSpace` VALUES (970,10,'rear','T',927);
+INSERT INTO `RackSpace` VALUES (970,2,'front','T',944);
+INSERT INTO `RackSpace` VALUES (970,2,'interior','T',944);
+INSERT INTO `RackSpace` VALUES (970,2,'rear','T',944);
+INSERT INTO `RackSpace` VALUES (970,1,'front','T',944);
+INSERT INTO `RackSpace` VALUES (970,1,'interior','T',944);
+INSERT INTO `RackSpace` VALUES (970,1,'rear','T',944);
+INSERT INTO `RackSpace` VALUES (971,5,'front','T',942);
+INSERT INTO `RackSpace` VALUES (971,5,'interior','T',942);
+INSERT INTO `RackSpace` VALUES (971,5,'rear','T',942);
+INSERT INTO `RackSpace` VALUES (971,4,'front','T',942);
+INSERT INTO `RackSpace` VALUES (971,4,'interior','T',942);
+INSERT INTO `RackSpace` VALUES (971,4,'rear','T',942);
+INSERT INTO `RackSpace` VALUES (971,3,'front','T',942);
+INSERT INTO `RackSpace` VALUES (971,3,'interior','T',942);
+INSERT INTO `RackSpace` VALUES (971,3,'rear','T',942);
+INSERT INTO `RackSpace` VALUES (971,2,'front','T',942);
+INSERT INTO `RackSpace` VALUES (971,2,'interior','T',942);
+INSERT INTO `RackSpace` VALUES (971,2,'rear','T',942);
+INSERT INTO `RackSpace` VALUES (971,1,'front','T',942);
+INSERT INTO `RackSpace` VALUES (971,1,'interior','T',942);
+INSERT INTO `RackSpace` VALUES (971,1,'rear','T',942);
+INSERT INTO `RackSpace` VALUES (973,5,'front','T',943);
+INSERT INTO `RackSpace` VALUES (973,5,'interior','T',943);
+INSERT INTO `RackSpace` VALUES (973,5,'rear','T',943);
+INSERT INTO `RackSpace` VALUES (973,4,'front','T',943);
+INSERT INTO `RackSpace` VALUES (973,4,'interior','T',943);
+INSERT INTO `RackSpace` VALUES (973,4,'rear','T',943);
+INSERT INTO `RackSpace` VALUES (973,3,'front','T',943);
+INSERT INTO `RackSpace` VALUES (973,3,'interior','T',943);
+INSERT INTO `RackSpace` VALUES (973,3,'rear','T',943);
+INSERT INTO `RackSpace` VALUES (973,2,'front','T',943);
+INSERT INTO `RackSpace` VALUES (973,2,'interior','T',943);
+INSERT INTO `RackSpace` VALUES (973,2,'rear','T',943);
+INSERT INTO `RackSpace` VALUES (973,1,'front','T',943);
+INSERT INTO `RackSpace` VALUES (973,1,'interior','T',943);
+INSERT INTO `RackSpace` VALUES (973,1,'rear','T',943);
+INSERT INTO `RackSpace` VALUES (971,6,'front','U',NULL);
+INSERT INTO `RackSpace` VALUES (971,6,'interior','U',NULL);
+INSERT INTO `RackSpace` VALUES (971,6,'rear','U',NULL);
+INSERT INTO `RackSpace` VALUES (973,6,'front','U',NULL);
+INSERT INTO `RackSpace` VALUES (973,6,'interior','U',NULL);
+INSERT INTO `RackSpace` VALUES (973,6,'rear','U',NULL);
+INSERT INTO `RackSpace` VALUES (973,17,'rear','T',954);
+INSERT INTO `RackSpace` VALUES (972,20,'front','T',953);
+INSERT INTO `RackSpace` VALUES (968,6,'front','T',952);
+INSERT INTO `RackSpace` VALUES (967,1,'rear','T',949);
+INSERT INTO `RackSpace` VALUES (973,37,'rear','T',931);
+INSERT INTO `RackSpace` VALUES (973,37,'interior','T',931);
+INSERT INTO `RackSpace` VALUES (973,40,'rear','T',929);
+INSERT INTO `RackSpace` VALUES (973,40,'interior','T',929);
+INSERT INTO `RackSpace` VALUES (973,15,'rear','T',941);
+INSERT INTO `RackSpace` VALUES (973,15,'interior','T',941);
+INSERT INTO `RackSpace` VALUES (973,15,'front','T',941);
+INSERT INTO `RackSpace` VALUES (973,13,'front','T',939);
+INSERT INTO `RackSpace` VALUES (973,11,'rear','T',937);
+INSERT INTO `RackSpace` VALUES (973,11,'interior','T',937);
+INSERT INTO `RackSpace` VALUES (973,9,'interior','T',935);
+INSERT INTO `RackSpace` VALUES (973,7,'interior','T',933);
+INSERT INTO `RackSpace` VALUES (974,16,'rear','T',946);
+INSERT INTO `RackSpace` VALUES (971,38,'rear','T',930);
+INSERT INTO `RackSpace` VALUES (971,40,'interior','T',928);
+INSERT INTO `RackSpace` VALUES (971,15,'rear','T',940);
+INSERT INTO `RackSpace` VALUES (971,13,'rear','T',938);
+INSERT INTO `RackSpace` VALUES (971,11,'rear','T',936);
+INSERT INTO `RackSpace` VALUES (971,9,'rear','T',934);
+INSERT INTO `RackSpace` VALUES (971,7,'rear','T',932);
+INSERT INTO `RackSpace` VALUES (968,12,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,11,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,10,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,9,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,8,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,7,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,6,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,5,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,4,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,3,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,2,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (968,1,'rear','A',NULL);
+INSERT INTO `RackSpace` VALUES (974,9,'rear','T',955);
+INSERT INTO `RackSpace` VALUES (971,17,'rear','T',951);
+INSERT INTO `RackSpace` VALUES (970,9,'rear','T',948);
+INSERT INTO `RackSpace` VALUES (969,14,'rear','T',950);
+INSERT INTO `RackSpace` VALUES (969,2,'rear','T',947);
+INSERT INTO `RackSpace` VALUES (973,38,'rear','T',931);
+INSERT INTO `RackSpace` VALUES (973,38,'interior','T',931);
+INSERT INTO `RackSpace` VALUES (973,41,'rear','T',929);
+INSERT INTO `RackSpace` VALUES (973,41,'interior','T',929);
+INSERT INTO `RackSpace` VALUES (973,13,'rear','T',939);
+INSERT INTO `RackSpace` VALUES (973,13,'interior','T',939);
+INSERT INTO `RackSpace` VALUES (973,11,'front','T',937);
+INSERT INTO `RackSpace` VALUES (973,9,'rear','T',935);
+INSERT INTO `RackSpace` VALUES (973,9,'front','T',935);
+INSERT INTO `RackSpace` VALUES (973,7,'rear','T',933);
+INSERT INTO `RackSpace` VALUES (973,7,'front','T',933);
+INSERT INTO `RackSpace` VALUES (970,13,'rear','T',945);
+INSERT INTO `RackSpace` VALUES (971,37,'rear','T',930);
+INSERT INTO `RackSpace` VALUES (971,37,'interior','T',930);
+INSERT INTO `RackSpace` VALUES (971,38,'interior','T',930);
+INSERT INTO `RackSpace` VALUES (971,40,'rear','T',928);
+INSERT INTO `RackSpace` VALUES (971,41,'rear','T',928);
+INSERT INTO `RackSpace` VALUES (971,41,'interior','T',928);
+INSERT INTO `RackSpace` VALUES (971,15,'interior','T',940);
+INSERT INTO `RackSpace` VALUES (971,15,'front','T',940);
+INSERT INTO `RackSpace` VALUES (971,13,'interior','T',938);
+INSERT INTO `RackSpace` VALUES (971,13,'front','T',938);
+INSERT INTO `RackSpace` VALUES (971,11,'interior','T',936);
+INSERT INTO `RackSpace` VALUES (971,11,'front','T',936);
+INSERT INTO `RackSpace` VALUES (971,9,'interior','T',934);
+INSERT INTO `RackSpace` VALUES (971,9,'front','T',934);
+INSERT INTO `RackSpace` VALUES (971,7,'interior','T',932);
+INSERT INTO `RackSpace` VALUES (971,7,'front','T',932);
+INSERT INTO `RackSpace` VALUES (968,2,'front','T',917);
+INSERT INTO `RackSpace` VALUES (968,2,'interior','T',917);
+INSERT INTO `RackSpace` VALUES (968,1,'front','T',917);
+INSERT INTO `RackSpace` VALUES (968,1,'interior','T',917);
+INSERT INTO `RackSpace` VALUES (972,2,'front','T',956);
+INSERT INTO `RackSpace` VALUES (972,2,'interior','T',956);
+INSERT INTO `RackSpace` VALUES (972,2,'rear','T',956);
+INSERT INTO `RackSpace` VALUES (972,4,'front','T',957);
+INSERT INTO `RackSpace` VALUES (972,4,'interior','T',957);
+INSERT INTO `RackSpace` VALUES (972,4,'rear','T',957);
+INSERT INTO `RackSpace` VALUES (972,6,'front','T',958);
+INSERT INTO `RackSpace` VALUES (972,6,'interior','T',958);
+INSERT INTO `RackSpace` VALUES (972,6,'rear','T',958);
+INSERT INTO `RackSpace` VALUES (972,8,'front','T',959);
+INSERT INTO `RackSpace` VALUES (972,8,'interior','T',959);
+INSERT INTO `RackSpace` VALUES (972,8,'rear','T',959);
+INSERT INTO `RackSpace` VALUES (972,10,'front','T',960);
+INSERT INTO `RackSpace` VALUES (972,10,'interior','T',960);
+INSERT INTO `RackSpace` VALUES (972,10,'rear','T',960);
+INSERT INTO `RackSpace` VALUES (972,35,'interior','T',961);
+INSERT INTO `RackSpace` VALUES (972,35,'rear','T',961);
+INSERT INTO `RackSpace` VALUES (972,34,'interior','T',962);
+INSERT INTO `RackSpace` VALUES (972,34,'rear','T',962);
 
 INSERT INTO `TagTree` (`id`, `parent_id`, `tag`) VALUES (16,NULL,'Geo');
 INSERT INTO `TagTree` (`id`, `parent_id`, `tag`) VALUES (17,NULL,'network');
@@ -808,22 +823,22 @@ INSERT INTO `TagStorage` VALUES ('ipv4net',107,7);
 INSERT INTO `TagStorage` VALUES ('ipv4net',107,19);
 INSERT INTO `TagStorage` VALUES ('ipv4net',108,10);
 INSERT INTO `TagStorage` VALUES ('ipv4net',108,19);
-INSERT INTO `TagStorage` VALUES ('rack',40,8);
-INSERT INTO `TagStorage` VALUES ('rack',40,13);
-INSERT INTO `TagStorage` VALUES ('rack',41,8);
-INSERT INTO `TagStorage` VALUES ('rack',41,14);
-INSERT INTO `TagStorage` VALUES ('rack',42,8);
-INSERT INTO `TagStorage` VALUES ('rack',42,13);
-INSERT INTO `TagStorage` VALUES ('rack',43,9);
-INSERT INTO `TagStorage` VALUES ('rack',43,14);
-INSERT INTO `TagStorage` VALUES ('rack',44,9);
-INSERT INTO `TagStorage` VALUES ('rack',44,13);
-INSERT INTO `TagStorage` VALUES ('rack',45,7);
-INSERT INTO `TagStorage` VALUES ('rack',45,13);
-INSERT INTO `TagStorage` VALUES ('rack',46,9);
-INSERT INTO `TagStorage` VALUES ('rack',46,13);
-INSERT INTO `TagStorage` VALUES ('rack',47,10);
-INSERT INTO `TagStorage` VALUES ('rack',47,14);
+INSERT INTO `TagStorage` VALUES ('rack',967,8);
+INSERT INTO `TagStorage` VALUES ('rack',967,13);
+INSERT INTO `TagStorage` VALUES ('rack',968,8);
+INSERT INTO `TagStorage` VALUES ('rack',968,14);
+INSERT INTO `TagStorage` VALUES ('rack',969,8);
+INSERT INTO `TagStorage` VALUES ('rack',969,13);
+INSERT INTO `TagStorage` VALUES ('rack',970,9);
+INSERT INTO `TagStorage` VALUES ('rack',970,14);
+INSERT INTO `TagStorage` VALUES ('rack',971,9);
+INSERT INTO `TagStorage` VALUES ('rack',971,13);
+INSERT INTO `TagStorage` VALUES ('rack',972,7);
+INSERT INTO `TagStorage` VALUES ('rack',972,13);
+INSERT INTO `TagStorage` VALUES ('rack',973,9);
+INSERT INTO `TagStorage` VALUES ('rack',973,13);
+INSERT INTO `TagStorage` VALUES ('rack',974,10);
+INSERT INTO `TagStorage` VALUES ('rack',974,14);
 INSERT INTO `TagStorage` VALUES ('ipv6net','1','17');
 INSERT INTO `TagStorage` VALUES ('ipv6net','2','19');
 INSERT INTO `TagStorage` VALUES ('ipv6net','3','19');
index 5d44d73..61858c9 100644 (file)
@@ -172,6 +172,10 @@ tr.port_highlight, td.port_highlight {
        background-color: #e8e8e8;
 }
 
+.row_error {
+       background-color: #ffa0a0;
+}
+
 table.cooltable {
        border: 1px solid black;
 }
index 5f636b7..54a8832 100644 (file)
@@ -41,7 +41,7 @@ $max_dict_key = array
        '0.19.1' => 1559,
        '0.19.2' => 1559,
        '0.19.3' => 1559,
-       '0.20.0' => 1559,
+       '0.20.0' => 1562,
 );
 
 ?>
index 1c6a034..7e710a3 100644 (file)
@@ -18,9 +18,9 @@ $SQLSchema = array
                        'asset_no' => 'asset_no',
                        'objtype_id' => 'objtype_id',
                        'rack_id' => '(select rack_id from RackSpace where object_id = id order by rack_id asc limit 1)',
-                       'Rack_name' => '(select name from Rack where id = rack_id)',
+                       'rack_name' => '(select name from Rack where id = rack_id)',
                        'row_id' => '(select row_id from Rack where id = rack_id)',
-                       'Row_name' => '(select name from RackRow where id = row_id)',
+                       'row_name' => '(select name from Row where id = row_id)',
                        'has_problems' => 'has_problems',
                        'comment' => 'comment',
                        'nports' => '(SELECT COUNT(*) FROM Port WHERE object_id = RackObject.id)',
@@ -132,14 +132,28 @@ $SQLSchema = array
                        'id' => 'id',
                        'name' => 'name',
                        'height' => 'height',
+                       'label' => 'label',
+                       'asset_no' => 'asset_no',
+                       'has_problems' => 'has_problems',
                        'comment' => 'comment',
                        'row_id' => 'row_id',
-                       'row_name' => '(select name from RackRow where RackRow.id = row_id)',
+                       'row_name' => 'row_name',
                ),
                'keycolumn' => 'id',
                'ordcolumns' => array ('row_name', 'Rack.name'),
                'pidcolumn' => 'row_id',
        ),
+       'row' => array
+       (
+               'table' => 'Row',
+               'columns' => array
+               (
+                       'id' => 'id',
+                       'name' => 'name',
+               ),
+               'keycolumn' => 'id',
+               'ordcolumns' => array ('name'),
+       ),
        'vst' => array
        (
                'table' => 'VLANSwitchTemplate',
@@ -199,30 +213,50 @@ $port_role_options = array
 $object_attribute_cache = array();
 
 // Return detailed information about one rack row.
-function getRackRowInfo ($rackrow_id)
+function getRowInfo ($row_id)
 {
        $query =
-               "select RackRow.id as id, RackRow.name as name, count(Rack.id) as count, " .
+               "select Row.id as id, Row.name as name, count(Rack.id) as count, " .
                "if(isnull(sum(Rack.height)),0,sum(Rack.height)) as sum " .
-               "from RackRow left join Rack on Rack.row_id = RackRow.id " .
-               "where RackRow.id = ? " .
-               "group by RackRow.id";
-       $result = usePreparedSelectBlade ($query, array ($rackrow_id));
+               "from Row left join Rack on Rack.row_id = Row.id " .
+               "where Row.id = ? " .
+               "group by Row.id";
+       $result = usePreparedSelectBlade ($query, array ($row_id));
        if ($row = $result->fetch (PDO::FETCH_ASSOC))
                return $row;
        else
-               throw new EntityNotFoundException ('rackrow', $rackrow_id);
+               throw new EntityNotFoundException ('rackrow', $row_id);
 }
 
-function getRackRows ()
+function getRows ()
 {
-       $result = usePreparedSelectBlade ('SELECT id, name FROM RackRow ORDER BY name');
+       $result = usePreparedSelectBlade ('SELECT id, name FROM Row ORDER BY name');
        $rows = array();
        while ($row = $result->fetch (PDO::FETCH_ASSOC))
                $rows[$row['id']] = $row['name'];
        return $rows;
 }
 
+function getRacks ($row_id)
+{
+       $query = usePreparedSelectBlade
+       (
+               'SELECT  id, name, label, asset_no, height, comment, row_name FROM Rack WHERE row_id = ?',
+               array ($row_id)
+       );
+       $ret = array();
+       while ($row = $query->fetch (PDO::FETCH_ASSOC))
+               $ret[$row['rack_id']] = array (
+                       'name' => $row['name'],
+                       'label' => $row['type'],
+                       'asset_no' => $row['size'],
+                       'height' => $row['ctime'],
+                       'comment' => $row['mtime'],
+                       'row_name' => $row['atime'],
+               );
+       return $ret;
+}
+
 // Return a simple object list w/o related information, so that the returned value
 // can be directly used by printSelect(). An optional argument is the name of config
 // option with constraint in RackCode.
@@ -505,6 +539,8 @@ function amplifyCell (&$record, $dummy = NULL)
                }
                unset ($result);
                break;
+       case 'row':
+               $record['racks'] = getRacks ($record['id']);
        case 'rack':
                $record['mountedObjects'] = array();
                // start with default rackspace
@@ -570,7 +606,7 @@ SELECT
        (SELECT PortInnerInterface.iif_name FROM PortInnerInterface WHERE PortInnerInterface.id = Port.iif_id) AS iif_name,
        (SELECT Dictionary.dict_value FROM Dictionary WHERE Dictionary.dict_key = Port.type) AS oif_name,
        (SELECT COUNT(*) FROM PortLog WHERE PortLog.port_id = Port.id) AS log_count,
-       (SELECT name FROM RackObject WHERE Port.object_id = RackObject.id) AS object_name,
+       (SELECT name FROM Object WHERE Port.object_id = Object.id) AS object_name,
        Link.cable as cableid,
        pa.id as pa_id,
        pa.name as pa_name,
@@ -589,8 +625,8 @@ FROM
                Link
                INNER JOIN Port AS pa ON Link.porta = pa.id
                INNER JOIN Port AS pb ON Link.portb = pb.id
-               INNER JOIN RackObject AS oa ON pa.object_id = oa.id
-               INNER JOIN RackObject AS ob ON pb.object_id = ob.id
+               INNER JOIN Object AS oa ON pa.object_id = oa.id
+               INNER JOIN Object AS ob ON pb.object_id = ob.id
        ) ON (Port.id = Link.porta OR Port.id = Link.portb)
        LEFT JOIN PortLog ON PortLog.id = (SELECT id FROM PortLog WHERE PortLog.port_id = Port.id ORDER BY date DESC LIMIT 1)
 WHERE
@@ -638,53 +674,33 @@ function getObjectPortsAndLinks ($object_id)
        return sortPortList ($ret, TRUE);
 }
 
-function commitAddRack ($name, $height, $row_id, $comment, $taglist)
-{
-       usePreparedInsertBlade
-       (
-               'Rack',
-               array
-               (
-                       'row_id' => $row_id,
-                       'name' => $name,
-                       'height' =>  $height,
-                       'comment' => $comment
-               )
-       );
-       $last_insert_id = lastInsertID();
-       produceTagsForLastRecord ('rack', $taglist, $last_insert_id);
-       recordHistory ('Rack', $last_insert_id);
-}
-
 function commitAddObject ($new_name, $new_label, $new_type_id, $new_asset_no, $taglist = array())
 {
        usePreparedInsertBlade
        (
-               'RackObject',
+               'Object',
                array
                (
                        'name' => !strlen ($new_name) ? NULL : $new_name,
-                       'label' => $new_label,
+                       'label' => !strlen ($new_label) ? NULL : $new_label,
                        'objtype_id' => $new_type_id,
                        'asset_no' => !strlen ($new_asset_no) ? NULL : $new_asset_no,
                )
        );
-       $last_insert_id = lastInsertID();
+       $object_id = lastInsertID();
        // Do AutoPorts magic
-       executeAutoPorts ($last_insert_id, $new_type_id);
+       executeAutoPorts ($object_id, $new_type_id);
        // Now tags...
-       produceTagsForLastRecord ('object', $taglist, $last_insert_id);
-
-       recordHistory ('RackObject', $last_insert_id);
-
-       return $last_insert_id;
+       produceTagsForLastRecord ('object', $taglist, $object_id);
+       recordObjectHistory ($object_id);
+       return $object_id;
 }
 
 function commitUpdateObject ($object_id, $new_name, $new_label, $new_has_problems, $new_asset_no, $new_comment)
 {
        usePreparedUpdateBlade
        (
-               'RackObject',
+               'Object',
                array
                (
                        'name' => !mb_strlen ($new_name) ? NULL : $new_name,
@@ -698,7 +714,7 @@ function commitUpdateObject ($object_id, $new_name, $new_label, $new_has_problem
                        'id' => $object_id
                )
        );
-       recordHistory ('RackObject', $object_id);
+       recordObjectHistory ($object_id);
 }
 
 // used by getEntityRelatives for sorting
@@ -757,6 +773,30 @@ function getEntityRelatives ($type, $entity_type, $entity_id)
        return $ret;
 }
 
+function commitLinkEntities ($parent_entity_type, $parent_entity_id, $child_entity_type, $child_entity_id)
+{
+       usePreparedInsertBlade
+       (
+               'EntityLink',
+               array
+               (
+                       'parent_entity_type' => $parent_entity_type,
+                       'parent_entity_id' => $parent_entity_id,
+                       'child_entity_type' => $child_entity_type,
+                       'child_entity_id' => $child_entity_id,
+               )
+       );
+}
+
+function commitUpdateEntityLink ($link_id, $parent_entity_type, $parent_entity_id, $child_entity_type, $child_entity_id)
+{
+       usePreparedExecuteBlade
+       (
+               'UPDATE EntityLink SET parent_entity_type=?, parent_entity_id=?, child_entity_type=?, child_entity_id=? WHERE id=?',
+               array ($parent_entity_type, $parent_entity_id, $child_entity_type, $child_entity_id, $link_id)
+       );
+}
+
 function commitUnlinkEntities ($link_id)
 {
        usePreparedDeleteBlade ('EntityLink', array ('id' => $link_id));
@@ -768,25 +808,25 @@ function getVMClusterSummary ()
 {
        $result = usePreparedSelectBlade
        (
-               "SELECT RO.id, RO.name, " .
+               "SELECT O.id, O.name, " .
                "(SELECT COUNT(*) FROM EntityLink EL " .
-               "LEFT JOIN RackObject RO_H ON EL.child_entity_id = RO_H.id " .
-               "LEFT JOIN AttributeValue AV ON RO_H.id = AV.object_id " .
+               "LEFT JOIN Object O_H ON EL.child_entity_id = O_H.id " .
+               "LEFT JOIN AttributeValue AV ON O_H.id = AV.object_id " .
                "WHERE EL.parent_entity_type = 'object' " .
                "AND EL.child_entity_type = 'object' " .
-               "AND EL.parent_entity_id = RO.id " .
-               "AND RO_H.objtype_id = 4 " .
+               "AND EL.parent_entity_id = O.id " .
+               "AND O_H.objtype_id = 4 " .
                "AND AV.attr_id = 26 " .
                "AND AV.uint_value = 1501) AS hypervisors, " .
                "(SELECT COUNT(*) FROM EntityLink EL " .
-               "LEFT JOIN RackObject RO_VM ON EL.child_entity_id = RO_VM.id " .
+               "LEFT JOIN Object O_VM ON EL.child_entity_id = O_VM.id " .
                "WHERE EL.parent_entity_type = 'object' " .
                "AND EL.child_entity_type = 'object' " .
-               "AND EL.parent_entity_id = RO.id " .
-               "AND RO_VM.objtype_id = 1504) AS VMs " .
-               "FROM RackObject RO " .
-               "WHERE RO.objtype_id = 1505 " .
-               "ORDER BY RO.name"
+               "AND EL.parent_entity_id = O.id " .
+               "AND O_VM.objtype_id = 1504) AS VMs " .
+               "FROM Object O " .
+               "WHERE O.objtype_id = 1505 " .
+               "ORDER BY O.name"
        );
        return $result->fetchAll (PDO::FETCH_ASSOC);
 }
@@ -795,30 +835,30 @@ function getVMResourcePoolSummary ()
 {
        $result = usePreparedSelectBlade
        (
-               "SELECT RO.id, RO.name, " .
-               "(SELECT RO_C.id " .
+               "SELECT O.id, O.name, " .
+               "(SELECT O_C.id " .
                "FROM EntityLink EL " .
-               "LEFT JOIN RackObject RO_C ON EL.parent_entity_id = RO_C.id " .
-               "WHERE EL.child_entity_id = RO.id " .
+               "LEFT JOIN Object O_C ON EL.parent_entity_id = O_C.id " .
+               "WHERE EL.child_entity_id = O.id " .
                "AND EL.parent_entity_type = 'object' " .
                "AND EL.child_entity_type = 'object' " .
-               "AND RO_C.objtype_id = 1505) AS cluster_id, " .
-               "(SELECT RO_C.name " .
+               "AND O_C.objtype_id = 1505) AS cluster_id, " .
+               "(SELECT O_C.name " .
                "FROM EntityLink EL " .
-               "LEFT JOIN RackObject RO_C ON EL.parent_entity_id = RO_C.id " .
-               "WHERE EL.child_entity_id = RO.id " .
+               "LEFT JOIN Object O_C ON EL.parent_entity_id = O_C.id " .
+               "WHERE EL.child_entity_id = O.id " .
                "AND EL.parent_entity_type = 'object' " .
                "AND EL.child_entity_type = 'object' " .
-               "AND RO_C.objtype_id = 1505) AS cluster_name, " .
+               "AND O_C.objtype_id = 1505) AS cluster_name, " .
                "(SELECT COUNT(*) FROM EntityLink EL " .
-               "LEFT JOIN RackObject RO_VM ON EL.child_entity_id = RO_VM.id " .
+               "LEFT JOIN Object O_VM ON EL.child_entity_id = O_VM.id " .
                "WHERE EL.parent_entity_type = 'object' " .
                "AND EL.child_entity_type = 'object' " .
-               "AND EL.parent_entity_id = RO.id " .
-               "AND RO_VM.objtype_id = 1504) AS VMs " .
-               "FROM RackObject RO " .
-               "WHERE RO.objtype_id = 1506 " .
-               "ORDER BY RO.name"
+               "AND EL.parent_entity_id = O.id " .
+               "AND O_VM.objtype_id = 1504) AS VMs " .
+               "FROM Object O " .
+               "WHERE O.objtype_id = 1506 " .
+               "ORDER BY O.name"
        );
        return $result->fetchAll (PDO::FETCH_ASSOC);
 }
@@ -827,33 +867,33 @@ function getVMHypervisorSummary ()
 {
        $result = usePreparedSelectBlade
        (
-               "SELECT RO.id, RO.name, " .
-               "(SELECT RO_C.id " .
+               "SELECT O.id, O.name, " .
+               "(SELECT O_C.id " .
                "FROM EntityLink EL " .
-               "LEFT JOIN RackObject RO_C ON EL.parent_entity_id = RO_C.id " .
-               "WHERE EL.child_entity_id = RO.id " .
+               "LEFT JOIN Object O_C ON EL.parent_entity_id = O_C.id " .
+               "WHERE EL.child_entity_id = O.id " .
                "AND EL.parent_entity_type = 'object' " .
                "AND EL.child_entity_type = 'object' " .
-               "AND RO_C.objtype_id = 1505) AS cluster_id, " .
-               "(SELECT RO_C.name " .
+               "AND O_C.objtype_id = 1505) AS cluster_id, " .
+               "(SELECT O_C.name " .
                "FROM EntityLink EL " .
-               "LEFT JOIN RackObject RO_C ON EL.parent_entity_id = RO_C.id " .
-               "WHERE EL.child_entity_id = RO.id " .
+               "LEFT JOIN Object O_C ON EL.parent_entity_id = O_C.id " .
+               "WHERE EL.child_entity_id = O.id " .
                "AND EL.parent_entity_type = 'object' " .
                "AND EL.child_entity_type = 'object' " .
-               "AND RO_C.objtype_id = 1505) AS cluster_name, " .
+               "AND O_C.objtype_id = 1505) AS cluster_name, " .
                "(SELECT COUNT(*) FROM EntityLink EL " .
-               "LEFT JOIN RackObject RO_VM ON EL.child_entity_id = RO_VM.id " .
+               "LEFT JOIN Object O_VM ON EL.child_entity_id = O_VM.id " .
                "WHERE EL.parent_entity_type = 'object' " .
                "AND EL.child_entity_type = 'object' " .
-               "AND EL.parent_entity_id = RO.id " .
-               "AND RO_VM.objtype_id = 1504) AS VMs " .
-               "FROM RackObject RO " .
-               "LEFT JOIN AttributeValue AV ON RO.id = AV.object_id " .
-               "WHERE RO.objtype_id = 4 " .
+               "AND EL.parent_entity_id = O.id " .
+               "AND O_VM.objtype_id = 1504) AS VMs " .
+               "FROM Object O " .
+               "LEFT JOIN AttributeValue AV ON O.id = AV.object_id " .
+               "WHERE O.objtype_id = 4 " .
                "AND AV.attr_id = 26 " .
                "AND AV.uint_value = 1501 " .
-               "ORDER BY RO.name"
+               "ORDER BY O.name"
        );
        return $result->fetchAll (PDO::FETCH_ASSOC);
 }
@@ -862,10 +902,10 @@ function getVMSwitchSummary ()
 {
        $result = usePreparedSelectBlade
        (
-               "SELECT RO.id, RO.name " .
-               "FROM RackObject RO " .
-               "WHERE RO.objtype_id = 1507 " .
-               "ORDER BY RO.name"
+               "SELECT O.id, O.name " .
+               "FROM Object O " .
+               "WHERE O.objtype_id = 1507 " .
+               "ORDER BY O.name"
        );
        return $result->fetchAll (PDO::FETCH_ASSOC);
 }
@@ -882,7 +922,7 @@ function commitDeleteObject ($object_id = 0)
        // Reset most of stuff
        commitResetObject ($object_id);
        // Object itself
-       usePreparedDeleteBlade ('RackObject', array ('id' => $object_id));
+       usePreparedDeleteBlade ('Object', array ('id' => $object_id));
 }
 
 function commitResetObject ($object_id = 0)
@@ -914,11 +954,11 @@ function commitResetObject ($object_id = 0)
        // Ports & links
        usePreparedDeleteBlade ('Port', array ('object_id' => $object_id));
        // CN
-       usePreparedUpdateBlade ('RackObject', array ('name' => NULL, 'label' => ''), array ('id' => $object_id));
+       usePreparedUpdateBlade ('Object', array ('name' => NULL, 'label' => ''), array ('id' => $object_id));
        // FQDN
        commitUpdateAttrValue ($object_id, 3, "");
        // log history
-       recordHistory ('RackObject', $object_id);
+       recordObjectHistory ($object_id);
 }
 
 function commitDeleteRack($rack_id)
@@ -930,7 +970,7 @@ function commitDeleteRack($rack_id)
        usePreparedDeleteBlade ('Rack', array ('id' => $rack_id));
 }
 
-function commitUpdateRack ($rack_id, $new_name, $new_height, $new_row_id, $new_comment)
+function commitUpdateRack ($rack_id, $new_row_id, $new_name, $new_height, $new_label, $new_has_problems, $new_asset_no, $new_comment)
 {
        // Can't shrink a rack if rows being deleted contain mounted objects
        $check_result = usePreparedSelectBlade ('SELECT COUNT(*) AS count FROM RackSpace WHERE rack_id = ? AND unit_no > ?', array ($rack_id, $new_height));
@@ -938,22 +978,33 @@ function commitUpdateRack ($rack_id, $new_name, $new_height, $new_row_id, $new_c
        unset ($check_result);
        if ($check_row['count'] > 0)
                throw new InvalidArgException ('new_height', $new_height, 'Cannot shrink rack, objects are still mounted there');
+
+       // Update the row
        usePreparedUpdateBlade
        (
-               'Rack',
+               'EntityLink',
+               array ('parent_entity_id' => $new_row_id),
+               array ('child_entity_type' => 'object', 'child_entity_id' => $rack_id)
+       );
+
+       // Update the height
+       commitUpdateAttrValue ($rack_id, 27, $new_height);
+
+       // Update the rack
+       usePreparedUpdateBlade
+       (
+               'Object',
                array
                (
                        'name' => $new_name,
-                       'height' => $new_height,
+                       'label' => !mb_strlen ($new_label) ? NULL : $new_label,
+                       'has_problems' => $new_has_problems,
+                       'asset_no' => !mb_strlen ($new_asset_no) ? NULL : $new_asset_no,
                        'comment' => $new_comment,
-                       'row_id' => $new_row_id,
                ),
-               array
-               (
-                       'id' => $rack_id,
-               )
+               array ('id' => $rack_id)
        );
-       recordHistory ('Rack', $rack_id);
+       recordObjectHistory ($rack_id);
 }
 
 // This function accepts rack data returned by amplifyCell(), validates and applies changes
@@ -1021,7 +1072,7 @@ function processGridForm (&$rackData, $unchecked_state, $checked_state, $object_
        }
        if ($rackchanged)
        {
-               usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
+               usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
                $dbxlink->commit();
                return TRUE;
        }
@@ -1080,17 +1131,15 @@ function createMolecule ($molData)
 
 // History logger. This function assumes certain table naming convention and
 // column design:
-// 1. History table name equals to dictionary table name plus 'History'.
-// 2. History table must have the same row set (w/o keys) plus one row named
-// 'ctime' of type 'timestamp'.
-function recordHistory ($tableName, $orig_id)
+// - History table must have the same row set (w/o keys) plus one row named
+//   'ctime' of type 'timestamp'.
+function recordObjectHistory ($object_id)
 {
        global $remote_username;
        usePreparedExecuteBlade
        (
-               "INSERT INTO ${tableName}History SELECT *, CURRENT_TIMESTAMP(), ? " .
-               "FROM ${tableName} WHERE id=?",
-               array ($remote_username, $orig_id)
+               "INSERT INTO ObjectHistory SELECT *, CURRENT_TIMESTAMP(), ? FROM Object WHERE id=?",
+               array ($remote_username, $object_id)
        );
 }
 
@@ -1258,10 +1307,10 @@ function getAllIPv4Allocations ()
        $result = usePreparedSelectBlade
        (
                "select object_id as object_id, ".
-               "RackObject.name as object_name, ".
+               "Object.name as object_name, ".
                "IPv4Allocation.name as name, ".
                "INET_NTOA(ip) as ip ".
-               "from IPv4Allocation join RackObject on id=object_id "
+               "from IPv4Allocation join Object on id=object_id "
        );
        $ret = array();
        while ($row = $result->fetch (PDO::FETCH_ASSOC))
@@ -1304,8 +1353,8 @@ function linkPorts ($porta, $portb, $cable = NULL)
        // log new links
        $result = usePreparedSelectBlade
        (
-               "SELECT Port.id, Port.name as port_name, RackObject.name as obj_name FROM Port " .
-               "INNER JOIN RackObject ON Port.object_id = RackObject.id WHERE Port.id IN (?, ?)",
+               "SELECT Port.id, Port.name as port_name, Object.name as obj_name FROM Port " .
+               "INNER JOIN Object ON Port.object_id = Object.id WHERE Port.id IN (?, ?)",
                array ($porta, $portb)
        );
        while ($row = $result->fetch (PDO::FETCH_ASSOC))
@@ -2100,16 +2149,37 @@ function getRackSearchResult ($terms)
                $terms,
                'name'
        );
+       $byLabel = getSearchResultByField
+       (
+               'Rack',
+               array ('id'),
+               'label',
+               $terms,
+               'name'
+       );
+       $byAssetNo = getSearchResultByField
+       (
+               'Rack',
+               array ('id'),
+               'asset_no',
+               $terms,
+               'name'
+       );
        // Filter out dupes.
        foreach ($byName as $res1)
+       {
                foreach (array_keys ($byComment) as $key2)
                        if ($res1['id'] == $byComment[$key2]['id'])
-                       {
                                unset ($byComment[$key2]);
-                               continue 2;
-                       }
+               foreach (array_keys ($byLabel) as $key3)
+                       if ($res1['id'] == $byLabel[$key3]['id'])
+                               unset ($byLabel[$key3]);
+               foreach (array_keys ($byAssetNo) as $key4)
+                       if ($res1['id'] == $byAssetNo[$key4]['id'])
+                               unset ($byAssetNo[$key4]);
+       }
        $ret = array();
-       foreach (array_merge ($byName, $byComment) as $row)
+       foreach (array_merge ($byName, $byComment, $byLabel, $byAssetNo) as $row)
                $ret[$row['id']] = spotEntity ('rack', $row['id']);
        return $ret;
 }
@@ -2439,7 +2509,7 @@ function getObjectParentCompat ()
 }
 
 // Used to determine if a type of object may have a parent or not
-function rackObjectTypeMayHaveParent ($objtype_id)
+function objectTypeMayHaveParent ($objtype_id)
 {
        $result = usePreparedSelectBlade ('SELECT COUNT(*) FROM ObjectParentCompat WHERE child_objtype_id = ?', array ($objtype_id));
        $row = $result->fetch (PDO::FETCH_NUM);
@@ -2559,7 +2629,7 @@ function getRackspaceStats ()
 {
        $ret = array();
        $subject = array();
-       $subject[] = array ('q' => 'select count(*) from RackRow', 'txt' => 'Rack rows');
+       $subject[] = array ('q' => 'select count(*) from Row', 'txt' => 'Rows');
        $subject[] = array ('q' => 'select count(*) from Rack', 'txt' => 'Racks');
        $subject[] = array ('q' => 'select avg(height) from Rack', 'txt' => 'Average rack height');
        $subject[] = array ('q' => 'select sum(height) from Rack', 'txt' => 'Total rack units in field');
@@ -2580,8 +2650,7 @@ The following allows figuring out records in TagStorage, which refer to non-exis
 
 mysql> select entity_id from TagStorage left join Files on entity_id = id where entity_realm = 'file' and id is null;
 mysql> select entity_id from TagStorage left join IPv4Network on entity_id = id where entity_realm = 'ipv4net' and id is null;
-mysql> select entity_id from TagStorage left join RackObject on entity_id = id where entity_realm = 'object' and id is null;
-mysql> select entity_id from TagStorage left join Rack on entity_id = id where entity_realm = 'rack' and id is null;
+mysql> select entity_id from TagStorage left join Object on entity_id = id where entity_realm = 'object' and id is null;
 mysql> select entity_id from TagStorage left join IPv4VS on entity_id = id where entity_realm = 'ipv4vs' and id is null;
 mysql> select entity_id from TagStorage left join IPv4RSPool on entity_id = id where entity_realm = 'ipv4rspool' and id is null;
 mysql> select entity_id from TagStorage left join UserAccount on entity_id = user_id where entity_realm = 'user' and user_id is null;
@@ -2627,9 +2696,9 @@ function getChapterRefc ($chapter_id, $keylist)
        switch ($chapter_id)
        {
        case CHAP_OBJTYPE:
-               // RackObjectType chapter is referenced by AttributeMap and RackObject tables
+               // ObjectType chapter is referenced by AttributeMap and Object tables
                $query = 'select dict_key as uint_value, (select count(*) from AttributeMap where objtype_id = dict_key) + ' .
-                       "(select count(*) from RackObject where objtype_id = dict_key) as refcnt from Dictionary where chapter_id = ?";
+                       "(select count(*) from Object where objtype_id = dict_key) as refcnt from Dictionary where chapter_id = ?";
                break;
        case CHAP_PORTTYPE:
                // PortOuterInterface chapter is referenced by PortCompat, PortInterfaceCompat and Port tables
@@ -2643,8 +2712,8 @@ function getChapterRefc ($chapter_id, $keylist)
                $query = "select uint_value, count(object_id) as refcnt 
                        from AttributeMap am 
                        inner join AttributeValue av on am.attr_id = av.attr_id
-                       inner join RackObject ro on ro.id = av.object_id
-                       where am.chapter_id = ? and ro.objtype_id = am.objtype_id
+                       inner join Object o on o.id = av.object_id
+                       where am.chapter_id = ? and o.objtype_id = am.objtype_id
                        group by uint_value";
                break;
        }
@@ -2662,8 +2731,8 @@ function getAttrMap ()
        (
                'SELECT id, type, name, chapter_id, (SELECT dict_value FROM Dictionary WHERE dict_key = objtype_id) '.
                'AS objtype_name, (SELECT name FROM Chapter WHERE id = chapter_id) ' .
-               'AS chapter_name, objtype_id, (SELECT COUNT(object_id) FROM AttributeValue AS av INNER JOIN RackObject AS ro ' .
-               'ON av.object_id = ro.id WHERE av.attr_id = Attribute.id AND ro.objtype_id = AttributeMap.objtype_id) ' .
+               'AS chapter_name, objtype_id, (SELECT COUNT(object_id) FROM AttributeValue AS av INNER JOIN Object AS o ' .
+               'ON av.object_id = o.id WHERE av.attr_id = Attribute.id AND o.objtype_id = AttributeMap.objtype_id) ' .
                'AS refcnt FROM Attribute LEFT JOIN AttributeMap ON id = attr_id ORDER BY Attribute.name, objtype_name'
        );
        $ret = array();
@@ -2728,15 +2797,15 @@ function fetchAttrsForObjects($object_set)
        $ret = array();
        $query =
                "select A.id as attr_id, A.name as attr_name, A.type as attr_type, C.name as chapter_name, " .
-               "C.id as chapter_id, AV.uint_value, AV.float_value, AV.string_value, D.dict_value, RO.id as object_id from " .
-               "RackObject as RO inner join AttributeMap as AM on RO.objtype_id = AM.objtype_id " .
+               "C.id as chapter_id, AV.uint_value, AV.float_value, AV.string_value, D.dict_value, O.id as object_id from " .
+               "Object as O inner join AttributeMap as AM on O.objtype_id = AM.objtype_id " .
                "inner join Attribute as A on AM.attr_id = A.id " .
-               "left join AttributeValue as AV on AV.attr_id = AM.attr_id and AV.object_id = RO.id " .
+               "left join AttributeValue as AV on AV.attr_id = AM.attr_id and AV.object_id = O.id " .
                "left join Dictionary as D on D.dict_key = AV.uint_value and AM.chapter_id = D.chapter_id " .
                "left join Chapter as C on AM.chapter_id = C.id";
        if (is_array ($object_set) && !empty ($object_set))
        {
-               $query .= ' WHERE RO.id IN (';
+               $query .= ' WHERE O.id IN (';
                foreach ($object_set as $object_id)
                        $query .= intval ($object_id) . ', ';
                $query = trim ($query, ', ') . ')';
@@ -3106,7 +3175,7 @@ function commitUpdateVS ($vsid = 0, $vip = '', $vport = 0, $proto = '', $name =
 function loadThumbCache ($rack_id = 0)
 {
        $ret = NULL;
-       $result = usePreparedSelectBlade ("SELECT thumb_data FROM Rack WHERE id = ? AND thumb_data IS NOT NULL", array ($rack_id));
+       $result = usePreparedSelectBlade ('SELECT thumb_data FROM RackThumbnail WHERE rack_id = ? AND thumb_data IS NOT NULL', array ($rack_id));
        $row = $result->fetch (PDO::FETCH_ASSOC);
        if ($row)
                $ret = base64_decode ($row['thumb_data']);
@@ -3719,9 +3788,9 @@ function getNATv4ForObject ($object_id)
                "INET_NTOA(remoteip) as remoteip, ".
                "remoteport, ".
                "IPv4NAT.object_id as object_id, ".
-               "RackObject.name as object_name, ".
+               "Object.name as object_name, ".
                "description ".
-               "from ((IPv4NAT join IPv4Allocation on remoteip=IPv4Allocation.ip) join RackObject on IPv4NAT.object_id=RackObject.id) ".
+               "from ((IPv4NAT join IPv4Allocation on remoteip=IPv4Allocation.ip) join Object on IPv4NAT.object_id=Object.id) ".
                "where IPv4Allocation.object_id=? ".
                "order by remoteip, remoteport, proto, localip, localport",
                array ($object_id)
@@ -4621,9 +4690,9 @@ function getLogRecords()
 {
        $result = usePreparedSelectBlade
        (
-               'SELECT o.id as logid, r.name, o.content, o.date, o.user, r.id as object_id ' .
-               'FROM ObjectLog o Left JOIN RackObject r ON o.object_id = r.id ' .
-               'ORDER BY o.date DESC'
+               'SELECT OL.id AS log_id, O.objtype_id, O.name, OL.content, OL.date, OL.user, O.id AS object_id ' .
+               'FROM ObjectLog OL LEFT JOIN Object O ON OL.object_id = O.id ' .
+               'ORDER BY OL.date DESC'
        );
        return $result->fetchAll (PDO::FETCH_ASSOC);
 }
index 21f6fea..691c61c 100644 (file)
@@ -1609,6 +1609,9 @@ $dictionary = array
        1557 => array ('chapter_id' => 32, 'dict_value' => 'VMware%GPASS%Distributed vSwitch'),
        1558 => array ('chapter_id' => 32, 'dict_value' => 'Cisco%GPASS%Nexus 1000V'),
        1559 => array ('chapter_id' => 33, 'dict_value' => 'NS-OS 4.0'),
+       1560 => array ('chapter_id' => 1, 'dict_value' => 'Rack'),
+       1561 => array ('chapter_id' => 1, 'dict_value' => 'Row'),
+       1562 => array ('chapter_id' => 1, 'dict_value' => 'Location'),
 // NOTICE: do not add new dictionary entries here, add them to the gap above (~1425)!
 );
 
index e791d80..ef4682d 100644 (file)
@@ -69,6 +69,13 @@ $rtwidth = array
        2 => 9
 );
 
+$location_obj_types = array
+(
+       1560,
+       1561,
+       1562
+);
+
 $virtual_obj_types = array
 (
        1504,
@@ -981,7 +988,7 @@ function getRSUforRack ($data)
 }
 
 // Same for row.
-function getRSUforRackRow ($rowData)
+function getRSUforRow ($rowData)
 {
        if (!count ($rowData))
                return 0;
index a44e635..cf37c62 100644 (file)
@@ -381,7 +381,7 @@ CREATE TABLE `AttributeValue` (
   UNIQUE KEY `object_id` (`object_id`,`attr_id`),
   KEY `attr_id-uint_value` (`attr_id`,`uint_value`),
   KEY `attr_id-string_value` (`attr_id`,`string_value`(12)),
-  CONSTRAINT `AttributeValue-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
+  CONSTRAINT `AttributeValue-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `CachedPAV` (
@@ -408,7 +408,7 @@ CREATE TABLE `CachedPVM` (
   `port_name` char(255) NOT NULL,
   `vlan_mode` enum('access','trunk') NOT NULL default 'access',
   PRIMARY KEY  (`object_id`,`port_name`),
-  CONSTRAINT `CachedPVM-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
+  CONSTRAINT `CachedPVM-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `Chapter` (
@@ -488,7 +488,7 @@ CREATE TABLE `IPv4Allocation` (
   `type` enum('regular','shared','virtual','router') default NULL,
   PRIMARY KEY  (`object_id`,`ip`),
   KEY `ip` (`ip`),
-  CONSTRAINT `IPv4Allocation-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
+  CONSTRAINT `IPv4Allocation-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `IPv4LB` (
@@ -502,7 +502,7 @@ CREATE TABLE `IPv4LB` (
   KEY `IPv4LB-FK-rspool_id` (`rspool_id`),
   KEY `IPv4LB-FK-vs_id` (`vs_id`),
   CONSTRAINT `IPv4LB-FK-vs_id` FOREIGN KEY (`vs_id`) REFERENCES `IPv4VS` (`id`),
-  CONSTRAINT `IPv4LB-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`),
+  CONSTRAINT `IPv4LB-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`),
   CONSTRAINT `IPv4LB-FK-rspool_id` FOREIGN KEY (`rspool_id`) REFERENCES `IPv4RSPool` (`id`)
 ) ENGINE=InnoDB;
 
@@ -528,7 +528,7 @@ CREATE TABLE `IPv4NAT` (
   KEY `localip` (`localip`),
   KEY `remoteip` (`remoteip`),
   KEY `object_id` (`object_id`),
-  CONSTRAINT `IPv4NAT-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`)
+  CONSTRAINT `IPv4NAT-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`)
 ) ENGINE=InnoDB;
 
 CREATE TABLE `IPv4Network` (
@@ -588,7 +588,7 @@ CREATE TABLE `IPv6Allocation` (
   `type` enum('regular','shared','virtual','router') default NULL,
   PRIMARY KEY  (`object_id`,`ip`),
   KEY `ip` (`ip`),
-  CONSTRAINT `IPv6Allocation-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
+  CONSTRAINT `IPv6Allocation-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `IPv6Network` (
@@ -639,7 +639,7 @@ CREATE TABLE `MountOperation` (
   `comment` text,
   PRIMARY KEY  (`id`),
   KEY `object_id` (`object_id`),
-  CONSTRAINT `MountOperation-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
+  CONSTRAINT `MountOperation-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `ObjectLog` (
@@ -651,7 +651,7 @@ CREATE TABLE `ObjectLog` (
   PRIMARY KEY (`id`),
   KEY `object_id` (`object_id`),
   KEY `date` (`date`),
-  CONSTRAINT `ObjectLog-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
+  CONSTRAINT `ObjectLog-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `ObjectParentCompat` (
@@ -676,7 +676,7 @@ CREATE TABLE `Port` (
   KEY `l2address` (`l2address`),
   KEY `Port-FK-iif-oif` (`iif_id`,`type`),
   CONSTRAINT `Port-FK-iif-oif` FOREIGN KEY (`iif_id`, `type`) REFERENCES `PortInterfaceCompat` (`iif_id`, `oif_id`),
-  CONSTRAINT `Port-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
+  CONSTRAINT `Port-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `PortAllowedVLAN` (
@@ -738,30 +738,7 @@ CREATE TABLE `PortVLANMode` (
   CONSTRAINT `PortVLANMode-FK-object-port` FOREIGN KEY (`object_id`, `port_name`) REFERENCES `CachedPVM` (`object_id`, `port_name`)
 ) ENGINE=InnoDB;
 
-CREATE TABLE `Rack` (
-  `id` int(10) unsigned NOT NULL auto_increment,
-  `name` char(255) default NULL,
-  `row_id` int(10) unsigned NOT NULL default '1',
-  `height` tinyint(3) unsigned NOT NULL default '42',
-  `comment` text,
-  `thumb_data` blob,
-  PRIMARY KEY  (`id`),
-  UNIQUE KEY `name_in_row` (`row_id`,`name`),
-  CONSTRAINT `Rack-FK-row_id` FOREIGN KEY (`row_id`) REFERENCES `RackRow` (`id`)
-) ENGINE=InnoDB;
-
-CREATE TABLE `RackHistory` (
-  `id` int(10) unsigned default NULL,
-  `name` char(255) default NULL,
-  `row_id` int(10) unsigned default NULL,
-  `height` tinyint(3) unsigned default NULL,
-  `comment` text,
-  `thumb_data` blob,
-  `ctime` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
-  `user_name` char(64) default NULL
-) ENGINE=InnoDB;
-
-CREATE TABLE `RackObject` (
+CREATE TABLE `Object` (
   `id` int(10) unsigned NOT NULL auto_increment,
   `name` char(255) default NULL,
   `label` char(255) default NULL,
@@ -770,11 +747,11 @@ CREATE TABLE `RackObject` (
   `has_problems` enum('yes','no') NOT NULL default 'no',
   `comment` text,
   PRIMARY KEY  (`id`),
-  UNIQUE KEY `RackObject_asset_no` (`asset_no`),
+  UNIQUE KEY `asset_no` (`asset_no`),
   UNIQUE KEY `name` (`name`)
 ) ENGINE=InnoDB;
 
-CREATE TABLE `RackObjectHistory` (
+CREATE TABLE `ObjectHistory` (
   `id` int(10) unsigned default NULL,
   `name` char(255) default NULL,
   `label` char(255) default NULL,
@@ -785,14 +762,7 @@ CREATE TABLE `RackObjectHistory` (
   `ctime` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
   `user_name` char(64) default NULL,
   KEY `id` (`id`),
-  CONSTRAINT `RackObjectHistory-FK-object_id` FOREIGN KEY (`id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
-) ENGINE=InnoDB;
-
-CREATE TABLE `RackRow` (
-  `id` int(10) unsigned NOT NULL auto_increment,
-  `name` char(255) NOT NULL,
-  PRIMARY KEY  (`id`),
-  UNIQUE KEY `name` (`name`)
+  CONSTRAINT `ObjectHistory-FK-object_id` FOREIGN KEY (`id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `RackSpace` (
@@ -803,8 +773,15 @@ CREATE TABLE `RackSpace` (
   `object_id` int(10) unsigned default NULL,
   PRIMARY KEY  (`rack_id`,`unit_no`,`atom`),
   KEY `RackSpace_object_id` (`object_id`),
-  CONSTRAINT `RackSpace-FK-rack_id` FOREIGN KEY (`rack_id`) REFERENCES `Rack` (`id`),
-  CONSTRAINT `RackSpace-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
+  CONSTRAINT `RackSpace-FK-rack_id` FOREIGN KEY (`rack_id`) REFERENCES `Object` (`id`),
+  CONSTRAINT `RackSpace-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB;
+
+CREATE TABLE `RackThumbnail` (
+  `rack_id` int(10) unsigned NOT NULL,
+  `thumb_data` blob,
+  UNIQUE KEY `rack_id` (`rack_id`),
+  CONSTRAINT `RackThumbnail-FK-rack_id` FOREIGN KEY (`rack_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
 CREATE TABLE `Script` (
@@ -917,7 +894,7 @@ CREATE TABLE `VLANSwitch` (
   KEY `out_of_sync` (`out_of_sync`),
   KEY `last_errno` (`last_errno`),
   CONSTRAINT `VLANSwitch-FK-domain_id` FOREIGN KEY (`domain_id`) REFERENCES `VLANDomain` (`id`),
-  CONSTRAINT `VLANSwitch-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`),
+  CONSTRAINT `VLANSwitch-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`),
   CONSTRAINT `VLANSwitch-FK-template_id` FOREIGN KEY (`template_id`) REFERENCES `VLANSwitchTemplate` (`id`)
 ) ENGINE=InnoDB;
 
@@ -935,6 +912,22 @@ CREATE TABLE `VLANValidID` (
   PRIMARY KEY  (`vlan_id`)
 ) ENGINE=InnoDB;
 
+CREATE VIEW `Row` AS SELECT id, name
+  FROM `Object`
+  WHERE objtype_id = 1561;
+
+CREATE VIEW `Rack` AS SELECT id, name, label, asset_no, has_problems,
+  (SELECT AV.uint_value FROM `AttributeValue` AV WHERE AV.object_id = Object.id AND AV.attr_id = 27) AS height,
+  comment,
+  (SELECT thumb_data FROM `RackThumbnail` WHERE RackThumbnail.rack_id = Object.id) AS thumb_data,
+  (SELECT parent_entity_id FROM `EntityLink` WHERE parent_entity_type = 'object' AND child_entity_type = 'object' AND child_entity_id = Object.id) AS row_id,
+  (SELECT name FROM `Row` WHERE id = row_id) AS row_name
+  FROM `Object`
+  WHERE objtype_id = 1560;
+
+CREATE VIEW `RackObject` AS SELECT * FROM `Object`
+ WHERE `objtype_id` NOT IN (1560, 1561, 1562);
+
 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
 END_OF_FILE;
 ##########################################################################
@@ -959,7 +952,8 @@ INSERT INTO `Attribute` (`id`, `type`, `name`) VALUES
 (22,'string','HW warranty expiration'),
 (24,'string','SW warranty expiration'),
 (25,'string','UUID'),
-(26,'dict','Hypervisor');
+(26,'dict','Hypervisor'),
+(27,'uint','Height');
 
 INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES
 (2,1,NULL),
@@ -1092,10 +1086,11 @@ INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES
 (1507,14,NULL),
 (1507,20,NULL),
 (1507,21,NULL),
-(1507,22,NULL);
+(1507,22,NULL),
+(1560,27,NULL);
 
 INSERT INTO `Chapter` (`id`, `sticky`, `name`) VALUES
-(1,'yes','RackObjectType'),
+(1,'yes','ObjectType'),
 (2,'yes','PortOuterInterface'),
 (11,'no','server models'),
 (12,'no','network switch models'),
index 66b996f..dbe6a02 100644 (file)
@@ -286,7 +286,7 @@ function renderRackspace ()
        $rows = array();
        $cellfilter = getCellFilter();
        $rackCount = 0;
-       foreach (getRackRows() as $row_id => $row_name) {
+       foreach (getRows() as $row_id => $row_name) {
                $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
                $found_racks = array_merge($found_racks, $rackList);
                $rows[] = array(
@@ -365,7 +365,7 @@ function renderRackspaceRowEditor ()
        echo "<tr><th>&nbsp;</th><th>Name</th><th>&nbsp;</th></tr>\n";
        if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
                printNewItemTR();
-       foreach (getRackRows() as $row_id => $row_name)
+       foreach (getRows() as $row_id => $row_name)
        {
                echo "<tr><td>";
                if ($rc = count (listCells ('rack', $row_id)))
@@ -389,7 +389,7 @@ function renderRackspaceRowEditor ()
 
 function renderRow ($row_id)
 {
-       $rowInfo = getRackRowInfo ($row_id);
+       $rowInfo = getRowInfo ($row_id);
        $cellfilter = getCellFilter();
        $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
        // Main layout starts.
@@ -401,8 +401,8 @@ function renderRow ($row_id)
        echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
        echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
        echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
-       echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
-       renderProgressBar (getRSUforRackRow ($rackList));
+       echo "<tr><th width='50%' class=tdright>% used:</th><td class=tdleft>";
+       renderProgressBar (getRSUforRow ($rackList));
        echo "</td></tr>\n";
        echo "</table><br>\n";
        finishPortlet();
@@ -426,7 +426,8 @@ function renderRow ($row_id)
                                echo '</tr>';
                        echo '<tr>';
                }
-               echo "<td align=center class=row_${order}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
+               $class = ($rack['has_problems'] == 'yes') ? 'error' : $order;
+               echo "<td align=center class=row_${class}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
                echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
                echo " title='${rack['height']} units'";
                echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
@@ -536,18 +537,19 @@ function renderRack ($rack_id, $hl_obj_id = 0)
 
 function renderNewRackForm ($row_id)
 {
+       $default_height = getConfigVar ('DEFAULT_RACK_HEIGHT');
+       if ($default_height == 0)
+               $default_height = '';
        startPortlet ('Add one');
        printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
        echo '<table border=0 align=center>';
-       $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
-       if ($defh == 0)
-               $defh = '';
-       echo "<tr><th class=tdright>Rack name (*):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td>";
+       echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=name tabindex=1></td>";
        echo "<td rowspan=4>Assign tags:<br>";
        renderNewEntityTags ('rack');
        echo "</td></tr>\n";
-       echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height1 tabindex=2 value='${defh}'></td></tr>\n";
-       echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
+       echo "<tr><th class=tdright>Height in units (required):</th><td class=tdleft><input type=text name=height1 tabindex=2 value='${default_height}'></td></tr>\n";
+       echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=label tabindex=3></td></tr>\n";
+       echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=asset_no tabindex=4></td></tr>\n";
        echo "<tr><td class=submit colspan=2>";
        printImageHREF ('CREATE', 'Add', TRUE);
        echo "</td></tr></table></form>";
@@ -556,14 +558,11 @@ function renderNewRackForm ($row_id)
        startPortlet ('Add many');
        printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
        echo '<table border=0 align=center>';
-       $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
-       if ($defh == 0)
-               $defh = '';
-       echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height2 value='${defh}'></td>";
+       echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=height2 value='${default_height}'></td>";
        echo "<td rowspan=3 valign=top>Assign tags:<br>";
        renderNewEntityTags ('rack');
        echo "</td></tr>\n";
-       echo "<tr><th class=tdright>Rack names (*):</th><td class=tdleft><textarea name=rack_names cols=40 rows=25></textarea></td></tr>\n";
+       echo "<tr><th class=tdright>Rack names (required):</th><td class=tdleft><textarea name=names cols=40 rows=25></textarea></td></tr>\n";
        echo "<tr><td class=submit colspan=2>";
        printImageHREF ('CREATE', 'Add', TRUE);
        echo '</form></table>';
@@ -597,7 +596,7 @@ function renderEditObjectForm()
                echo "<tr><td>&nbsp;</td><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no value='${object['asset_no']}'></td></tr>\n";
        }
        // parent selection
-       if (rackObjectTypeMayHaveParent ($object['objtype_id']))
+       if (objectTypeMayHaveParent ($object['objtype_id']))
        {
                $parents = getEntityRelatives ('parents', 'object', $object_id);
                foreach ($parents as $link_id => $parent_details)
@@ -692,7 +691,7 @@ function renderEditObjectForm()
 
        echo '<table border=0 width=100%><tr><td>';
        startPortlet ('history');
-       renderHistory ($pageno, $object_id);
+       renderObjectHistory ($object_id);
        finishPortlet();
        echo '</td></tr></table>';
 }
@@ -704,29 +703,77 @@ function renderEditRackForm ($rack_id)
        $rack = spotEntity ('rack', $rack_id);
        amplifyCell ($rack);
 
-       startPortlet ('Rack attributes');
+       startPortlet ('Attributes');
        printOpFormIntro ('updateRack');
        echo '<table border=0 align=center>';
-       echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
-       printSelect (getRackRows(), array ('name' => 'rack_row_id'), $rack['row_id']);
+       echo "<tr><td>&nbsp;</td><th class=tdright>Rack row:</th><td class=tdleft>";
+       printSelect (getRows(), array ('name' => 'row_id'), $rack['row_id']);
        echo "</td></tr>\n";
-       echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
-       echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
-       echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
+       echo "<tr><td>&nbsp;</td><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=name value='${rack['name']}'></td></tr>\n";
+       echo "<tr><td>&nbsp;</td><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=height value='${rack['height']}'></td></tr>\n";
+       echo "<tr><td>&nbsp;</td><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=label value='${rack['label']}'></td></tr>\n";
+       echo "<tr><td>&nbsp;</td><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=asset_no value='${rack['asset_no']}'></td></tr>\n";
+       // optional attributes
+       $values = getAttrValues ($rack_id);
+       $num_attrs = count($values);
+       $num_attrs = $num_attrs-1; // subtract for the 'height' attribute
+       echo "<input type=hidden name=num_attrs value=${num_attrs}>\n";
+       $i = 0;
+       foreach ($values as $record)
+       {
+               // Skip the 'height' attribute as it's already displayed as a required field
+               if ($record['id'] == 27)
+                       continue;
+               echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
+               echo '<tr><td>';
+               if (strlen ($record['value']))
+               {
+                       echo "<a href='".makeHrefProcess(array('op'=>'clearSticker', 'rack_id'=>$rack_id, 'attr_id'=>$record['id']))."'>";
+                       printImageHREF ('clear', 'Clear value');
+                       echo '</a>';
+               }
+               else
+                       echo '&nbsp;';
+               echo '</td>';
+               echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
+               switch ($record['type'])
+               {
+                       case 'uint':
+                       case 'float':
+                       case 'string':
+                               echo "<input type=text name=${i}_value value='${record['value']}'>";
+                               break;
+                       case 'dict':
+                               $chapter = readChapter ($record['chapter_id'], 'o');
+                               $chapter[0] = '-- NOT SET --';
+                               $chapter = cookOptgroups ($chapter, 1560, $record['key']);
+                               printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
+                               break;
+               }
+               echo "</td></tr>\n";
+               $i++;
+       }
+       echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=has_problems";
+       if ($rack['has_problems'] == 'yes')
+               echo ' checked';
+       echo "></td></tr>\n";
        if (count ($rack['mountedObjects']) == 0)
        {
-               echo "<tr><th class=tdright>Actions:</th><td class=tdleft><a href='".
-                       makeHrefProcess(array('op'=>'deleteRack', 'rack_id'=>$rack_id)).
-                       "' onclick=\"javascript:return confirm('Are you sure you want to delete the rack?')\">Delete rack</a></td></tr>\n";
+               echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>"; 
+               echo "<a href='".
+                       makeHrefProcess(array('op'=>'deleteRack', 'rack_id'=>$rack_id)).
+                       "' onclick=\"javascript:return confirm('Are you sure you want to delete the rack?')\">" . getImageHREF ('destroy', 'Delete rack') . "</a>";
+               echo "&nbsp;</td></tr>\n";
        }
-       echo "<tr><td class=submit colspan=2>";
+       echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=comment rows=10 cols=80>${rack['comment']}</textarea></td></tr>";
+       echo "<tr><td class=submit colspan=3>";
        printImageHREF ('SAVE', 'Save changes', TRUE);
        echo "</td></tr>\n";
        echo '</form></table><br>';
        finishPortlet();
        
        startPortlet ('History');
-       renderHistory ($pageno, $rack_id);
+       renderObjectHistory ($rack_id);
        finishPortlet();
 }
 
@@ -738,7 +785,21 @@ function renderRackInfoPortlet ($rackData)
        echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
        echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
        echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
-       echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
+       if (strlen ($rackData['asset_no']))
+               echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${rackData['label']}</td></tr>\n";
+       if (strlen ($rackData['asset_no']))
+               echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${rackData['asset_no']}</td></tr>\n";
+       if ($rackData['has_problems'] == 'yes')
+               echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
+       // Display populated attributes, but skip Height since it's already displayed above
+       foreach (getAttrValues ($rackData['id']) as $record)
+               if ($record['id'] != 27 && strlen ($record['value']))
+               {
+                       echo "<tr><th width='50%' class=sticker>${record['name']}:</th><td class=sticker>" .
+                               formatAttributeValue ($record) .
+                               "</td></tr>\n";
+               }
+       echo "<tr><th width='50%' class=tdright>% used:</th><td class=tdleft>";
        renderProgressBar (getRSUforRack ($rackData));
        echo "</td></tr>\n";
        echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
@@ -809,7 +870,7 @@ function finishPortlet ()
        echo "</div>\n";
 }
 
-function renderRackObject ($object_id)
+function renderObject ($object_id)
 {
        global $nextorder, $virtual_obj_types;
        $info = spotEntity ('object', $object_id);
@@ -832,12 +893,12 @@ function renderRackObject ($object_id)
                'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
        ));
        echo "'>" . decodeObjectType ($info['objtype_id'], 'o') . '</a></td></tr>';
+       if (strlen ($info['label']))
+               echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
        if (strlen ($info['asset_no']))
                echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
        elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
                echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
-       if (strlen ($info['label']))
-               echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
        if ($parents = getEntityRelatives ('parents', 'object', $object_id))
        {
                foreach ($parents as $parent)
@@ -1804,7 +1865,7 @@ function renderDepot ()
                                echo "</td><td class='${secondclass}'>${obj['label']}</td>";
                                echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
                                if ($obj['rack_id'])
-                                       echo "<td class='${secondclass}'><a href='".makeHref(array('page'=>'row', 'row_id'=>$obj['row_id']))."'>${obj['Row_name']}</a>/<a href='".makeHref(array('page'=>'rack', 'rack_id'=>$obj['rack_id']))."'>${obj['Rack_name']}</a></td>";
+                                       echo "<td class='${secondclass}'><a href='".makeHref(array('page'=>'row', 'row_id'=>$obj['row_id']))."'>${obj['row_name']}</a>/<a href='".makeHref(array('page'=>'rack', 'rack_id'=>$obj['rack_id']))."'>${obj['rack_name']}</a></td>";
                                else
                                        echo "<td class='${secondclass}'>Unmounted</td>";
                                echo '</tr>';
@@ -1846,43 +1907,21 @@ END;
 }
 
 // History viewer for history-enabled simple dictionaries.
-function renderHistory ($object_type, $object_id)
+function renderObjectHistory ($object_id)
 {
-       switch ($object_type)
-       {
-               case 'row':
-                       $query = "select ctime, user_name, name, comment from RackRowHistory where id = ? order by ctime";
-                       $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
-                       $extra = 3;
-                       break;
-               case 'rack':
-                       $query =
-                               "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
-                               "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
-                               "where rh.id = ? order by ctime";
-                       $header = '<tr><th>change time</th><th>author</th><th>rack name</th><th>rack row name</th><th>rack height</th><th>rack comment</th></tr>';
-                       $extra = 5;
-                       break;
-               case 'object':
-                       $query =
-                               "select ctime, user_name, RackObjectHistory.name as name, label, asset_no, has_problems, dict_value, comment " .
-                               "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
-                               "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=? order by ctime";
-                       $header = '<tr><th>change time</th><th>author</th><th>common name</th><th>visible label</th><th>asset no</th><th>has problems?</th><th>object type</th><th>comment</th></tr>';
-                       $extra = 7;
-                       break;
-               default:
-                       throw new InvalidArgException ('object_type', $object_type);
-       }
-       $result = usePreparedSelectBlade ($query, array ($object_id));
-       echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
        $order = 'odd';
        global $nextorder;
-       echo $header;
+       echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
+       echo '<tr><th>change time</th><th>author</th><th>name</th><th>visible label</th><th>asset no</th><th>has problems?</th><th>comment</th></tr>';
+       $result = usePreparedSelectBlade
+       (
+               'SELECT ctime, user_name, name, label, asset_no, has_problems, comment FROM ObjectHistory WHERE id=? ORDER BY ctime',
+               array ($object_id)
+       );
        while ($row = $result->fetch (PDO::FETCH_NUM))
        {
                echo "<tr class=row_${order}><td>${row[0]}</td>";
-               for ($i = 1; $i <= $extra; $i++)
+               for ($i = 1; $i <= 6; $i++)
                        echo "<td>" . $row[$i] . "</td>";
                echo "</tr>\n";
                $order = $nextorder[$order];
@@ -3292,18 +3331,21 @@ function renderNATv4ForObject ($object_id)
 
 function renderAddMultipleObjectsForm ()
 {
-       global $virtual_obj_types;
+       global $location_obj_types, $virtual_obj_types;
        $typelist = readChapter (CHAP_OBJTYPE, 'o');
        $typelist[0] = 'select type...';
        $typelist = cookOptgroups ($typelist);
        $max = getConfigVar ('MASSCOUNT');
        $tabindex = 100;
 
-       // create a list containing only physical object types
+       // create a list of object types to exclude (virtual and location-related ones)
+       $exclude_typelist = array_merge($location_obj_types, $virtual_obj_types);
+
        $phys_typelist = $typelist;
        foreach ($phys_typelist['other'] as $key => $value)
        {
-               if ($key > 0 && in_array($key, $virtual_obj_types))
+               // remove from list if type should be excluded
+               if ($key > 0 && in_array($key, $exclude_typelist))
                        unset($phys_typelist['other'][$key]);
        }
        startPortlet ('Physical objects');
@@ -4253,7 +4295,9 @@ function renderEditAttrMapForm ()
                echo "</select></td><td class=tdleft>";
                printImageHREF ('add', '', TRUE);
                echo ' ';
-               printNiftySelect (cookOptgroups (readChapter (CHAP_OBJTYPE, 'o')), array ('name' => 'objtype_id', 'tabindex' => 101));
+               $objtypes = readChapter (CHAP_OBJTYPE, 'o');
+               unset ($objtypes[1561], $objtypes[1562]); // attributes may not be assigned to rows or locations yet
+               printNiftySelect (cookOptgroups ($objtypes), array ('name' => 'objtype_id', 'tabindex' => 101));
                echo ' <select name=chapter_no tabindex=102><option value=0>-- dictionary chapter for [D] attributes --</option>';
                foreach (getChapterList() as $chapter)
                        if ($chapter['sticky'] != 'yes')
@@ -7087,7 +7131,7 @@ function dynamic_title_decoder ($path_position)
                        );
                case 'row':
                        assertUIntArg ('row_id');
-                       $rowInfo = getRackRowInfo ($_REQUEST['row_id']);
+                       $rowInfo = getRowInfo ($_REQUEST['row_id']);
                        return array
                        (
                                'name' => $rowInfo['name'],
@@ -9049,8 +9093,20 @@ function renderObjectLogEditor ()
 {
        global $nextorder;
 
-       echo '<center><h3>log records for this object (<a href=?page=objectlog>complete list</a>)</h3></center>';
+       if (isset($_REQUEST['object_id']))
+       {
+               $entity = 'object';
+               $id_name = 'object_id';
+               $object_id = $_REQUEST['object_id'];
+       }
+       else
+       {
+               $entity = 'rack';
+               $id_name = 'rack_id';
+               $object_id = $_REQUEST['rack_id'];
+       }
 
+       echo "<center><h2>Log records for this ${entity} (<a href=?page=objectlog>complete list</a>)</h2></center>";
        printOpFormIntro ('add');
        echo "<table with=80% align=center border=0 cellpadding=5 cellspacing=0 align=center class=cooltable><tr valign=top class=row_odd>";
        echo '<td class=tdcenter>' . getImageHREF ('CREATE', 'add record', TRUE, 101) . '</td>';
@@ -9059,14 +9115,14 @@ function renderObjectLogEditor ()
        echo '</tr></form>';
 
        $order = 'even';
-       foreach (getLogRecordsForObject ($_REQUEST['object_id']) as $row)
+       foreach (getLogRecordsForObject ($object_id) as $row)
        {
                echo "<tr class=row_${order} valign=top>";
                echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
                echo '<td class="slbconf rsvtext">' . string_insert_hrefs (htmlspecialchars ($row['content'], ENT_NOQUOTES)) . '</td>';
-               echo "<td class=tdleft><a href=\"".makeHrefProcess(array('op'=>'del', 'logid'=>$row['id'], 'object_id'=>$_REQUEST['object_id']))."\">";
+               echo "<td class=tdleft><a href=\"".makeHrefProcess(array('op'=>'del', 'log_id'=>$row['id'], $id_name=>$object_id))."\">";
                echo getImageHREF ('DESTROY', 'Delete log entry') . '</a></td>';
-               echo '</tr>';
+               echo "</tr>\n";
                $order = $nextorder[$order];
        }
        echo '</table>';
@@ -9089,11 +9145,22 @@ function allObjectLogs ()
                $order = 'odd';
                foreach ($logs as $row)
                {
+                       // Link to a different page if the object is a Rack
+                       if ($row['objtype_id'] == 1560)
+                       {
+                               $entity = 'rack';
+                               $id_name = 'rack_id';
+                       }
+                       else
+                       {
+                               $entity = 'object';
+                               $id_name = 'object_id';
+                       }
                        echo "<tr class=row_${order} valign=top>";
-                       echo "<td align=left><a href='".makeHref(array('page'=>'object', 'tab'=>'log', 'object_id'=>$row['object_id']))."'>${row['name']}</a></td>";
+                       echo "<td align=left><a href='".makeHref(array('page'=>$entity, 'tab'=>'log', $id_name=>$row['object_id']))."'>${row['name']}</a></td>";
                        echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
                        echo '<td class="slbconf rsvtext">' . string_insert_hrefs (htmlspecialchars ($row['content'], ENT_NOQUOTES)) . '</td>';
-                       echo '</tr>';
+                       echo "</tr>\n";
                        $order = $nextorder[$order];
                }
                echo '</table>';
index 81cfb47..2020e46 100644 (file)
@@ -40,9 +40,9 @@ $tab['rackspace']['history'] = 'History';
 $tabhandler['rackspace']['default'] = 'renderRackspace';
 $tabhandler['rackspace']['edit'] = 'renderRackspaceRowEditor';
 $tabhandler['rackspace']['history'] = 'renderRackspaceHistory';
-$ophandler['rackspace']['edit']['addRow'] = 'tableHandler';
-$ophandler['rackspace']['edit']['delete'] = 'tableHandler';
-$ophandler['rackspace']['edit']['updateRow'] = 'tableHandler';
+$ophandler['rackspace']['edit']['addRow'] = 'addRow';
+$ophandler['rackspace']['edit']['delete'] = 'deleteRow';
+$ophandler['rackspace']['edit']['updateRow'] = 'updateRow';
 
 $page['depot']['parent'] = 'index';
 $page['depot']['title'] = 'Objects';
@@ -71,12 +71,14 @@ $page['rack']['bypass_type'] = 'uint';
 $page['rack']['parent'] = 'row';
 $tab['rack']['default'] = 'View';
 $tab['rack']['edit'] = 'Properties';
+$tab['rack']['log'] = 'Log';
 $tab['rack']['design'] = 'Design';
 $tab['rack']['problems'] = 'Problems';
 $tab['rack']['tags'] = 'Tags';
 $tab['rack']['files'] = 'Files';
 $tabhandler['rack']['default'] = 'renderRackPage';
 $tabhandler['rack']['edit'] = 'renderEditRackForm';
+$tabhandler['rack']['log'] = 'renderObjectLogEditor';
 $tabhandler['rack']['design'] = 'renderRackDesign';
 $tabhandler['rack']['problems'] = 'renderRackProblems';
 $tabhandler['rack']['tags'] = 'renderEntityTags';
@@ -86,6 +88,8 @@ $ophandler['rack']['design']['updateRack'] = 'updateRackDesign';
 $ophandler['rack']['problems']['updateRack'] = 'updateRackProblems';
 $ophandler['rack']['edit']['updateRack'] = 'updateRack';
 $ophandler['rack']['edit']['deleteRack'] = 'deleteRack';
+$ophandler['rack']['log']['add'] = 'addObjectlog';
+$ophandler['rack']['log']['del'] = 'deleteObjectLog';
 $ophandler['rack']['tags']['saveTags'] = 'saveEntityTags';
 $ophandler['rack']['files']['addFile'] = 'addFileToEntity';
 $ophandler['rack']['files']['linkFile'] = 'linkFileToEntity';
@@ -116,7 +120,7 @@ $tab['object']['files'] = 'Files';
 $tab['object']['8021qorder'] = '802.1Q order';
 $tab['object']['8021qports'] = '802.1Q ports';
 $tab['object']['8021qsync'] = '802.1Q sync';
-$tabhandler['object']['default'] = 'renderRackObject';
+$tabhandler['object']['default'] = 'renderObject';
 $tabhandler['object']['edit'] = 'renderEditObjectForm';
 $tabhandler['object']['log'] = 'renderObjectLogEditor';
 $tabhandler['object']['rackspace'] = 'renderRackSpaceForObject';
index cae86cd..972bfcb 100644 (file)
@@ -48,37 +48,6 @@ $msgcode = array();
 global $opspec_list;
 $opspec_list = array();
 
-$opspec_list['rackspace-edit-addRow'] = array
-(
-       'table' => 'RackRow',
-       'action' => 'INSERT',
-       'arglist' => array
-       (
-               array ('url_argname' => 'name', 'assertion' => 'string')
-       ),
-);
-$opspec_list['rackspace-edit-delete'] = array
-(
-       'table' => 'RackRow',
-       'action' => 'DELETE',
-       'arglist' => array
-       (
-               array ('url_argname' => 'row_id', 'table_colname' => 'id', 'assertion' => 'uint')
-       ),
-);
-$opspec_list['rackspace-edit-updateRow'] = array
-(
-       'table' => 'RackRow',
-       'action' => 'UPDATE',
-       'set_arglist' => array
-       (
-               array ('url_argname' => 'name', 'assertion' => 'string')
-       ),
-       'where_arglist' => array
-       (
-               array ('url_argname' => 'row_id', 'table_colname' => 'id', 'assertion' => 'uint')
-       ),
-);
 $opspec_list['object-ports-delPort'] = array
 (
        'table' => 'Port',
@@ -1122,7 +1091,7 @@ function updateObject ()
        }
        // Invalidate thumb cache of all racks objects could occupy.
        foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
-               usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
+               usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
        $dbxlink->commit();
        return showFuncMessage (__FUNCTION__, 'OK');
 }
@@ -1222,7 +1191,7 @@ function deleteObject ()
        $racklist = getResidentRacksData ($_REQUEST['object_id'], FALSE);
        commitDeleteObject ($_REQUEST['object_id']);
        foreach ($racklist as $rack_id)
-               usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
+               usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
        return showFuncMessage (__FUNCTION__, 'OK', array ($oinfo['dname']));
 }
 
@@ -1232,7 +1201,7 @@ function resetObject ()
        $racklist = getResidentRacksData (getBypassValue(), FALSE);
        commitResetObject (getBypassValue());
        foreach ($racklist as $rack_id)
-               usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
+               usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
        return showFuncMessage (__FUNCTION__, 'OK');
 }
 
@@ -1794,18 +1763,26 @@ function addRack ()
        $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
        if (isset ($_REQUEST['got_data']))
        {
-               assertStringArg ('rack_name');
-               assertUIntArg ('rack_height1');
-               assertStringArg ('rack_comment', TRUE);
-               commitAddRack ($_REQUEST['rack_name'], $_REQUEST['rack_height1'], $_REQUEST['row_id'], $_REQUEST['rack_comment'], $taglist);
-               return showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['rack_name']));
+               assertStringArg ('name');
+               assertUIntArg ('height1');
+               assertStringArg ('label', TRUE);
+               assertStringArg ('asset_no', TRUE);
+               $rack_id = commitAddObject ($_REQUEST['name'], $_REQUEST['label'], 1560, $_REQUEST['asset_no'], $taglist);
+
+               // Update the height
+               commitUpdateAttrValue ($rack_id, 27, $_REQUEST['height1']);
+
+               // Link it to the row
+               commitLinkEntities ('object', $_REQUEST['row_id'], 'object', $rack_id);
+
+               return showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['name']));
        }
        elseif (isset ($_REQUEST['got_mdata']))
        {
-               assertUIntArg ('rack_height2');
-               assertStringArg ('rack_names', TRUE);
+               assertUIntArg ('height2');
+               assertStringArg ('names', TRUE);
                // copy-and-paste from renderAddMultipleObjectsForm()
-               $names1 = explode ("\n", $_REQUEST['rack_names']);
+               $names1 = explode ("\n", $_REQUEST['names']);
                $names2 = array();
                foreach ($names1 as $line)
                {
@@ -1818,8 +1795,13 @@ function addRack ()
                }
                foreach ($names2 as $cname)
                {
-                       commitAddRack ($cname, $_REQUEST['rack_height2'], $_REQUEST['row_id'], '', $taglist);
-                       showFuncMessage (__FUNCTION__, 'OK', array ($cname));
+                       $rack_id = commitAddObject ($cname, '', 1560, NULL, $taglist);
+
+                       // Update the height
+                       commitUpdateAttrValue ($rack_id, 27, $_REQUEST['height2']);
+
+                       // Link it to the row
+                       commitLinkEntities ('object', $_REQUEST['row_id'], 'object', $rack_id);
                }
        }
        else
@@ -1835,7 +1817,7 @@ function deleteRack ()
        amplifyCell ($rackData);
        if (count ($rackData['mountedObjects']))
                return showFuncMessage (__FUNCTION__, 'ERR1');
-       commitDeleteRack ($_REQUEST['rack_id']);
+       commitDeleteObject ($_REQUEST['rack_id']);
        showFuncMessage (__FUNCTION__, 'OK', array ($rackData['name']));
        return buildRedirectURL ('rackspace', 'default');
 }
@@ -1843,15 +1825,58 @@ function deleteRack ()
 $msgcode['updateRack']['OK'] = 6;
 function updateRack ()
 {
-       assertUIntArg ('rack_row_id');
-       assertUIntArg ('rack_height');
-       assertStringArg ('rack_name');
-       assertStringArg ('rack_comment', TRUE);
+       assertUIntArg ('row_id');
+       assertStringArg ('name');
+       assertUIntArg ('height');
+       assertStringArg ('label', TRUE);
+       $has_problems = (isset ($_REQUEST['has_problems']) and $_REQUEST['has_problems'] == 'on') ? 'yes' : 'no';
+       assertStringArg ('asset_no', TRUE);
+       assertStringArg ('comment', TRUE);
 
        $rack_id = getBypassValue();
-       usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
-       commitUpdateRack ($rack_id, $_REQUEST['rack_name'], $_REQUEST['rack_height'], $_REQUEST['rack_row_id'], $_REQUEST['rack_comment']);
-       return showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['rack_name']));
+       usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
+       commitUpdateRack ($rack_id, $_REQUEST['row_id'], $_REQUEST['name'], $_REQUEST['height'], $_REQUEST['label'], $has_problems, $_REQUEST['asset_no'], $_REQUEST['comment']);
+
+       // Update optional attributes
+       $oldvalues = getAttrValues ($rack_id);
+       $num_attrs = isset ($_REQUEST['num_attrs']) ? $_REQUEST['num_attrs'] : 0;
+       for ($i = 0; $i < $num_attrs; $i++)
+       {
+               assertUIntArg ("${i}_attr_id");
+               $attr_id = $_REQUEST["${i}_attr_id"];
+
+               // Skip the 'height' attribute as it's already handled by commitUpdateRack
+               if ($attr_id == 27)
+                       continue;
+
+               // Field is empty, delete attribute and move on. OR if the field type is a dictionary and it is the --NOT SET-- value of 0
+               if (!strlen ($_REQUEST["${i}_value"]) || ($oldvalues[$attr_id]['type']=='dict' && $_REQUEST["${i}_value"] == 0))
+               {
+                       commitUpdateAttrValue ($rack_id, $attr_id);
+                       continue;
+               }
+
+               // The value could be uint/float, but we don't know ATM. Let SQL
+               // server check this and complain.
+               assertStringArg ("${i}_value");
+               $value = $_REQUEST["${i}_value"];
+               switch ($oldvalues[$attr_id]['type'])
+               {
+                       case 'uint':
+                       case 'float':
+                       case 'string':
+                               $oldvalue = $oldvalues[$attr_id]['value'];
+                               break;
+                       case 'dict':
+                               $oldvalue = $oldvalues[$attr_id]['key'];
+                               break;
+                       default:
+               }
+               if ($value === $oldvalue) // ('' == 0), but ('' !== 0)
+                       continue;
+               commitUpdateAttrValue ($rack_id, $attr_id, $value);
+       }
+       return showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['name']));
 }
 
 function updateRackDesign ()
@@ -2638,9 +2663,9 @@ function addObjectlog ()
 {
        assertStringArg ('logentry');
        global $remote_username, $sic;
-       $oi = spotEntity ('object', $sic['object_id']);
-       usePreparedExecuteBlade ('INSERT INTO ObjectLog SET object_id=?, user=?, date=NOW(), content=?', array ($sic['object_id'], $remote_username, $sic['logentry']));
-       showSuccess ('Log entry for ' . mkA ($oi['dname'], 'object', $sic['object_id'], 'log') . " added by ${remote_username}");
+       $object_id = isset($sic['object_id']) ? $sic['object_id'] : $sic['rack_id'];
+       usePreparedExecuteBlade ('INSERT INTO ObjectLog SET object_id=?, user=?, date=NOW(), content=?', array ($object_id, $remote_username, $sic['logentry']));
+       showSuccess ('Log entry added');
 }
 
 function getOpspec()
index 255c1a2..ea0c688 100644 (file)
@@ -61,30 +61,30 @@ function findSparePorts ($port_id, $only_racks = array())
 // Return a list of all objects which are possible parents
 //    Special case for VMs and VM Virtual Switches
 //        - only select Servers with the Hypervisor attribute set to Yes
-function findRackObjectParentCandidates ($object_id)
+function findObjectParentCandidates ($object_id)
 {
        $object = spotEntity ('object', $object_id);
        $args = array ($object['objtype_id'], $object_id, $object_id);
 
-       $query  = "SELECT RO.id, RO.name FROM RackObject RO ";
-       $query .= "LEFT JOIN ObjectParentCompat OPC ON RO.objtype_id = OPC.parent_objtype_id ";
+       $query  = "SELECT O.id, O.name FROM Object O ";
+       $query .= "LEFT JOIN ObjectParentCompat OPC ON O.objtype_id = OPC.parent_objtype_id ";
        $query .= "WHERE OPC.child_objtype_id = ? ";
-       $query .= "AND RO.id != ? ";
+       $query .= "AND O.id != ? ";
        // exclude existing parents
-       $query .= "AND RO.id NOT IN (SELECT parent_entity_id FROM EntityLink WHERE parent_entity_type = 'object' AND child_entity_type = 'object' AND child_entity_id = ?) ";
+       $query .= "AND O.id NOT IN (SELECT parent_entity_id FROM EntityLink WHERE parent_entity_type = 'object' AND child_entity_type = 'object' AND child_entity_id = ?) ";
        if ($object['objtype_id'] == 1504 || $object['objtype_id'] == 1507)
        {
                array_push($args, $object['objtype_id'], $object_id, $object_id);
                $query .= "AND OPC.parent_objtype_id != 4 ";
                $query .= "UNION ";
-               $query .= "SELECT RO.id, RO.name FROM RackObject RO  ";
-               $query .= "LEFT JOIN ObjectParentCompat OPC ON RO.objtype_id = OPC.parent_objtype_id ";
-               $query .= "LEFT JOIN AttributeValue AV ON RO.id = AV.object_id ";
+               $query .= "SELECT O.id, O.name FROM Object O  ";
+               $query .= "LEFT JOIN ObjectParentCompat OPC ON O.objtype_id = OPC.parent_objtype_id ";
+               $query .= "LEFT JOIN AttributeValue AV ON O.id = AV.object_id ";
                $query .= "WHERE OPC.child_objtype_id = ? ";
-               $query .= "AND (RO.objtype_id = 4 AND AV.attr_id = 26 AND AV.uint_value = 1501) ";
-               $query .= "AND RO.id != ? ";
+               $query .= "AND (O.objtype_id = 4 AND AV.attr_id = 26 AND AV.uint_value = 1501) ";
+               $query .= "AND O.id != ? ";
                // exclude existing parents
-               $query .= "AND RO.id NOT IN (SELECT parent_entity_id FROM EntityLink WHERE parent_entity_type = 'object' AND child_entity_type = 'object' AND child_entity_id = ?) ";
+               $query .= "AND O.id NOT IN (SELECT parent_entity_id FROM EntityLink WHERE parent_entity_type = 'object' AND child_entity_type = 'object' AND child_entity_id = ?) ";
        }
        $query .= "ORDER BY 2";
 
@@ -133,7 +133,7 @@ header ('Content-Type: text/html; charset=UTF-8');
                        echo '<div style="background-color: #f0f0f0; border: 1px solid #3c78b5; padding: 10px; height: 100%; text-align: center; margin: 5px;">';
                        echo '<h2>Choose a container:</h2>';
                        echo '<form action="javascript:;">';
-                       $parents = findRackObjectParentCandidates($object_id);
+                       $parents = findObjectParentCandidates($object_id);
                        printSelect ($parents, array ('name' => 'parents', 'size' => getConfigVar ('MAXSELSIZE')));
                        echo '<br>';
                        echo "<input type=submit value='Proceed' onclick='".
index 14d8925..0a55bc0 100644 (file)
@@ -90,7 +90,11 @@ function renderRackThumb ($rack_id = 0)
                $capture = ob_get_clean();
                header("Content-type: image/png");
                echo $capture;
-               usePreparedUpdateBlade ('Rack', array ('thumb_data' => base64_encode ($capture)), array ('id' => $rack_id));
+               usePreparedExecuteBlade
+               (
+                       'REPLACE INTO RackThumbnail SET rack_id=?, thumb_data=?',
+                       array ($rack_id, base64_encode ($capture))
+               );
                return;
        }
        // error text in the buffer
@@ -119,8 +123,9 @@ function generateMiniRack ($rack_id)
                $color[$statecode] = colorFromHex ($img, getConfigVar ('color_' . $statecode));
        $color['black'] = colorFromHex ($img, '000000');
        $color['gray'] = colorFromHex ($img, 'c0c0c0');
+       $border_color = ($rackData['has_problems'] == 'yes') ? $color['Thw'] : $color['gray'];
        imagerectangle ($img, 0, 0, $totalwidth - 1, $totalheight - 1, $color['black']);
-       imagerectangle ($img, 1, 1, $totalwidth - 2, $totalheight - 2, $color['gray']);
+       imagerectangle ($img, 1, 1, $totalwidth - 2, $totalheight - 2, $border_color);
        imagerectangle ($img, 2, 2, $totalwidth - 3, $totalheight - 3, $color['black']);
        for ($unit_no = 1; $unit_no <= $rackData['height']; $unit_no++)
        {
index ddbca5d..28d5214 100644 (file)
@@ -1114,6 +1114,79 @@ CREATE TABLE `IPv4Log` (
                        $query[] = "DELETE FROM Config WHERE varname = 'HNDP_RUNNERS_LISTSRC'";
                        $query[] = "ALTER TABLE TagStorage MODIFY COLUMN entity_realm ENUM('file','ipv4net','ipv4vs','ipv4rspool','object','rack','user','ipv6net','vst') NOT NULL default 'object'";
                        $query[] = "ALTER TABLE `TagStorage` ADD COLUMN `user` char(64) DEFAULT NULL, ADD COLUMN `date` datetime DEFAULT NULL";
+
+                       // Rename object tables and keys
+                       $dbxlink->query ('ALTER TABLE `RackObject` RENAME TO `Object`');
+                       $dbxlink->query ('ALTER TABLE `RackObjectHistory` RENAME TO `ObjectHistory`');
+                       $query[] = 'ALTER TABLE `Object` DROP KEY `RackObject_asset_no`';
+                       $query[] = 'ALTER TABLE `Object` ADD UNIQUE KEY `asset_no` (`asset_no`)';
+                       $query[] = 'ALTER TABLE `ObjectHistory` DROP FOREIGN KEY `RackObjectHistory-FK-object_id`';
+                       $query[] = 'ALTER TABLE `ObjectHistory` ADD CONSTRAINT `ObjectHistory-FK-object_id` FOREIGN KEY (`id`) REFERENCES `Object` (`id`) ON DELETE CASCADE';
+                       $query[] = 'ALTER TABLE `RackSpace` DROP FOREIGN KEY `RackSpace-FK-rack_id`';
+                       $query[] = 'ALTER TABLE `RackSpace` ADD CONSTRAINT `RackSpace-FK-rack_id` FOREIGN KEY (`rack_id`) REFERENCES `Object` (`id`)';
+                       // Rack height is now an attribute
+                       $query[] = "INSERT INTO `Attribute` (`id`,`type`,`name`) VALUES (27,'uint','Height')";
+                       $query[] = 'INSERT INTO `AttributeMap` (`objtype_id`,`attr_id`,`chapter_id`) VALUES (1560,27,NULL)';
+                       // Turn rows into objects
+                       $result = $dbxlink->query ('SELECT * FROM RackRow');
+                       $rows = $result->fetchAll (PDO::FETCH_ASSOC);
+                       unset ($result);
+                       foreach ($rows as $row)
+                       {
+                               $prepared = $dbxlink->prepare ('INSERT INTO `Object` (`name`,`objtype_id`) VALUES (?,?)');
+                               $prepared->execute (array($row['name'], 1561));
+                               $row_id = $dbxlink->lastInsertId();
+                               // Turn all racks in this row into objects
+                               $result = $dbxlink->query ("SELECT id, name, height, comment FROM Rack WHERE row_id=${row['id']}");
+                               $racks = $result->fetchAll (PDO::FETCH_ASSOC);
+                               unset ($result);
+                               foreach ($racks as $rack) 
+                               {
+                                       // Add the rack as an object, set the height as an attribute, link the rack to the row,
+                                       // update rackspace, tags and files to reflect new rack_id, move history
+                                       $prepared = $dbxlink->prepare ('INSERT INTO `Object` (`name`,`objtype_id`,`comment`) VALUES (?,?,?)');
+                                       $prepared->execute (array($rack['name'], 1560, $rack['comment']));
+                                       $rack_id = $dbxlink->lastInsertId();
+                                       $query[] = "INSERT INTO `AttributeValue` (`object_id`,`attr_id`,`uint_value`) VALUES (${rack_id},27,${rack['height']})";
+                                       $query[] = "INSERT INTO `EntityLink` (`parent_entity_type`,`parent_entity_id`,`child_entity_type`,`child_entity_id`) VALUES ('object',${row_id},'object',${rack_id})";
+                                       $query[] = "UPDATE `RackSpace` SET `rack_id`=${rack_id} WHERE `rack_id`=${rack['id']}";
+                                       $query[] = "UPDATE `TagStorage` SET `entity_realm`='object', `entity_id`=${rack_id} WHERE `entity_realm`='rack' AND `entity_id`=${rack['id']}";
+                                       $query[] = "UPDATE `FileLink` SET `entity_type`='object', `entity_id`=${rack_id} WHERE `entity_type`='rack' AND `entity_id`=${rack['id']}";
+                                       $query[] = "INSERT INTO `ObjectHistory` (`id`,`name`,`objtype_id`,`comment`,`ctime`,`user_name`) SELECT ${rack_id},`name`,1560,`comment`,`ctime`,`user_name` FROM `RackHistory` WHERE `id`=${rack['id']}";
+                               }
+                       }
+                       $query[] = 'DROP TABLE `Rack`';
+                       $query[] = 'DROP TABLE `RackRow`';
+                       $query[] = 'DROP TABLE `RackHistory`';
+                       $query[] = "
+CREATE TABLE `RackThumbnail` (
+  `rack_id` int(10) unsigned NOT NULL,
+  `thumb_data` blob,
+  UNIQUE KEY `rack_id` (`rack_id`),
+  CONSTRAINT `RackThumbnail-FK-rack_id` FOREIGN KEY (`rack_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB
+";
+                       $query[] = "
+CREATE VIEW `Row` AS SELECT id, name
+  FROM `Object`
+  WHERE objtype_id = 1561
+";
+                       $query[] = "
+CREATE VIEW `Rack` AS SELECT id, name, label, asset_no, has_problems,
+  (SELECT AV.uint_value FROM `AttributeValue` AV WHERE AV.object_id = Object.id AND AV.attr_id = 27) AS height,
+  comment,
+  (SELECT thumb_data FROM `RackThumbnail` WHERE RackThumbnail.rack_id = Object.id) AS thumb_data,
+  (SELECT parent_entity_id FROM `EntityLink` WHERE parent_entity_type = 'object' AND child_entity_type = 'object' AND child_entity_id = Object.id) AS row_id,
+  (SELECT name FROM `Row` WHERE id = row_id) AS row_name
+  FROM `Object`
+  WHERE objtype_id = 1560;
+";
+                       $query[] = "
+CREATE VIEW `RackObject` AS SELECT * FROM `Object`
+ WHERE `objtype_id` NOT IN (1560, 1561, 1562)
+";
+                       $query[] = "UPDATE `Chapter` SET `name` = 'ObjectType' WHERE `id` = 1";
+                       $query[] = "DELETE FROM RackSpace WHERE object_id IS NULL AND state = 'T'";
                        $query[] = "UPDATE Config SET varvalue = '0.20.0' WHERE varname = 'DB_VERSION'";
                        break;
                default: