Providers/Modules/NPM/Plugin/plugin/npmd_config_lib.rb (1,031 lines of code) (raw):
class Logger
require 'thread'
LOG_DEPTH_INC_RESC = 1 # Depth increase of method scope for rescue
LOG_DEPTH_INC_LOOP = 2 # Depth increase of method scope for loop
def self.log_error(msg, depth=0)
_methodname = getMethodname(depth)
_message = "[#{_methodname}]:#{msg}"
$log.error "[NPMD]:#{_message}"
end
def self.log_info(msg, depth=0)
_methodname = getMethodname(depth)
$log.info "[NPMD]:[#{_methodname}]:#{msg}"
end
def self.log_warn(msg, depth=0)
_methodname = getMethodname(depth)
$log.warn "[NPMD]:[#{_methodname}]:#{msg}"
end
class << self
alias_method :logError, :log_error
alias_method :logInfo, :log_info
alias_method :logWarn, :log_warn
end
private
def self.getMethodname(depth)
_depth = depth > 0 ? depth : 0
begin
caller_locations(2 + _depth, 1)[0].label
rescue
caller_locations(2 + LOG_DEPTH_INC_RESC, 1)[0].label
end
end
def self.loop
LOG_DEPTH_INC_LOOP
end
def self.resc
LOG_DEPTH_INC_RESC
end
end
# Module to parse config received from DSC and generate Agent Configuration
module NPMDConfig
require 'rexml/document'
require 'json'
require 'ipaddr'
require 'socket'
# Need to have method to get the subnetmask
class ::IPAddr
def getNetMaskString
_to_string(@mask_addr)
end
end
# This class holds the methods for creating
# a config understood by NPMD Agent from a hash
class AgentConfigCreator
public
# Variables for tracking errors
@@agent_ip_drops = 0
@@agent_drops = 0
@@network_subnet_drops = 0
@@network_drops = 0
@@rule_subnetpair_drops = 0
@@rule_drops = 0
# Strings utilized in drop summary
DROP_IPS = "Agent IPs"
DROP_AGENTS = "Agents"
DROP_SUBNETS = "Network subnets"
DROP_NETWORKS = "Networks"
DROP_SUBNETPAIRS= "Rule subnetpairs"
DROP_RULES = "Rules"
# Reset error checking
def self.resetErrorCheck
@@agent_ip_drops = 0
@@agent_drops = 0
@@network_subnet_drops = 0
@@network_drops = 0
@@rule_subnetpair_drops = 0
@@rule_drops = 0
end
# Generating the error string
def self.getErrorSummary
_agentIpDrops=""
_agentDrops=""
_networkSNDrops=""
_networkDrops=""
_ruleSNPairDrops=""
_ruleDrops=""
if @@agent_ip_drops != 0
_agentIpDrops = "#{DROP_IPS}=#{@@agent_ip_drops}"
end
if @@agent_drops != 0
_agentDrops= "#{DROP_AGENTS}=#{@@agent_drops}"
end
if @@network_subnet_drops != 0
_networkSNDrops = "#{DROP_SUBNETS}=#{@@network_subnet_drops}"
end
if @@network_drops != 0
_networkDrops = "#{DROP_NETWORKS}=#{@@network_drops}"
end
if @@rule_subnetpair_drops != 0
_ruleSNPairDrops = "#{DROP_SUBNETPAIRS}=#{@@rule_subnetpair_drops}"
end
if @@rule_drops != 0
_ruleDrops = "#{DROP_RULES}=#{@@rule_drops}"
end
_str = _agentIpDrops + " " + _agentDrops + " " +
_networkSNDrops + " " + _networkDrops + " " +
_ruleSNPairDrops + " " + _ruleDrops
end
# Only accessible method
def self.createJsonFromUIConfigHash(configHash)
begin
if configHash == nil
Logger::logError "Config received is NIL"
return nil
end
_subnetInfo = getProcessedSubnetHash(configHash["Subnets"])
_doc = {"Configuration" => {}}
_doc["Configuration"] ["Metadata"] = createMetadataElements(configHash["Metadata"])
_doc["Configuration"] ["Agents"] = createAgentElements(configHash["Agents"], _subnetInfo["Masks"])
_doc["Configuration"] ["Networks"] = createNetworkElements(configHash["Networks"], _subnetInfo["IDs"])
_doc["Configuration"] ["Rules"] = createRuleElements(configHash["Rules"], _subnetInfo["IDs"]) unless !configHash.has_key?("Rules")
_doc["Configuration"] ["Epm"] = createEpmElements(configHash["Epm"]) unless !configHash.has_key?("Epm")
_doc["Configuration"] ["ConnectionMonitorConfiguration"] = configHash["ConnectionMonitorConfiguration"] unless !configHash.has_key?("ConnectionMonitorConfiguration")
_doc["Configuration"] ["ER"] = createERElements(configHash["ER"]) unless !configHash.has_key?("ER")
_configJson = _doc.to_json
_configJson
rescue StandardError => e
Logger::logError "Got error creating JSON from UI Hash: #{e}", Logger::resc
raise "Got error creating AgentJson: #{e}"
end
end
private
def self.getNetMask(ipaddrObj)
_tempIp = IPAddr.new(ipaddrObj.getNetMaskString)
_tempIp.to_s
end
def self.getProcessedSubnetHash(subnetHash)
_h = Hash.new
_h["Masks"] = Hash.new
_h["IDs"] = Hash.new
begin
subnetHash.each do |key, value|
_tempIp = IPAddr.new(value)
_h["Masks"][key] = getNetMask(_tempIp)
_h["IDs"][key] = value
end
_h
rescue StandardError => e
Logger::logError "Got error while creating subnet hash: #{e}", Logger::resc
nil
end
end
def self.createMetadataElements(metadataHash)
_metadata = Hash.new
_metadata["Version"] = metadataHash.has_key?("Version") ? metadataHash["Version"] : String.new
_metadata["Protocol"] = metadataHash.has_key?("Protocol") ? metadataHash["Protocol"] : String.new
_metadata["SubnetUid"] = metadataHash.has_key?("SubnetUid") ? metadataHash["SubnetUid"] : String.new
_metadata["AgentUid"] = metadataHash.has_key?("AgentUid") ? metadataHash["AgentUid"] : String.new
_metadata[:"WorkspaceResourceId"] = metadataHash["WorkspaceResourceID"] if metadataHash.has_key?("WorkspaceResourceID")
_metadata[:"WorkspaceId"] = metadataHash["WorkspaceID"] if metadataHash.has_key?("WorkspaceID")
_metadata[:"LastUpdated"] = metadataHash["LastUpdated"] if metadataHash.has_key?("LastUpdated")
return _metadata
end
def self.createAgentElements(agentArray, maskHash)
_agents = Array.new
agentArray.each do |x|
_agent = Hash.new
_agent["Name"] = x["Guid"];
_agent["Capabilities"] = x["Capability"].to_s;
_agent["ResourceId"] = x["ResourceId"].to_s;
_agent["IPConfiguration"] = [];
x["IPs"].each do |ip|
_ipConfig = Hash.new
_ipConfig["IP"] = ip["IP"];
_subnetMask = maskHash[ip["SubnetName"]];
if _subnetMask.nil?
Logger::logWarn "Did not find subnet mask for subnet name #{ip["SubnetName"]} in hash", 2*Logger::loop
@@agent_ip_drops += 1
else
_ipConfig["Mask"] = maskHash[ip["SubnetName"]];
end
_agent["IPConfiguration"].push(_ipConfig);
end
_agents.push(_agent);
if _agents.empty?
@@agent_drops += 1
end
end
_agents
end
def self.createNetworkElements(networkArray, subnetIdHash)
_networks = Array.new
networkArray.each do |x|
_network = Hash.new
_network["Name"] = x["Name"];
_network["Subnet"] = Array.new
x["Subnets"].each do |sn|
_subnet = Hash.new
_subnetId = subnetIdHash[sn]
if _subnetId.nil?
Logger::logWarn "Did not find subnet id for subnet name #{sn} in hash", 2*Logger::loop
@@network_subnet_drops += 1
else
_subnet["ID"] = subnetIdHash[sn];
_subnet["Disabled"] = "False" # TODO
_subnet["Tag"] = "" # TODO
end
_network["Subnet"].push(_subnet);
end
_networks.push(_network);
if _networks.empty?
@@network_drops += 1
end
end
_networks
end
def self.createActOnElements(elemArray, subnetIdHash)
_networkTestMatrix = Array.new
elemArray.each do |a|
_sSubnetId = "*"
_dSubnetId = "*"
if a["SS"] != "*" and a["SS"] != ""
_sSubnetId = subnetIdHash[a["SS"].to_s]
end
if a["DS"] != "*" and a["DS"] != ""
_dSubnetId = subnetIdHash[a["DS"].to_s]
end
if _sSubnetId.nil?
Logger::logWarn "Did not find subnet id for source subnet name #{a["SS"].to_s} in hash", 2*Logger::loop
@@rule_subnetpair_drops += 1
elsif _dSubnetId.nil?
Logger::logWarn "Did not find subnet id for destination subnet name #{a["DS"].to_s} in hash", 2*Logger::loop
@@rule_subnetpair_drops += 1
else
# Process each subnetpair
_snPair = Hash.new
_snPair["SourceSubnet"] = _sSubnetId
_snPair["SourceNetwork"] = a["SN"]
_snPair["DestSubnet"] = _dSubnetId
_snPair["DestNetwork"] = a["DN"]
_networkTestMatrix.push(_snPair);
end
end
_networkTestMatrix
end
def self.createRuleElements(ruleArray, subnetIdHash)
_rules = Array.new
ruleArray.each do |x|
_rule = Hash.new
_rule["Name"] = x["Name"];
_rule["Description"] = x["Description"]
_rule["Protocol"] = x["Protocol"].to_s;
_rule["NetworkTestMatrix"] = createActOnElements(x["Rules"], subnetIdHash);
_rule["AlertConfiguration"] = Hash.new;
_rule["Exceptions"] = createActOnElements(x["Exceptions"], subnetIdHash);
_rule["DiscoverPaths"] = x["DiscoverPaths"].to_s
_rule["Port"] = x["Port"].to_s
_rule["ListenOnPort"] = x["ListenOnPort"]
_rule["BiDirectional"] = x["BiDirectional"]
_rule["TestFrequencyInSec"] = x["Frequency"]
_rule["CMResourceId"] = x.has_key?("CMResourceId") ? x["CMResourceId"] : String.new
_rule["IngestionWorkspaceId"] = x.has_key?("IngestionWorkspaceId") ? x["IngestionWorkspaceId"] : String.new
_rule["WorkspaceAlias"] = x.has_key?("WorkspaceAlias") ? x["WorkspaceAlias"] : String.new
_rule["WorkspaceResourceId"] = x["WorkspaceResourceId"]
if _rule["NetworkTestMatrix"].empty?
Logger::logWarn "Skipping rule #{x["Name"]} as network test matrix is empty", Logger::loop
@@rule_drops += 1
else
# Alert Configuration
_rule["AlertConfiguration"]["ChecksFailedPercent"] = x["LossThreshold"].to_s
_rule["AlertConfiguration"]["RoundTripTimeMs"] = x["LatencyThreshold"].to_s
end
if !_rule.empty?
_rules.push(_rule)
end
end
_rules
end
def self.createEpmElements(epmHash)
return if epmHash.nil?
_epmRules = Hash.new
_rule = Array.new
epmHash.each do |key, rules|
for i in 0..rules.length-1
_ruleHash = Hash.new
_iRule = rules[i] # get individual rule
_ruleHash["ID"] = _iRule["ID"]
_ruleHash["Name"] = _iRule["Name"]
_ruleHash["CMResourceId"] = _iRule.has_key?("CMResourceId") ? _iRule["CMResourceId"] : String.new
_ruleHash["IngestionWorkspaceId"] = _iRule.has_key?("IngestionWorkspaceId") ? _iRule["IngestionWorkspaceId"] : String.new
_ruleHash["WorkspaceAlias"] = _iRule.has_key?("WorkspaceAlias") ? _iRule["WorkspaceAlias"] : String.new
_ruleHash["Redirect"] = "false"
_ruleHash["WorkspaceResourceId"] = _iRule["WorkspaceResourceId"]
_ruleHash["DiscoverPaths"] = _iRule.has_key?("DiscoverPaths") ? _iRule["DiscoverPaths"].to_s : "true"
_ruleHash["NetTests"] = (_iRule["NetworkThresholdLoss"].to_i >= -2 and _iRule["NetworkThresholdLatency"].to_i >= -2) ? "true" : "false"
_ruleHash["AppTests"] = (_iRule["AppThresholdLatency"].to_i >= -2) ? "true" : "false"
_ruleHash["ValidStatusCodeRanges"] = _iRule.has_key?("ValidStatusCodeRanges") ? _iRule["ValidStatusCodeRanges"] : nil;
_ruleHash["SourceAgentIds"] = _iRule["SourceAgentIds"]
if (_ruleHash["NetTests"] == "true")
_ruleHash["NetworkThreshold"] = {"ChecksFailedPercent" => _iRule["NetworkThresholdLoss"].to_s, "RoundTripTimeMs" => _iRule["NetworkThresholdLatency"].to_s}
end
if (_ruleHash["AppTests"] == "true")
_ruleHash["AppThreshold"] = {"ChecksFailedPercent" => (_iRule.has_key?("AppThresholdLoss") ? _iRule["AppThresholdLoss"].to_s : nil), "RoundTripTimeMs" => _iRule["AppThresholdLatency"].to_s}
end
# Fill endpoints
_epList = _iRule["Endpoints"]
_endpointList = Array.new
for j in 0.._epList.length-1
_epHash = Hash.new
_epHash["Name"] = _epList[j]["Name"]
_epHash["ID"] = _epList[j]["Id"]
_epHash["DestAddress"] = _epList[j]["URL"]
_epHash["DestPort"] = _epList[j]["Port"].to_s
_epHash["TestProtocol"] = _epList[j]["Protocol"]
_epHash["MonitoringInterval"] = _iRule["Poll"].to_s
_epHash["TimeDrift"] = _epList[j]["TimeDrift"].to_s
_epHash["Type"] = _epList[j]["Type"].to_s
_epHash["ListenOnPort"] = _epList[j]["ListenOnPort"]
_endpointList.push(_epHash)
end
_ruleHash["Endpoints"] = _endpointList
_rule.push(_ruleHash)
end
end
_epmRules["Rules"] = _rule
_epmRules
end
def self.createERElements(erHash)
return if erHash.nil?
_er = Hash.new
erHash.each do |key, rules|
# Fill Private Peering Rules
if key == "PrivatePeeringRules"
_ruleList = Array.new
for i in 0..rules.length-1
_pvtRule = Hash.new
_iRule = rules[i]
_pvtRule["Name"] = _iRule["Name"]
_pvtRule["ConnectionResourceId"] = _iRule["ConnectionResourceId"]
_pvtRule["CircuitResourceId"] = _iRule["CircuitResourceId"]
_pvtRule["CircuitName"] = _iRule["CircuitName"]
_pvtRule["VirtualNetworkName"] = _iRule["vNetName"]
_pvtRule["Protocol"] = _iRule["Protocol"].to_s
#Thresholds
_thresholdMap = Hash.new
_thresholdMap["ChecksFailedPercent"] = _iRule["LossThreshold"].to_s
_thresholdMap["RoundTripTimeMs"] = _iRule["LatencyThreshold"].to_s
_pvtRule["AlertConfiguration"] = _thresholdMap
#OnPremAgents
_onPremAgents = Array.new
_onPremAgentList = _iRule["OnPremAgents"]
for j in 0.._onPremAgentList.length-1
_onPremAgents.push(_onPremAgentList[j])
end
_pvtRule["OnPremAgents"] = _onPremAgents
#AzureAgents
_azureAgents = Array.new
_azureAgentsList = _iRule["AzureAgents"]
for k in 0.._azureAgentsList.length-1
_azureAgents.push(_azureAgentsList[k])
end
_pvtRule["AzureAgents"] = _azureAgents
_ruleList.push(_pvtRule)
end
_er[:"PrivateRules"] = _ruleList if !_ruleList.empty?
end
# Fill MS Peering Rules
if key == "MSPeeringRules"
_ruleList = Array.new
for i in 0..rules.length-1
_msRule = Hash.new
_iRule = rules[i]
_msRule["Name"] = _iRule["Name"]
_msRule["CircuitName"] = _iRule["CircuitName"]
_msRule["Protocol"] = _iRule["Protocol"].to_s
_msRule["CircuitResourceId"] = _iRule["CircuitResourceId"]
#Thresholds
_thresholdMap = Hash.new
_thresholdMap["ChecksFailedPercent"] = _iRule["LossThreshold"].to_s
_thresholdMap["RoundTripTimeMs"] = _iRule["LatencyThreshold"].to_s
_msRule["AlertConfiguration"] = _thresholdMap
#OnPremAgents
_onPremAgents = Array.new
_onPremAgentList = _iRule["OnPremAgents"]
for j in 0.._onPremAgentList.length-1
_onPremAgents.push(_onPremAgentList[j])
end
_msRule["OnPremAgents"] = _onPremAgents
#Urls
_urls = Array.new
_urlList = _iRule["UrlList"]
for k in 0.._urlList.length-1
_urlHash = Hash.new
_urlHash["Target"] = _urlList[k]["url"]
_urlHash["Port"] = _urlList[k]["port"].to_s
_urls.push(_urlHash)
end
_msRule["URLs"] = _urls
_ruleList.push(_msRule)
end
_er[:"MSPeeringRules"] = _ruleList if !_ruleList.empty?
end
end
_er
end
end
# This class holds the methods for parsing
# a config sent via DSC into a hash
class UIConfigParser
public
# Only accessible method
def self.parse(string)
begin
_doc = REXML::Document.new(string)
if _doc.elements.empty? or _doc.root.nil?
Logger::logWarn "UI config string converted to nil/empty rexml doc"
return nil
end
_configVersion = _doc.elements[RootConfigTag].attributes[Version].to_i
unless _configVersion == 3
Logger::logWarn "Config version #{_configVersion} is not supported"
return nil
else
Logger::logInfo "Supported version of config #{_configVersion} found"
end
_config = _doc.elements[RootConfigTag + "/" + SolnConfigV3Tag]
if _config.nil? or _config.elements.empty?
Logger::logWarn "found nothing for path #{RootConfigTag}/#{SolnConfigV3Tag} in config string"
return nil
end
@agentData = JSON.parse(_config.elements[AgentInfoTag].text())
@metadata = JSON.parse(_config.elements[MetadataTag].text())
_h = Hash.new
_h[KeyMetadata] = @metadata
_h[KeyNetworks] = getNetworkHashFromJson(_config.elements[NetworkInfoTag].text())
_h[KeySubnets] = getSubnetHashFromJson(_config.elements[SubnetInfoTag].text())
_h[KeyAgents] = getAgentHashFromJson(_config.elements[AgentInfoTag].text())
_h[KeyRules] = getRuleHashFromJson(_config.elements[RuleInfoTag].text()) unless _config.elements[RuleInfoTag].nil?
_h[KeyEpm] = getEpmHashFromJson(_config.elements[EpmInfoTag].text()) unless _config.elements[EpmInfoTag].nil?
_h[KeyCM] = getCMHashFromJson(_config.elements[EpmInfoTag].text()) unless _config.elements[EpmInfoTag].nil?
_h[KeyER] = getERHashFromJson(_config.elements[ERInfoTag].text()) unless _config.elements[ERInfoTag].nil?
_h = nil if (_h[KeyNetworks].nil? or _h[KeySubnets].nil? or _h[KeyAgents].nil?)
if _h == nil
Logger::logError "UI Config parsed as nil"
end
return _h
rescue REXML::ParseException => e
Logger::logError "Got XML parse exception at #{e.line()}, #{e.position()}", Logger::resc
raise "Got XML parse exception at #{e.line()}, #{e.position()}"
end
nil
end
private
RootConfigTag = "Configuration"
SolnConfigV3Tag = "NetworkMonitoringAgentConfigurationV3"
MetadataTag = "Metadata"
NetworkInfoTag = "NetworkNameToNetworkMap"
SubnetInfoTag = "SubnetIdToSubnetMap"
AgentInfoTag = "AgentFqdnToAgentMap"
RuleInfoTag = "RuleNameToRuleMap"
EpmInfoTag = "EPMConfiguration"
EpmTestInfoTag = "TestIdToTestMap"
EpmCMInfoTag = "ConnectionMonitorIdToInfoMap"
EpmEndpointInfoTag = "EndpointIdToEndpointMap"
EpmAgentInfoTag = "AgentIdToTestIdsMap"
ERInfoTag = "erConfiguration"
ERPrivatePeeringInfoTag = "erPrivateTestIdToERTestMap";
ERMSPeeringInfoTag = "erMSTestIdToERTestMap";
ERCircuitInfoTag = "erCircuitIdToCircuitResourceIdMap";
Version = "Version"
KeyMetadata = "Metadata"
KeyNetworks = "Networks"
KeySubnets = "Subnets"
KeyAgents = "Agents"
KeyRules = "Rules"
KeyEpm = "Epm"
KeyER = "ER"
KeyCM = "ConnectionMonitorConfiguration"
# Hash of {AgentID => {AgentContract}}
@agentData = {}
# Hash of Metadata
@metadata = {}
def self.getCurrentAgentId()
begin
_agentId = ""
_ips = []
addr_infos = Socket.getifaddrs
addr_infos.each do |addr_info|
if addr_info.addr and (addr_info.addr.ipv4? or addr_info.addr.ipv6?)
_ips.push(addr_info.addr.ip_address)
end
end
@agentData.each do |key, value|
next if value.nil? or !(value["IPs"].is_a?Array)
value["IPs"].each do |ip|
for ipAddr in _ips
if ip["Value"] == ipAddr
_agentId = key
break
end
end
end
end
return _agentId
end
end
def self.getNetworkHashFromJson(text)
begin
_h = JSON.parse(text)
_a = Array.new
_h.each do |key, value|
next if value.nil? or value["Subnets"].nil?
_network = Hash.new
_network["Name"] = key
_network["Subnets"] = value["Subnets"]
_a << _network
end
_a
rescue JSON::ParserError => e
Logger::logError "Error in Json Parse in network data: #{e}", Logger::resc
nil
end
end
def self.getSubnetHashFromJson(text)
begin
_h = JSON.parse(text)
rescue JSON::ParserError => e
Logger::logError "Error in Json Parse in subnet data: #{e}", Logger::resc
nil
end
end
def self.getAgentHashFromJson(text)
begin
_h = JSON.parse(text)
_a = Array.new
_h.each do |key, value|
next if value.nil? or !(value["IPs"].is_a?Array)
_agent = Hash.new
_agent["Guid"] = key
_agent["Capability"] = value["Protocol"] unless value["Protocol"].nil?
_agent["ResourceId"] = value["ResourceId"] unless value["ResourceId"].nil?
_agent["IPs"] = Array.new
value["IPs"].each do |ip|
_tempIp = Hash.new
_tempIp["IP"] = ip["Value"]
# Store agent subnet name as string
_tempIp["SubnetName"] = ip["Subnet"].to_s
_agent["IPs"] << _tempIp
end
_a << _agent
end
_a
rescue JSON::ParserError => e
Logger::logError "Error in Json Parse in agent data: #{e}", Logger::resc
nil
end
end
def self.getRuleHashFromJson(text)
begin
_h = JSON.parse(text)
_a = Array.new
_h.each do |key, value|
next if value.nil? or
!(value["ActOn"].is_a?Array) or
!(value["Exceptions"].is_a?Array)
_rule = Hash.new
_rule["Name"] = key
_rule["LossThreshold"] = (!value["Threshold"].nil? and value["Threshold"].has_key?("Loss")) ? value["Threshold"]["Loss"] : "-2"
_rule["LatencyThreshold"] = (!value["Threshold"].nil? and value["Threshold"].has_key?("Latency")) ? value["Threshold"]["Latency"] : "-2.0"
_rule["Protocol"] = value["Protocol"] unless value["Protocol"].nil?
_rule["Rules"] = value["ActOn"]
_rule["Exceptions"] = value["Exceptions"]
_rule["DiscoverPaths"] = value.has_key?("DiscoverPaths") ? value["DiscoverPaths"].to_s : "true"
_rule["Description"] = value["Description"]
_rule["Enabled"] = value["Enabled"]
_rule["Port"] = value["port"]
_rule["ListenOnPort"] = value["listenOnPort"]
_rule["BiDirectional"] = value["bidirectional"]
_rule["Frequency"] = value["frequency"]
_rule["WorkspaceResourceId"] = @metadata.has_key?("WorkspaceResourceID") ? @metadata["WorkspaceResourceID"] : String.new
_connectionMonitorId = value.has_key?("ConnectionMonitorId") ? value["ConnectionMonitorId"].to_s : String.new
# Iterate over ConnectionMonitorInfoMap to get following info
if !_connectionMonitorId.empty?
_cmMap = _h.has_key?(EpmCMInfoTag) ? _h[EpmCMInfoTag] : Hash.new
if !_cmMap.empty?
_cmId = _cmMap[_connectionMonitorId.to_s]
_rule["CMResourceId"] = _cmId["resourceId"]
_rule["IngestionWorkspaceId"] = _cmId["ingestionWorkspaceId"]
_rule["WorkspaceAlias"] = _cmId["workspaceAlias"]
end
end
_a << _rule
end
_a
rescue JSON::ParserError => e
Logger::logError "Error in Json Parse in rule data: #{e}", Logger::resc
nil
end
end
def self.getCMHashFromJson(text)
begin
_h = JSON.parse(text)
_cmConfiguration = _h[KeyCM]
rescue JSON::ParserError => e
Logger::logError "Error in Json Parse in ConnectionMonitorConfiguration data: #{e}", Logger::resc
nil
end
end
def self.getEpmHashFromJson(text)
begin
_h = JSON.parse(text)
_epmRules = {"Rules" => []}
_testAgentMap = getTestAgents(_h[EpmAgentInfoTag])
_testIds = _h[EpmTestInfoTag]
_testIds.each_key do |testId|
_test = _h[EpmTestInfoTag][testId]
_rule = Hash.new
_rule["ID"] = testId
_rule["Name"] = _test["Name"]
_rule["Poll"] = _test["Poll"]
_rule["WorkspaceResourceId"] = @metadata.has_key?("WorkspaceResourceID") ? @metadata["WorkspaceResourceID"] : String.new
_rule["DiscoverPaths"] = _test.has_key?("DiscoverPaths") ? _test["DiscoverPaths"].to_s : "true"
_rule["AppThresholdLoss"] = _test["AppThreshold"].nil? ? "-3" : (_test["AppThreshold"].has_key?("Loss") ? _test["AppThreshold"]["Loss"] : "-2")
_rule["AppThresholdLatency"] = _test["AppThreshold"].nil? ? "-3.0" : (_test["AppThreshold"].has_key?("Latency") ? _test["AppThreshold"]["Latency"] : "-2.0")
_rule["NetworkThresholdLoss"] = _test["NetworkThreshold"].nil? ? "-3" : (_test["NetworkThreshold"].has_key?("Loss") ? _test["NetworkThreshold"]["Loss"] : "-2")
_rule["NetworkThresholdLatency"] = _test["NetworkThreshold"].nil? ? "-3.0" : (_test["NetworkThreshold"].has_key?("Latency") ? _test["NetworkThreshold"]["Latency"] : "-2.0")
_rule["ValidStatusCodeRanges"] = _test.has_key?("ValidStatusCodeRanges") ? _test["ValidStatusCodeRanges"] : nil
_rule["SourceAgentIds"] = _testAgentMap[testId]
_connectionMonitorId = _test.has_key?("ConnectionMonitorId") ? _test["ConnectionMonitorId"].to_s : String.new
# Iterate over ConnectionMonitorInfoMap to get following info
if !_connectionMonitorId.empty?
_cmMap = _h.has_key?(EpmCMInfoTag) ? _h[EpmCMInfoTag] : Hash.new
if !_cmMap.empty?
_cmId = _cmMap[_connectionMonitorId.to_s]
_rule["CMResourceId"] = _cmId["resourceId"]
_rule["IngestionWorkspaceId"] = _cmId["ingestionWorkspaceId"]
_rule["WorkspaceAlias"] = _cmId["workspaceAlias"]
end
end
# Collect endpoints details
_rule["Endpoints"] = []
# Get the list of endpoint ids
_endpoints = _test["Endpoints"]
_endpoints.each do |ep|
_endpointHash = Hash.new
_endpoint = _h[EpmEndpointInfoTag][ep]
_endpointHash["Id"] = ep
_endpointHash["Name"] = _endpoint.has_key?("name") ? _endpoint["name"] : String.new
_endpointHash["URL"] = _endpoint["url"]
_endpointHash["Port"] = _endpoint["port"]
_endpointHash["Protocol"] = _endpoint["protocol"]
_endpointHash["ListenOnPort"] = _endpoint.has_key?("listenOnPort") ? _endpoint["listenOnPort"] : String.new
_endpointHash["Type"] = _endpoint.has_key?("type") ? _endpoint["type"] : String.new
_endpointHash["TimeDrift"] = getEndpointTimedrift(testId, ep, _test["Poll"], getWorkspaceId()) #TODO
_rule["Endpoints"].push(_endpointHash)
end
_epmRules["Rules"].push(_rule)
end
_epmRules
rescue JSON::ParserError => e
Logger::logError "Error in Json Parse in EPM data: #{e}", Logger::resc
raise "Got exception in EPM parsing: #{e}"
nil
end
end
def self.getTestAgents(agentTestIdMap)
begin
h = agentTestIdMap.each_with_object({}) { |(k,v),g| (v.each{ |item| g.has_key?(item) ? g[item].push(k.to_i) : g[item] ||= [] << k.to_i}) }
return h
end
end
def self.getWorkspaceId()
begin
_workspaceId = @metadata.has_key?("WorkspaceID") ? @metadata["WorkspaceID"] : String.new
return _workspaceId
end
end
def self.getEndpointTimedrift(testId, endpointId, monitoringInterval, workspaceId)
begin
hashString = testId + endpointId + workspaceId
monIntervalInSecs = monitoringInterval * 60
hashCode = getHashCode(hashString)
timeDrift = hashCode % monIntervalInSecs
return timeDrift.to_s
end
end
def self.getHashCode(str)
result = 0
mul = 1
max_mod = 2**31 - 1
str.chars.reverse_each do |c|
result += mul * c.ord
result %= max_mod
mul *= 31
end
result
end
def self.getERHashFromJson(text)
begin
_h = JSON.parse(text)
_agentId = getCurrentAgentId()
if _agentId.empty?
return nil
else
_erRules = {"PrivatePeeringRules" => [], "MSPeeringRules" => []}
# Iterate over OnPrem and Azure Agent Lists to check if this agent is part of this test
_privateTestMap = _h[ERPrivatePeeringInfoTag]
_microsoftTestMap = _h[ERMSPeeringInfoTag]
_circuitIdMap = _h[ERCircuitInfoTag]
if _privateTestMap.empty? && _microsoftTestMap.empty?
Logger::logInfo "ER configuration is not present"
end
# Private Peering Rules
if !_privateTestMap.empty?
_privateTestMap.each do |key, value|
# Get list of onPremAgents in this test
_isAgentPresent = false
_privateRule = Hash.new
_onPremAgents = value["onPremAgents"]
_onPremAgents.each do |x|
if x == _agentId
# Append this test to ER Config
_isAgentPresent = true
_privateRule = getERPrivateRuleFromUIConfig(key, value, _circuitIdMap)
break;
end
end
if !_isAgentPresent
_azureAgents = value["azureAgents"]
_azureAgents.each do |x|
if x == _agentId
_isAgentPresent = true
_privateRule = getERPrivateRuleFromUIConfig(key, value, _circuitIdMap)
break;
end
end
end
if !_privateRule.empty?
_erRules["PrivatePeeringRules"].push(_privateRule)
end
end
end
# MS Peering Rules
if !_microsoftTestMap.empty?
_microsoftTestMap.each do |key, value|
_microsoftRule = Hash.new
_onPremAgents = value["onPremAgents"]
_onPremAgents.each do |x|
if x == _agentId
# Append this test to ER Config
_isAgentPresent = true
_microsoftRule = getERMicrosoftRuleFromUIConfig(key, value, _circuitIdMap)
break;
end
end
if !_microsoftRule.empty?
_erRules["MSPeeringRules"].push(_microsoftRule)
end
end
end
_erRules
end
rescue JSON::ParserError => e
Logger::logError "Error in Json Parse in ER data: #{e}", Logger::resc
nil
end
end
def self.getERPrivateRuleFromUIConfig(key, value, _circuitIdMap)
_ruleHash = Hash.new
_ruleHash["Name"] = key
_ruleHash["Protocol"] = value["protocol"]
_ruleHash["CircuitId"] = value["circuitId"]
_ruleHash["LossThreshold"] = (!value["threshold"].nil? and value["threshold"].has_key?("loss")) ? value["threshold"]["loss"] : "-2"
_ruleHash["LatencyThreshold"] = (!value["threshold"].nil? and value["threshold"].has_key?("latency")) ? value["threshold"]["latency"] : "-2.0"
_ruleHash["CircuitName"] = value["circuitName"]
_ruleHash["vNetName"]= value["vNet"]
_ruleHash["ConnectionResourceId"]= value["connectionResourceId"]
_ruleHash["CircuitResourceId"] = _circuitIdMap[value["circuitId"]]
_ruleHash["OnPremAgents"] = value["onPremAgents"]
_ruleHash["AzureAgents"] = value["azureAgents"]
return _ruleHash
end
def self.getERMicrosoftRuleFromUIConfig(key, value, _circuitIdMap)
_ruleHash = Hash.new
_ruleHash["Name"] = key
_ruleHash["CircuitName"] = value["circuitName"]
_ruleHash["CircuitId"] = value["circuitId"]
_ruleHash["Protocol"] = value["protocol"]
_ruleHash["CircuitResourceId"] = _circuitIdMap[value["circuitId"]]
_ruleHash["LossThreshold"] = (!value["threshold"].nil? and value["threshold"].has_key?("loss")) ? value["threshold"]["loss"] : "-2"
_ruleHash["LatencyThreshold"] = (!value["threshold"].nil? and value["threshold"].has_key?("latency")) ? value["threshold"]["latency"] : "-2.0"
_ruleHash["UrlList"] = value["urlList"]
_ruleHash["OnPremAgents"] = value["onPremAgents"]
return _ruleHash
end
end
# Only function needed to be called from this module
def self.GetAgentConfigFromUIConfig(uiXml)
_uiHash = UIConfigParser.parse(uiXml)
AgentConfigCreator.resetErrorCheck()
_agentJson = AgentConfigCreator.createJsonFromUIConfigHash(_uiHash)
_errorStr = AgentConfigCreator.getErrorSummary()
return _agentJson, _errorStr
end
end
# NPM Contracts verification for data being uploaded
module NPMContract
DATAITEM_AGENT = "agent"
DATAITEM_PATH = "path"
DATAITEM_DIAG = "diagnostics"
DATAITEM_ENDPOINT_HEALTH = "endpointHealth"
DATAITEM_ENDPOINT_MONITORING = "endpointMonitoringData"
DATAITEM_ENDPOINT_DIAGNOSTICS = "endpointDiagnostics"
DATAITEM_EXROUTE_MONITORING = "expressrouteMonitoringData"
DATAITEM_CONNECTIONMONITOR_TEST = "connectionMonitorTestResult"
DATAITEM_CONNECTIONMONITOR_PATH = "connectionMonitorPathData"
DATAITEM_AGENT_DIAGNOSTICS = "agentDiagnostics"
DATAITEM_VALID = 1
DATAITEM_ERR_INVALID_FIELDS = 2
DATAITEM_ERR_INVALID_TYPE = 3
CONTRACT_AGENT_DATA_KEYS = ["AgentFqdn",
"AgentIP",
"AgentCapability",
"SubnetId",
"PrefixLength",
"AddressType",
"SubType",
"TimeGenerated",
"OSType",
"NPMAgentEnvironment"]
CONTRACT_AGENT_DIAGNOSTICS_KEYS = ["SubType",
"TimeGenerated",
"NotificationCode",
"NotificationType",
"Computer"]
CONTRACT_PATH_DATA_KEYS = ["SourceNetwork",
"SourceNetworkNodeInterface",
"SourceSubNetwork",
"DestinationNetwork",
"DestinationNetworkNodeInterface",
"DestinationSubNetwork",
"RuleName",
"TimeSinceActive",
"LossThreshold",
"LatencyThreshold",
"LossThresholdMode",
"LatencyThresholdMode",
"SubType",
"HighLatency",
"MedianLatency",
"LowLatency",
"LatencyHealthState",
"Loss",
"LossHealthState",
"Path",
"Computer",
"TimeGenerated",
"Protocol",
"MinHopLatencyList",
"MaxHopLatencyList",
"AvgHopLatencyList",
"TraceRouteCompletionTime"]
CONTRACT_DIAG_DATA_KEYS = ["SubType",
"Message"]
CONTRACT_ENDPOINT_HEALTH_DATA_KEYS = ["SubType",
"TestName",
"ServiceTestId",
"ConnectionMonitorResourceId",
"Target",
"Port",
"EndpointId",
"Protocol",
"TimeSinceActive",
"ServiceResponseTime",
"ServiceLossPercent",
"ServiceLossHealthState",
"ServiceResponseHealthState",
"ResponseCodeHealthState",
"ServiceResponseThresholdMode",
"ServiceResponseThreshold",
"ServiceResponseCode",
"Loss",
"LossHealthState",
"LossThresholdMode",
"LossThreshold",
"NetworkTestEnabled",
"MedianLatency",
"HighLatency",
"LowLatency",
"LatencyThresholdMode",
"LatencyThreshold",
"LatencyHealthState",
"TimeGenerated",
"Computer"]
CONTRACT_ENDPOINT_PATH_DATA_KEYS = ["SubType",
"TestName",
"ServiceTestId",
"ConnectionMonitorResourceId",
"Target",
"Port",
"TimeSinceActive",
"EndpointId",
"SourceNetworkNodeInterface",
"DestinationNetworkNodeInterface",
"Path",
"Loss",
"NetworkTestEnabled",
"HighLatency",
"MedianLatency",
"LowLatency",
"LossHealthState",
"LatencyHealthState",
"LossThresholdMode",
"LossThreshold",
"LatencyThresholdMode",
"LatencyThreshold",
"Computer",
"Protocol",
"MinHopLatencyList",
"MaxHopLatencyList",
"AvgHopLatencyList",
"TraceRouteCompletionTime",
"TimeGenerated"]
CONTRACT_ENDPOINT_DIAG_DATA_KEYS = ["SubType",
"TestName",
"ServiceTestId",
"ConnectionMonitorResourceId",
"Target",
"NotificationCode",
"EndpointId",
"TimeGenerated",
"Computer"]
CONTRACT_EXROUTE_MONITOR_DATA_KEYS = ["SubType",
"TimeGenerated",
"Circuit",
"ComputerEnvironment",
"vNet",
"Target",
"PeeringType",
"CircuitResourceId",
"ConnectionResourceId",
"Path",
"SourceNetworkNodeInterface",
"DestinationNetworkNodeInterface",
"Loss",
"HighLatency",
"MedianLatency",
"LowLatency",
"LossHealthState",
"LatencyHealthState",
"RuleName",
"TimeSinceActive",
"LossThreshold",
"LatencyThreshold",
"LossThresholdMode",
"LatencyThresholdMode",
"Computer",
"Protocol",
"MinHopLatencyList",
"MaxHopLatencyList",
"AvgHopLatencyList",
"TraceRouteCompletionTime",
"DiagnosticHop",
"DiagnosticHopLatency"]
CONTRACT_CONNECTIONMONITOR_TEST_RESULT_KEYS = ["SubType",
"RecordId",
"Computer",
"ConnectionMonitorResourceId",
"TimeCreated",
"TestGroupName",
"TestConfigurationName",
"SourceType",
"SourceResourceId",
"SourceAddress",
"SourceName",
"SourceIP",
"SourceSubnet",
"DestinationType",
"DestinationResourceId",
"DestinationAddress",
"DestinationName",
"DestinationAgentId",
"Protocol",
"DestinationPort",
"DestinationIP",
"DestinationSubnet",
"ChecksTotal",
"ChecksFailed",
"ChecksFailedPercentThreshold",
"RoundTripTimeMsThreshold",
"MinRoundTripTimeMs",
"MaxRoundTripTimeMs",
"AvgRoundTripTimeMs",
"JitterMs",
"TestResult",
"TestResultCriterion",
"AdditionalData",
"IngestionWorkspaceResourceId"]
CONTRACT_CONNECTIONMONITOR_PATH_DATA_KEYS = ["SubType",
"RecordId",
"Computer",
"TopologyId",
"ConnectionMonitorResourceId",
"TimeCreated",
"TestGroupName",
"TestConfigurationName",
"SourceType",
"SourceResourceId",
"SourceAddress",
"SourceName",
"SourceIP",
"SourceSubnet",
"DestinationType",
"DestinationResourceId",
"DestinationAddress",
"DestinationName",
"DestinationIP",
"DestinationSubnet",
"DestinationAgentId",
"ChecksTotal",
"ChecksFailed",
"ChecksFailedPercentThreshold",
"RoundTripTimeMsThreshold",
"MinRoundTripTimeMs",
"MaxRoundTripTimeMs",
"AvgRoundTripTimeMs",
"JitterMs",
"HopAddresses",
"HopTypes",
"HopLinkTypes",
"HopResourceIds",
"Issues",
"Hops",
"DestinationPort",
"Protocol",
"PathTestResult",
"PathTestResultCriterion",
"AdditionalData",
"IngestionWorkspaceResourceId",
"UploadDirectly"]
def self.IsValidDataitem(item, itemType)
_contract=[]
if itemType == DATAITEM_AGENT
_contract = CONTRACT_AGENT_DATA_KEYS
elsif itemType == DATAITEM_PATH
_contract = CONTRACT_PATH_DATA_KEYS
elsif itemType == DATAITEM_DIAG
_contract = CONTRACT_DIAG_DATA_KEYS
elsif itemType == DATAITEM_ENDPOINT_HEALTH
_contract = CONTRACT_ENDPOINT_HEALTH_DATA_KEYS
elsif itemType == DATAITEM_ENDPOINT_MONITORING
_contract = CONTRACT_ENDPOINT_PATH_DATA_KEYS
elsif itemType == DATAITEM_ENDPOINT_DIAGNOSTICS
_contract = CONTRACT_ENDPOINT_DIAG_DATA_KEYS
elsif itemType == DATAITEM_EXROUTE_MONITORING
_contract = CONTRACT_EXROUTE_MONITOR_DATA_KEYS
elsif itemType == DATAITEM_CONNECTIONMONITOR_TEST
_contract = CONTRACT_CONNECTIONMONITOR_TEST_RESULT_KEYS
elsif itemType == DATAITEM_CONNECTIONMONITOR_PATH
_contract = CONTRACT_CONNECTIONMONITOR_PATH_DATA_KEYS
elsif itemType == DATAITEM_AGENT_DIAGNOSTICS
_contract = CONTRACT_AGENT_DIAGNOSTICS_KEYS
end
return DATAITEM_ERR_INVALID_TYPE, nil if _contract.empty?
item.keys.each do |k|
return DATAITEM_ERR_INVALID_FIELDS, k if !_contract.include?(k)
end
return DATAITEM_VALID, nil
end
end