/*
* Maybe move this to an event on device complete if this ends up being a perforamnce issue.
* The reason is this BR would run as long there's data in serial_number or correlation_id.
*/
(function() {
var g_disco_functions = new DiscoveryFunctions();
var fVMGr = current;
var fInstanceGr;
var fHypervisorGr;
startVirtualComputerCheck();
setIsVirtualForCloudIPs();
// Updated as per request from CMDB STRY3415899
function startVirtualComputerCheck() {
// Putting the easier ones to identify at the front so we don't spend extra effort looking up the others
if (isSolarisZone())
handleSolariZone();
else if (isVMWare()) {
// only process rec if just inserted or serial_number changed AND serial_number is non-nil
if (!(JSUtil.notNil(current.serial_number)))
return;
handleVMWare();
} else if (isHyperV())
handleHyperV();
else if (!isCredentialless())
return;
current.virtual = true;
// By this point we know if we have found a vm instance record
if (JSUtil.nil(fInstanceGr))
return;
// We DO have an instance record, so let's create the "instantiates" relationship between VM and Instance
g_disco_functions.createRelationshipIfNotExists(fVMGr, fInstanceGr, "Instantiates::Instantiated by");
// Now, let's find the hypervisor...
fHypervisorGr = findVMWareByImage(fInstanceGr);
if (JSUtil.nil(fHypervisorGr))
return;
// The HyperVisor DOES exist, so let's create the "virtualized by" 'relationship between VM and Hypervisor
// However, before we do that, let's see if VM already has relationship with another Hypervisor and if so, we
// need to migrate the relationship.
// *note: This shouldn't happen if the relationship was properly managed from the VM instance side.
// But we'll do it just in case...
reconcileRelationVMtoHyperVisor();
}
function isSolarisZone() {
if (fVMGr.sys_class_name != "cmdb_ci_solaris_server")
return false;
if (!fVMGr.correlation_id.hasValue())
return false;
if (!fVMGr.correlation_id.startsWith("zone-"))
return false;
return true;
}
function isVMWare() {
if (!fVMGr.serial_number.hasValue())
return false;
if (!fVMGr.serial_number.toLowerCase().startsWith("vmware-"))
return false;
return true;
}
function isHyperV() {
var serialNumber = fVMGr.serial_number;
if (!serialNumber.hasValue())
return false;
var instGr = new GlideRecord("cmdb_ci_hyper_v_instance");
var serials = ['chassis_serial', 'bios_serial', 'baseboard_serial'];
return serials.some(
function(serial) {
instGr.initialize();
if (instGr.get(serial, serialNumber)) {
fInstanceGr = instGr;
return true;
}
}
);
}
function handleSolariZone() {
var matchingId = fVMGr.correlation_id.substring(5);
var gr = new GlideRecord('cmdb_ci_solaris_instance');
gr.addQuery('correlation_id', matchingId);
gr.query();
if (gr.next())
fInstanceGr = gr;
}
function isCredentialless() {
var potentialVmInstances, potentialGuests;
// Check to see if this is a record being created by credentialless discovery. If so we'll attempt to
// reconcile with a VMWare VM based on IP. We're limiting the check to VMWare VMs because that limits the
// risk while solving the associated INT.
if (!current.ip_address || !current.ip_address.changes() || current.discovery_source != 'CredentiallessDiscovery')
return;
potentialVmInstances = new GlideRecord('cmdb_ci_vmware_instance');
potentialVmInstances.addQuery('ip_address', current.ip_address);
potentialVmInstances.setLimit(2);
potentialVmInstances.query();
// find all potential "other" guests with the IP
potentialGuests = new GlideRecord('cmdb_ci_computer');
potentialGuests.addQuery('ip_address', current.ip_address);
potentialGuests.addQuery('sys_id', '!=', current.sys_id);
potentialGuests.setLimit(2);
potentialGuests.query();
commonVMWareHandling(potentialVmInstances, potentialGuests);
return !!fInstanceGr;
}
function handleVMWare() {
var serial_number, matchingId, potentialVmInstances, potentialGuests, warnMsg;
serial_number = fVMGr.serial_number;
matchingId = fVMGr.serial_number.substring(7);
// find all potential VM instances with this serial number
potentialVmInstances = new GlideRecord('cmdb_ci_vmware_instance');
//potentialVmInstances.addQuery('correlation_id', matchingId);
potentialVmInstances.addQuery('correlation_id', 'STARTSWITH', matchingId);
potentialVmInstances.query();
// find all potential "other" guests with the same serial number
potentialGuests = new GlideRecord('cmdb_ci_computer');
potentialGuests.addQuery('serial_number', serial_number);
potentialGuests.addQuery('sys_id', '!=', fVMGr.sys_id);
potentialGuests.query();
commonVMWareHandling(potentialVmInstances, potentialGuests);
if (!fInstanceGr) {
warnMsg = gs.getMessage('Unable to uniquely match VMWare instance with guest based on serial number: {0}.\n' +
'The correct VMWare instance associated with this guest will be resolved during the next vCenter discovery.', serial_number);
DiscoveryLogger.warn(warnMsg, "Virtual Computer Check", "");
}
}
function commonVMWareHandling(potentialVmInstances, potentialGuests) {
var unreconciledVmInstances, unreconciledGuests, unreconciledVmSize, unreconciledGuestSize;
// if there's only one VM instance, and no other guests
// save the VM instance and return
if (potentialVmInstances.getRowCount() == 1 && potentialGuests.getRowCount() == 0) {
potentialVmInstances.next();
fInstanceGr = potentialVmInstances;
return;
}
unreconciledGuests = [];
while (potentialGuests.next()) {
unreconciledGuests.push(potentialGuests.getValue('sys_id'));
}
unreconciledVmInstances = [];
// Filter out any VM instances & guests that are already reconciled with a relationship.
while (potentialVmInstances.next()) {
var vmInstance = potentialVmInstances.getValue('sys_id');
var isReconciled = JSUtil.getBooleanValue(potentialVmInstances, 'guest_reconciled');
// if a relationship between this guest and a VM instance already exists then return
if (isReconciled && g_disco_functions.relationshipExists(fVMGr, vmInstance, "Instantiates::Instantiated by"))
return;
if (isReconciled) {
// if the relationship between another guest and this VM instance exists, then don't consider it an unreconciled relationship
var relFound = false;
for (var i = unreconciledGuests.length - 1; i >= 0; i--) {
if (g_disco_functions.relationshipExists(unreconciledGuests[i], vmInstance, "Instantiates::Instantiated by")) {
relFound = true;
unreconciledGuests.splice(i, 1);
}
}
if (!relFound)
unreconciledVmInstances.push(vmInstance);
} else
unreconciledVmInstances.push(vmInstance);
}
unreconciledVmSize = unreconciledVmInstances.length;
unreconciledGuestSize = unreconciledGuests.length;
// If we have no unreconciled VM instances then return
if (unreconciledVmSize == 0)
return;
// If we have only 1 unreconciled VM instance and no other unreconciled guests
// save the VM instance and return
if (unreconciledVmSize == 1 && unreconciledGuestSize == 0) {
fInstanceGr = unreconciledVmInstances[0];
return;
}
}
function handleHyperV() {
matchingId = fVMGr.serial_number + '';
// The fInstanceGr is already handled in isHyperV() method. Just so that we don't waste another query.
}
function findVMWareByImage(instGr) {
var gr = new GlideRecord("cmdb_rel_ci");
gr.query("parent", instGr.sys_id);
gr.query("type", g_disco_functions.findCIRelationshipType("cmdb_rel_type", "Registered on::Has registered"));
gr.query();
if (gr.next())
return gr.child;
else {
//There are no Registered on::Has registered relationships for vm instance,
//i.e vm was migrated and Registered on::Has registered was deleted, deleting the Virtualized by::Virtualizes relationships
var relGr = new GlideRecord('cmdb_rel_ci');
relGr.addQuery("parent", fVMGr.sys_id);
relGr.addQuery("type", g_disco_functions.findCIRelationshipType("cmdb_rel_type", "Virtualized by::Virtualizes"));
relGr.query();
if (relGr.next())
relGr.deleteMultiple();
}
return;
}
function reconcileRelationVMtoHyperVisor() {
var gr = new GlideRecord('cmdb_rel_ci');
gr.query('parent', fVMGr.sys_id);
gr.query('type', g_disco_functions.findCIRelationshipType("cmdb_rel_type", "Virtualized by::Virtualizes"));
gr.query();
// If we found nothing, then let's simply create the relationship between VM and Hypervisor
if (gr.getRowCount() == 0) {
g_disco_functions.createRelationshipIfNotExists(fVMGr, fHypervisorGr, "Virtualized by::Virtualizes");
return;
}
// We found existng relationship(s) between VM and HyperVisor(s). Theoretically there should be only 1
// If we did find multiple, then We want to just correct the first relationship and then delete the rest
var done = false;
while (gr.next()) {
if (done == true) {
gr.deleteRecord();
continue;
}
// If they don't match, let's re-point the child to the correct hypervisor
if ((gr.child.sys_id + '') !== (fHypervisorGr.sys_id + '')) {
gr.child = fHypervisorGr.sys_id;
gr.update();
} // The other possibliy is that the sys_id matches, in which case there would be nothing to do
done = true;
}
}
function setIsVirtualForCloudIPs() {
var IP = current.ip_address.toString();
if (IP.startsWith('10.245') || IP.startsWith('10.247') || IP.startsWith('10.248') || IP.startsWith('10.249'))
current.virtual = true;
}
}
)();
No comments:
Post a Comment