When an ESX/i server is added to the CMDB to create cmdb_ci_server records for new hardware, running Discovery will not re-classify these records and will end up with a duplicate one in the cmdb_ci_esx_server table. 

VMware uses different classifiers than the normal CIs which doesn't handle duplicates outside of "cmdb_ci_esx_server".

Steps to Reproduce

  1. Create a cmdb_ci_server record for an ESX server.  Set the serial number correctly.
  2. Discover the vCenter.
  3. Observe that the existing cmdb_ci_server record doesn't get reclassified and a new record is created in the cmdb_ci_esxi_server table.


Below are the changes committed to the code. Make sure to inform the customer that these changes will need to be reverted upon upgrade.

  1. In the "VCenterESXHostsSensor":
    • Add a "reclassify" member to the 'schema' variable
    • Add the 'morid' and 'correlation_id' to the index in addition to the 'serial_number'
      schema = {
              cmdb_ci_esx_server: {
                  fixup: fixupEsx,
                  preWriteRels: preWriteEsxRels,
                  index: [ ['morid','correlation_id'], [ 'serial_number'] ],  
                  childOf: {
                      cmdb_ci_vcenter_datacenter: 'Contains::Contained by',
                      cmdb_ci_esx_resource_pool: 'Defines resources for::Gets resources from',
                      cmdb_ci_vmware_instance: 'Registered on::Has registered',
                      cmdb_ci_vmware_template: 'Registered on::Has registered',
                      cmdb_ci_vcenter_cluster: 'Members::Member of',
                      cmdb_ci_vcenter_network: 'Provided by::Provides',
                      cmdb_ci_vcenter_datastore: 'Used by::Uses'
                  reclassify: {
                  cmdb_ci_server: [ 'serial_number' ]
  2. In script include "JsonCi", apply the following 2 changes:
    • Change the following code on line 311


      gr = || getRecord(obj, tableSchema.index);


      gr = || getRecord(obj, tableSchema);
    • Change the entire "GetRecord()" function to the following
      function getRecord(obj, schema) {
        var reclassify,
          indexes = schema.index,
          tableName = obj.sys_class_name; // used by findRecord()
        if (!searchIndexes(indexes) && schema.reclassify) {
          for (tableName in schema.reclassify) {
            if (searchIndexes(schema.reclassify[tableName])) {
              g_disco_functions.reclassify(, obj.sys_class_name);
        return || new GlideRecord(obj.sys_class_name); // Must be obj.sys_class_name - tableName may have been modified during reclassification
        function searchIndexes(indexes) {
          if (indexes[0] instanceof Array)
            return indexes.some(findRecord);
          return findRecord(indexes);
        function findRecord(idx) {
          var gr = new GlideRecord(tableName);
          if ((indexes.filterRecord && indexes.filterRecord(obj, idx, tableName)) ||
            (idx.filterRecord && idx.filterRecord(obj, idx, tableName)))
          if (!idx.every(addQuery))
          if ( {
            obj.sys_id = '' + gr.sys_id;
   = gr;
            return true;
          function addQuery(name) {
            var val = obj[name],
              ok = true;
            if (val && typeof val == 'object')
              ok = val = val.sys_id;
            if (val === undefined)
              return false;
            gr.addQuery(name, val);
            return ok;

Related Problem: PRB1268924

Seen In

There is no data to report.

Fixed In


Associated Community Threads

There is no data to report.

Article Information

Last Updated:2019-05-21 11:43:40