The XML schema for a subnet monitoring script is as follows:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:mstns="http://tempuri.org/XMLSchema.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="scopeMonitor">
<xs:complexType>
<xs:sequence>
<xs:element name="scope" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="server" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="superscope" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="threshold" type="xs:integer" minOccurs="1" maxOccurs="1" />
<xs:element name="available" type="xs:integer" minOccurs="1" maxOccurs="1" />
<xs:element name="fixed" type="xs:boolean" minOccurs="1" maxOccurs="1" />
<xs:element name="thresholdType" type="xs:string" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The value of the thresholdType element will be either static or
dynamic, depending on whether the threshold being crossed is one of the dynamically
allocatable addresses (that is, available addresses in address pools) or a threshold set
for static addresses (that is, available addresses outside of address pools).
<server> tag and a <superscope>
tag.An example XML structure for a subnet monitoring script for a scope might look like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<scopeMonitor>
<scope>123.45.67.0/24</scope>
<threshold>20</threshold>
<available>8</available>
<fixed>0</fixed>
<thresholdType>dynamic</thresholdType>
<customFields>
<customField customFieldID="1" customFieldName="Title" objectID="526" objectType="6" value="Your subnet title"></customField>
<customField customFieldID="2" customFieldName="Description" objectID="526" objectType="6" value="You subnet description"></customField>
<customFields>
</scopeMonitor>
The XML structure differs slightly if a superscope (MS DHCP) or a shared-network (ISC DHCP) configuration is used. An example XML structure for a scope monitoring script for a superscope/shared-network configuration might look like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<scopeMonitor>
<server>dhcp1.corp.net.</server>
<superscope>office</superscope>
<threshold>20</threshold>
<available>22</available>
<fixed>1</fixed>
<thresholdType>dynamic</thresholdType>
</scopeMonitor>
A subnet monitoring script does not have any return value.
Example PowerShell script
.ps1 extension) are run
natively by Micetro on Windows with powershell. The script can then
read the stdin with [Console]::In.ReadToEnd().Instructions:
- Copy the ScopeMonScript.ps1 to the scripts folder: C:\\ProgramData\\Men and Mice\\Central\scripts.
- In the Web Application, navigate to , and under Subnet monitoring events select Set defaults.
- Select
ScopeMonScript.ps1in the Script to invoke field. - Configure a dynamic threshold.
The monitor will be executed every ten minutes during the DHCP synchronization interval.
param([Parameter(Mandatory=$false,ValueFromPipeLine=$false)]$UserName = "",
[Parameter(Mandatory=$false,ValueFromPipeLine=$false)]$Password = "",
[Parameter(Mandatory=$false,ValueFromPipeLine=$false)]$xmlFileName = "")
$strInput = get-content $xmlFileName
#$strInput = $args
# write output for troubleshooting in file:
#Add-Content -Path .\monitoroutput.xml $strInput
$strXML = [string]::Join(" ", $strInput)
$objXML = [xml]$strXML
$subnetMonitor = (Select-Xml -XML $objXML -XPath "/subnetMonitor").Node
# Check if it's an alert or fixed message
# The script only cares about alerts
if ($subnetMonitor.fixed -eq "0")
{
$strAlert = "Alert: The following scope or subnet has fewer IPs available than the configured threshold."
# We could send here an email or generate a trap or...
#Send-MailMessage -SmtpServer "smpt.example.com" -From "subnetmonitor@example.com" -To "alert1@example.com;alert2@example.net" -Subject "Subnet Monitor Message" -Body $strOutput
# First handle the superscopes
if ($subnetMonitor.superscope -ne $null -and $subnetMonitor.superscope -ne "")
{
$strOutput = @"
$strAlert
Superscope: $($subnetMonitor.superscope)
Alert Date: $(Get-Date -Format G)
Server: $($subnetMonitor.server)
Threshold: $($subnetMonitor.threshold)
IPs Available: $($subnetMonitor.available)
Subnet Type: $($subnetMonitor.thresholdType)
"@
New-EventLog -Source SubnetMonitor -LogName Application
Write-EventLog -LogName Application -Source SubnetMonitor -EventID 1063 -EntryType Warning -message "$strOutput"
#Add-Content -Path .\superscopemonitor_msg.txt $strOutput
}
else
{
# then in the else clause the normal scopes
$strOutput = @"
$strAlert
Alert Date: $(Get-Date -Format G)
Scope: $($subnetMonitor.subnet)
Threshold: $($subnetMonitor.threshold)
IPs Available: $($subnetMonitor.available)
Subnet Type: $($subnetMonitor.thresholdType)
"@
New-EventLog -Source SubnetMonitor -LogName Application
Write-EventLog -LogName Application -Source SubnetMonitor -EventID 1064 -EntryType Warning -message "$strOutput"
#Add-Content -Path .\scopemonitor_msg.txt $strOutput
}
}
else
{
# possible issue fixed message
}
Example Python script
country and
city using a location code. The intended use is to mark the
locations of
servers.import sys
import xml.etree.ElementTree as ET
def get_custom_field_element(custom_fields, name):
element = custom_fields.find(f"./customField[@customFieldName='{name}']")
if element is None:
raise KeyError(f"Custom property '{name}' was not found.")
return element
def get_result(root):
# username variable is not used but this is how to get the username
username = root.get('userName')
custom_fields = root.find("./customFields")
result = ET.Element("result", {"success": "0"})
try:
location_element = get_custom_field_element(custom_fields, 'Location')
country_element = get_custom_field_element(custom_fields, 'Country')
city_element = get_custom_field_element(custom_fields, 'City')
except KeyError as e:
ET.SubElement(result, "error", {"code": "1", "message": str(e)})
return result
location = location_element.get('value')
# A database could be queried instead here
LOCATION_MAP = {
'l1': ('USA', 'Washington'),
'l2': ('UK', 'London')
}
if location not in LOCATION_MAP:
ET.SubElement(result, "error", {"code": "1", "message": "Unknown location."})
return result
result.set("success", "1")
country, city = LOCATION_MAP[location]
country_element.set('value', country)
city_element.set('value', city)
result.append(custom_fields)
return result
# Read all input and parse as XML
root = ET.fromstring(sys.stdin.read())
result = get_result(root)
print('<?xml version="1.0"?>')
# This will write the generated result xml to standard output
ET.dump(result)