Name
sn_itom_pattern.CPGChangeProcessingUtil
Description
No description available
Script
var CPGChangeProcessingUtil = Class.create();
CPGChangeProcessingUtil.prototype = {
initialize: function() {
},
updateResourceGroupNameInObjectID: function(objectId) {
var value;
var parts = /\/subscriptions\/.*\/resourceGroups\/(.*?)\/.*/i.exec(objectId);
if (parts)
value = objectId.replace(parts[1], parts[1].toLowerCase());
return value;
},
getObjectIDOfResourceGroup: function(objectId) {
var value;
var parts = /(\/subscriptions\/.*\/resourceGroups\/(.*?))(\/.*?)/.exec(objectId);
if (parts)
value = parts[1];
return value.toLowerCase();
},
buildUniqueObjectsPayloadForIRE: function(payload, processedIndexes, changePayloadGR, startIndex) {
var payloadInfoId = changePayloadGR.getUniqueValue();
var uniqueObjectArray = [];
var cloudModelObjects = [];
for (i in payload) {
if (processedIndexes.indexOf(i) == -1) {
//IRE can process only unique payloads. we are filtering payload by resource group because all the resources has relationship with resource group.
//if we don't filter paylaods by resource group, we get error because we refer object_id of resource group in all resources.
var targetResourceType = payload[i].resourceType;
var object_id = payload[i].targetResourceId.toLowerCase();
if (uniqueObjectArray.indexOf(object_id) == -1) {
processedIndexes.push(i);
uniqueObjectArray.push(object_id);
var objectDetailsList = payload[i].targetResourceId.split('/'); //split the object_id
var responseProcessor = new sn_cmp.ResponseProcessor(objectDetailsList[2], payload[i].location, 'Azure Resource Changes');
//build IRE bulk payload and process
var cloudModelObject = responseProcessor.processResponseObject(payload[i], targetResourceType, null);
cloudModelObjects.push(cloudModelObject);
}
}
}
gs.debug(gs.getMessage('Azure Change Processing - Sending {0} resource changes for IRE to bulk process the unique payloads', cloudModelObjects.length));
var processedPayload = new sn_cmp_api.CloudModelProcessorScript().updateCIs(new global.JSON().encode(cloudModelObjects), changePayloadGR.sys_domain);
//Case 1 : Errored Count - If processedPayloadValue is empty then corresponding payload has errored out at IRE end / it is duplicate
var processedPayloadParsed = JSON.parse(processedPayload);
var instanceURL = gs.getProperty('glide.servlet.uri');
var ireLogsUrl = instanceURL + 'syslog_list.do?sysparm_query=messageLIKEidentification_engine^sys_created_onONLast hour@javascript:gs.beginningOfLastHour()@javascript:gs.endOfLastHour()';
for (var l = startIndex; l < processedIndexes.length; l++) {
var j = processedIndexes[l] * 1;
var objectId = payload[j].targetResourceId;
var objectIdsList = payload[j].targetResourceId.split('/'); //split the object_id
var resource_type = objectIdsList[6] + '/' + objectIdsList[7];
var table_name = this.getTableByResourceType(resource_type);//can we cache it instead of querying the db.
objectId = this.updateResourceGroupNameInObjectID(objectId);
var processedPayloadKey = table_name + '~' + objectId;
var processedPayloadKeyExists = processedPayloadParsed.hasOwnProperty(processedPayloadKey);
var eventTrailErroredGR = new GlideRecord('sn_cmp_event_trail');
var changeDate = payload[j].changeTime;
var latestChangeTimeErrored = changeDate.substring(0, changeDate.indexOf(":")).replace('T', ' ') + changeDate.substring(changeDate.indexOf(":"), changeDate.length);
latestChangeTimeErrored = latestChangeTimeErrored.substring(0, latestChangeTimeErrored.length - 1);
if (!processedPayloadKeyExists) {
eventTrailErroredGR.setValue('change_type', payload[j].changeType);
eventTrailErroredGR.setValue('change_time', new GlideDateTime(latestChangeTimeErrored));
eventTrailErroredGR.setValue('status', 'errored');
eventTrailErroredGR.setValue('reason', '[code]IRE Payload has an error, to Check IRE Logs Press <a href="' + ireLogsUrl + '" target="_blank">' + '<u><b>Here</b></u>' + '</a>[/code]');
eventTrailErroredGR.setValue('affected_payload', JSON.stringify(payload[j]));
eventTrailErroredGR.setValue('payload_info', changePayloadGR.getUniqueValue());
eventTrailErroredGR.setValue('sys_domain', changePayloadGR.sys_domain);
eventTrailErroredGR.insert();
}
}
//populate interim telemetry information for the partial bulk payload [with unique CIs] accepted by IRE
var skippedCount = this.getSkippedAndErroredCountDetails(payloadInfoId, 'skipped');
var erroredCount = this.getSkippedAndErroredCountDetails(payloadInfoId, 'errored');
var processed_count = processedIndexes.length - (skippedCount + erroredCount);
changePayloadGR.setValue('processed_count', processed_count);
changePayloadGR.setValue('skipped_count', skippedCount);
changePayloadGR.setValue('errored_count', erroredCount);
changePayloadGR.update();
},
getSkippedAndErroredCountDetails: function(payloadInfoId, status) {
var eventGR = new GlideAggregate('sn_cmp_event_trail');
eventGR.addQuery('payload_info', payloadInfoId);
eventGR.addQuery('status', status);
eventGR.addAggregate('COUNT');
eventGR.query();
if (eventGR.next())
return eventGR.getAggregate('COUNT');
return 0;
},
getTableByResourceType: function(resourceType) {
var gr = new GlideRecord('sn_capi_resource_type');
gr.addQuery('name', resourceType);
gr.query();
if (gr.next() && gr.isValidField(('ci_class')))
return '' + gr.ci_class;
return '';
},
isCMObjectEmpty: function(cmObject) {
return (cmObject && Object.keys(cmObject).length === 0);
},
calculateDynamicFrequency: function(credential, operationName, runPeriod, currentTimestamp) {
var maxFrequency = gs.getProperty("sn_cmp.azure.change_enquiry.max_frequency_in_hours");
//Get the last successful order [multiple orders created for a schedule job based on the credential]
//Check when the last order is created based on which decide the frequency for next order.
//In case of throttling[429] in Azure, CAPI might take long time to receive the response. We have to wait until the response is received else we get out of order events.
var orderGR = this.getOrderRecord(credential, operationName, 7); //status is completed.
var lastSuccessfulOrder = null;
//first time schedule trigger on a fresh instance. No order record.
var dateTimeList = runPeriod.split(' ');
var dynamicTimestampToAddInSeconds = 0;
var setMaxFrequency = false;
if (orderGR) {
lastSuccessfulOrder = orderGR.sys_created_on;
//fetch last successful order in seconds
var lastSuccessfulOrderTimestamp = GlideDateTime.subtract(new GlideDateTime(lastSuccessfulOrder), currentTimestamp);
var epochTime = lastSuccessfulOrderTimestamp.getNumericValue();
var lastSuccessfulOrderInSeconds = epochTime / 1000; //convert to seconds
if (lastSuccessfulOrderInSeconds >= (maxFrequency * 60 * 60)) //greater than 4 hours.
setMaxFrequency = true;
else
dynamicTimestampToAddInSeconds = lastSuccessfulOrderInSeconds+1; //adding 1 seconds buffer so that we will not miss any changes when the frequency is reduced.
} else
setMaxFrequency = true;
var orderFormFrequency = Math.ceil(dynamicTimestampToAddInSeconds) + 'seconds';
if (setMaxFrequency) //time in hours from property [this will happen during the 1st time / when mid is down for long time and just awake]
orderFormFrequency = maxFrequency + 'hours';
else if (dynamicTimestampToAddInSeconds >= 60) //convert to minutes
orderFormFrequency = Math.ceil(dynamicTimestampToAddInSeconds / 60) + 'minutes';
return orderFormFrequency;
},
getOrderRecord: function(credential, operationName, status) {
var credentialString = '"Credential":"' + credential + '"';
var orderGR = new GlideRecord('sn_cmp_order');
orderGR.addQuery('entity_type', '2');
orderGR.addQuery('operation_name', operationName);
orderGR.addQuery('status', status); //status is completed.
orderGR.addQuery('order_form_data', 'CONTAINS', credentialString);
orderGR.orderByDesc('sys_created_on');
orderGR.setLimit(1);
orderGR.query();
if (orderGR.next())
return orderGR;
return null;
},
type: 'CPGChangeProcessingUtil'
};
Sys ID
ee2f9f17877ce150fe6d65783cbb35f9