Name
sn_cmdb_ws.CMDBWsInsightUtil
Description
No description available
Script
var CMDBWsInsightUtil = Class.create();
CMDBWsInsightUtil.prototype = Object.extendsObject(CMDBWorkspaceUtil, {
initialize: function() {
this.DC_PROVIDER_MAPPING = {};
},
QB_STATUS: {
COMPLETE: 'COMPLETE',
MAX_LIMIT: 'MAX_LIMIT',
TIME_OUT: 'TIME_OUT',
DISABLED: 'DISABLED'
},
DATACENTER_TYPE: {
CLOUD: 'cloud',
NONCLOUD: 'non_cloud'
},
NONCLOUD_AS_PROVIDER: "Non-cloud",
DC_CLASS_FIELD: "u_logical_datacenter_1.sys_class_name",
CLOUD_SERVICE_ACC_DC_TYPE_FIELD: "u_cloud_service_account_1.datacenter_type",
CLOUD_SERVICE_ACC_CATEGORY: "439485f577b3111078521605bc5a99ae",
COUNT: "COUNT",
/**
* Returns a string of comma separated cloud datacenters
* @param {Boolean} checkAcl whether or not not check the caller's ACL
* @return {String}
*/
getCloudFilters: function(checkAcl) {
return this.getDataCentersOfType(this.DATACENTER_TYPE.CLOUD, checkAcl).join(",");
},
/**
* Returns a string of comma separated non-cloud datacenters
* @param {Boolean} checkAcl whether or not not check the caller's ACL
* @return {String}
*/
getNonCloudFilters: function(checkAcl) {
return this.getDataCentersOfType(this.DATACENTER_TYPE.NONCLOUD, checkAcl).join(",");
},
/**
* Returns an array of datacenters configured for given type
* @param {String} type type of datacenter
* @param {Boolean} checkAcl whether or not not check the caller's ACL
* @return {array}
*/
getDataCentersOfType: function(type, checkAcl) {
var gr;
if (checkAcl) {
gr = new GlideRecordSecure(this.TABLES.SN_CMDB_WS_DATACENTER_TYPE);
} else {
gr = new GlideRecord(this.TABLES.SN_CMDB_WS_DATACENTER_TYPE);
}
gr.addQuery(this.COLS.TYPE, type);
gr.query();
var datacenters = [];
while (gr.next()) {
datacenters.push(gr.getValue(this.COLS.DATACENTER_CLASS));
}
return datacenters;
},
hasCloudDataCenterData: function() {
if (gs.tableExists(this.TABLES.CLOUD_SERVICE_ACCOUNT)) {
var gr = new GlideRecord(this.TABLES.CMDB_CI_LOGICAL_DATACENTER);
gr.addQuery(this.COLS.SYS_CLASS_NAME, 'IN', this.getCloudFilters(false));
gr.setLimit(1);
gr.query();
return gr.hasNext();
} else
return false;
},
/**
* Helper function to check if Cloud vs Noncloud asset tab should be included on landing page
* @return {Boolean}
*/
showCloudVsNonCloudAsset: function() {
var hasCloudData = this.hasCloudDataCenterData();
return hasCloudData;
},
/**
* Helper function to check if Cloud vs Noncloud status container should be shown
* @return {Boolean}
*/
showCloudVsNonCloudStatusContainer: function() {
var count = -1;
var gr = new GlideAggregate(this.TABLES.SN_CMDB_WS_PRODUCT_INSIGHT_DATA);
gr.addAggregate(this.COLS.COUNT);
gr.query();
if (gr.next()) {
count = gr.getAggregate(this.COLS.COUNT);
}
return count > 0 ? true : false;
},
getQueryLatestExecutionData: function(savedQueryId) {
//Originally this function was supposed to be a replica of the same function in QueryBuilderReport (because QBR was not open to all scopes), however
//we need more data than just latest executionId, we also need, last updated on, status and result table name
var status = [this.QB_STATUS.COMPLETE, this.QB_STATUS.MAX_LIMIT, this.QB_STATUS.TIME_OUT];
var result = {
executionId: null,
status: null,
updated: null,
result_table: null
};
var glideSavedQuery = new GlideRecord(this.TABLES.QB_SAVED_QUERY);
if (glideSavedQuery.get(savedQueryId) && glideSavedQuery.canRead()) {
result.result_table = glideSavedQuery.getValue(this.COLS.RESULT_TABLE);
}
var glideQbStatus = new GlideRecord(this.TABLES.QB_QUERY_STATUS);
glideQbStatus.addQuery(this.COLS.TABLE_NAME, result.result_table);
glideQbStatus.addQuery(this.COLS.STATUS, 'IN', status);
glideQbStatus.orderByDesc(this.COLS.UPDATED);
glideQbStatus.setLimit(1);
glideQbStatus.query();
if (glideQbStatus.next() && glideQbStatus.canRead()) {
result.executionId = glideQbStatus.getUniqueValue();
result.status = glideQbStatus.getValue(this.COLS.STATUS);
result.updated = glideQbStatus.getValue(this.COLS.UPDATED);
}
return result;
},
calculateAggregates: function() {
//before doing any agregates, check for cloud data existence, and only proceed if cloud data exists on the instance
if (this.hasCloudDataCenterData()) {
var gr = new GlideRecord(this.TABLES.SN_CMDB_WS_QUERY_CATEGORY);
gr.addQuery(this.COLS.ACTIVE, true);
gr.query();
while (gr.next()) { //for each of the type and ci class combo, i.e, "Cloud Application", "non-cloud server"
var ciClass = gr.getValue(this.COLS.CI_CLASS);
var type = gr.getValue(this.COLS.TYPE);
var qbSavedQuery = gr.getValue(this.COLS.QUERY);
var lastRefreshed = gr.getValue(this.COLS.LAST_REFRESHED);
var ciCategorySysId = gr.getUniqueValue();
gs.debug("processing " + type + " " + ciClass + " query, last refreshed " + lastRefreshed);
var lastExecution = this.getQueryLatestExecutionData(qbSavedQuery);
if (gs.nil(lastRefreshed) || new GlideDateTime(lastExecution.updated).after(new GlideDateTime(lastRefreshed))) {
//make sure results table exists first - no point in aggregating if result table does not exist
if (gs.tableExists(lastExecution.result_table)) {
//get new aggregate for this ciClass and type combo - only if last execution status is "COMPLETE"
if (lastExecution.status == this.QB_STATUS.COMPLETE) {
if (type == this.DATACENTER_TYPE.CLOUD) {
this.calculateCloudAggregate(ciCategorySysId, lastExecution.executionId, lastExecution.result_table);
} else {
this.calculateNonCloudAggregate(ciCategorySysId, lastExecution.executionId, lastExecution.result_table);
}
// reset the failure count
gr.setValue(this.COLS.FAILURE_COUNT, 0);
} else {
//mark agg data for this ci class & type as "retired"
gs.debug("The last execution of " + type + " " + ciClass + " did not complete. It was " + lastExecution.status);
this._updateState(this.STATES.READY, this.STATES.RETIRED, ciCategorySysId);
// +1 the current failure count
gr.setValue(this.COLS.FAILURE_COUNT, parseInt(gr.getValue(this.COLS.FAILURE_COUNT)) + 1);
}
//update the status and lastRefresh date on the query_category table
gr.setValue(this.COLS.LAST_REFRESHED, lastExecution.updated);
gr.setValue(this.COLS.STATUS, lastExecution.status);
gr.update();
} else {
gs.debug("result table for " + type + " " + ciClass + " does not exist yet");
}
} else {
gs.debug("last execution query's updated time for " + type + " " + ciClass + " has not changed. No new data");
// if the underlying job has been disabled, mark the category as disabled and retire the aggregate data
var sysAutoGr = new GlideRecord(this.TABLES.SYSAUTO_QUERY_BUILDER);
sysAutoGr.addQuery(this.COLS.QUERY, qbSavedQuery);
sysAutoGr.query();
if (sysAutoGr.next()) {
var isJobActive = sysAutoGr.getDisplayValue(this.COLS.ACTIVE) === 'true' ? true : false;
if (!isJobActive) {
this._updateState(this.STATES.READY, this.STATES.RETIRED, ciCategorySysId);
gr.setValue(this.COLS.STATUS, this.QB_STATUS.DISABLED);
gr.update();
}
}
}
}
}
},
updateQBJobActive: function(queryId, active) {
var sysAutoGr = new GlideRecord(this.TABLES.SYSAUTO_QUERY_BUILDER);
sysAutoGr.addQuery(this.COLS.QUERY, queryId);
sysAutoGr.query();
if (sysAutoGr.next()) {
sysAutoGr.setValue(this.COLS.ACTIVE, active);
sysAutoGr.update();
}
},
getProvider: function(dcClass) {
var providerName = null;
if (this.DC_PROVIDER_MAPPING[dcClass]) {
gs.debug("dc provider mapping exists for " + dcClass + ". It is " + this.DC_PROVIDER_MAPPING[dcClass]);
return this.DC_PROVIDER_MAPPING[dcClass];
} else {
gs.debug("dc provider mapping does not exist for " + dcClass + ". Looking up");
//given a logical datacenter class, return the shortened provider name
var gr = new GlideRecord(this.TABLES.SN_CMDB_WS_DATACENTER_TYPE);
gr.addQuery(this.COLS.DATACENTER_CLASS, dcClass);
gr.query();
if (gr.next()) {
providerName = gr.getValue(this.COLS.CLOUD_PROVIDER);
//add to dc provider mapping
this.DC_PROVIDER_MAPPING[dcClass] = providerName;
}
}
return providerName;
},
calculateCloudAggregate: function(ciCategory, executionId, resultTable) {
this._updateState(this.STATES.DRAFT, this.STATES.RETIRED, ciCategory);
//needs a different group by for cloud service account, since it needs to be grouped by datacenter_type field
var groupByField = ciCategory === this.CLOUD_SERVICE_ACC_CATEGORY ? this.CLOUD_SERVICE_ACC_DC_TYPE_FIELD : this.DC_CLASS_FIELD;
var agg = new GlideAggregate(resultTable);
agg.addQuery(this.COLS.QUERY, executionId);
agg.addAggregate(this.COUNT);
agg.groupBy(groupByField);
agg.query();
while (agg.next()) {
var dcClass = agg.getValue(groupByField);
var count = agg.getAggregate(this.COUNT);
var provider = this.getProvider(dcClass); //convert the dcClass into a provider
//insert into the agg table if count is a positive number
if (count > 0) {
gs.debug("Inserting record into agg table for cloud " + ciCategory + " provider " + provider + " count " + count);
this._populateCloudInsightAggData(this.CATEGORY.CLOUD_AND_NONCLOUD_CIS, ciCategory, provider, count, this.STATES.DRAFT);
}
}
// Update the existing records in "Ready" state to "Retired"
this._updateState(this.STATES.READY, this.STATES.RETIRED, ciCategory);
// Update the existing records in "Draft" state to "Ready"
this._updateState(this.STATES.DRAFT, this.STATES.READY, ciCategory);
},
calculateNonCloudAggregate: function(ciCategory, executionId, resultTable) {
var aggCount = -1;
//if there are any agg records in "draft" state, for this ciCategory, mark them as "retired"
this._updateState(this.STATES.DRAFT, this.STATES.RETIRED, ciCategory);
var agg = new GlideAggregate(resultTable);
agg.addQuery(this.COLS.QUERY, executionId); //query=4228348f41e31110f8774131f61c4c85
agg.addAggregate(this.COUNT);
agg.query();
if (agg.next()) {
aggCount = agg.getAggregate(this.COUNT);
}
if (aggCount > 0) { //only insert when agg count is a positive number
gs.debug("Inserting record into agg table for non-cloud " + ciCategory + " count " + aggCount);
this._populateCloudInsightAggData(this.CATEGORY.CLOUD_AND_NONCLOUD_CIS, ciCategory, this.NONCLOUD_AS_PROVIDER, aggCount, this.STATES.DRAFT);
}
// Update the existing records in "Ready" state to "Retired"
this._updateState(this.STATES.READY, this.STATES.RETIRED, ciCategory);
// Update the existing records in "Draft" state to "Ready"
this._updateState(this.STATES.DRAFT, this.STATES.READY, ciCategory);
},
_updateState: function(sourceState, targetState, ciCategory) {
var gr = new GlideRecord(this.TABLES.SN_CMDB_WS_PRODUCT_INSIGHT_DATA);
if (ciCategory)
gr.addQuery(this.COLS.CI_CATEGORY, ciCategory);
gr.addQuery(this.COLS.STATE, sourceState);
gr.setValue(this.COLS.STATE, targetState);
gr.updateMultiple();
},
_populateCloudInsightAggData: function(chart, ciCategory, cloudProvider, count, state) {
var gr = new GlideRecord(this.TABLES.SN_CMDB_WS_PRODUCT_INSIGHT_DATA);
gr.initialize();
gr.setValue(this.COLS.CHART, chart);
gr.setValue(this.COLS.CI_CATEGORY, ciCategory);
gr.setValue(this.COLS.CLOUD_PROVIDER, cloudProvider);
gr.setValue(this.COLS.COUNT, count);
gr.setValue(this.COLS.STATE, state);
gr.insert();
},
getCIClasses: function() {
var ciClassesArr = [];
var ga = new GlideAggregate(this.TABLES.SN_CMDB_WS_PRODUCT_INSIGHT_DATA);
ga.addQuery(this.COLS.STATE, this.STATES.READY);
ga.groupBy(this.COLS.CI_CATEGORY + this.COLS.DOT + this.COLS.CI_CLASS);
ga.orderBy(this.COLS.CI_CATEGORY + this.COLS.DOT + this.COLS.CI_CLASS);
ga.query();
while (ga.next()) {
ciClassesArr.push(ga.getValue(this.COLS.CI_CATEGORY + this.COLS.DOT + this.COLS.CI_CLASS));
}
return ciClassesArr;
},
getDataCenterTypeOfCloudProvider: function(cloudProvider) {
var gr = new GlideRecord(this.TABLES.SN_CMDB_WS_DATACENTER_TYPE);
gr.addQuery(this.COLS.CLOUD_PROVIDER, cloudProvider);
gr.query();
return gr;
},
isValidRecord: function(table, query) {
var gr = new GlideRecord(table);
gr.addEncodedQuery(query);
gr.setLimit(1);
gr.query();
return gr.hasNext();
},
migrateInsightDataRecords: function() {
var insightDataGr = new GlideRecord(this.TABLES.SN_CMDB_WS_INSIGHT_DATA);
insightDataGr.query();
while (insightDataGr.next()) {
var gr = new GlideRecord(this.TABLES.SN_CMDB_WS_PRODUCT_INSIGHT_DATA);
gr.initialize();
gr.setValue(this.COLS.CHART, this.CATEGORY.CLOUD_AND_NONCLOUD_CIS);
gr.setValue(this.COLS.CI_CATEGORY, insightDataGr.getValue(this.COLS.CI_CATEGORY));
gr.setValue(this.COLS.CLOUD_PROVIDER, insightDataGr.getValue(this.COLS.CLOUD_PROVIDER));
gr.setValue(this.COLS.COUNT, insightDataGr.getValue(this.COLS.COUNT));
gr.setValue(this.COLS.STATE, insightDataGr.getValue(this.COLS.STATE));
gr.insert();
}
},
type: 'CMDBWsInsightUtil'
});
Sys ID
dbfdf10eeb13111094bbb5d5d852280d