How to automate CMDB Discovery Schedules through integrating with DNS/IPAM tools
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-21-2023 01:26 PM - edited 03-24-2023 03:49 PM
Authors: @JFro and @Camila Godoy
Introduction
In this post, we will describe how we designed and developed an integration to automate our ServiceNow discovery using an IP Management tool.
We can often agree that discovery:
- Can be Complicated to manage
- Causes large bursts of network traffic and processing overhead
- Schedules have a lack of change automation
- No Source of Truth
External links:
Infoblox WAPI documentation link can be obtained from your appliance @ https://dns.company.com/wapidoc/index.html
Solution Summary
Our solution relies on Infoblox (IP management tool) to provide subnet data that allows us to automate discovery schedules on CMDB. The following steps represents a summary of actions from teams involved on this project.
- The Network Team Created definitions and normalization of their data and an API endpoint.
- ServiceNow CMDB Engineering Team developed an integration to pull the data and store it in a table. When inserted or updated, this data will generate discovery schedules to run at the least busy minute. In addition, it will automatically classify if a schedule should run daily, weekly, or not be created based on network type, DMZ type, and on our discovery IP count. These schedules get Activated and Inactivated based on the lifecycle of the network information coming from Infoblox.
- The Configuration Management team adopted Discovery Admin to help classify, assign incidents, and solve the errors created by discovery.
Design
Table format and fields mapping to payload
Full view of the integration
Infoblox data Lifecycle
Data logic sample used to classify when a schedule runs
Discovery Time Setup | Network Type | DMZ Type | Notes |
Cloud | x | y | Exclude – this is already built with an integration. |
Daily | a | b |
|
Weekly | c | d |
|
IP count (Future Enhancement)
When range counts zero IPs for 7 days, regardless of the classification, it will move from daily to weekends. It will move back to daily once the IP counts changes from zero.
See commented code in the end of the discoveryScheduleManager Script include.
Step 1 – Network Team
- Classify the networks:
- DMZ Type
- Description
- Network Type
- Create an API endpoint integration to your IPAM
Step 2 – CMDB Engineering
- Create outbound REST
- Construct a message to point the API endpoint on the Infoblox Appliance. You’ll need to configure the credentials to connect to your appliance, here we’re using Basic Auth
- The REST Message contains the HTTP Method. For Infoblox there’s a couple HTTP Query Parameters to configure. ‘_max_results’ when at a negative value the appliance will return an error if the results exceed that value and when positive it just truncates the results. Since we want everything and throw an error if that’s exceeded, we set it to the max negative value =-99999. The ‘_return_fields’ with a value of ‘extattrs’ tells the appliance to also send along the Extensible Attributes fields which is where we’re storing our Network Type, DMZ Type, and Comments for each network.
- Create a Scheduled job to call our script include and run our import function
- Create a Staging table for Infoblox Data
Infoblox API Fields | ServiceNow Fields | Description | Audit |
network | u_name | This field stores network names defined on infoblox. | True |
comment | u_description | This field contains general description of the network. | True |
network_type | u_network_type | This field contains network type such: iot, data_center, network_infrastructure, and others. | True |
Zone | u_dmz_type | This field contains zone type details such: external_dmz, external_transit and others | True |
U_cmdb_discovery | u_infoblox_discovery_time | This field stores data defined by Infoblox of what discovery time a combination of zone and network type should have. | True |
| u_discovery_time_setup | This field will indicate if this network will be discovered daily or weekly. The logic set of this field can be found below on Table 2. | True |
| u_status | This field will update to retired if a network is not updated by the integration for more than 15 days. | True |
| u_network_ip | This field contains the ip network. | True |
| u_network_mask | This field contains the network mask. It will be populated with a client script based on the network field. | True |
| u_cmdb_discovery | This field sync with the Active field in the discovery schedule. | True |
| u_discovery_schedule | This is a field reference to the discovery schedule table. | True |
| u_active_ip_count | This field will give a count of how many IPS we can interrogate in the ip range. | True |
| u_discovery_ip_zero_count | This counts how many times a Range had 0 ips. If the count is 7 days in a row, this set the range to be discovered weekly. | True |
| u_last_discovered | This field will be updated by the integration. | False |
- Create Script Include to parse response and retire records
var InfobloxImport = Class.create();
InfobloxImport.prototype = {
initialize: function() {
var status;
var requestBody;
var responseBody;
var restMessage;
},
_fetchdata: function() {
try {
var webService = 'Infoblox Networks';
var command = 'Default Get';
restMessage = new sn_ws.RESTMessageV2(webService, command);
var response = restMessage.execute();
responseBody = response.getBody();
status = response.getStatusCode();
return responseBody;
} catch (ex) {
responseBody = ex.getMessage();
status = 500;
return responseBody;
} finally {
requestBody = restMessage ? restMessage.getRequestBody() : null;
}
},
run: function() {
var payload = this._fetchdata();
if (status == 200) {
this._process_results(payload);
} else {
var error = "A Infoblox import exception occurred. There was no data returned";
this._createInc(error);
}
},
_process_results: function(payload) {
var parsedData = JSON.parse(payload);
var iputils = new IpUtils;
var errors_array = [];
for (var i = 0; i < parsedData.length; i++) {
var cidr = parsedData[i].network;
var network = cidr.split("/")[0];
var subnet = cidr.split("/")[1];
var networkType = parsedData[i].extattrs.network_type.value;
var zone = parsedData[i].extattrs.zone.value;
var schdTime = parsedData[i].extattrs.cmdb_discovery.value;
var validTimes = gs.getProperty('discovery.infoblox.valid_times');
var validNetworkTypes = gs.getProperty('discovery.infoblox.valid_network_types');
var validZones = gs.getProperty('discovery.infoblox.valid_zones');
var isValidNetworkType = validNetworkTypes.includes(networkType) && networkType != "";
var isValidZone = validZones.includes(zone) && zone != "";
var ipValid = iputils.validIP(network);
var maskValid = iputils.validMask(subnet);
if(schdTime == "daily" || schdTime == "Daily"){
infobloxTime = 1;
} else if (schdTime == "weekly" || schdTime == "Weekly"){
infobloxTime = 2;
} else if (schdTime == "cloud" || schdTime == "Cloud") {
infobloxTime = 3;
} else if (schdTime == "Internet" || schdTime == "internet") {
infobloxTime = 4;
} else if (schdTime == "non-routable") {
infobloxTime = 5;
} else {
infobloxTime = "";
}
//check if network and mask are valid
if (isValidNetworkType && isValidZone && ipValid && maskValid) {
var grIB = new GlideRecord("u_cmdb_infoblox");
grIB.addQuery("u_name", cidr);
grIB.query();
if (grIB.next()) {
grIB.u_description = parsedData[i].comment;
grIB.u_infoblox_discovery_time_setup = infobloxTime;
grIB.u_dmz_type = zone;
grIB.u_network_type = networkType;
var rightnow = new GlideDateTime();
grIB.u_last_discovered = rightnow;
grIB.update();
} else {
//record doesn't exist, insert
grIB.initialize();
grIB.u_name = cidr;
grIB.u_network_ip = network;
grIB.u_network_mask = subnet;
grIB.u_description = parsedData[i].comment;
grIB.u_infoblox_discovery_time_setup = infobloxTime;
grIB.u_dmz_type = zone;
grIB.u_network_type = networkType;
var rightnow = new GlideDateTime();
grIB.u_last_discovered = rightnow;
grIB.insert();
}
} else {
//subnet or mask from row is invalid
//create an array to hold anything in error and submit all as one inc
errors_array.push(parsedData[i]);
}
}
if (errors_array) {
this._createInc(errors_array);
}
},
_createInc: function(errors_array) {
grInc = new GlideRecord("incident");
grInc.initialize();
grInc.caller = "";
grInc.assignment_group = "sys_id of assignment group"; //Insert your assignement group here
grInc.business_service = "sys_id of business service to relate inc to"; // Insert your service if that required
grInc.u_incident_type = "Data Issue";
grInc.severity = 3;
grInc.priority = 5;
grInc.contact_type = "Self Discovered";
var errors_to_string = JSON.stringify(errors_array, null, '\t');
grInc.description = "There was an error with the data import from Infoblox integration. Objects with errors: " + "\n \n" + errors_to_string;
grInc.short_description = "Infoblox Data Import Error";
grInc.insert();
return;
},
retire: function(days){
var ibGr = new GlideRecord("u_cmdb_infoblox");
var query = "u_last_discoveredRELATIVELT@dayofweek@ago@" + days + "^u_status=1";
ibGr.addEncodedQuery(query);
ibGr.query();
while(ibGr.next()){
ibGr.u_status = 4;
ibGr.update();
}
},
type: 'InfobloxImport'
};
- Create Business rules:
- Manage update or insert
- Classify network ranges as weekly, daily, or to ignore
- Call Discovery Schedule Manager Script Include to manage the auto creation of discovery schedules
(function executeRule(current, previous /*null when async*/ ) {
var discoScheduleMgmt = new discoveryScheduleManager;
var dailyNetworks = gs.getProperty('discovery.infoblox.daily_networks');
var weeklyNetworks = gs.getProperty('discovery.infoblox.weekly_networks');
var dailyZones = gs.getProperty('discovery.infoblox.daily_zones');
var weeklyZones = gs.getProperty('discovery.infoblox.weekly_zones');
var runType = "";
var networkIp = current.u_network_ip;
var netmask = current.u_network_mask;
var networkType = current.u_network_type.toLowerCase();
var zone = current.u_dmz_type.toLowerCase();
var isDailyNetwork = (dailyNetworks.indexOf(networkType) > -1);
var isDailyZone = (dailyZones.indexOf(zone) > -1);
var isWeeklyNetwork = (weeklyNetworks.indexOf(networkType) > -1);
var isWeeklyZone = (weeklyZones.indexOf(zone) > -1);
if (isWeeklyNetwork && isWeeklyZone) {
runType = 2; //"Weekly"
} else if (isDailyNetwork && isDailyZone) {
runType = 1; //"Daily"
}
if (current.operation == 'delete') {
discoScheduleMgmt.removeSchedule(networkIp, netmask, networkType);
} else if (current.operation() == "update" && current.u_cmdb_discovery.changes() || current.u_status.changes() && current.u_discovery_schedule && !current.u_network_type.changes() && !current.u_dmz_type.changes()) {
if (current.u_status.changes()) {
if (current.u_status.changesFrom(1)) {
current.u_cmdb_discovery = "false";
//udpate disco schedule record
var dschd = new GlideRecord("discovery_schedule");
dschd.get(current.u_discovery_schedule.sys_id);
dschd.active = "false";
dschd.update();
} else if (current.u_status.changesTo(1)) {
current.u_cmdb_discovery = "true";
//udpate disco schedule record
var dschd = new GlideRecord("discovery_schedule");
dschd.get(current.u_discovery_schedule.sys_id);
dschd.active = "true";
dschd.update();
}
} else if (current.u_cmdb_discovery.changes()) {
if (current.u_cmdb_discovery.changesTo("true")) {
//udpate disco schedule record
var dschd = new GlideRecord("discovery_schedule");
dschd.get(current.u_discovery_schedule.sys_id);
dschd.active = "true";
dschd.update();
current.u_status = 1;
} else if (current.u_cmdb_discovery.changesTo("false")) {
//udpate disco schedule record
var dschd = new GlideRecord("discovery_schedule");
dschd.get(current.u_discovery_schedule.sys_id);
dschd.active = "false";
dschd.update();
//set current status
current.u_status = 2;
}
}
} else if ((runType == 1 || runType == 2) && (current.operation() == "insert" || current.operation() == "update")) {
//Create new schedule
var discoScheduleSysId = discoScheduleMgmt.discoScheduleCreator(networkIp, netmask, runType, networkType, zone);
current.u_discovery_schedule = discoScheduleSysId;
//udpate disco schedule record
var dschd = new GlideRecord("discovery_schedule");
dschd.get(current.u_discovery_schedule.sys_id);
dschd.active = "true";
dschd.update();
current.u_discovery_time_setup = runType;
current.u_status = 1;
current.u_cmdb_discovery = "true";
} else if ((runType != 1 && runType != 2) && (current.operation() == "insert" || current.operation() == "update")) {
var dschd = new GlideRecord("discovery_schedule");
dschd.addQuery("sys_id", current.u_discovery_schedule.sys_id);
dschd.query();
if (dschd.next()) {
dschd.active = "false";
dschd.update();
}
current.u_status = 2; //removed from discovery
current.u_cmdb_discovery = "false";
current.u_discovery_time_setup = 3;
} else if ((runType == 1 || runType == 2) && current.operation() == "update" && (current.u_dmz_type.changes() || current.u_network_type.changes())) {
//move schedule
var previousRunTime = previous.u_discovery_time_setup;
if (previousRunTime != runType) {
if (previousRunTime == 1 && runType == 2) {
var discoScheduleSysId = discoScheduleMgmt.moveToWeekend(current.u_discovery_schedule.sys_id);
} else if (previousRunTime == 2 && runType == 1) {
var discoScheduleSysId = discoScheduleMgmt.moveToDaily(current.u_discovery_schedule.sys_id);
}
//Link Infoblox record to discovery schedule
if (discoScheduleSysId) {
current.u_discovery_schedule = discoScheduleSysId;
current.u_status = 1;
current.u_cmdb_discovery = "true";
current.u_discovery_time_setup = runType;
var rightnow = new GlideDateTime();
current.u_last_discovered = rightnow;
}
}
} else if (current.operation() == "update" && current.u_active_ip_count.changes() && current.u_network_type == "data_center" || current.u_network_type == "infrastructure_management" || current.u_network_type == "network_infrastructure") { //Move disco schedule between daily or weekly depending on if there was IPs active
//Future code for swinging schedules between daily and weekly based on discovered ip count
// if (current.u_active_ip_count.changesTo(0)) {
// discoScheduleMgmt.moveToWeekend(current.u_discovery_schedule.sys_id);
// } else if (current.u_active_ip_count.changesFrom(0)) {
// discoScheduleMgmt.moveToDaily(current.u_discovery_schedule.sys_id);
// }
}
})(current, previous);
** Commented code is not currently running.
- Create Script Include to manage Discovery Schedules
var discoveryScheduleManager = Class.create();
discoveryScheduleManager.prototype = {
initialize: function () {
//Init
},
discoScheduleCreator: function (networkIp, netmask, runType, networkType, zone) {
if (runType == "daily" || runType == "Daily" || runType == 1) {
var schedulesStartTime = new GlideDateTime("1970-01-01 12:00:00");
var schedulesEndTime = new GlideDateTime("1970-01-02 05:59:59");
//Dealing with Glide Time fields in order to pass in a start and end run time made the code hard to follow.
//Using a simple array that maps the valid run hours
//1970-01-01 06:00:00 on schedule record = 00:00:00 run time on form
//1970-01-02 00:00:00 = 18:00:00
//Run times map, initializing to 0 count for discovery schedules count
var runTimes = {
"1970-01-02 00:": 0,
"1970-01-02 01:": 0,
"1970-01-02 02:": 0,
"1970-01-02 03:": 0,
"1970-01-02 04:": 0,
"1970-01-02 05:": 0,
"1970-01-01 06:": 0,
"1970-01-01 07:": 0,
"1970-01-01 08:": 0
};
runType = 'daily';
var runAs = 'sys_id of runas account'; //Replace with your run as account
var runDay = 1;
var maxRun = '0 01:30:00'; //Schedule Max Run Time
var midType = 'specific_cluster';
var InstanceName = "";
var midCluster = 'sys_id of cluster'; //Replace with your discovery cluster
var networkName = networkIp + "/" + netmask;
var schdName = networkType + "/" + zone + " - " + networkName;
} else if (runType == "weekly" || runType == "Weekly" || runType == 2) {
var schedulesStartTime = new GlideDateTime("1970-01-01 09:00:00");
var schedulesEndTime = new GlideDateTime("1970-01-02 00:00:00");
var runTimes = {
"1970-01-01 09:": 0,
"1970-01-01 10:": 0,
"1970-01-01 11:": 0,
"1970-01-01 12:": 0,
"1970-01-01 13:": 0,
"1970-01-01 14:": 0,
"1970-01-01 15:": 0,
"1970-01-01 16:": 0,
"1970-01-01 17:": 0,
"1970-01-01 18:": 0,
"1970-01-01 19:": 0,
"1970-01-01 20:": 0,
"1970-01-01 21:": 0,
"1970-01-01 22:": 0,
"1970-01-01 23:": 0,
"1970-01-02 00:": 0
};
runType = 'weekly';
var runDay = "0";
var runAs = 'sys_id of runas account'; //Replace with sysid of runas account
var maxRun = '0 01:30:00'; //Schedule Max Run Time
var midType = 'specific_cluster';
var midCluster = 'sys_id of cluster'; //Replace with your discovery cluster
var networkName = networkIp + "/" + netmask;
var schdName = networkType + "/" + zone + " - " + networkName;
} else {
return;
}
var grDiscSchedule_gr = this.createNewSchedule(runTimes, networkName, networkIp, netmask, runAs, runDay, midType, midCluster, runType, maxRun, schdName);
return grDiscSchedule_gr;
},
createNewSchedule: function (runTimes, networkName, networkIp, netmask, runAs, runDay, midType, midCluster, runType, maxRun, schdName) {
var grDiscRangeItemSysId = this.createRangeItem(networkIp, netmask, networkName);
//Create Range Set
var grDiscRangeSetSysId = this.createRangeSet(networkName);
//Set assoc between range and range set
var grDiscRange = new GlideRecord('discovery_range_item');
grDiscRange.get(grDiscRangeItemSysId);
grDiscRange.parent = grDiscRangeSetSysId;
grDiscRange.setWorkflow('false');
grDiscRange.update();
if (runType == "weekly") {
runDay = this.findLeastBusyWeekendDay();
}
var leastBusyHour = this.findLeastBusyHour(runTimes, runType, runDay);
var leastBusyMin = this.findLeastBusyMin(leastBusyHour, runType, runDay);
var scheduleRunTime = leastBusyHour + leastBusyMin + ":00";
var discSched_gr = this.createSchedule(networkName, runDay, runType, scheduleRunTime, runAs, maxRun, midCluster, midType, schdName);
//Associate Range to Schedule
var DiscSchedRange = new GlideRecord('discovery_schedule_range');
DiscSchedRange.addQuery("dscheduler", discSched_gr);
DiscSchedRange.addQuery("range", grDiscRangeSetSysId);
DiscSchedRange.query();
if (DiscSchedRange.next()) {
//Discovery schedule range to schedule already exists
return discSched_gr;
} else {
DiscSchedRange.init();
DiscSchedRange.range = grDiscRangeSetSysId;
DiscSchedRange.dscheduler = discSched_gr;
DiscSchedRange.insert();
//Return our disco schedule sys_id to associate back to infoblox table
return discSched_gr;
}
},
createRangeItem: function (networkIp, netmask, networkName) {
var grDiscRangeItem = new GlideRecord('discovery_range_item');
grDiscRangeItem.addQuery('network_ip', networkIp);
grDiscRangeItem.query();
if (grDiscRangeItem.next()) {
var grDiscRangeItemSysId = grDiscRangeItem.sys_id;
//Discovery Range Item already exists
return grDiscRangeItemSysId;
} else {
grDiscRangeItem.init();
grDiscRangeItem.name = networkName;
grDiscRangeItem.summary = networkName;
grDiscRangeItem.network_ip = networkIp;
grDiscRangeItem.netmask = netmask;
grDiscRangeItem.type = 'IP Network';
var grDiscRangeItemSysId = grDiscRangeItem.insert();
return grDiscRangeItemSysId;
}
},
createRangeSet: function (networkName) {
//Create Range Set
var grDiscRangeSet = new GlideRecord('discovery_range');
grDiscRangeSet.addQuery('name', networkName);
grDiscRangeSet.query();
if (grDiscRangeSet.next()) {
var grDiscRangeSetSysId = grDiscRangeSet.sys_id;
//Discovery Range Set already exists
return grDiscRangeSetSysId;
} else {
grDiscRangeSet.init();
grDiscRangeSet.name = networkName;
var grDiscRangeSetSysId = grDiscRangeSet.insert();
return grDiscRangeSetSysId;
}
},
createSchedule: function (networkName, runDay, runType, scheduleRunTime, runAs, maxRun, midCluster, midType, schdName) {
var grDiscSchedule = new GlideRecord('discovery_schedule');
grDiscSchedule.addQuery('name', schdName);
grDiscSchedule.query();
if (grDiscSchedule.next()) {
grDiscSchedule.active = 'true';
grDiscSchedule.update();
return grDiscSchedule.sys_id;
} else {
grDiscSchedule.init();
grDiscSchedule.name = schdName;
grDiscSchedule.discover = 'CIs';
grDiscSchedule.disco_run_type = runType;
grDiscSchedule.active = 'true';
grDiscSchedule.run_type = runType;
grDiscSchedule.run_as = runAs;
grDiscSchedule.max_run.setDisplayValue(maxRun);
grDiscSchedule.setValue("run_time", scheduleRunTime);
grDiscSchedule.mid_cluster = midCluster;
grDiscSchedule.mid_select_method = midType;
grDiscSchedule.run_dayofmonth = 1;
grDiscSchedule.run_dayofweek = runDay;
grDiscSchedule_gr = grDiscSchedule.insert();
return grDiscSchedule_gr;
}
},
findLeastBusyWeekendDay: function () {
var startDay = 6;
var endDay = 7;
var runType = "weekly";
var discoScheduleArray = [{
"hour": "",
"count": ""
}];
var discoScheduleMap = {};
//Pad out the array so it contains all days
for (var i = startDay; i <= endDay; ++i) {
discoScheduleMap[i] = 0;
}
var grDiscoSchedules = new GlideRecord('discovery_schedule');
grDiscoSchedules.addEncodedQuery("run_dayofweek=6^ORrun_dayofweek=7");
grDiscoSchedules.addQuery("run_type", runType);
grDiscoSchedules.query();
while (grDiscoSchedules.next()) {
var runday = grDiscoSchedules.run_dayofweek;
if (runday in discoScheduleMap) {
discoScheduleMap[runday] = discoScheduleMap[runday] + 1;
} else {
discoScheduleMap[runday] = 1;
}
}
//Find the least busy hour in our window by count of schedules in that hour
var keys = Object.keys(discoScheduleMap);
// Iterate through all the key values
var minimumKey = keys[0];
for (var i = 1; i < keys.length; i++) {
var minimum = discoScheduleMap[minimumKey];
var value = discoScheduleMap[keys[i]];
if (minimum > value) minimumKey = keys[i];
}
return minimumKey;
},
findLeastBusyHour: function (runTimes, runType, runDay) {
//Build our query string from our map of run times
var queryString = "run_type=" + runType + "^run_dayofweek=" + runDay + "^run_timeSTARTSWITH";
Object.keys(runTimes).forEach(function (key) {
queryString = queryString + key + "^ORrun_timeSTARTSWITH";
});
var grDiscoSchedules = new GlideRecord('discovery_schedule');
grDiscoSchedules.addEncodedQuery(queryString);
grDiscoSchedules.query();
while (grDiscoSchedules.next()) {
var runhour = grDiscoSchedules.run_time.substring(0, grDiscoSchedules.run_time.getValue().length - 5);
if (runTimes.hasOwnProperty(runhour)) {
runTimes[runhour] = runTimes[runhour] + 1;
} else {
runTimes[runhour] = 0;
}
}
//Find the least busy hour in our window by count of schedules in that hour
var keys = Object.keys(runTimes);
var minimumKey = keys[0];
for (var i = 1; i < keys.length; i++) {
var minimum = runTimes[minimumKey];
var value = runTimes[keys[i]];
if (minimum > value) minimumKey = keys[i];
}
return minimumKey;
},
findLeastBusyMin: function (leastBusyHour, runType, runDay) {
var discoScheduleArray = [{
"min": "",
"count": ""
}];
var discoScheduleMap = {};
//Pad out the array so it contains all minutes instead of just what's in the schedules
for (var i = 0; i <= 59; ++i) {
minuteIndex = zeroPad(i, 2);
discoScheduleMap[minuteIndex] = 0;
}
function zeroPad(num, places) {
var zero = places - num.toString().length + 1;
return Array(+(zero > 0 && zero)).join("0") + num;
}
var grDiscoSchedules = new GlideRecord('discovery_schedule');
grDiscoSchedules.addQuery("run_time", "STARTSWITH", leastBusyHour);
grDiscoSchedules.addQuery("run_type", runType);
grDiscoSchedules.addQuery("run_dayofweek", runDay);
grDiscoSchedules.query();
while (grDiscoSchedules.next()) {
var runMin = grDiscoSchedules.run_time.substring(grDiscoSchedules.run_time.getByFormat("yyyy-MM-dd HH:mm:ss").length - 5, grDiscoSchedules.run_time.getByFormat("yyyy-MM-dd HH:mm:ss").length - 3);
if (runMin in discoScheduleMap) {
discoScheduleMap[runMin] = discoScheduleMap[runMin] + 1;
} else {
discoScheduleMap[runMin] = 1;
}
}
//Find the least busy hour in our window by count of schedules in that hour
var keys = Object.keys(discoScheduleMap);
var minimumKey = keys[0];
for (var i = 1; i < keys.length; i++) {
var minimum = discoScheduleMap[minimumKey];
var value = discoScheduleMap[keys[i]];
if (minimum > value) minimumKey = keys[i];
}
return minimumKey;
},
moveToWeekend: function (dSchd) {
//Move discovery schedule to the weekend
var runTimes = {
"1970-01-01 09:": 0,
"1970-01-01 10:": 0,
"1970-01-01 11:": 0,
"1970-01-01 12:": 0,
"1970-01-01 13:": 0,
"1970-01-01 14:": 0,
"1970-01-01 15:": 0,
"1970-01-01 16:": 0,
"1970-01-01 17:": 0,
"1970-01-01 18:": 0,
"1970-01-01 19:": 0,
"1970-01-01 20:": 0,
"1970-01-01 21:": 0,
"1970-01-01 22:": 0,
"1970-01-01 23:": 0,
"1970-01-02 00:": 0
};
var runType = "weekly";
var discoSchd = new GlideRecord('discovery_schedule');
discoSchd.get(dSchd);
var runDay = this.findLeastBusyWeekendDay();
var leastBusyHour = this.findLeastBusyHour(runTimes, runType, runDay);
var leastBusyMin = this.findLeastBusyMin(leastBusyHour, runType, runDay);
var scheduleRunTime = leastBusyHour + leastBusyMin + ":00";
discoSchd.setValue("run_time", scheduleRunTime);
discoSchd.disco_run_type = "weekly";
discoSchd.run_type = "weekly";
discoSchd.run_dayofweek = runDay;
discoSchd.active = 'true';
discoSchd.update();
return discoSchd.sys_id;
},
moveToDaily: function (dSchd) {
//Move discovery schedule to daily
var runTimes = {
"1970-01-02 00:": 0,
"1970-01-02 01:": 0,
"1970-01-02 02:": 0,
"1970-01-02 03:": 0,
"1970-01-02 04:": 0,
"1970-01-02 05:": 0,
"1970-01-01 06:": 0,
"1970-01-01 07:": 0,
"1970-01-01 08:": 0
};
var runType = 'daily';
var runDay = 1;
var discoSchd = new GlideRecord('discovery_schedule');
discoSchd.get(dSchd);
var leastBusyHour = this.findLeastBusyHour(runTimes, runType, runDay);
var leastBusyMin = this.findLeastBusyMin(leastBusyHour, runType, runDay);
var scheduleRunTime = leastBusyHour + leastBusyMin + ":00";
discoSchd.setValue("run_time", scheduleRunTime);
discoSchd.disco_run_type = runType;
discoSchd.run_dayofweek = runDay;
discoSchd.active = 'true';
discoSchd.update();
return discoSchd.sys_id;
},
removeSchedule: function (networkIp, netmask) {
var networkName = networkIp + "/" + netmask;
var grDiscSchedule = new GlideRecord('discovery_schedule');
grDiscSchedule.addQuery('name', networkName);
grDiscSchedule.query();
if (grDiscSchedule.next()) {
grDiscSchedule.active = 'false';
}
return;
},
buildAll: function () {
var infobloxNetworks = new GlideRecord('u_cmdb_infoblox');
infobloxNetworks.addQuery('u_cmdb_discovery', true);
infobloxNetworks.query();
while (infobloxNetworks.next()) {
var networkType = infobloxNetworks.u_network_type;
var networkIp = infobloxNetworks.u_network_ip;
var netmask = infobloxNetworks.u_network_mask;
var u_discovery_time_setup = infobloxNetworks.u_discovery_time_setup;
var discoScheduleSysId = this.discoScheduleCreator(networkIp, netmask, networkType, u_discovery_time_setup);
if (discoScheduleSysId) {
infobloxNetworks.u_discovery_schedule = discoScheduleSysId;
infobloxNetworks.u_mapped_to_discovery_schedule = 'true';
infobloxNetworks.update();
}
}
return;
},
type: 'discoveryScheduleManager'
};
Step 3 – Configuration management
- Adopt QuickNexus "Discovery Admin" tooling
- Configure auto-assignment for incidents related to errors
- Create KPIs to calculate discovery health
- Manage errors from Discovery Admin
- Labels:
-
Discovery
- 3,105 Views
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-24-2023 08:02 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-24-2023 01:55 PM
Thank you, @AJ-TechTrek !
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-14-2023 03:58 AM
How to configure Discovery process for data received through Service Graph connector for Infoblox