External scripts

Overview

The system can be configured to run external scripts under several conditions:

  • When object properties are modified.

  • When zone contents are changed.

  • When the number of free addresses in subnets go below a set threshold.

Scripts associated with object types are often used to perform lookups in external data sources and return data from these sources. To configure the system to run a script when properties for an object are modified or when zone contents are changed, do the following:

  1. Log in as Administrator.

  2. From the menu, select Tools, System Settings.

  3. In the System settings dialog box, click the External Commands tab.

  4. In the applicable field (e.g., Range script, IP Address script, etc.), type the script name and necessary startup parameters. You must enter all information for the script as you would when invoking the script from the command line. It is assumed that the script is located in the same directory as Men&Mice Central; however, if the script is stored in a different location, the path for the script must be entered.

Example 1:

Running a script named mytest.vb. To run a script named mytest.vb that is located in the Men&Mice Central directory using the scripting host cscript, the following would be placed in the appropriate field: cscript /B mytest.vb

Example 2:

Running an executable named checkdata.exe. To run an executable named checkdata.exe that is located in the Men&Mice Central directory the following would be placed in the appropriate field: checkdata.exe.

  1. Click OK.

To configure the system to run a script when the number of free addresses in a subnet goes below a user-definable threshold, refer to IP Address Management—Subnet Monitoring and Utilization History.

../../../_images/admin-external-scripts.png

Script Interfaces

When Men&Mice Central runs an external script, it sends an XML structure as an argument to the script being called. The XML structure contains information about all custom properties that are defined for the object type. The XML structure also contains the login name of the user that triggered the script.

The XML structures differs a little depending on the type of script (property change, zone contents change, scope monitoring).

Property Change Script Interface

The XML schema for a property change script is as follows:

 1<?xml version="1.0" encoding="ISO-8859-1"?>
 2<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">
 3<xs:element name="externalScriptParameters">
 4<xs:complexType>
 5<xs:sequence>
 6<xs:element ref="customFields" minOccurs="1" maxOccurs="1" />
 7</xs:sequence>
 8<xs:attribute name="userName" type="xs:string" />
 9</xs:complexType>
10</xs:element>
11<xs:element name="customFields">
12<xs:complexType>
13<xs:sequence>
14<xs:element ref="customField" minOccurs="1" maxOccurs="unbounded" />
15</xs:sequence>
16</xs:complexType>
17</xs:element>
18<xs:element name="customField">
19<xs:complexType>
20<xs:sequence>
21</xs:sequence>
22<xs:attribute name="customFieldID" type="xs:string" />
23<xs:attribute name="customFieldName" type="xs:string" />
24<xs:attribute name="objectID" type="xs:string" />
25<xs:attribute name="objectType" type="xs:string" />
26<xs:attribute name="value" type="xs:string" />
27</xs:complexType>
28</xs:element>
29</xs:schema>

An example XML structure with three custom properties named Location, Country and Region might look as follows:

 1<?xml version="1.0"?>
 2<externalScriptParameters username="administrator">
 3<customFields>
 4<customField customFieldID="24" customFieldName="Location"
 5objectID="27" objectType="4" value="location1"></customField>
 6<customField customFieldID="25" customFieldName="Country"
 7objectID="27" objectType="4" value=""></customField>
 8<customField customFieldID="26" customFieldName="Region"
 9objectID="27" objectType="4" value=""></customField>
10</customFields>
11</externalScriptParameters>

Upon completion, the script must create a new XML structure and return it to Men&Mice Central. The schema for the XML structure that is returned is as follows:

 1<?xml version="1.0" encoding="ISO-8859-1"?>
 2<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
 3elementFormDefault="qualified" xmlns="http://tempuri.org/
 4XMLSchema.xsd" xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
 5xmlns:xs="http://www.w3.org/2001/XMLSchema">
 6<xs:element name="result">
 7<xs:complexType>
 8<xs:choice minOccurs="1" maxOccurs="2">
 9<xs:element ref="customFields" />
10<xs:element ref="error" />
11</xs:choice>
12<xs:attribute name="success" type="xs:string" />
13</xs:complexType>
14</xs:element>
15<xs:element name="customFields">
16<xs:complexType>
17<xs:sequence>
18<xs:element ref="customField" minOccurs="0" maxOccurs="unbounded"/>
19</xs:sequence>
20</xs:complexType>
21</xs:element>
22<xs:element name="customField">
23<xs:complexType>
24<xs:sequence>
25</xs:sequence>
26<xs:attribute name="customFieldID" type="xs:string" />
27<xs:attribute name="customFieldName" type="xs:string" />
28<xs:attribute name="objectID" type="xs:string" />
29<xs:attribute name="objectType" type="xs:string" />
30<xs:attribute name="value" type="xs:string" />
31</xs:complexType>
32</xs:element>
33<xs:element name="error">
34<xs:complexType>
35<xs:sequence>
36</xs:sequence>
37<xs:attribute name="code" type="xs:string" />
38<xs:attribute name="message" type="xs:string" />
39</xs:complexType>
40</xs:element>
41</xs:schema>

An example XML structure with three custom properties named Location, Country and region might look as follows:

1<?xml version="1.0"?>
2<result success="1">
3<customFields>
4<customField customFieldID="24" customFieldName="loc" objectID="27" objectType="4" value="location1"></customField>
5<customField customFieldID="25" customFieldName="Country" objectID="27" objectType="4" value="USA"></customField>
6<customField customFieldID="26" customFieldName="Region" objectID="27" objectType="4" value="Texas"></customField>
7</customFields>
8</result>

Men&Mice Central uses the information in the XML structure to update other custom properties or to display an error message if the success attribute on the result element is set to 0. The following XML example shows how an error message can be returned by the external script.

1<?xml version="1.0"?><result success="0"><error code="1"message="The error message."></error></result>

The XML structure is not required to return information about all custom properties, only fields that the script has changed. Unknown property fields are ignored by Men&Mice Central.

Zone Content Change Script Interface

The XML schema for a zone content change script is as follows:

 1<?xml version="1.0" encoding="ISO-8859-1"?>
 2<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">
 3<xs:element name="externalScriptParameters">
 4<xs:complexType>
 5<xs:sequence>
 6<xs:element ref="object" minOccurs="1" maxOccurs="1" />
 7</xs:sequence>
 8<xs:attribute name="userName" type="xs:string" />
 9</xs:complexType>
10</xs:element>
11<xs:element name="object">
12<xs:complexType>
13<xs:sequence>
14<xs:element name="id" type="xs:integer" minOccurs="1" maxOccurs="1" />
15<xs:element name="type" type="xs:integer" minOccurs="1" maxOccurs="1" />
16<xs:element name="server" type="xs:string" minOccurs="1" maxOccurs="1" />
17<xs:element name="view" type="xs:string" minOccurs="1" maxOccurs="1" />
18<xs:element name="zone" type="xs:string" minOccurs="1" maxOccurs="1" />
19<xs:element name="fqName" type="xs:string" minOccurs="1" maxOccurs="1" />
20</xs:sequence>
21</xs:complexType>
22</xs:element>
23</xs:schema>

An example XML structure for a zone change script might look as follows for a zone that exists in a view:

 1<?xml version="1.0" encoding="ISO-8859-1"?>
 2<externalScriptParameters userName="administrator">
 3<object>
 4<id>2534</id>
 5<type>13</type>
 6<server>bind1.corp.net.</server>
 7<view>internal</view>
 8<zone>zone.com.</zone>
 9<fqName>bind1.corp.net.:internal:zone.com.</fqName>
10</object>
11</externalScriptParameters>

An example XML structure for a zone change script might look as follows for a zone that is not in a view:

 1<?xml version="1.0" encoding="ISO-8859-1"?>
 2<externalScriptParameters userName="administrator">
 3<object>
 4<id>2635</id>
 5<type>13</type>
 6<server>dns1.corp.net.</server>
 7<view />
 8<zone>my.zone.com.</zone>
 9<fqName>dns1.corp.net.::my.zone.com.</fqName>
10</object>
11</externalScriptParameters>

A zone content change script does not have any return value.

Subnet Monitoring Script Interface

The XML schema for a subnet monitoring script is as follows:

 1<?xml version="1.0" encoding="ISO-8859-1"?>
 2<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">
 3<xs:element name="scopeMonitor">
 4<xs:complexType>
 5<xs:sequence>
 6<xs:element name="scope" type="xs:string" minOccurs="0" maxOccurs="1" />
 7<xs:element name="server" type="xs:string" minOccurs="0" maxOccurs="1" />
 8<xs:element name="superscope" type="xs:string" minOccurs="0" maxOccurs="1" />
 9<xs:element name="threshold" type="xs:integer" minOccurs="1" maxOccurs="1" />
10<xs:element name="available" type="xs:integer" minOccurs="1" maxOccurs="1" />
11<xs:element name="fixed" type="xs:boolean" minOccurs="1" maxOccurs="1" />
12<xs:element name="thresholdType" type="xs:string" minOccurs="1" maxOccurs="1" />
13</xs:sequence>
14</xs:complexType>
15</xs:element>
16</xs:schema>

The value of the thresholdType element will be either static or dynamic depending on whether the threshold being crossed is one of dynamically allocatable addresses (i.e., available addresses in address pools) or if it is a threshold set for static addresses (i.e., available addresses outside of address pools).

Note

The global subnet monitor, set through the system settings dialog, is the only one that takes superscopes into account. When the global subnet monitor actions are performed, due to the conditions being met for a superscope, the XML generated will contain a <server> tag and a <superscope> tag.

An example XML structure for a subnet monitoring script might look as follows for scope:

 1<?xml version="1.0" encoding="ISO-8859-1"?>
 2<scopeMonitor>
 3<scope>123.45.67.0/24</scope>
 4<threshold>20</threshold>
 5<available>8</available>
 6<fixed>0</fixed>
 7<thresholdType>dynamic</thresholdType>
 8<customFields>
 9<customField customFieldID="1" customFieldName="Title" objectID="526" objectType="6" value="Your subnet title"></customField>
10<customField customFieldID="2" customFieldName="Description" objectID="526" objectType="6" value="You subnet description"></customField>
11<customFields>
12</scopeMonitor>

The XML structure is slightly different if a superscope (MS DHCP) or a shared-network (ISC DHCP) configuration is used. An example XML structure for a scope monitoring script might look as follows for a superscope / shared-network configuration:

1<?xml version="1.0" encoding="ISO-8859-1"?>
2<scopeMonitor>
3<server>dhcp1.corp.net.</server>
4<superscope>office</superscope>
5<threshold>20</threshold>
6<available>22</available>
7<fixed>1</fixed>
8<thresholdType>dynamic</thresholdType>
9</scopeMonitor>

A subnet monitoring script does not have any return value.

Example Visual Basic Script

The following example script, written in Visual Basic, shows how a script could return different values depending on the user that is running the script. The script is called when an object property changes.

 1Dim fso, stdin, stdout, stderr, xmlDoc
 2
 3'The next four lines connect the script and the "Men&Mice Suite"
 4Set fso = CreateObject ("Scripting.FileSystemObject")
 5Set stdin = fso.GetStandardStream (0)
 6Set stdout = fso.GetStandardStream (1)
 7Set stderr = fso.GetStandardStream (2)
 8Set xmlDoc=CreateObject("Microsoft.XMLDOM") xmlDoc.async="false" 'read xml
 9from MMSuite xmlDoc.loadXml(stdin.ReadAll)
10
11Dim xElLocationCodeField, theCode, xElCustomFields, theUser
12'Get the username
13theUser = xmlDoc.selectSingleNode("/externalScriptParameters").getAttribute("userName")
14
15'Select all the customfields
16Set xElCustomFields = xmlDoc.selectSingleNode("/externalScriptParameters/customFields")
17
18'Get the current value of the location code field
19Set xElLocationCodeField = xElCustomFields.selectSingleNode("customField[@customFieldName='Location']")
20theCode = xElLocationCodeField.getAttribute("value")
21
22Dim success, retVal1, retVal2 success = false
23
24' Very simple logic, here a DB query could be performed or some other lookup
25  if theCode = "l1" then
26  retVal1="USA"
27  retVal2="Washington"
28  success = true
29    elseif theCode = "l2" then
30  retVal1="UK"
31  retVal2="London"
32  success = true
33end if
34' logic ends
35
36Dim xReturnDoc, xElResult
37
38'create return document
39Set xReturnDoc = CreateObject("Microsoft.XMLDOM")
40Set xElResult = xReturnDoc.createElement("result")
41
42if success then
43  xElResult.setAttribute "success", "1"
44 'set the value of xml that we return. It is OK to omit fields that are not changed by script
45 xElResult.appendChild xElCustomFields.cloneNode(true)
46 Dim xElChange
47 Set xElChange = xElResult.selectSingleNode("/customFields/customField[@customFieldName='Country']")
48 xElChange.setAttribute "value", retVal1
49 Set xElChange = xElResult.selectSingleNode("/customFields/customField[@customFieldName='City']")
50 xElChange.setAttribute "value", retVal2
51else
52 xElResult.setAttribute "success", "0"
53
54'add error element
55 Dim xElError
56 Set xElError = xReturnDoc.createElement("error")
57 xElError.setAttribute "code", "1"
58 xElError.setAttribute "message", "Unknown location."
59 xElResult.appendChild xElError
60end if
61
62xReturnDoc.appendChild xElResult
63
64'finally return the xml
65stdout.WriteLine xReturnDoc.xml

Example PowerShell Script

Note

Powershell scripts can be run natively by Men&Mice by starting the command with “powershell”, “powershell.exe” or simply with the path to the .ps1 file. Powershell can then read the stdin with [Console]::In.ReadToEnd()

Instructions

  1. Copy the psExec.vbs and the ScopeMonScript.ps1 to the c:ProgramDataMen and MiceCentral directory.

  2. In Tools->System Settings->Monitoring, add it in the Default scope monitoring settings as follows:

1cscript /B /T:120 ./psExec.vbs ScopeMonScript.ps1 ignore ignore

And then configure a dynamic threshold. The monitor will be executed every 10 minutes during the DHCP synchronization interval.

 1param([Parameter(Mandatory=$false,ValueFromPipeLine=$false)]$UserName = "",
 2[Parameter(Mandatory=$false,ValueFromPipeLine=$false)]$Password = "",
 3[Parameter(Mandatory=$false,ValueFromPipeLine=$false)]$xmlFileName = "")
 4$strInput = get-content $xmlFileName
 5#$strInput = $args
 6# write output for troubleshooting in file:
 7#Add-Content -Path .\monitoroutput.xml $strInput
 8
 9$strXML = [string]::Join(" ", $strInput)
10$objXML = [xml]$strXML
11$subnetMonitor = (Select-Xml -XML $objXML -XPath "/subnetMonitor").Node
12
13# Check if it's an alert or fixed message
14# The script only cares about alerts
15if ($subnetMonitor.fixed -eq "0")
16{
17    $strAlert = "Alert:  The following scope or subnet has fewer IPs available than the configured threshold."
18
19    # We could send here an email or generate a trap or...
20    #Send-MailMessage -SmtpServer "smpt.example.com" -From "subnetmonitor@example.com" -To "alert1@example.com;alert2@example.net" -Subject "Subnet Monitor Message" -Body $strOutput
21
22    # First handle the superscopes
23    if ($subnetMonitor.superscope -ne $null -and $subnetMonitor.superscope -ne "")
24    {
25    $strOutput = @"
26
27    $strAlert
28    Superscope: $($subnetMonitor.superscope)
29    Alert Date:    $(Get-Date -Format G)
30    Server:        $($subnetMonitor.server)
31    Threshold:    $($subnetMonitor.threshold)
32    IPs Available:    $($subnetMonitor.available)
33    Subnet Type:    $($subnetMonitor.thresholdType)
34    "@
35        New-EventLog -Source SubnetMonitor -LogName Application
36        Write-EventLog -LogName Application -Source SubnetMonitor -EventID 1063 -EntryType Warning -message "$strOutput"
37        #Add-Content -Path .\superscopemonitor_msg.txt $strOutput
38        }
39    else
40    {
41    # then in the else clause the normal scopes
42
43    $strOutput = @"
44
45    $strAlert
46      Alert Date:    $(Get-Date -Format G)
47      Scope:        $($subnetMonitor.subnet)
48      Threshold:    $($subnetMonitor.threshold)
49      IPs Available:    $($subnetMonitor.available)
50      Subnet Type:    $($subnetMonitor.thresholdType)
51      "@
52        New-EventLog -Source SubnetMonitor -LogName Application
53        Write-EventLog -LogName Application -Source SubnetMonitor -EventID 1064 -EntryType Warning -message "$strOutput"
54        #Add-Content -Path .\scopemonitor_msg.txt $strOutput
55    }
56  }
57  else
58  {
59  # possible issue fixed message
60  }