r4165 add support for "container" objects to handle blades, VMs, etc.
authorAaron Dummer <aaron@dummer.info>
Sat, 29 Jan 2011 01:42:38 +0000 (01:42 +0000)
committerAaron Dummer <aaron@dummer.info>
Sat, 29 Jan 2011 01:42:38 +0000 (01:42 +0000)
13 files changed:
ChangeLog
inc/config.php
inc/database.php
inc/dictionary.php
inc/interface.php
inc/navigation.php
inc/ophandlers.php
inc/triggers.php
install.php
pix/tango-mail-attachment-16x16.png [new file with mode: 0644]
pix/virtualresources.png [new file with mode: 0644]
popup.php
upgrade.php

index 1e9519b..1442c78 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@
        new feature: SNMPv3 support (#379, by Jens Weibler)
        new feature: 802.1Q template copier
        new feature: merge "objectlog" extension (by Ernest Shaffer)
+       new feature: add support for "container" objects to handle blades, VMs, etc. (by Aaron Dummer)
        update: cache image files thumbnails and make them JPEGs (#369, by Matt Mills)
        update: enhance rackspace click helpers (by Jeroen Benda)
        update: object type cannot be changed after the object is created
index 25da955..3f1dcf3 100644 (file)
@@ -35,7 +35,7 @@ $max_dict_key = array
        '0.18.3' => 1356,
        '0.18.4' => 1364,
        '0.18.5' => 1370,
-       '0.19.0' => 1394,
+       '0.19.0' => 1559,
 );
 
 define ('TAGNAME_REGEXP', '/^[\p{L}0-9]([. _~-]?[\p{L}0-9])*$/u');
index 2df700c..5af7b85 100644 (file)
@@ -646,6 +646,176 @@ function commitUpdateObject ($object_id, $new_name, $new_label, $new_barcode, $n
        return recordHistory ('RackObject', $object_id);
 }
 
+// find either parents or children of a record
+function getEntityRelatives ($type, $entity_type, $entity_id)
+{
+       if ($type == 'parents')
+       {
+               // searching for parents
+               $sql =
+                       'SELECT id, parent_entity_type AS entity_type, parent_entity_id AS entity_id FROM EntityLink ' .
+                       'WHERE child_entity_type = ? AND child_entity_id = ?';
+       }
+       else
+       {
+               // searching for children
+               $sql =
+                       'SELECT id, child_entity_type AS entity_type, child_entity_id AS entity_id FROM EntityLink ' .
+                       'WHERE parent_entity_type = ? AND parent_entity_id = ?';
+       }
+       $query = usePreparedSelectBlade ($sql, array ($entity_type, $entity_id));
+       $rows = $query->fetchAll (PDO::FETCH_ASSOC);
+       $ret = array();
+       foreach ($rows as $row)
+       {
+               // get info of the relative (only objects supported now, others may be added later)
+               switch ($row['entity_type'])
+               {
+                       case 'object':
+                               $page = 'object';
+                               $id_name = 'object_id';
+                               $relative = spotEntity ($row['entity_type'], $row['entity_id']);
+                               $name = $relative['dname'];
+                               break;
+               }
+
+               // name needs to have some value for hrefs to work
+        if (!strlen ($name))
+                       $name = sprintf("[Unnamed %s]", formatEntityName($row['entity_type']));
+
+               $ret[$row['id']] = array(
+                               'page' => $page,
+                               'id_name' => $id_name,
+                               'entity_type' => $row['entity_type'],
+                               'entity_id' => $row['entity_id'],
+                               'name' => $name
+               );
+       }
+       // FIXME: .amd - doesn't work when getEntityRelatives is called twice
+       /*
+       // sort by name
+       function compare_name ($a, $b)
+       {
+               return strnatcmp($a['name'], $b['name']);
+       }
+       uasort($ret, 'compare_name');
+       */
+       return $ret;
+}
+
+function commitUnlinkEntities ($link_id)
+{
+       return usePreparedDeleteBlade ('EntityLink', array ('id' => $link_id));
+}
+
+// The following functions return stats about VM-related info.
+// TODO: simplify the queries
+function getVMClusterSummary ()
+{
+       $result = usePreparedSelectBlade
+       (
+               "SELECT RO.id, RO.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 " .
+               "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 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 " .
+               "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"
+       );
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+function getVMResourcePoolSummary ()
+{
+       $result = usePreparedSelectBlade
+       (
+               "SELECT RO.id, RO.name, " .
+               "(SELECT RO_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 " .
+               "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 " .
+               "FROM EntityLink EL " .
+               "LEFT JOIN RackObject RO_C ON EL.parent_entity_id = RO_C.id " .
+               "WHERE EL.child_entity_id = RO.id " .
+               "AND EL.parent_entity_type = 'object' " .
+               "AND EL.child_entity_type = 'object' " .
+               "AND RO_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 " .
+               "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"
+       );
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+function getVMHypervisorSummary ()
+{
+       $result = usePreparedSelectBlade
+       (
+               "SELECT RO.id, RO.name, " .
+               "(SELECT RO_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 " .
+               "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 " .
+               "FROM EntityLink EL " .
+               "LEFT JOIN RackObject RO_C ON EL.parent_entity_id = RO_C.id " .
+               "WHERE EL.child_entity_id = RO.id " .
+               "AND EL.parent_entity_type = 'object' " .
+               "AND EL.child_entity_type = 'object' " .
+               "AND RO_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 " .
+               "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 AV.attr_id = 26 " .
+               "AND AV.uint_value = 1501 " .
+               "ORDER BY RO.name"
+       );
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+function getVMSwitchSummary ()
+{
+       $result = usePreparedSelectBlade
+       (
+               "SELECT RO.id, RO.name " .
+               "FROM RackObject RO " .
+               "WHERE RO.objtype_id = 1507 " .
+               "ORDER BY RO.name"
+       );
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
 // Remove file links related to the entity, but leave the entity and file(s) intact.
 function releaseFiles ($entity_realm, $entity_id)
 {
@@ -1991,6 +2161,48 @@ function getPortOIFCompat ()
        return $result->fetchAll (PDO::FETCH_ASSOC);
 }
 
+// Returns an array of all object type pairs from the ObjectParentCompat table.
+function getObjectParentCompat ()
+{
+       $query =
+               'SELECT parent_objtype_id, child_objtype_id, d1.dict_value AS parent_name, d2.dict_value AS child_name FROM ' .
+               'ObjectParentCompat AS pc INNER JOIN Dictionary AS d1 ON pc.parent_objtype_id = d1.dict_key ' .
+               'INNER JOIN Dictionary AS d2 ON pc.child_objtype_id = d2.dict_key ' .
+               'ORDER BY parent_name, child_name';
+       $result = usePreparedSelectBlade ($query);
+       return $result->fetchAll (PDO::FETCH_ASSOC);
+}
+
+// Used to determine if a type of object may have a parent or not
+function rackObjectTypeMayHaveParent ($objtype_id)
+{
+       $result = usePreparedSelectBlade ('SELECT COUNT(*) FROM ObjectParentCompat WHERE child_objtype_id = ?', array ($objtype_id));
+       $row = $result->fetch (PDO::FETCH_NUM);
+       if ($row[0] > 0)
+               return TRUE;
+       return FALSE;
+}
+
+// Add a pair to the ObjectParentCompat table.
+function commitSupplementOPC ($parent_objtype_id, $child_objtype_id)
+{
+       if ($parent_objtype_id <= 0)
+               throw new InvalidArgException ('parent_objtype_id', $parent_objtype_id);
+       if ($child_objtype_id <= 0)
+               throw new InvalidArgException ('child_objtype_id', $child_objtype_id);
+       return usePreparedInsertBlade
+       (
+               'ObjectParentCompat',
+               array ('parent_objtype_id' => $parent_objtype_id, 'child_objtype_id' => $child_objtype_id)
+       );
+}
+
+// Remove a pair from the ObjectParentCompat table.
+function commitReduceOPC ($parent_objtype_id, $child_objtype_id)
+{
+       return usePreparedDeleteBlade ('ObjectParentCompat', array ('parent_objtype_id' => $parent_objtype_id, 'child_objtype_id' => $child_objtype_id));
+}
+
 function getDictStats ()
 {
        $stock_chapters = array (1, 2, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28);
index ab859b3..3340230 100644 (file)
@@ -231,17 +231,17 @@ $dictionary = array
        145 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 4503'),
        146 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6513'),
        147 => array ('chapter_id' => 12, 'dict_value' => '[[Cisco%GPASS%Catalyst 4948 | http://www.cisco.com/en/US/products/ps6026/index.html]]'),
-       148 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6509-E'),
-       149 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6509-NEB-A'),
-       150 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6506-E'),
-       151 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6504-E'),
-       152 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6503-E'),
-       153 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6503'),
-       154 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6506'),
-       155 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6509-NEB'),
-       156 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 4506'),
-       157 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 4507R'),
-       158 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 4510R'),
+       148 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6509-E'),
+       149 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6509-NEB-A'),
+       150 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6506-E'),
+       151 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6504-E'),
+       152 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6503-E'),
+       153 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6503'),
+       154 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6506'),
+       155 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6509-NEB'),
+       156 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 4506'),
+       157 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 4507R'),
+       158 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 4510R'),
        159 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst Express 500-24PC'),
        160 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst Express 500-24TT'),
        161 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst Express 500G-12TC'),
@@ -450,7 +450,7 @@ $dictionary = array
        366 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%2900'),
        367 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%2970'),
        368 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%SC1435'),
-       369 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 6509'),
+       369 => array ('chapter_id' => 30, 'dict_value' => 'Cisco%GPASS%Catalyst 6509'),
        370 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%ME 6524GS-8S'),
        371 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%ME 6524GT-8S'),
        372 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 4503-E'),
@@ -876,7 +876,7 @@ $dictionary = array
        792 => array ('chapter_id' => 11, 'dict_value' => 'SGI%GPASS%Altix XE250'),
        793 => array ('chapter_id' => 11, 'dict_value' => 'SGI%GPASS%Altix XE310'),
        794 => array ('chapter_id' => 11, 'dict_value' => 'SGI%GPASS%Altix XE320'),
-       795 => array ('chapter_id' => 12, 'dict_value' => '[[Cisco%GPASS%Catalyst 3032-DEL | http://www.cisco.com/en/US/products/ps8772/index.html]]'),
+       795 => array ('chapter_id' => 12, 'dict_value' => '[[Cisco (blade)%GPASS%Catalyst 3032-DEL | http://www.cisco.com/en/US/products/ps8772/index.html]]'),
        796 => array ('chapter_id' => 13, 'dict_value' => 'Linux%GSKIP%Ubuntu 8.10'),
        797 => array ('chapter_id' => 13, 'dict_value' => '[[BSD%GSKIP%OpenBSD 4.4 | http://openbsd.org/44.html]]'),
        798 => array ('chapter_id' => 1, 'dict_value' => 'Network security'),
@@ -1075,7 +1075,7 @@ $dictionary = array
        991 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R710'),
        992 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R805'),
        993 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R905'),
-       994 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%M1000e'),
+       994 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%M1000e'),
        995 => array ('chapter_id' => 18, 'dict_value' => 'Dell PowerVault%GPASS%MD1000'),
        996 => array ('chapter_id' => 18, 'dict_value' => 'Dell PowerVault%GPASS%MD1120'),
        997 => array ('chapter_id' => 18, 'dict_value' => 'Dell EqualLogic PS5000'),
@@ -1229,7 +1229,7 @@ $dictionary = array
        1147 => array ('chapter_id' => 27, 'dict_value' => '[[APC%GPASS%AP9565 | http://www.apc.com/products/resource/include/techspec_index.cfm?base_sku=AP9565]]'),
        1148 => array ('chapter_id' => 27, 'dict_value' => '[[APC%GPASS%AP9568 | http://www.apc.com/products/resource/include/techspec_index.cfm?base_sku=AP9568]]'),
        1149 => array ('chapter_id' => 27, 'dict_value' => '[[APC%GPASS%AP9572 | http://www.apc.com/products/resource/include/techspec_index.cfm?base_sku=AP9572]]'),
-       1150 => array ('chapter_id' => 12, 'dict_value' => '[[Cisco%GPASS%Catalyst 6509-V-E | http://www.cisco.com/en/US/products/ps9306/index.html]]'),
+       1150 => array ('chapter_id' => 30, 'dict_value' => '[[Cisco%GPASS%Catalyst 6509-V-E | http://www.cisco.com/en/US/products/ps9306/index.html]]'),
        1151 => array ('chapter_id' => 27, 'dict_value' => '[[APC%GPASS%AP7902J | http://www.apc.com/products/resource/include/techspec_index.cfm?base_sku=AP7902J]]'),
        1152 => array ('chapter_id' => 27, 'dict_value' => '[[APC%GPASS%AP7930J | http://www.apc.com/products/resource/include/techspec_index.cfm?base_sku=AP7930J]]'),
        1153 => array ('chapter_id' => 27, 'dict_value' => '[[APC%GPASS%AP7932J | http://www.apc.com/products/resource/include/techspec_index.cfm?base_sku=AP7932J]]'),
@@ -1474,6 +1474,71 @@ $dictionary = array
        1392 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 2960S-48FPS-L'),
        1393 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 2960S-48LPS-L'),
        1394 => array ('chapter_id' => 12, 'dict_value' => 'Cisco%GPASS%Catalyst 2960S-24PS-L'),
+
+//                                     ^
+//                                     ^
+// add new dictionary entries up here  ^
+       1500 => array ('chapter_id' => 29, 'dict_value' => 'No'),
+       1501 => array ('chapter_id' => 29, 'dict_value' => 'Yes'),
+       1502 => array ('chapter_id' => 1, 'dict_value' => 'Server chassis'),
+       1503 => array ('chapter_id' => 1, 'dict_value' => 'Network chassis'),
+       1504 => array ('chapter_id' => 1, 'dict_value' => 'VM'),
+       1505 => array ('chapter_id' => 1, 'dict_value' => 'VM Cluster'),
+       1506 => array ('chapter_id' => 1, 'dict_value' => 'VM Resource Pool'),
+       1507 => array ('chapter_id' => 1, 'dict_value' => 'VM Virtual Switch'),
+       1508 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%VMware ESX 3.5'),
+       1509 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%VMware ESXi 3.5'),
+       1510 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%VMware ESX 4.0'),
+       1511 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%VMware ESXi 4.0'),
+       1512 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%VMware ESX 4.1'),
+       1513 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%VMware ESXi 4.1'),
+       1514 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%XenServer 4.0'),
+       1515 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%XenServer 5.0'),
+       1516 => array ('chapter_id' => 13, 'dict_value' => 'Hypervisor%GSKIP%XenServer 5.5'),
+       1517 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%1855'),
+       1518 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%1955'),
+       1519 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M605'),
+       1520 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M610'),
+       1521 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M610x'),
+       1522 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M710'),
+       1523 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M805'),
+       1524 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M905'),
+       1525 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M910'),
+       1526 => array ('chapter_id' => 26, 'dict_value' => 'Brocade (blade)%GPASS%McDATA 3014'),
+       1527 => array ('chapter_id' => 26, 'dict_value' => 'Brocade (blade)%GPASS%McDATA 4314'),
+       1528 => array ('chapter_id' => 26, 'dict_value' => 'Brocade (blade)%GPASS%McDATA 4416'),
+       1529 => array ('chapter_id' => 26, 'dict_value' => 'Brocade (blade)%GPASS%M4424'),
+       1530 => array ('chapter_id' => 26, 'dict_value' => 'Brocade (blade)%GPASS%M5424'),
+       1531 => array ('chapter_id' => 12, 'dict_value' => 'Dell PowerConnect (blade)%GPASS%5316M'),
+       1532 => array ('chapter_id' => 12, 'dict_value' => 'Dell PowerConnect (blade)%GPASS%M6220'),
+       1533 => array ('chapter_id' => 12, 'dict_value' => 'Dell PowerConnect (blade)%GPASS%M8024'),
+       1534 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%Catalyst 3130G'),
+       1535 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%Catalyst 3130X'),
+       1536 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6148-GE-TX'),
+       1537 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6148A-GE-45AF'),
+       1538 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6148A-GE-TX'),
+       1539 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6408A-GBIC'),
+       1540 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6416-GBIC'),
+       1541 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6516A-GBIC'),
+       1542 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6548-GE-TX'),
+       1543 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6548-GE-45AF'),
+       1544 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6704-10GE'),
+       1545 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6708-10G-3C'),
+       1546 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6708-10G-3CXL'),
+       1547 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6716-10GT-3C'),
+       1548 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6716-10GT-3CXL'),
+       1549 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6724-SFP'),
+       1550 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6748-GE-TX'),
+       1551 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-X6748-SFP'),
+       1552 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-SUP720-3B'),
+       1553 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-XSUP720-3BX'),
+       1554 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-SUP32-GE-3B'),
+       1555 => array ('chapter_id' => 12, 'dict_value' => 'Cisco (blade)%GPASS%WS-SUP32-10GE-3B'),
+       1556 => array ('chapter_id' => 32, 'dict_value' => 'VMware%GPASS%Standard vSwitch'),
+       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'),
+// NOTICE: do not add new dictionary entries here, add them to the gap above (~1395)!
 );
 
 ?>
index e66541a..d7cac33 100644 (file)
@@ -88,6 +88,9 @@ $image['8021q']['height'] = 200;
 $image['objectlog']['path'] = 'pix/crystal-mimetypes-shellscript-218x200.png';
 $image['objectlog']['width'] = 218;
 $image['objectlog']['height'] = 200;
+$image['virtual']['path'] = 'pix/virtualresources.png';
+$image['virtual']['width'] = 218;
+$image['virtual']['height'] = 200;
 $image['download']['path'] = 'pix/download.png';
 $image['download']['width'] = 16;
 $image['download']['height'] = 16;
@@ -214,12 +217,15 @@ $image['object']['height'] = 16;
 $image['OBJECT']['path'] = 'pix/bracket-32x32.png';
 $image['OBJECT']['width'] = 32;
 $image['OBJECT']['height'] = 32;
-$image['ATTACH']['path'] = 'pix/tango-mail-attachment-32x32.png';
-$image['ATTACH']['width'] = 32;
-$image['ATTACH']['height'] = 32;
+$image['attach']['path'] = 'pix/tango-mail-attachment-16x16.png';
+$image['attach']['width'] = 16;
+$image['attach']['height'] = 16;
 $image['Attach']['path'] = 'pix/tango-mail-attachment-22x22.png';
 $image['Attach']['width'] = 22;
 $image['Attach']['height'] = 22;
+$image['ATTACH']['path'] = 'pix/tango-mail-attachment-32x32.png';
+$image['ATTACH']['width'] = 32;
+$image['ATTACH']['height'] = 32;
 $image['favorite']['path'] = 'pix/tango-emblem-favorite.png';
 $image['favorite']['width'] = 16;
 $image['favorite']['height'] = 16;
@@ -583,11 +589,21 @@ function renderRack ($rack_id, $hl_obj_id = 0)
                                        else
                                                $prefix = "<div title='no asset tag";
                                        // Don't tell about label, if it matches common name.
+                                       $body = '';
                                        if ($objectData['name'] != $objectData['label'] and strlen ($objectData['label']))
-                                               $suffix = ", visible label is \"${objectData['label']}\"'>";
+                                               $body = ", visible label is \"${objectData['label']}\"";
+                                       // Display list of child objects, if any
+                                       $objectChildren = getEntityRelatives ('children', 'object', $objectData['id']);
+                                       if (count($objectChildren) > 0)
+                                       {
+                                               foreach ($objectChildren as $child)
+                                                       $childNames[] = $child['name'];
+                                               natsort($childNames);
+                                               $suffix = sprintf(", contains %s'>", implode(', ', $childNames));
+                                       }
                                        else
                                                $suffix = "'>";
-                                       echo $prefix . $suffix;
+                                       echo $prefix . $body . $suffix;
                                        echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$objectData['id']))."'>${objectData['dname']}</a></div>";
                                        break;
                                case 'A':
@@ -658,9 +674,54 @@ function renderEditObjectForm ($object_id)
        echo "<tr><td>&nbsp;</td><th colspan=2><h2>Attributes</h2></th></tr>";
        // baseline info
        echo "<tr><td>&nbsp;</td><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
-       echo "<tr><td>&nbsp;</td><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
-       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";
-       echo "<tr><td>&nbsp;</td><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
+       if (considerConfiguredConstraint ($object, 'VIRTUAL_OBJ_LISTSRC'))
+       {
+               echo "<input type=hidden name=object_label value=''>\n";
+               echo "<input type=hidden name=object_asset_no value=''>\n";
+               echo "<input type=hidden name=object_barcode value=''>\n";
+       }
+       else
+       {
+               echo "<tr><td>&nbsp;</td><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
+               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";
+               echo "<tr><td>&nbsp;</td><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
+       }
+       // parent selection
+       if (rackObjectTypeMayHaveParent ($object['objtype_id']))
+       {
+               $parents = getEntityRelatives ('parents', 'object', $object_id);
+               foreach ($parents as $link_id => $parent_details)
+               {
+                       if (!isset($label))
+                               $label = count($parents) > 1 ? 'Containers:' : 'Container:';
+                       echo "<tr><td>&nbsp;</td>";
+                       echo "<th class=tdright>${label}</th><td class=tdleft>";
+                       echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$parent_details['entity_id']))."'>${parent_details['name']}</a>";
+                       echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
+                       echo "<a href='".
+                               makeHrefProcess(array(
+                                       'op'=>'unlinkEntities', 
+                                       'link_id'=>$link_id,
+                                       'object_id'=>$object_id,
+                                       'page='=>'object',
+                                       'tab'=>'edit')).
+                       "'>";
+                       printImageHREF ('cut', 'Unlink container');
+                       echo "</a>";
+                       echo "</td></tr>\n";
+                       $label = '&nbsp;';
+               }
+               echo "<tr><td>&nbsp;</td>";
+               echo "<th class=tdright>Select container:</th><td class=tdleft>";
+               echo "<span";
+               $helper_args = array ('object_id' => $object_id);
+               $popup_args = 'height=700, width=400, location=no, menubar=no, '.
+                       'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
+               echo " onclick='window.open(\"" . makeHrefForHelper ('objlist', $helper_args);
+               echo "\",\"findlink\",\"${popup_args}\");'>";
+               printImageHREF ('attach', 'Select a container');
+               echo "</span></td></tr>\n";
+       }
        // optional attributes
        $values = getAttrValues ($object_id);
        echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
@@ -934,6 +995,31 @@ function renderRackObject ($object_id)
                echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
        if (strlen ($info['barcode']))
                echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
+       if ($parents = getEntityRelatives ('parents', 'object', $object_id))
+       {
+               foreach ($parents as $parent)
+               {
+                       if (!isset($label))
+                               $label = count($parents) > 1 ? 'Containers:' : 'Container:';
+                       echo "<tr><th width='50%' class=tdright>${label}</th><td class=tdleft>";
+                       echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$parent['entity_id']))."'>${parent['name']}</a>";
+                       echo "</td></tr>\n";
+                       $label = '&nbsp;';
+               }
+               unset ($label);
+       }
+       if ($children = getEntityRelatives ('children', 'object', $object_id))
+       {
+               foreach ($children as $child)
+               {
+                       if (!isset($label))
+                               $label = 'Contains:';
+                       echo "<tr><th width='50%' class=tdright>${label}</th><td class=tdleft>";
+                       echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$child['entity_id']))."'>${child['name']}</a>";
+                       echo "</td></tr>\n";
+                       $label = '&nbsp;';
+               }
+       }
        if ($info['has_problems'] == 'yes')
                echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
        foreach (getAttrValues ($object_id) as $attr_id => $record)
@@ -1231,12 +1317,15 @@ function renderRackObject ($object_id)
 
        // After left column we have (surprise!) right column with rackspace portlet only.
        echo "<td class=pcright>";
-       // rackspace portlet
-       startPortlet ('rackspace allocation');
-       foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
-               renderRack ($rack_id, $object_id);
-       echo '<br>';
-       finishPortlet();
+       if (!considerConfiguredConstraint ($info, 'VIRTUAL_OBJ_LISTSRC'))
+       {
+               // rackspace portlet
+               startPortlet ('rackspace allocation');
+               foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
+                       renderRack ($rack_id, $object_id);
+               echo '<br>';
+               finishPortlet();
+       }
        echo "</td></tr>";
        echo "</table>\n";
 }
@@ -3541,8 +3630,17 @@ function renderAddMultipleObjectsForm ()
        $typelist = cookOptgroups ($typelist);
        $max = getConfigVar ('MASSCOUNT');
        $tabindex = 100;
+       $virt_obj_listsrc = getConfigVar ('VIRTUAL_OBJ_LISTSRC');
 
-       startPortlet ('Distinct types, same tags');
+       // create a list containing only physical object types
+       // FIXME: find a cleaner way of checking whether or not an object type exists in the config var
+       $phys_typelist = $typelist;
+       foreach ($phys_typelist['other'] as $key => $value)
+       {
+               if ($key > 0 && substr_count($virt_obj_listsrc, 'typeid_'.$key.'}') > 0)
+                       unset($phys_typelist['other'][$key]);
+       }
+       startPortlet ('Physcial objects');
        printOpFormIntro ('addObjects');
        echo '<table border=0 align=center>';
        echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
@@ -3551,7 +3649,7 @@ function renderAddMultipleObjectsForm ()
        {
                echo '<tr><td>';
                // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
-               printNiftySelect ($typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
+               printNiftySelect ($phys_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
                echo '</td>';
                echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
                echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
@@ -3570,6 +3668,39 @@ function renderAddMultipleObjectsForm ()
        echo "</form></table>\n";
        finishPortlet();
 
+       // create a list containing only virtual object types
+       // FIXME: find a cleaner way of checking whether or not an object type exists in the config var
+       $virt_typelist = $typelist;
+       foreach ($virt_typelist['other'] as $key => $value)
+       {
+               if ($key > 0 && substr_count($virt_obj_listsrc, 'typeid_'.$key.'}') == 0)
+                       unset($virt_typelist['other'][$key]);
+       }
+       startPortlet ('Virtual objects');
+       printOpFormIntro ('addObjects');
+       echo "<input type=hidden name=virtual_objects value=''>\n";
+       echo '<table border=0 align=center>';
+       echo "<tr><th>Object type</th><th>Common name</th><th>Tags</th></tr>\n";
+       for ($i = 0; $i < $max; $i++)
+       {
+               echo '<tr><td>';
+               // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
+               printNiftySelect ($virt_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
+               echo '</td>';
+               echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
+               if ($i == 0)
+               {
+                       echo "<td valign=top rowspan=${max}>";
+                       renderNewEntityTags ('object');
+                       echo "</td>\n";
+               }
+               echo "</tr>\n";
+               $tabindex++;
+       }
+       echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
+       echo "</form></table>\n";
+       finishPortlet();
+
        startPortlet ('Same type, same tags');
        printOpFormIntro ('addLotOfObjects');
        echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
@@ -4081,6 +4212,63 @@ function renderPortOIFCompatEditor()
        echo '</table>';
 }
 
+function renderObjectParentCompatViewer()
+{
+       global $nextorder;
+       $order = 'odd';
+       $last_left_parent_id = NULL;
+       echo '<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>';
+       echo '<tr><th>Parent</th><th>Child</th></tr>';
+       foreach (getObjectParentCompat() as $pair)
+       {
+               if ($last_left_parent_id != $pair['parent_objtype_id'])
+               {
+                       $order = $nextorder[$order];
+                       $last_left_parent_id = $pair['parent_objtype_id'];
+               }
+               echo "<tr class=row_${order}><td>${pair['parent_name']}</td><td>${pair['child_name']}</td></tr>\n";
+       }
+       echo '</table>';
+}
+
+function renderObjectParentCompatEditor()
+{
+       function printNewitemTR()
+       {
+               printOpFormIntro ('add');
+               echo '<tr><th class=tdleft>';
+               printImageHREF ('add', 'add pair', TRUE);
+               echo '</th><th class=tdleft>';
+               printSelect (readChapter (CHAP_OBJTYPE), array ('name' => 'parent_objtype_id'));
+               echo '</th><th class=tdleft>';
+               printSelect (readChapter (CHAP_OBJTYPE), array ('name' => 'child_objtype_id'));
+               echo "</th></tr></form>\n";
+       }
+
+       global $nextorder;
+       $last_left_parent_id = NULL;
+       $order = 'odd';
+       echo '<br><table class=cooltable align=center border=0 cellpadding=5 cellspacing=0>';
+       echo '<tr><th>&nbsp;</th><th>Parent</th><th>Child</th></tr>';
+       if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
+               printNewitemTR();
+       foreach (getObjectParentCompat() as $pair)
+       {
+               if ($last_left_parent_id != $pair['parent_objtype_id'])
+               {
+                       $order = $nextorder[$order];
+                       $last_left_parent_id = $pair['parent_objtype_id'];
+               }
+               echo "<tr class=row_${order}><td>";
+               echo '<a href="' . makeHrefProcess (array ('op' => 'del', 'parent_objtype_id' => $pair['parent_objtype_id'], 'child_objtype_id' => $pair['child_objtype_id'])) . '">';
+               printImageHREF ('delete', 'remove pair');
+               echo "</a></td><td class=tdleft>${pair['parent_name']}</td><td class=tdleft>${pair['child_name']}</td></tr>\n";
+       }
+       if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
+               printNewitemTR();
+       echo '</table>';
+}
+
 // Find direct sub-pages and dump as a list.
 // FIXME: assume all config kids to have static titles at the moment,
 // but use some proper abstract function later.
@@ -9136,6 +9324,104 @@ function renderGlobalLogEditor()
        echo '</table>';
 }
 
+function renderVirtualResourcesSummary ()
+{
+       global $pageno, $nextorder;
+
+       echo "<table border=0 class=objectview>\n";
+       echo "<tr><td class=pcleft>";
+
+       $clusters = getVMClusterSummary ();
+       startPortlet ('Clusters (' . count ($clusters) . ')');
+       if (count($clusters) > 0)
+       {
+               echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
+               echo "<tr><th>Cluster</th><th>Hypervisors</th><th>VMs</th></tr>\n";
+               $order = 'odd';
+               foreach ($clusters as $cluster)
+               {
+                       echo "<tr class=row_${order} valign=top><td class='tdleft'><a href='".makeHref(array('page'=>'object', 'object_id'=>$cluster['id']))."'><strong>${cluster['name']}</strong></a></td>";
+                       echo "<td class='tdleft'>${cluster['hypervisors']}</td>";
+                       echo "<td class='tdleft'>${cluster['VMs']}</td>";
+                       echo "</tr>\n";
+                       $order = $nextorder[$order];
+               }
+               echo "</table>\n";
+       }
+       else
+               echo '<b>No clusters exist</b>';
+       finishPortlet();
+
+       echo "</td><td class=pcright>";
+
+       $pools = getVMResourcePoolSummary ();
+       startPortlet ('Resource Pools (' . count ($pools) . ')');
+       if (count($pools) > 0)
+       {
+               echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
+               echo "<tr><th>Pool</th><th>Cluster</th><th>VMs</th></tr>\n";
+               $order = 'odd';
+               foreach ($pools as $pool)
+               {
+                       echo "<tr class=row_${order} valign=top><td class='tdleft'><a href='".makeHref(array('page'=>'object', 'object_id'=>$pool['id']))."'><strong>${pool['name']}</strong></a></td>";
+                       echo "<td class='tdleft'><a href='".makeHref(array('page'=>'object', 'object_id'=>$pool['cluster_id']))."'><strong>${pool['cluster_name']}</strong></a></td>";
+                       echo "<td class='tdleft'>${pool['VMs']}</td>";
+                       echo "</tr>\n";
+                       $order = $nextorder[$order];
+               }
+               echo "</table>\n";
+       }
+       else
+               echo '<b>No pools exist</b>';
+       finishPortlet();
+
+       echo "</td></tr><tr><td class=pcleft>";
+
+       $hypervisors = getVMHypervisorSummary ();
+       startPortlet ('Hypervisors (' . count ($hypervisors) . ')');
+       if (count($hypervisors) > 0)
+       {
+               echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
+               echo "<tr><th>Pool</th><th>Cluster</th><th>VMs</th></tr>\n";
+               $order = 'odd';
+               foreach ($hypervisors as $hypervisor)
+               {
+                       echo "<tr class=row_${order} valign=top><td class='tdleft'><a href='".makeHref(array('page'=>'object', 'object_id'=>$hypervisor['id']))."'><strong>${hypervisor['name']}</strong></a></td>";
+                       echo "<td class='tdleft'><a href='".makeHref(array('page'=>'object', 'object_id'=>$hypervisor['cluster_id']))."'><strong>${hypervisor['cluster_name']}</strong></a></td>";
+                       echo "<td class='tdleft'>${hypervisor['VMs']}</td>";
+                       echo "</tr>\n";
+                       $order = $nextorder[$order];
+               }
+               echo "</table>\n";
+       }
+       else
+               echo '<b>No hypervisors exist</b>';
+       finishPortlet();
+
+       echo "</td><td class=pcright>";
+
+       $switches = getVMSwitchSummary ();
+       startPortlet ('Virtual Switches (' . count ($switches) . ')');
+       if (count($switches) > 0)
+       {
+               echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
+               echo "<tr><th>Name</th></tr>\n";
+               $order = 'odd';
+               foreach ($switches as $switch)
+               {
+                       echo "<tr class=row_${order} valign=top><td class='tdleft'><a href='".makeHref(array('page'=>'object', 'object_id'=>$switch['id']))."'><strong>${switch['name']}</strong></a></td>";
+                       echo "</tr>\n";
+                       $order = $nextorder[$order];
+               }
+               echo "</table>\n";
+       }
+       else
+               echo '<b>No virtual switches exist</b>';
+       finishPortlet();
+
+       echo "</td></tr></table>\n";
+}
+
 function switchportInfoJS($object_id)
 {
        global $gwrxlator;
index 4be9109..24a4fec 100644 (file)
@@ -16,7 +16,7 @@ $indexlayout = array
 (
        array ('rackspace', 'depot', 'ipv4space', 'ipv6space'),
        array ('files', 'reports', 'ipv4slb', '8021q'),
-       array ('config', 'objectlog'),
+       array ('config', 'objectlog', 'virtual'),
 );
 
 $page['index']['title'] = 'Main page';
@@ -130,6 +130,7 @@ $tabhandler['object']['8021qorder'] = 'render8021QOrderForm';
 $tabhandler['object']['8021qports'] = 'renderObject8021QPorts';
 $tabhandler['object']['8021qsync'] = 'renderObject8021QSync';
 $trigger['object']['rackspace'] = 'trigger_rackspace';
+$trigger['object']['ports'] = 'trigger_ports';
 $trigger['object']['ipv4'] = 'trigger_ipv4';
 $trigger['object']['ipv6'] = 'trigger_ipv6';
 $trigger['object']['nat4'] = 'trigger_natv4';
@@ -146,6 +147,8 @@ $trigger['object']['tags'] = 'trigger_tags';
 $trigger['object']['8021qorder'] = 'trigger_object_8021qorder';
 $trigger['object']['8021qports'] = 'trigger_object_8021qports';
 $trigger['object']['8021qsync'] = 'trigger_object_8021qsync';
+$ophandler['object']['edit']['linkEntities'] = 'linkEntities';
+$ophandler['object']['edit']['unlinkEntities'] = 'unlinkEntities';
 $ophandler['object']['rackspace']['updateObjectAllocation'] = 'updateObjectAllocation';
 $ophandler['object']['ports']['addPort'] = 'addPortForObject';
 $ophandler['object']['ports']['editPort'] = 'editPortForObject';
@@ -414,6 +417,15 @@ $tabhandler['perms']['default'] = 'renderRackCodeViewer';
 $tabhandler['perms']['edit'] = 'renderRackCodeEditor';
 $ophandler['perms']['edit']['saveRackCode'] = 'saveRackCode';
 
+$page['parentmap']['title'] = 'Object container compatibility';
+$page['parentmap']['parent'] = 'config';
+$tab['parentmap']['default'] = 'View';
+$tab['parentmap']['edit'] = 'Edit';
+$tabhandler['parentmap']['default'] = 'renderObjectParentCompatViewer';
+$tabhandler['parentmap']['edit'] = 'renderObjectParentCompatEditor';
+$ophandler['parentmap']['edit']['add'] = 'tableHandler';
+$ophandler['parentmap']['edit']['del'] = 'tableHandler';
+
 $page['portmap']['title'] = 'Port compatibility';
 $page['portmap']['parent'] = 'config';
 $tab['portmap']['default'] = 'View';
@@ -629,4 +641,9 @@ $tab['objectlog']['default'] = 'View';
 $tabhandler['objectlog']['default'] = 'allObjectLogs';
 #$tabhandler['objectlog']['add'] = 'renderGlobalLogEditor';
 
+$page['virtual']['title'] = 'Virtual Resources';
+$page['virtual']['parent'] = 'index';
+$tab['virtual']['default'] = 'Summary';
+$tabhandler['virtual']['default'] = 'renderVirtualResourcesSummary';
+
 ?>
index 52b3e36..3221ca8 100644 (file)
@@ -174,6 +174,26 @@ $opspec_list['file-edit-updateFile'] = array
                array ('url_argname' => 'file_id', 'table_colname' => 'id', 'assertion' => 'uint')
        ),
 );
+$opspec_list['parentmap-edit-add'] = array
+(
+       'table' => 'ObjectParentCompat',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'parent_objtype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'child_objtype_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['parentmap-edit-del'] = array
+(
+       'table' => 'ObjectParentCompat',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'parent_objtype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'child_objtype_id', 'assertion' => 'uint'),
+       ),
+);
 $opspec_list['portmap-edit-add'] = array
 (
        'table' => 'PortCompat',
@@ -1157,6 +1177,15 @@ function addMultipleObjects()
                        $log = mergeLogs ($log, oneLiner (184, array ($i + 1)));
                        break;
                }
+
+               // set to empty values for virtual objects
+               if (isset ($_REQUEST['virtual_objects']))
+               {
+                       $_REQUEST["${i}_object_label"] = '';
+                       $_REQUEST["${i}_object_barcode"] = '';
+                       $_REQUEST["${i}_object_asset_no"] = '';
+               }
+
                assertUIntArg ("${i}_object_type_id", TRUE);
                assertStringArg ("${i}_object_name", TRUE);
                assertStringArg ("${i}_object_label", TRUE);
@@ -1321,7 +1350,7 @@ function resetMyPreference ()
 $msgcode['resetUIConfig']['OK'] = 57;
 function resetUIConfig()
 {
-       setConfigVar ('MASSCOUNT','15');
+       setConfigVar ('MASSCOUNT','8');
        setConfigVar ('MAXSELSIZE','30');
        setConfigVar ('ROW_SCALE','2');
        setConfigVar ('PORTS_PER_ROW','12');
@@ -1350,7 +1379,7 @@ function resetUIConfig()
        setConfigVar ('PREVIEW_IMAGE_MAXPXS', '320');
        setConfigVar ('VENDOR_SIEVE', '');
        setConfigVar ('IPV4LB_LISTSRC', '{$typeid_4}');
-       setConfigVar ('IPV4OBJ_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_12} or {$typeid_445} or {$typeid_447} or {$typeid_798}');
+       setConfigVar ('IPV4OBJ_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_12} or {$typeid_445} or {$typeid_447} or {$typeid_798} or {$typeid_1504}');
        setConfigVar ('IPV4NAT_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_798}');
        setConfigVar ('ASSETWARN_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8}');
        setConfigVar ('NAMEWARN_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8}');
@@ -1388,6 +1417,8 @@ function resetUIConfig()
        setConfigVar ('SHRINK_TAG_TREE_ON_CLICK', 'yes');
        setConfigVar ('MAX_UNFILTERED_ENTITIES', '0');
        setConfigVar ('SYNCDOMAIN_MAX_PROCESSES', '0');
+    setConfigVar ('VIRTUAL_OBJ_LISTSRC', '{$typeid_1504} or {$typeid_1505} or {$typeid_1506} or {$typeid_1507}');
+    setConfigVar ('PORT_EXCLUSION_LISTSRC', '{$typeid_3} or {$typeid_10} or {$typeid_11} or {$typeid_1505} or {$typeid_1506}');
        return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
@@ -1999,6 +2030,38 @@ function querySNMPData ()
        return doSNMPmining ($_REQUEST['object_id'], $snmpsetup);
 }
 
+$msgcode['linkEntities']['OK'] = 51;
+$msgcode['linkEntities']['ERR2'] = 109;
+function linkEntities ()
+{
+       assertStringArg ('parent_entity_type');
+       assertUIntArg ('parent_entity_id');
+       assertStringArg ('child_entity_type');
+       assertUIntArg ('child_entity_id');
+       $result = usePreparedInsertBlade
+       (
+               'EntityLink',
+               array
+               (
+                       'parent_entity_type' => $_REQUEST['parent_entity_type'],
+                       'parent_entity_id' => $_REQUEST['parent_entity_id'],
+                       'child_entity_type' => $_REQUEST['child_entity_type'],
+                       'child_entity_id' => $_REQUEST['child_entity_id'],
+               )
+       );
+       if ($result === FALSE)
+               return buildRedirectURL (__FUNCTION__, 'ERR2');
+       return buildRedirectURL (__FUNCTION__, 'OK');
+}
+
+$msgcode['unlinkEntities']['OK'] = 49;
+$msgcode['unlinkEntities']['ERR'] = 111;
+function unlinkEntities ()
+{
+       assertUIntArg ('link_id');
+       return buildRedirectURL (__FUNCTION__, commitUnlinkEntities ($_REQUEST['link_id']) === FALSE ? 'ERR' : 'OK');
+}
+
 $msgcode['addFileWithoutLink']['OK'] = 5;
 // File-related functions
 function addFileWithoutLink ()
index 8bd5dc0..4d3433a 100644 (file)
@@ -195,11 +195,26 @@ function trigger_file_editText ()
 
 function trigger_rackspace ()
 {
+       // Hide the tab if the object type exists in the virtual config option
+       assertUIntArg ('object_id');
+       if (considerConfiguredConstraint (spotEntity ('object', $_REQUEST['object_id']), 'VIRTUAL_OBJ_LISTSRC')) 
+               return '';
+
        $rackspace = getRackspaceStats();
        if ($rackspace['Racks'] > 0) return 'std';
        return '';
 }
 
+function trigger_ports ()
+{
+       assertUIntArg ('object_id');
+       // Hide the tab if the object type exists in the exclusion config option
+       if (considerConfiguredConstraint (spotEntity ('object', $_REQUEST['object_id']), 'PORT_EXCLUSION_LISTSRC')) 
+               return '';
+
+       return 'std';
+}
+
 // Offer the generic VLAN setup tab for every object, which already
 // has a VLAN domain associated or at least can have one (in the latter
 // case additionally heat the tab, if no domain is set.
index 3e3546c..93dbdcd 100644 (file)
@@ -415,6 +415,16 @@ CREATE TABLE `Dictionary` (
   UNIQUE KEY `chap_to_val` (`chapter_id`,`dict_value`)
 ) ENGINE=MyISAM AUTO_INCREMENT=50000;
 
+CREATE TABLE `EntityLink` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `parent_entity_type` enum('ipv4net','ipv4rspool','ipv4vs','ipv6net','object','rack','user') NOT NULL,
+  `parent_entity_id` int(10) unsigned NOT NULL,
+  `child_entity_type` enum('file','object') NOT NULL,
+  `child_entity_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `EntityLink-unique` (`parent_entity_type`,`parent_entity_id`,`child_entity_type`,`child_entity_id`)
+) ENGINE=InnoDB;
+
 CREATE TABLE `File` (
   `id` int(10) unsigned NOT NULL auto_increment,
   `name` char(255) NOT NULL,
@@ -607,6 +617,12 @@ CREATE TABLE `ObjectLog` (
   CONSTRAINT `ObjectLog-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB;
 
+CREATE TABLE `ObjectParentCompat` (
+  `parent_objtype_id` int(10) unsigned NOT NULL,
+  `child_objtype_id` int(10) unsigned NOT NULL,
+  UNIQUE KEY `parent_child` (`parent_objtype_id`,`child_objtype_id`)
+) ENGINE=InnoDB;
+
 CREATE TABLE `Port` (
   `id` int(10) unsigned NOT NULL auto_increment,
   `object_id` int(10) unsigned NOT NULL default '0',
@@ -896,7 +912,8 @@ INSERT INTO `Attribute` (`id`, `type`, `name`) VALUES
 (21,'string','support contract expiration'),
 (22,'string','HW warranty expiration'),
 (24,'string','SW warranty expiration'),
-(25,'string','UUID');
+(25,'string','UUID'),
+(26,'dict','Hypervisor');
 
 INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES
 (2,1,NULL),
@@ -910,8 +927,9 @@ INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES
 (4,14,NULL),
 (4,21,NULL),
 (4,22,NULL),
-(4,25,NULL),
 (4,24,NULL),
+(4,25,NULL),
+(4,26,29),
 (5,1,NULL),
 (5,2,18),
 (6,1,NULL),
@@ -981,7 +999,38 @@ INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES
 (1323,1,NULL),
 (1323,2,28),
 (1323,3,NULL),
-(1323,5,NULL);
+(1323,5,NULL),
+(1502,1,NULL),
+(1502,2,31),
+(1502,3,NULL),
+(1502,14,NULL),
+(1502,20,NULL),
+(1502,21,NULL),
+(1502,22,NULL),
+(1503,1,NULL),
+(1503,2,30),
+(1503,3,NULL),
+(1503,14,NULL),
+(1503,20,NULL),
+(1503,21,NULL),
+(1503,22,NULL),
+(1504,3,NULL),
+(1504,4,13),
+(1504,14,NULL),
+(1504,24,NULL),
+(1505,14,NULL),
+(1506,14,NULL),
+(1506,17,NULL),
+(1506,18,NULL),
+(1507,1,NULL),
+(1507,2,32),
+(1507,3,NULL),
+(1507,4,33),
+(1507,5,NULL),
+(1507,14,NULL),
+(1507,20,NULL),
+(1507,21,NULL),
+(1507,22,NULL);
 
 INSERT INTO `Chapter` (`id`, `sticky`, `name`) VALUES
 (1,'yes','RackObjectType'),
@@ -1001,7 +1050,12 @@ INSERT INTO `Chapter` (`id`, `sticky`, `name`) VALUES
 (25,'no','wireless models'),
 (26,'no','fibre channel switch models'),
 (27,'no','PDU models'),
-(28,'no','Voice/video hardware');
+(28,'no','Voice/video hardware'),
+(29,'no','Yes/No'),
+(30,'no','network chassis models'),
+(31,'no','server chassis models'),
+(32,'no','virtual switch models'),
+(33,'no','virtual switch OS type');
 
 INSERT INTO `PortInnerInterface` VALUES
 (1,'hardwired'),
@@ -1014,6 +1068,18 @@ INSERT INTO `PortInnerInterface` VALUES
 (8,'XFP'),
 (9,'SFP+');
 
+INSERT INTO `ObjectParentCompat` VALUES
+(3,13),
+(4,1504),
+(4,1507),
+(1502,4),
+(1503,8),
+(1505,4),
+(1505,1504),
+(1505,1506),
+(1505,1507),
+(1506,1504);
+
 INSERT INTO `PortInterfaceCompat` VALUES
 (2,1208),(2,1195),(2,1196),(2,1197),(2,1198),(2,1199),(2,1200),(2,1201),
 (3,1078),(3,24),(3,34),(3,1202),(3,1203),(3,1204),(3,1205),(3,1206),(3,1207),
@@ -1217,7 +1283,7 @@ INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, is_userdef
 ('color_Th','80ffff','string','no','yes','no','HSV: 180-50-100. Taken atoms with highlight. They are not stored in the database and are only used for highlighting.'),
 ('color_Tw','804040','string','no','yes','no','HSV: 0-50-50. Taken atoms with object problem. This is detected at runtime.'),
 ('color_Thw','ff8080','string','no','yes','no','HSV: 0-50-100. An object can be both current and problematic. We run highlightObject() first and markupObjectProblems() second.'),
-('MASSCOUNT','15','uint','no','no','yes','&quot;Fast&quot; form is this many records tall'),
+('MASSCOUNT','8','uint','no','no','yes','&quot;Fast&quot; form is this many records tall'),
 ('MAXSELSIZE','30','uint','no','no','yes','&lt;SELECT&gt; lists height'),
 ('enterprise','MyCompanyName','string','no','no','no','Organization name'),
 ('ROW_SCALE','2','uint','no','no','yes','Picture scale for rack row display'),
@@ -1247,7 +1313,7 @@ INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, is_userdef
 ('PREVIEW_IMAGE_MAXPXS','320','uint','yes','no','yes','Max pixels per axis for image file preview'),
 ('VENDOR_SIEVE','','string','yes','no','yes','Vendor sieve configuration'),
 ('IPV4LB_LISTSRC','{\$typeid_4}','string','yes','no','no','List source: IPv4 load balancers'),
-('IPV4OBJ_LISTSRC','{\$typeid_4} or {\$typeid_7} or {\$typeid_8} or {\$typeid_12} or {\$typeid_445} or {\$typeid_447} or {\$typeid_798}','string','yes','no','no','List source: IPv4-enabled objects'),
+('IPV4OBJ_LISTSRC','{\$typeid_4} or {\$typeid_7} or {\$typeid_8} or {\$typeid_12} or {\$typeid_445} or {\$typeid_447} or {\$typeid_798} or {\$typeid_1502} or {\$typeid_1503} or {\$typeid_1504} or {\$typeid_1507}','string','yes','no','no','List source: IPv4-enabled objects'),
 ('IPV4NAT_LISTSRC','{\$typeid_4} or {\$typeid_7} or {\$typeid_8} or {\$typeid_798}','string','yes','no','no','List source: IPv4 NAT performers'),
 ('ASSETWARN_LISTSRC','{\$typeid_4} or {\$typeid_7} or {\$typeid_8}','string','yes','no','no','List source: object, for which asset tag should be set'),
 ('NAMEWARN_LISTSRC','{\$typeid_4} or {\$typeid_7} or {\$typeid_8}','string','yes','no','no','List source: object, for which common name should be set'),
@@ -1286,6 +1352,8 @@ INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, is_userdef
 ('SHRINK_TAG_TREE_ON_CLICK','yes','string','no','no','yes','Dynamically hide useless tags in tagtree'),
 ('MAX_UNFILTERED_ENTITIES','0','uint','no','no','yes','Max item count to display on unfiltered result page'),
 ('SYNCDOMAIN_MAX_PROCESSES','0','uint','yes','no', 'no', 'How many worker proceses syncdomain cron script should create'),
+('VIRTUAL_OBJ_LISTSRC','{\$typeid_1504} or {\$typeid_1505} or {\$typeid_1506} or {\$typeid_1507}','string','yes','no','no','List source: virtual objects'),
+('PORT_EXCLUSION_LISTSRC','{\$typeid_3} or {\$typeid_10} or {\$typeid_11} or {\$typeid_1505} or {\$typeid_1506}','string','yes','no','no','List source: objects without ports'),
 ('DB_VERSION','0.19.0','string','no','yes','no','Database version.');
 
 INSERT INTO `Script` VALUES ('RackCode','allow {\$userid_1}');
diff --git a/pix/tango-mail-attachment-16x16.png b/pix/tango-mail-attachment-16x16.png
new file mode 100644 (file)
index 0000000..529bb7f
Binary files /dev/null and b/pix/tango-mail-attachment-16x16.png differ
diff --git a/pix/virtualresources.png b/pix/virtualresources.png
new file mode 100644 (file)
index 0000000..668da1c
Binary files /dev/null and b/pix/virtualresources.png differ
index 8e58b08..14424f5 100644 (file)
--- a/popup.php
+++ b/popup.php
@@ -63,6 +63,43 @@ function findSparePorts ($port_id, $only_racks = array())
        return $ret;
 }
 
+// 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)
+{
+       $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 .= "WHERE OPC.child_objtype_id = ? ";
+       $query .= "AND RO.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 = ?) ";
+       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 .= "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 != ? ";
+               // 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 .= "ORDER BY 2";
+
+       $result = usePreparedSelectBlade ($query, $args);
+       $ret = array();
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               $ret[$row['id']] = $row['name'];
+       return $ret;
+}
+
 function sortObjectAddressesAndNames ($a, $b)
 {
        $objname_cmp = sortTokenize($a['object_name'], $b['object_name']);
@@ -90,6 +127,26 @@ header ('Content-Type: text/html; charset=UTF-8');
        assertStringArg ('helper');
        switch ($_REQUEST['helper'])
        {
+               case 'objlist':
+                       $pageno = 'object';
+                       $tabno = 'default';
+                       fixContext();
+                       if (!permitted())
+                               renderAccessDenied();
+                       assertUIntArg ('object_id');
+                       $object_id = $_REQUEST['object_id'];
+                       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);
+                       printSelect ($parents, array ('name' => 'parents', 'size' => getConfigVar ('MAXSELSIZE')));
+                       echo '<br>';
+                       echo "<input type=submit value='Proceed' onclick='".
+                       "if (getElementById(\"parents\").value != \"\") {".
+                       "       opener.location=\"process.php?page=object&tab=edit&op=linkEntities&object_id=${object_id}&child_entity_type=object&child_entity_id=${object_id}&parent_entity_type=object&parent_entity_id=\"+getElementById(\"parents\").value; ".
+                       "       window.close();}'>";
+                       echo '</form></div>';
+                       break;
                case 'portlist':
                        $pageno = 'depot';
                        $tabno = 'default';
index e14ecec..339b15d 100644 (file)
@@ -756,6 +756,7 @@ CREATE TABLE `VLANValidID` (
                        $query[] = "UPDATE Config SET varvalue = '0.18.5' WHERE varname = 'DB_VERSION'";
                        break;
                case '0.19.0':
+                       $query = array_merge ($query, reloadDictionary ($batchid));
                        $query[] = 'ALTER TABLE `File` ADD `thumbnail` LONGBLOB NULL AFTER `atime`';
                        $query[] = "
 CREATE TABLE `IPv6Address` (
@@ -810,6 +811,24 @@ CREATE TABLE `ObjectLog` (
   KEY `date` (`date`),
   CONSTRAINT `ObjectLog-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `RackObject` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB
+";
+                       $query[] = "
+CREATE TABLE `ObjectParentCompat` (
+  `parent_objtype_id` int(10) unsigned NOT NULL,
+  `child_objtype_id` int(10) unsigned NOT NULL,
+  UNIQUE KEY `parent_child` (`parent_objtype_id`,`child_objtype_id`)
+) ENGINE=InnoDB
+";
+                       $query[] = "
+CREATE TABLE `EntityLink` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `parent_entity_type` enum('ipv4net','ipv4rspool','ipv4vs','ipv6net','object','rack','user') NOT NULL,
+  `parent_entity_id` int(10) unsigned NOT NULL,
+  `child_entity_type` enum('file','object') NOT NULL,
+  `child_entity_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `EntityLink-unique` (`parent_entity_type`,`parent_entity_id`,`child_entity_type`,`child_entity_id`)
+) ENGINE=InnoDB
 ";
                        $query[] = "ALTER TABLE `TagStorage` CHANGE COLUMN `entity_realm` `entity_realm` ENUM('file','ipv4net','ipv4vs','ipv4rspool','object','rack','user','ipv6net') NOT NULL DEFAULT 'object' FIRST";
                        $query[] = "ALTER TABLE `FileLink` CHANGE COLUMN `entity_type` `entity_type` ENUM('ipv4net','ipv4rspool','ipv4vs','object','rack','user','ipv6net') NOT NULL DEFAULT 'object' AFTER `file_id`";
@@ -819,6 +838,60 @@ CREATE TABLE `ObjectLog` (
                        $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, description) VALUES ('SYNCDOMAIN_MAX_PROCESSES','0','uint','yes','no', 'How many worker proceses syncdomain cron script should create')";
                        $query[] = "ALTER TABLE `VLANSwitchTemplate` ADD COLUMN `mutex_rev` int(10) NOT NULL AFTER `max_local_vlans`";
                        $query[] = "ALTER TABLE `VLANSwitchTemplate` ADD COLUMN `saved_by` char(64) NOT NULL AFTER `description`";
+                       $query[] = "INSERT INTO `Attribute` (`id`, `type`, `name`) VALUES (26,'dict','Hypervisor')";
+                       $query[] = "INSERT INTO `Chapter` (`id`, `sticky`, `name`) VALUES (29,'no','Yes/No')";
+                       $query[] = "INSERT INTO `Chapter` (`id`, `sticky`, `name`) VALUES (30,'no','network chassis models')";
+                       $query[] = "INSERT INTO `Chapter` (`id`, `sticky`, `name`) VALUES (31,'no','server chassis models')";
+                       $query[] = "INSERT INTO `Chapter` (`id`, `sticky`, `name`) VALUES (32,'no','virtual switch models')";
+                       $query[] = "INSERT INTO `Chapter` (`id`, `sticky`, `name`) VALUES (33,'no','virtual switch OS type')";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (4,26,29)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1502,1,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1502,2,31)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1502,3,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1502,14,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1502,20,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1502,21,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1502,22,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1503,1,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1503,2,30)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1503,3,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1503,14,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1503,20,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1503,21,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1503,22,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1504,3,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1504,4,13)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1504,14,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1504,24,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1505,14,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1506,14,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1506,17,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1506,18,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,1,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,2,32)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,3,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,4,33)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,5,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,14,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,20,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,21,NULL)";
+                       $query[] = "INSERT INTO `AttributeMap` (`objtype_id`, `attr_id`, `chapter_id`) VALUES (1507,22,NULL)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (3,13)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (4,1504)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (4,1507)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (1502,4)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (1503,8)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (1505,4)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (1505,1504)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (1505,1506)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (1505,1507)";
+                       $query[] = "INSERT INTO `ObjectParentCompat` (`parent_objtype_id`, `child_objtype_id`) VALUES (1506,1504)";
+                       $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, is_userdefined, description) VALUES ('VIRTUAL_OBJ_LISTSRC','{\$typeid_1504} or {\$typeid_1505} or {\$typeid_1506} or {\$typeid_1507}','string','yes','no','no','List source: virtual objects')";
+                       $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, is_userdefined, description) VALUES ('PORT_EXCLUSION_LISTSRC','{\$typeid_3} or {\$typeid_10} or {\$typeid_11} or {\$typeid_1505} or {\$typeid_1506}','string','yes','no','no','List source: objects without ports')";
+                       $query[] = "UPDATE RackObject SET objtype_id = 1502 WHERE id IN (SELECT object_id FROM AttributeValue WHERE attr_id = 2 AND uint_value = 994)";
+                       $query[] = "UPDATE RackObject SET objtype_id = 1503 WHERE id IN (SELECT object_id FROM AttributeValue WHERE attr_id = 2 AND (uint_value BETWEEN 148 AND 158 OR uint_value = 369 OR uint_value = 1150))";
+                       $query[] = "UPDATE Config SET varvalue = CONCAT(varvalue, ' or {\$typeid_2} or {\$typeid_6} or {\$typeid_1502} or {\$typeid_1503} or {\$typeid_1504} or {\$typeid_1507}') WHERE varname = 'IPV4OBJ_LISTSRC'";
+                       $query[] = "UPDATE Config SET varvalue = '8' WHERE varname = 'MASSCOUNT'";
                        $query[] = "UPDATE RackObject SET label = NULL WHERE label = ''";
                        $query[] = "UPDATE Config SET varvalue = '0.19.0' WHERE varname = 'DB_VERSION'";
                        break;