Name
global.VMUtils
Description
Some utility functions used by discovery for virtual machines and provisioning for virtual machines
Script
var VMUtils;
(function() {
var morMap = { },
uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/i,
correlationIdRegex = /^([0-9a-f]{2} ){7}[0-9a-f]{2}-[0-9a-f]{2}( [0-9a-f]{2}){7}$/i,
spaceRegex = / /g,
dashRegex = /-/g,
hexByteRegex = /[0-9a-f]{2}/ig,
morTypeToTable = {
VirtualMachine: 'cmdb_ci_vmware_instance',
Network: 'cmdb_ci_vmware_network',
VmwareDistributedVirtualSwitch: 'cmdb_ci_vmware_dvs',
DistributedVirtualPortgroup: 'cmdb_ci_network',
HostSystem: 'cmdb_ci_esx_server',
ClusterComputeResource: 'cmdb_ci_vcenter_cluster',
ComputeResource: 'cmdb_ci_esx_server',
VirtualApp: 'cmdb_ci_esx_resource_pool',
ResourcePool: 'cmdb_ci_esx_resource_pool',
Datastore: 'cmdb_ci_vcenter_datastore',
Datacenter: 'cmdb_ci_vcenter_datacenter',
StoragePod: 'cmdb_ci_vcenter_datastore',
Folder: 'cmdb_ci_vcenter_folder'
},
copiedParms = [ 'debug', 'isTriggered','fixed_credential_id',
'priority', 'mid_selector_details',
'vcenter_sys_id', 'vcenter_uuid', 'datacenter_sys_id', 'datacenter_mor_id',
'ignoreCert', 'vcenter_port', 'avoid_id_engine', 'enable_cmp_qa', 'vcenter_timeout',
'esx_sys_id', 'delete_stale_relationships' ];
VMUtils = {
turnUuidToCorrelationId: turnUuidToCorrelationId,
turnCorrelationIdToUuid: turnCorrelationIdToUuid,
isChangeRequestRequired: isChangeRequestRequired,
lookupSysIds: lookupSysIds,
lookupSysIdsInTables: lookupSysIdsInTables,
lookupSysIdsESX : lookupSysIdsESX,
getRecForMor: getRecForMor,
triggerNextPage: triggerNextPage,
triggerProbes: triggerProbes
};
/**
* Given a managed object reference (or any object of the same form) return the
* GlideRecord for it. Returns undefined if the record can't be found.
*/
function getRecForMor(mo, table, vCenterInstanceUuid) {
table = table || morTypeToTable[mo.type];
var gr = checkTable(table);
if (!gr && (table == 'cmdb_ci_vmware_instance'))
gr = checkTable('cmdb_ci_vmware_template');
return gr;
function checkTable(table) {
var gr = new GlideRecord(table);
gr.addQuery('vcenter_uuid', vCenterInstanceUuid);
gr.addQuery('object_id', mo.val);
gr.addQuery('install_status','!=',7);
gr.query();
if (gr.getRowCount() == 1) {
gr.next();
return gr;
}
}
}
/**
* Convert the UUID to a format that matches the original format in our system. vCenter works with UUIDs
* where the ESX Linux console worked with this format
*/
function turnUuidToCorrelationId(uuid) {
// The format of the uuid returned from vCenter is fixed to match this reg exp, according
// to the documentation, so it should match, but verify anyway and return an empty string
// if it doesn't match
var verify = uuidRegex.exec(uuid);
if (verify) {
var stripped = uuid.replace(dashRegex, '');
var match = hexByteRegex.exec(stripped);
var id = '';
while (match) {
if (id.length > 0)
id += ' ';
id += match;
match = hexByteRegex.exec(stripped);
}
// Based on the expected format, currently will always be in the same spot
return id.substr(0, 23) + '-' + id.substr(24);
}
return '';
};
/**
* Turn a correlation ID into a UUID for a virtual machine in our system
*/
function turnCorrelationIdToUuid(correlation_id) {
var verify = correlationIdRegex.exec(correlation_id);
if (verify) {
var collapsed = correlation_id.replace(spaceRegex, '');
var uuid = collapsed.substr(0,8) + "-" + collapsed.substr(8,4) + "-"
+ collapsed.substr(12,9) + "-" + collapsed.substr(21);
return uuid;
}
return '';
};
function isChangeRequestRequired(action) {
};
/*
* Given a list of MORs, look up their sys_ids.
* @param mors: Array of MORs or a single MOR.
* @param table: Table name to search
* @param esx: sys_id of the ESX Server that owns the objects
* @param morColumn: Optional, defaults to 'object_id'. Name of the MOR id column in 'table'.
* @param morsResult: Optional, array to contain matching mor ids.
* @return: an array or single sys_id depending on the type of the 'mors' parameter
*
* sys_ids will be cached, so invalid sys_ids could be returned for deleted records.
*/
function lookupSysIdsESX(mors, table, esx, morColumn, morsResult){
return lookupSysIdsCommon(mors, table, false, esx, morColumn, morsResult);
}
function lookupSysIdsCommon(mors, table, isVCenter, refId, morColumn, morsResult){
var gr, returnOne,
morsToLookup = [ ],
sysIds = [ ],
found = 0;
morColumn = morColumn || 'object_id';
morMap[table] = morMap[table] || { };
if (typeof mors == 'string') {
returnOne = true;
mors = [ mors ];
}
if (!mors)
return sysIds;
// See which mors I haven't looked up yet
mors.forEach(
function(mor) {
if (!morMap[table][mor.morid || mor])
morsToLookup.push(mor.morid || mor);
});
// Look them up
if (morsToLookup.length) {
gr = new GlideRecord(table);
if (isVCenter)
gr.addQuery('vcenter_ref', refId);
else {
if (table === 'cmdb_ci_esx_server')
gr.addQuery ('sys_id',refId);
else
gr.addQuery('server', refId);// reference to cmdb_ci_esx_server
}
gr.addQuery(morColumn, 'IN', morsToLookup);
gr.query();
while (gr.next()) {
found++;
morMap[table][gr[morColumn]] = '' + gr.sys_id;
}
}
mors.forEach(
function(mor) {
var sysId = morMap[table][mor.morid || mor];
if (sysId)
sysIds.push(sysId);
if (morsResult instanceof Array)
morsResult.push(mor.morid || mor);
if (typeof morsResult == 'string')
mor[morsResult] = sysId || mor[morsResult];
});
return returnOne ? sysIds[0] : sysIds;
}
/*
* Given a list of MORs, look up their sys_ids.
* @param mors: Array of MORs or a single MOR.
* @param table: Table name to search
* @param vcenter: sys_id of the vCenter that owns the objects
* @param morColumn: Optional, defaults to 'object_id'. Name of the MOR id column in 'table'.
* @param morsResult: Optional, array to contain matching mor ids.
* @return: an array or single sys_id depending on the type of the 'mors' parameter
*
* sys_ids will be cached, so invalid sys_ids could be returned for deleted records.
*/
function lookupSysIds(mors, table, vcenter, morColumn, morsResult) {
return lookupSysIdsCommon(mors, table, true, vcenter, morColumn, morsResult);
}
/*
* * Given a list of MORs, look up their sys_ids by calling "lookupSysIds" method for each table.
* @param mors: Array of MORs or a single MOR.
* @param tables: Array of table names to search in
* @param vcenter: sys_id of the vCenter that owns the objects
* @param morColumn: Optional, defaults to 'object_id'. Name of the MOR id column in 'table'.
* @param morsResult: Optional, array to contain matching mor ids.
*
* @return: An array. If no sys_ids found then it returns empty array.
*
* sys_ids will be cached, so invalid sys_ids could be returned for deleted records.
*/
function lookupSysIdsInTables(mors, tables, vcenter, morColumn, morsResult) {
var sysIds = [ ];
var morsCopy = [];
if (tables instanceof Array)
tables.forEach(function(table) {
var sysId = lookupSysIds(mors, table, vcenter, morColumn, morsResult);
/*
* Lookup functions are dependent on modifying the object passed in as a param (mors)
* Multiple cis per mor causes prev result to be overwritten (DEF0359344)
* Need to save each result per table and modify original mors obj
* Need to deep copy obj because original mors obj gets overwritten per DEF
*/
if (sysId) {
var deepCopy = JSON.parse(JSON.stringify(mors));
morsCopy = morsCopy.concat(deepCopy);
}
if (sysId instanceof Array)
sysIds = sysIds.concat(sysId);
else if (typeof sysId == 'string')
sysIds.push(sysId);
});
// Need to modify original obj (mors) to align with current impl
// Direct assignment (mors=morsCopy) does not modify original obj
for (var i=0; i < morsCopy.length; i++) {
mors[i] = morsCopy[i];
}
return sysIds;
}
// Utility to trigger discovery of the next page of objects. Used by
// vCenter sensors.
//////////////////////////////////////////////////////////////////////////
function triggerNextPage(_this, leftovers, additionalParms) {
// If there's no next page then we don't have anything to do.
if (!leftovers || !leftovers.length)
return;
var parms = { mor_ids: JSON.stringify(leftovers) };
additionalParms = (additionalParms || [ ]).concat(copiedParms);
additionalParms.forEach(copyParm);
_this.triggerProbe(g_probe.getParameter('probe_name'), parms);
function copyParm(name) {
if (g_probe.getParameter(name))
parms[name] = g_probe.getParameter(name);
}
}
// Get parameters for the next probe to trigger
// _this {DiscoverySensor} this object, required to call DiscoverySensor.triggerProbes.
// ids {Object} MOR IDs of vCenter objects processed by the sensor. Usually
// contains a single type of object, but will contain all object
// types when called by the datacenters sensor.
// parms {Object} Optional parameters to pass. Used by datacenters sensor. Other
// sensors just copy parameters from the previous probe, but the
// previous probe doesn't have the required parameters for the
// datacenters sensor.
//////////////////////////////////////////////////////////////////////////
function triggerProbes(_this, ids, parms) {
var name, objects,
remaining = { };
parms = parms || { };
initForNextProbe();
_this.triggerProbes(prepFn, parms, copiedParms);
// Prepare to call the discovery_sensor_probe_conditional condition script.
// Called repeatedly for each probe until it returns falsey.
function prepFn(parms) {
var numInGroup,
data = { };
// Prepare to be called for another probe type
if (!Object.keys(remaining).length) {
initForNextProbe();
return;
}
// Chop off the correct number of items, based on the number of
// parallel probes for each type of probe.
for (name in remaining) {
numInGroup = Math.ceil(objects[name].length/remaining[name]);
data[name] = objects[name].splice(0, numInGroup);
remaining[name]--;
if (!objects[name].length || !remaining[name])
delete remaining[name];
}
return data;
}
function initForNextProbe() {
objects = { };
for (name in ids) {
objects[name] = [ ];
// Copy the identifying information out of the objects that were passed in.
ids[name].forEach(function(obj) { if (obj.morid) objects[name].push( { type: obj.type, morid: obj.morid }); else objects[name].push(obj); });
// The number of parallel probes remaining to trigger
remaining[name] = parseInt(_this.getParameter('parallel_' + name + '_probes')) || 1;
}
}
}
})();
Sys ID
32874afac0a8026440b78a55254b59c3