Name
global.MIDServerProfile
Description
This class contains utility functions for interacting with MID Server Profiles.
Script
var MIDServerProfile = Class.create();
MIDServerProfile.prototype = {
initialize: function() {
},
getParams: function(table_name, profile_id) {
var result = [];
var gr = new GlideRecord(table_name);
gr.addQuery("profile", profile_id);
gr.query();
while (gr.next()) {
var param = {};
param["name"] = gr.getValue("name");
param["value"] = gr.getValue("value");
result.push(param);
}
return result;
},
getProfile: function(profile_id) {
var gr = new GlideRecord('mid_server_profile');
if (!gr.get(profile_id))
return '{}';
var profile = {} ;
var configParms = this.getParams("mid_profile_config", profile_id);
// add the mid_profile_id config param
var param = {};
param["name"] = "mid_profile_id";
param["value"] = '' + profile_id;
configParams.push(param);
profile["config"] = configParams;
profile["wrapper_config"] = this.getParams("mid_profile_wrapper_config", profile_id);
return JSON.stringify(profile);
},
clone: function(oldProfileId, newProfileId) {
this._copyProfileM2MValues("mid_profile_application_m2m", "application", oldProfileId, newProfileId);
this._copyProfileM2MValues("mid_profile_capability_m2m", "capability", oldProfileId, newProfileId);
this._copyProfileM2MValues("mid_profile_cluster_m2m", "cluster", oldProfileId, newProfileId);
this._copyProfileM2MValues("mid_profile_ip_range_m2m", "ip_range", oldProfileId, newProfileId);
this._copyProfileValues("mid_profile_config", oldProfileId, newProfileId);
this._copyProfileValues("mid_profile_property", oldProfileId, newProfileId);
this._copyProfileValues("mid_profile_wrapper_config", oldProfileId, newProfileId);
},
syncProfileToMids: function(profileId, syncStrategy) {
var m2mTables = {
"capability" : {profileM2M: "mid_profile_capability_m2m", agentM2M: "ecc_agent_capability_m2m"},
"application": {profileM2M: "mid_profile_application_m2m", agentM2M: "ecc_agent_application_m2m"},
"cluster": {profileM2M: "mid_profile_cluster_m2m", agentM2M: "ecc_agent_cluster_member_m2m"},
"ip_range": {profileM2M: "mid_profile_ip_range_m2m", agentM2M: "ecc_agent_ip_range_m2m"}
};
var kvTables = {
"ecc_agent_config": {fieldName: "param_name", sourceTable: "mid_profile_config"},
"ecc_agent_property": {fieldName: "name", sourceTable: "mid_profile_property"}
};
if (!this._validateProfile(profileId, syncStrategy)) {
gs.addErrorMessage(gs.getMessage("An error has occurred while trying to sync profile settings to MID servers."));
return;
}
gs.log("Syncing profile to MID servers...", "MIDServerProfile");
var profileM2MSettings = this._getProfileM2MSettings(profileId, m2mTables);
var profileKVSettings = this._getProfileKVSettings(profileId, kvTables);
var scu = new MIDServerSystemCommandUtil;
var gr = new GlideRecord('ecc_agent');
gr.query("profile_id", profileId);
while (gr.next()) {
var isModified = false;
var table;
for (table in m2mTables)
isModified = this._updateAgentM2MSettings(gr.getUniqueValue(), table, profileM2MSettings[table], m2mTables[table].agentM2M, syncStrategy) || isModified;
// M2M tables share the same system command, only send it once after all M2M tables are synced
if (isModified && gs.getProperty("mid.com.snc.process_flow.integration.integration_hub_mid_caching_enabled", "false") == "true")
scu.issueSystemCommandToSpecificMID("environment_clear", gr.name);
// System commands for kv tables are enqueued in ECCAgentSyncableChangesListener, don't enqueue here
for (table in kvTables) {
this._updateAgentKVSettings(gr.getUniqueValue(), table, profileKVSettings[table], kvTables[table].fieldName, syncStrategy);
}
}
gs.log("Finished syncing profile to MID servers", "MIDServerProfile");
gs.addInfoMessage(gs.getMessage("Profile settings successfully synced to MID servers."));
},
_getProfileM2MSettings: function(profileId, tables) {
var settings = {}; // key: table name, value: array of sys Ids for each setting on table
// key is the field name of the corresponding table, e.g. cluster for ecc_agent_cluster_member_m2m
for (var fieldName in tables) {
settings[fieldName] = [];
var tableName = tables[fieldName].profileM2M;
var gr = new GlideRecord(tableName);
gr.query("profile", profileId);
while (gr.next()) {
var setting = gr.getValue(fieldName);
settings[fieldName].push(setting);
}
}
return settings;
},
_getProfileKVSettings: function(profileId, tables) {
var settings = {}; // key: table name, value: map of kv settings on table
for (var table in tables) {
settings[table] = {};
var tableName = tables[table].sourceTable;
var gr = new GlideRecord(tableName);
gr.query("profile", profileId);
while (gr.next()) {
var setting = gr.getValue("name");
var value = gr.getValue("value");
settings[table][setting] = value;
}
}
return settings;
},
_validateProfile: function(profileId, syncStrategy) {
gs.log("Validating profile...", "MIDServerProfile");
// Check does profile have cluster defined
// If so, validate the capabilities, if not then return as valid
var clusterGr = new GlideRecord("mid_profile_cluster_m2m");
clusterGr.query("profile", profileId);
if (!clusterGr.hasNext())
return true;
// A cluster is defined for the profile so ensure that the profile has capabilities as well. Any capability will suffice.
var capabilityGr = new GlideRecord("mid_profile_capability_m2m");
capabilityGr.query("profile", profileId);
if (!capabilityGr.hasNext()){
if (syncStrategy == "override_ifexists") {
// If sync strategy is to keep non-default settings, check that each mid has some capability.
// If a MID is found without a capability then fail validation
var agentGr = new GlideRecord("ecc_agent");
agentGr.query("profile_id", profileId);
var capGr = new GlideRecord("ecc_agent_capability_m2m");
while (agentGr.next()) {
capGr.query("agent", agentGr.getUniqueValue());
if (!capGr.hasNext()) {
gs.addErrorMessage(gs.getMessage("Agent {0} has no capabilities and cannot be included with cluster. Please add capability to agent or remove agent from cluster.", agentGr.getValue("name")));
return false;
}
}
} else {
gs.addErrorMessage(gs.getMessage("Profile has no capabilities and cannot be included with cluster. Please add capability or remove cluster from profile."));
return false;
}
}
return true;
},
// refFieldName is the other 'm' table in the m2m, e.g. 'profile' or 'agent'
_setProfileM2MValues: function(profileId, refFieldName, refSysId, sourceTable, destTable, fieldName, executeBRs, isNewRecord) {
var sourceGR = new GlideRecord(sourceTable);
sourceGR.addQuery("profile", profileId);
sourceGR.query();
var destGR = new GlideRecord(destTable);
while (sourceGR.next()) {
if (!isNewRecord) {
destGR.addQuery(refFieldName, refSysId);
destGR.addQuery(fieldName, sourceGR.getValue(fieldName));
destGR.query();
// These M2M records only have the two fields already queried, so nothing to update
if (destGR.hasNext())
continue;
}
destGR.initialize();
destGR.setWorkflow(executeBRs);
destGR.setValue(refFieldName, refSysId);
destGR.setValue(fieldName, sourceGR.getValue(fieldName));
destGR.insert();
}
},
_copyProfileM2MValues: function(tableName, fieldName, oldProfileId, newProfileId) {
this._setProfileM2MValues(oldProfileId, "profile", newProfileId, tableName, tableName, fieldName, false, true);
},
// settingsArr contains updated settings from profile. Ensure that agent has these M2M refs.
_updateAgentM2MSettings: function(agentSysId, settingName, settingsArr, tableName, syncStrategy) {
var isTableModified = false;
var gr = new GlideRecord(tableName);
gr.addQuery("agent", agentSysId);
gr.query();
while (gr.next()) {
var setting = gr.getValue(settingName);
var index = settingsArr.indexOf(setting);
if (index == -1) {
if (syncStrategy == "replace_all") {
gr.setWorkflow(false);
gr.deleteRecord();
isTableModified = true;
}
} else {
// remove setting from arr
// arr will contain only new settings afterwards which will be added
settingsArr.splice(index,1);
}
}
// Add in new settings
for (var i = 0; i < settingsArr.length; i++) {
gr.initialize();
gr.setWorkflow(false);
gr.setValue("agent", agentSysId);
gr.setValue(settingName, settingsArr[i]);
gr.insert();
isTableModified = true;
}
return isTableModified;
},
_updateAgentKVSettings: function(agentSysId, table, settingsMap, fieldName, syncStrategy){
var gr = new GlideRecord(table);
gr.query("ecc_agent", agentSysId);
while (gr.next()) {
var name = gr.getValue(fieldName);
var value = gr.getValue("value");
// Ensure setting can be modified
if (table == "ecc_agent_config") {
var mcp = SncMIDConfigParameter.byName(name);
// Unlisted parameters don't appear in the UI and cannot be added to a profile.
// If one exists for the MID, then it was added by the MID server and shouldn't be modified.
// Hidden params should be skipped as well since they should go in secrets file instead.
if (!mcp.isListed() || mcp.isHidden())
continue;
}
if (settingsMap[name]) {
// If it's in settings map that means it's part of profile, see if value has changed
if (settingsMap[name] != value) {
if (this._isIgnoredParam(name)){
gs.log(gs.getMessage("Cannot sync parameter \"{0}\", skipping...", name), "MIDServerProfile");
delete settingsMap[name];
continue;
}
gr.setValue("value", settingsMap[name]);
gr.update();
}
delete settingsMap[name];
} else {
if (syncStrategy == "replace_all") {
if (this._isIgnoredParam(name)){
gs.log(gs.getMessage("Cannot sync parameter \"{0}\", skipping...", name), "MIDServerProfile");
continue;
}
gr.deleteRecord();
}
}
}
// All the elements remaining in settingsMap are new profile settings, add them in
for (var setting in settingsMap) {
if (this._isIgnoredParam(setting)){
gs.log(gs.getMessage("Cannot sync parameter \"{0}\", skipping...", name), "MIDServerProfile");
continue;
}
gr.initialize();
gr.setWorkflow(false);
gr.setValue("ecc_agent", agentSysId);
gr.setValue(fieldName, setting);
gr.setValue("value", settingsMap[setting]);
gr.insert();
}
},
_copyProfileValues: function(tableName, oldProfileId, newProfileId) {
var gr = new GlideRecord(tableName);
gr.addQuery("profile", oldProfileId);
gr.query();
var grNew = new GlideRecord(tableName);
while (gr.next()) {
// url config parameter should be updated as it was already inserted when the new profile record was created
var shouldUpdate = false;
if (tableName == 'mid_profile_config' && gr.name == 'url') {
grNew.addQuery("profile", newProfileId);
grNew.addQuery('name', 'url');
grNew.query();
shouldUpdate = grNew.next();
}
if (shouldUpdate) {
grNew.setValue("value", gr.getValue("value"));
grNew.update();
} else {
grNew.initialize();
grNew.setValue("profile", newProfileId);
grNew.setValue("name", gr.getValue("name"));
grNew.setValue("value", gr.getValue("value"));
grNew.insert();
}
}
},
_isIgnoredParam: function(name) {
var IGNORED_PARAMS = ["mid.buildstamp", "mid_sys_id", "keypairs.mid_id", "home_dir", "url"];
return IGNORED_PARAMS.indexOf(name) != -1;
},
type: 'MIDServerProfile'
};
Sys ID
44e487e753463010347cddeeff7b12d3