Extending System Center Operations Manager Classes & Discovery
One of the things I've recently been working on is a question asked by a partner - how do I get extra information about my machines into Operations Manager? If you're not familiar with extending Operations Manager and using Classes & Discovery, it can be quite intimidating, but it's relatively simple. I figure if I can work out, most people probably can. This post will walk through extending the Windows Computer class with an extra attribute populated by an AD query.
First, download and install the Operations Manager Authoring Console: https://www.microsoft.com/downloads/details.aspx?FamilyID=6c8911c3-c495-4a03-96df-9731c37aa6d7&DisplayLang=en
It's also handy to have the Operations Manager Authoring Guide: https://www.microsoft.com/downloads/details.aspx?FamilyID=d826b836-59e5-4628-939e-2b852ed79859&DisplayLang=en. The Authoring Guide covers all the concepts involved, and is especially useful to know about classes and inheritance.
Start the Authoring Console & create a new Management Pack (File...New or click the icon). Create an Empty Management Pack. The best practice for the identity (see the Authoring Guide - Management Packs & Namespaces) is to use Vendor.ProductName.Version - in this case I'm going to use stufox.windowsserver with no version as this will be generic across all Windows server versions, and it's for demo purposes.
Name & description is up to you, this is what will show up in the Operations Manager console when you import the management pack.
Now you have a new blank Management Pack. The first thing to do is to create our new class, so go to Classes and click New Custom Class. You then need to provide a unique identifier for the Class, I'm going to create a class called stufox.windowsserver.ExtendedComputer which will be used to store the Description information from the Active Directory.
Once you click OK you will see the class creation screen. You need to set a few fields in here:
Base Class: Microsoft.Windows.Computer - this is the class that we're extending to create our new attribute.
Name: StuFox Extended Computer (this will appear in the Operations Manager console as the name of the attribute)
Description: Up to you
Change to the Properties tab, and right click in the left hand pane, and choose Add Property. Our property in this case is going to be ADDescription. The defaults are fine, although you can set a Display Name & Description if you want to.
Click OK to create the class.
Now that the class is created you need to create a discovery to populate the class. I'm going to use a VBscript to do this, there is a lot of information on MSDN about this:
How to create Discovery Data by using a script
How to use Runtime Scripts for Discovery
Change to the Health Model section & click Discoveries. Click New & choose Script.
In the screen that opens, set the following values:
Element ID: stufox.windowsserver.DiscoverAdDescription
Display Name: Discover AD Description
Target: Microsoft.Windows.Computer (important: the default will not be set to this, if you don't target it correctly you won't get any data)
Click Next and you will get to set the schedule for the discovery. This discovery doesn't really need to run very frequently - once every 24 hours is fine.
Click Next and you will get the script screen. This allows you to paste in a script written in VBScript or Jscript.
Set the filename to DiscoverDescription.vbs, and paste in the discovery script below (Caveat: This script isn't 100% production ready, I've just used it as an example to show how to get the information in there. There isn't much error handling, and there isn't any allowance for machines that aren't domain members. Use at your own risk!) . I've highlighted (bold, italic) two places you need to modify the script to set the class name to whatever your class name is set to. Set the timeout to 10 minutes.
Click the parameters button, and enter the following three parameters.
$mpelement$ $Target/Id$ $Target/Property[Type="Windows!Microsoft.Computer"]/PrincipalName$
Click OK to create the discovery. Once this has been created, highlight the discovery and choose Properties. Change to the Discovered Types tab and click Add. Highlight your custom class in the list, and choose OK. Right click the newly added class and choose the ADDescription property.
Save the management pack to your hard disk somewhere and it is ready to import into Operations Manager. It will just be a standard XML file that you can open with an XML editor (or notepad) if you like to see what's in there.
So, now that it's imported how do you tell that it's there? The discovery will be available to view in the Operations Manager Console. Go to the Authoring view, and then choose Object Discoveries. You may have to change the scope of the console to see the discovery - include your new management pack. You can also change the schedule of the discovery to force it to run at a time of your choosing if you like - in fact, because the management pack is unsealed you can edit the discovery script directly if you want to. This can be quite handy if like me you haven't necessarily ironed out all the bugs in your script. :)
Once the discovery is run, to see the if the data is in the database you can look at the Ops Mgr database - the data will be stored in a table named MT_<Class Name> - in this case it's MT_ExtendedComputer (Extended_Computer being the name of our new class).
You can troubleshoot by looking at the Operations Manager event logs on the Ops Mgr server. If you need to see if the script has made it down to the machines to actually run, you can go to a command prompt and change to the "Health Service State" directory where the Operations Manager agent is installed (by default C:\Program Files\System Center Operations Manager 2007) and then running dir /s discoverdescription.vbs. It will be in one of the "Monitoring Host Temporary Files x" directories.
I assume there will be some clever people out there who will show me better ways to write my script, feel free, I'm always open to good advice. One of the things I've thought about adding to it is the ability to determine if a machine is in a domain or not, and if not use the description from the local computer instead.
DiscoverDescription.vbs
'DiscoverDescription.vbs
'
' Script discovers the Description field from AD given the DNS name of the computer
'
Option Explicit
'On Error Resume Next
Const ADS_SCOPE_SUBTREE = 2
Dim oAPI, oArgs, strDescription
Dim SourceID, ManagedEntityId, TargetComputer, objRootDSE, strDomain
Dim wshnetwork, strCompName
Dim objConnection, objCommand, objRecordSet, objComputer, strComputerAccount
Dim oDiscoveryData, oInst
Set oAPI = CreateObject("MOM.ScriptAPI")
' Arguments:
' 0 - SourceID
' 1 - ManagedEntityID
' 2 - ComputerIdentity
Set oArgs = WScript.Arguments
if oArgs.Count < 3 Then
call oAPI.LogScriptEvent("DiscoverDescription.vbs",9999,2,"Script was called with fewer than 3 arguments and was not executed")
Wscript.quit -1
End If
SourceID = oArgs(0)
ManagedEntityId = oArgs(1)
TargetComputer = oArgs(2)
call oAPI.LogScriptEvent("DiscoverDescription.vbs",9999,1,"Source ID: " & SourceID & "ManagedEntityID: " & ManagedEntityID)
Set objRootDSE = GetObject("LDAP://RootDSE")
strDomain = objRootDSE.Get("DefaultNamingContext")
set wshnetwork=wscript.createobject("Wscript.Network")
strCompName=wshnetwork.computername
if err.number <> 0 Then
call oAPI.LogScriptEvent("DiscoverDescription.vbs",9997,2,"Error creating objects")
Wscript.quit -1
End If
set objConnection = CreateObject("ADODB.Connection")
set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
set objCommand.ActiveConnection = objConnection
if err.number <> 0 Then
call oAPI.LogScriptEvent("DiscoverDescription.vbs",9996,2,"Error creating ADO objects")
Wscript.quit -1
End If
objCommand.Properties("Page Size") = 1000
objCommand.Properties("SearchScope") = ADS_SCOPE_SUBTREE
objCommand.CommandText = "SELECT ADsPath FROM 'LDAP://"&strDomain&"' WHERE objectCategory='computer' AND name='"&strCompName&"'"
Set objRecordSet = objCommand.Execute
strDescription = ""
objRecordSet.MoveFirst
if NOT objRecordSet.EOF Then
Do until objRecordSet.EOF
strComputerAccount=objRecordSet.Fields("ADsPath").value
set objComputer = GetObject(strComputerAccount)
strDescription = left(objComputer.Description,255)
objRecordSet.MoveNext
Loop
Else
call oAPI.LogScriptEvent("DiscoverDescription.vbs",9998,2,"Active Directory Object could not be found")
End If
Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceID, ManagedEntityID)
set oInst = oDiscoveryData.CreateClassInstance("$MPElement[Name= 'stufox.windowsserver.ExtendedComputer ']$")
call oInst.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", TargetComputer)
call oInst.AddProperty("$MPElement[Name= 'stufox.windowsserver. ExtendedComputer' ]/ADDescription$",strDescription)
call oDiscoveryData.AddInstance(oInst)
call oAPI.Return(oDiscoveryData)