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.

NewMP1

 

Name & description is up to you, this is what will show up in the Operations Manager console when you import the management pack.

NewMP2

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.

NewClass1

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

NewClass2

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.

NewClass3

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)

NewDiscovery1

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.

NewDiscovery2

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.

NewDiscovery3

Click the parameters button, and enter the following three parameters.

$mpelement$ $Target/Id$ $Target/Property[Type="Windows!Microsoft.Computer"]/PrincipalName$

NewDiscovery4

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.

NewDiscovery5

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)