Granular Targeting In Operations Manager 2007
At a Glance:
- Using an existing target
- The problem with attribute discovery
- Creating targets with the authoring console
- Script-based discovery
Creating custom monitoring objects (rules, monitors, groups, and so on) is a normal part of many System Center Operations Manager (OpsMgr) 2007 administrators' routines. For every object that is authored, there is a common question that must be answered—what target to use.
Choosing the correct target for an object is critical, but the correct approach may not always be clear. OpsMgr provides a number of options for targeting. This article will take a look at several, with the goal of helping administrators choose the appropriate method for each scenario; and the terms "class" and "target" will be used interchangeably.
Let's assume you have an internal application called widget that needs to be monitored. All of the monitoring specifications have been defined and the work to build the monitoring objects for widget has begun. You quickly discover, however, that there is no precise target for widget! According to OpsMgr best practices, all rules, monitors, and so forth should be targeted to the most specific object possible in order to limit the scope of distribution to just the systems of interest. What are the options in OpsMgr that can help you meet this best practice goal?
Using an Existing Target
By default, OpsMgr includes a long list of targets, and that list grows as more management packs are imported. When you're creating a new management pack object (MPO) and considering the target, first review the available items to see if one of the preexisting targets is sufficient. If you're building MPOs to extend System Management Server (SMS) server monitoring, for example, it is likely that the existing targets that are imported along with the default SMS server management pack can be reused for your MPO.
Using default targets, however, doesn't always work. If the available targets are not sufficiently specific for the MPO being created, you can either work around the lack of an optimal target or create a new target.
One common approach (though it does have some drawbacks) is to associate the new MPO to the Windows client or Windows server class or to any other appropriate base class (again, be as specific as possible) that includes the required targets. When doing this, be sure to create the MPO in a disabled state. Then you can build a group containing all of the systems where these MPOs need to execute and override the disabled MPOs so the MPO is enabled for only the agents in the group. This allows the MPO to be delivered and run on just the agents that are allowed by the override.
What are the drawbacks of this approach? First of all, using this method targets the broader class of objects (Windows Computer, for example), so all monitored MPOs targeted in this way show up under the targeted object in Health Explorer (see Figure 1).
Figure 1 Health Explorer for computer targeted by override (Click the image for a larger view)
This is really just cosmetic, so it may not be a problem in a given environment. But targeting in this way does cause the health state of the parent object (such as Windows Computer) to be affected when the custom monitor is impacted. So, if the widget application has a problem, the health of the entire targeted object may be affected. Depending on what is being monitored, this may or may not be noteworthy.
Targeting MPOs to groups is not generally an appropriate approach in OpsMgr—so why does this work? Remember, groups in these examples are used as overrides and are not the actual target of the MPO.
This may seem like semantics, but think about groups in OpsMgr. Groups are objects, just like any other object. When an object is chosen as the target, this means that the MPO in question is being deployed to the agents that own the targeted object.
So, which agent owns the group object? Correct—the Root Management Server (RMS). Targeting a group will cause MPOs to be delivered to the agent that owns the group, meaning that MPOs will be deployed only to the RMS! If an MPO is targeted appropriately, the stage is already set for the MPOs to be deployed to the correct agents, but by disabling the MPO, you've stopped that process before it can start.
When an override is introduced, the existing target is still the target—the override just changes the disabled status to enabled for a few agents per group membership. But the agents where the MPO is enabled are already part of the original target for the MPO. I know it's a little confusing at first.
Now consider a scenario where nothing discussed thus far is workable. What do you do? There is only one remaining option: create a new target specifically for the MPOs, which you can do either by using the service monitoring template in the Operations Console or by creating a new target in the Authoring Console.
Before you consider those, however, what about creating an attribute discovery? You might be thinking that this is a viable option that has been overlooked. Let's take a look. It is possible to build an attribute discovery that gets information from the registry or from WMI. To work, the attribute discovery must be targeted at a class that contains the registry or WMI entries of interest. Common targets are Windows client or Windows Server classes, or even the more generic Windows Computer class.
Note that the term itself—attribute discovery—implies what is actually happening: a new attribute is being discovered and used to extend an existing class. True, a new class is created as a result, but it is actually the same old class with all the same members, just with a new attribute being reported. Based on this, you can see that building a new attribute discovery is not the same as creating a truly unique target.
How about an example? Suppose a new attribute discovery is created to find the registry key for the widget product. This discovery is targeted to be deployed to Windows Computer so that it will include all agents that might have the widget registry key.
After making this choice in the wizard, you get a warning that the Windows Computer class cannot be extended (it is in a sealed management pack after all—if this were not a sealed management pack, there would be no such warning) and a renamed target class is presented as a choice you can use in order to proceed (see Figure 2). This happens because the goal of attribute discovery is to extend an existing class.
Figure 2 Attribute discovery doesn’t create a unique class (Click the image for a larger view)
Now let's look at service templates, which can be used to create unique targets for systems that can be found based on an installed service. Service templates are exceedingly easy to use; Figure 3 shows an example.
Figure 3 A service template
Be aware, however, that using the template may result in the creation of additional MPOs beyond what you may intend or want. After using the service template, it's a good idea to check and see what additional objects have been created and determine if they should be retained (see Figure 4).
Figure 4 Objects created when a template was used (Click the image for a larger view)
Moreover, service templates will create a discovery and a new class for each and every service. This may be exactly what you want, or it might be too granular. For example, suppose your custom app has multiple services. In that case, a new class and a new service monitor will be created for each! It's more likely that the desired monitoring approach would be to have a single class with each service monitor targeted to only that class.
If you can't or don't want to use a service template, your only remaining option is to use the Authoring Console. One glance at the Authoring Console documentation shows that proper use of this feature requires a very deep discussion—one that is far beyond the scope of this article.
Nevertheless, a few simple examples that use the Authoring Console to create and populate a new target in OpsMgr are in order. I will give two examples that revisit the idea of using a registry entry to uniquely identify the widget application and a third example that will demonstrate discovery by script.
Creating Targets with the Authoring Console
In many cases, it is possible to scan the registry for a particular value or key that will uniquely identify the servers of interest that host the desired target. If a class (target) could be built and populated with systems where the widget registry key exists, that would be an easy way to create a unique target.
My first example walks through doing this by simply looking for the existence of a registry key. The second example will look for a specific value associated with the registry key. Note that while you can create a registry attribute discovery rule (as discussed earlier) and a discovery in the Authoring Console, as demonstrated in the following examples, the two do not achieve the same results—the former simply extends an existing class while the latter actually creates a new target.
Using a Registry Key
When the Authoring Console is first launched, you must choose whether to load an existing management pack or create a new one. When you choose to create a new management pack, a wizard appears and lets you select a template either for an empty management pack or for a Windows Application (Registry) management pack (see Figure 5).
Figure 5 Choosing a template for a new management pack (Click the image for a larger view)
Either one can be used to achieve the same results, but it is easy to create a new class using the Windows Application (Registry) template. You must simply supply a name and then select the registry template. Next, you have to supply the name and description for the management pack on the Name and Description screen. The value to enter here is the value displayed under the management packs node of the Operations Manager UI.
Then provide a description of the application on the Windows Application screen. The value entered here will be the value displayed in the Attributes node of the Operations Manager UI. Next, configure how often the discovery should run. The default here is every 15 seconds, which is probably far too often. Balance the need for rapid discovery against the performance impact that may occur with too frequent discovery. There generally is no compelling reason to have a discovery run more than once per day.
Now fill in the detail needed to find the registry key/value you're interested in. There are multiple attribute types available; if you simply want to check for the existence of a key, use the Bool type.
Finally, build the query expression. This may appear to be duplicate work—didn't you just build the query expression? Actually, no. The Registry Probe Configuration screen defines the registry key to look at and how to look at it. The Expression Filter screen is used to define what value is expected.
OK, with all of this done, what have you actually created? Did you meet the goal of building a new class? In the Authoring Console, select the service model node and click on classes. Note that a new class has been created. Examine the properties to understand more about this new class.
What about the discovery definition? Look under health model and note the discovery rule—review the properties here as well to see how the rule is actually built.
Building a discovery that looks for a registry value instead of a registry key is equally easy. Work through the wizard again, but, this time, modify the input to pull a registry value instead of a key.
To initiate the wizard after the initial template has been completed, navigate to Health Model | Discoveries. In the middle pane, right-click and select New | Registry (filtered). The entries will be the same as before except this time a registry value is specified.
It's that easy! With the new targets created, the example will stop here. But note that additional work still needs to be done in order to populate the management pack with MPOs. MPOs can either be created through the Operations Manager UI or directly in the Authoring Console—either way works fine.
You must remember, though, that if you open an MPO in the Authoring Console that you created in the Operations Console, it will not have the original name you gave it. Instead, the given name will be replaced with a string starting with UIGenerated. While this does not affect the function of the MPO whatsoever, it can be very frustrating if you are trying to find a specific MPO in the Authoring Console.
No matter which method you choose, a new class has been created that can be used for delivering rules. How do you know this new class and discovery works? You can take a look at the discovered inventory information for the new class, and the new class also shows up as a valid target for a new monitor (shown in Figure 6).
Figure 6 The new class is a valid target for a monitor (Click the image for a larger view)
Discovery via Script
To create a script-based discovery in an existing management pack, load that management pack into the Authoring Console. If you are starting from scratch, open the Authoring Console and choose to create a new management pack.
Because this is a script-based discovery, the only applicable choice is to create a blank management pack. The first step in this process is to define the class that will be populated with the script, along with the class properties (attributes) of interest. FileName, FileDirectory, and FileDescription are available properties defined by this class that can be manipulated in the script, which I will show to you shortly.
In addition, the DisplayName property is inherited from the System.Entity class and can also be manipulated by script. Note that only attributes that appear in this list can be manipulated with the discovery script, so make sure any items of interest are displayed here. Also note that as each property (attribute) is selected, details about the property will appear on the right. Be sure to fill out the Display Name entry for each property (attribute). If they are left blank, the discovery information will be returned but the column headers in the OpsMgr environment, such as in the Discovered Inventory view, will be blank.
With the class defined, you can create the script-based discovery. Navigate to Health Model | Discoveries. Right-click and select New | Script and create the Discovery. There is a great deal of information here. First, the general tab allows for naming the discovery and supplying a target on which the discovery should be run. Remember, be as specific as possible when defining the target.
For the purposes of this article, Windows Computer makes sense. On the Discovered Types tab, configure the type of object to be discovered. Notice that the name of the discovered type here matches the class name defined earlier.
Next is the Configuration tab, which displays information that is automatically generated when the script is defined. (Select Configure to see the script and the time scheduled for executing the script.) Also notice the Parameters box (which can be accessed by selecting Configure | Script | Parameters). Take a look at the parameters listed—I will refer to them later in this article.
The script to drive the discovery collection process and submit the results to OpsMgr is shown in Figure 7. This is a very basic script, but it supplies the framework for the key elements that are needed in order for script-based discovery to work.
Option Explicit Dim oArgs Set oArgs = WScript.Arguments Dim oAPI 'All of the work to submit discovery data is done in the context of 'API's defined in the OpsMgr 2007 SDK. Creating the oAPI object allows 'access to the OpsMgr 2007 scripting environment Set oAPI = CreateObject("MOM.ScriptAPI") Dim SourceId, ManagedEntityId, targetComputer ' SourceId is the GUID of the discovery object that runs the script. SourceId = oArgs(0) ' ManagedEntityId is the GUID of the computer class that is targeted by the script. ManagedEntityId = oArgs(1) ' targetComputer is the Fully Qualified Domain Name ' of the computer targeted by the script. The FQDN ' is in Arg(2) of the command prompt. targetComputer = oArgs(2) Dim oFSO, oDiscoveryData, oInst 'This operation sets the stage for creating new discovery data. Note that the 'values passed to the CreateDiscoveryData function are variables that are defined 'by the command line when executed. The parameters box was displayed earler. This 'is where the command-line parameters required by the CreateDiscoveryData object are 'defined and passed to the script. Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId) 'This section defines objects needed to access the file system environment Set oFSO = CreateObject("Scripting.FileSystemObject") If (oFSO.FolderExists("C:\WServer")) Then 'Assuming a folder called WServer was found on the root of the C drive, the script proceeds to create a new 'class instance. Once it's created, a number of property (attribute) values are filled in; note that all 'three of the properties (attributes) defined on the class are used in the script along with one property '(attribute) from the windows computer class. Note the difference in how the script refers to properties '(attributes) defined in the local class vs. a class that is accessed by reference. Also note the Name field 'as defined in the script. Here the name is a friendly name that easily maps back to a known class name. ' When the management pack is saved and imported into the Operations Console and the script delivered to the ' agents, these name values will no longer be friendly, they will be converted to the appropriate class GUID. 'Normally these converted values wouldn't be seen, but if the script directly on the agent is examined, 'the difference will be seen. Note that if the script attempts to define/use a property (attribute) 'that has not been defined in the referenced class, validation errors will be displayed. Set oInst = oDiscoveryData.CreateClassInstance("$MPElement[Name='Widget.Application.Script.Discovery.WidgetAppClass']$") Call oInst.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", targetComputer) Call oInst.AddProperty("$MPElement[Name='Widget.Application.Script.Discovery.WidgetAppClass']_ /FileName$", "TestFileName.exe") Call oInst.AddProperty("$MPElement[Name='Widget.Application.Script.Discovery.WidgetAppClass']_ /FileDirectory$", "TestFileDirectory") Call oInst.AddProperty("$MPElement[Name='Widget.Application.Script.Discovery.WidgetAppClass']_ /FileDescription$", "TestFileDescription.exe") 'Class Instance has now been created so the AddInstance method of the CreateDiscoveryData class is used to add 'the completed instance. From there the script returns the discovery data to OpsMgr for further processing. Call oDiscoveryData.AddInstance(oInst) Call oAPI.Return(oDiscoveryData) End If
Importing this management pack into OpsMgr results in the correct system being discovered, as shown in Figure 8. Note that each of the properties (attributes) defined in the script are displayed in the UI with the associated values.
Figure 8 Discovery via a script (Click the image for a larger view)
When you look at the script, you will see that the value for a discovered item can be passed explicitly or through a variable. And keep in mind that, as indicated earlier, if the Display Name field for the particular property (attribute) in the class had been left blank, the column headers FileName, FileDirectory, and FileDescription (see Figure 8) would have been blank as well.
Keep Track of Versions When you are working in the Authoring Console, it is common to generate multiple revisions before you're finished. You must make sure that each revision for use in OpsMgr is saved with the version number incremented.
The version number is accessed in the authoring Console by selecting File | Management Pack Properties. Failing to increment the version number may result in the importation of a new management pack over an existing one with the same version numbers. This can lead to confusion during import.
Sealed or Unsealed? When the management pack is completed, you'll need to decide whether it should be sealed for production purposes or left unsealed. There are advantages to leaving the management pack unsealed, such as the ability to store overrides in the management pack directly. But there are more compelling reasons to seal a custom management pack before introducing it into the production environment:
- Sealing a custom management pack for use in production is a best practice.
- Sealing allows for tighter version control and tighter change control.
- Sealing allows for the use of the same operational procedures for custom as well as commercial management packs. Requiring different procedures, such as where to place overrides for custom versus commercial management packs, introduces a lot of confusion.
- Classes created in an unsealed management pack will be visible and usable only by other MPOs stored in the same management pack. Sealing allows objects to be usable regardless of where the MPO is stored.
- A library of unsealed "source" management packs can be maintained under control of the OpsMgr administrators to prevent accidental or unintended changes.
Fully understanding targets is instrumental to success with OpsMgr. A poster called Rule and Monitor Targeting Best Practices is available in .pdf format at go.microsoft.com/fwlink/?LinkId=125048. You'll find it to be a very helpful reference for understanding different targets and when they might be appropriate to use.
Steve Rachui is a Dedicated Support Engineer with the Premier Field Engineering group at Microsoft. He has supported SMS since version 1.2 and MOM from version 2000. Steve can be reached at firstname.lastname@example.org.