Welcome to MSDN Blogs Sign in | Join | Help

Program Manager position in OpsMgr Team

We are looking for a program manager to help extend the product's capabilities in the area of Network Monitoring. Here is a link to the job posting:

http://members.microsoft.com/careers/search/details.aspx?JobID=80B78DD1-31B6-4676-9F03-D26AE4516C3C

Which discovery found the object

One of the interesting challenges that I have seen some customers experience is understanding which discovery discovered a particular object. There are a number of way to do this. One of the ways you can do this is by using powershell.

Here are the steps:

1 - Right click on the object that you want to investigate and select "Open" -> "Operations Manager Shell"

2 - Run the attached script.

Problem with the IIS Modules QFE (957123)

We have found a problem with the IIS Modules QFE and working on fixing it. In the meanwhile, the binaries for the QFE have been removed from the download site. The issue is in the setup code which causes the SDK and Configuration services on the RMS to be stopped and disabled. The setup code of the QFE may also modify the follow registry value on the RMS: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Server Management Groups\<MG NAME>\IsRootHealthService to 0.

If you installed the QFE on your RMS server and seeing the SDK service and Config service as disabled, you need to do the following to resolve the issue:

1 – If the registry key mentioned above was modified, set it back to 1

2 – Enable the SDK and Config services to their previous startup state

3 – Start the SDK and Config services.

 

 

 

 

IIS 7.0 Management Pack is now on the MP Catalog!

In order for the IIS 7.0 MP to properly work, you will need to install an agent QFE which drops a new module that the MP uses for discovery and monitoring.  Here is the link to the QFE: http://www.microsoft.com/downloads/details.aspx?FamilyID=f82ef6b3-a08e-4295-b9e3-fb78a74aefa8&DisplayLang=en

 

Also, you will need to install an IIS 7.0 QFE to resolve a small memory leak issue with IIS 7.0. The path to the QFE is: http://support.microsoft.com/kb/958661

 

The requirement for both QFEs is documented in the MP guide, but I figured I mention it one more time as these are pretty important.

Windows Server 2008 Cluster MP is now available!

I have seen a number of questions on this in the past so I am happy to announce that we just released the Windows Server 2008 Failover Cluster MP. You can now download it on:

http://www.microsoft.com/downloads/details.aspx?FamilyId=AC7F42F5-33E9-453D-A923-171C8E1E8E55&amp;displaylang=en&displaylang=en

Big thanks to those who helped validate the MP.

 

Great new blog

I just got a mail today from Marco Shaw about a great new blog authored by Daniele Grandini and Fabrizio Guaitolini. I recommend you check it out. The latest blog post is about building monitors that work only during business hours. This is something that I have been wanting to blog about for a while but didn’t have time yet. Looks like these guys wrote a great article about it.

http://nocentdocent.wordpress.com/

 

What if my discovery script fails?

Discovery is a very core feature of a management pack. Bugs in discovery can literally screw up the whole management pack. I saw an example of this today when I was debugging a problem where if the user disabled a network card, the WMI calls that I was making were returning no data and also a pretty generic error code. In my case, I wasn’t properly handling the condition and the result was that my discovery returned an empty list of discovered objects. This was interpretted by OpsMgr runtime as if the application was no longer installed and therefore, the objects representing the application were deleted. From the runtime perspective, this is completely the right behavior.

In case you are not familiar with how discovery data is handled, let me explain this a bit. In OpsMgr, there are two types of discovery data:

Snapshot - This is the default type of discovery data submitted by MP discoveries. When you submit this type of discovery data, basically you are saying "Whatever I am returning in the list of discovered objects, their properties and relationships is all that exists.". Let me explain what this means. Lets say that you wrote a management pack to discover SQL databases. The first time the discovery ran, it returned 2 databases called A and B. The next time the same discovery ran on the same server, it returned databases A and C. When the discovery data is actually processed on a management server, database B will be automatically deleted and database C will be added. Basically snapshot discovery is just like "last write wins". Whatever discovery data was submitted the last time the discovery ran, that is the data that will be stored into the OpsMgr DB and this data will be used for monitoring. The really nice thing about the functionality of Snapshot discovery is that as an MP author you dont need to have any logic in your management pack to figure out what you need to discover and what you discovered last time but is no longer available. All you need to do is execute your discovery logic and let OpsMgr take care of updating the DB based on the last data that your discovery returned.

Incremental - This is an advanced way to return discovery data and in most cases does not need to be used. With incremental discovery data, you can say "Add database A" or "Remove database B" without affecting the other databases you previously discovered. Unlike Snapshot discovery, the only changes that will take place are the changes that you specifically asked for by telling OpsMgr to add or remove a particular object.

Now let’s get back to the original problem. Given that the default type of discovery is Snapshot, I was causing all the alerts, performance, event and availability data to be deleted when my discovery was failing to execute properly and returning an empty list of discovered objects. From the operator perspective, this is a pretty bad experience as all of a sudden, a bunch of alerts would just vanish and the instances representing the application would vanish as well. The first solution that comes to mind is very simple. If I fail to retrieve the data from WMI, lets just not return any discovery data. This solution is definitely better as it does not cause the alerts and the objects that represent the application to vanish. The annoying side affect is that I start getting an alert saying that the OpsMgr agent ran a discovery script and it didn’t return any data. The exact title of the alert is 'Script or Executable Failed to Run". The problem with this alert is that all it basically tells you is that even though the script was expected to return some discovery data, it didn’t.

There is however a third option which puts you as the MP author in the driver seat. Basically what you want to do is tell OpsMgr something along the lines of "I am unable to query WMI to figure out whether the application is present or not, so I am not going to tell you anything, but I also don’t want you to start complaining and generating warnings."

In order to do this, you will need to switch to using Incremental discovery as it provides you with more granular control over the discovery data.

Basically here is what you want to do when you need to handle a failure in your discovery script and dont want to return any data, yet you dont want the existing data to be deleted and you dont want to see the generic warning about script execution failure.

 

‘Standard discovery code

Set oAPI = CreateObject("MOM.ScriptAPI")

Set oDiscoveryData = oAPI.CreateDiscoveryData(0,SourceId,ManagedEntityId)

 

If wasAbleToGetInfoFromWMI = false Then

‘Instead of Snapshot discovery, submit Incremental discovery data

oDiscoveryData.IsSnapshot = false

oAPI.LogScriptEvent “SampleScript.vbs”, 6125, 4, “Couldn’t get data”

      Call oAPI.Return (oDiscoveryData)

Exit Sub

End If

 

'Do the standard discovery 

 

Call oAPI.Return (oDiscoveryData)

 

The key in the sample script above is highlighted in yellow. The highlighted line tells OpsMgr that we are submitting Incremental rather than Snapshot discovery data. The rules of incremental discovery data are that we can tell OpsMgr to add or delete particular instances that we discovered in the past execution of the discovery. In this case, we didn’t specify that we want to remove or add any instances. So basically we are saying “Do nothing”. This is exactly what we want as we can’t access the instrumentation at point and don’t even know whether the application that we previously discovered is still there or not. The line after the highlighted line is an example of how you can log an event to the OpsMgr event log from the script. By logging the event, you are alerting the operator that something is wrong in a much more meaningful way.  Now you can create a simple alerting rule which will cause a warning alert to be create in OpsMgr when you are unable to perform the discovery. In that warning alert, you can put the information that the operators need in order to troubleshoot the issue, rather than presenting them with a generic “Script execution failure” warning which can be hard to troubleshoot.

By the way, here is a link to the documentation for the LogScriptEvent method which explains how to call it and what are the meanings of the parameters: http://msdn.microsoft.com/en-us/library/bb437630.aspx

Note: Other than handling a script execution failure or if you have a specific need to use incremental discovery, you should always use Snapshot discovery.

Populating groups from external sources

Groups are one of the most used areas of functionality in Operations Manager. When you are creating overrides, setting up role based security, scoping views, or running reports you are most likely using groups.  Generically speaking, groups allow you to express the fact that an arbitrary number of instances are related in some way. One of the most common scenarios is grouping of servers to express the fact that some servers are for example production servers and some servers are test/dev servers.  You can then use the "Production Servers" group when creating a user role to grant monitoring access to these servers in Operations Manager. 

Before we look at how a group can be populated from an external source such as Active Directory, lets examine what is actually a group and what does it mean for an object such as a computer or a database to be a member of a group.   

All groups in Operations Manager are objects whose base type is System.Group.  So when you create a new group in Operations Manager, the following MP elements are created for you:

Class - This class is derived from Microsoft.SystemCenter.InstanceGroup (this class is turn derived from System.Group). The class definition inside the MP looks like this:

<ClassTypes>

        <ClassType ID="UINameSpaced20b434de436466f835487b6d855bbe2.Group" Accessibility="Public" Abstract="false" Base="MicrosoftSystemCenterInstanceGroupLibrary!Microsoft.SystemCenter.InstanceGroup" Hosted="false" Singleton="true" />

      </ClassTypes> 

I highlighted the fact that the new class is marked as a singleton. In the computer science world, a singleton class means that there will always be only a single instance of the specified class. In the case of Operations Manager, this means that there is no need to create a discovery to discover an instance of the group. If a class is marked as a singleton, Operations Manager will automatically create a single instance of the class. 

I also highlighted the fact the class is marked as "Hosted=false". By default, when a class is marked as "Hosted=false" instances of this class will be managed by the RMS. Because the instance of the class which represents our group is managed by the RMS, it means that any discoveries/monitors/rules/tasks/diagnostics/recoveries will also run on the RMS. By the way, this explains the problems you see when you target a monitor to a group and it doesn’t work on any agents. 

Discovery - The UI also creates a discovery and this discovery is what actually will make computers or other objects be members of the group. Here is a sample discovery:

<Discovery ID="UINameSpaced20b434de436466f835487b6d855bbe2.Group.DiscoveryRule" Enabled="true" Target="UINameSpaced20b434de436466f835487b6d855bbe2.Group" ConfirmDelivery="false" Remotable="true" Priority="Normal">

        <Category>Discovery</Category>

        <DiscoveryTypes>

          <DiscoveryRelationship TypeID="MicrosoftSystemCenterInstanceGroupLibrary!Microsoft.SystemCenter.InstanceGroupContainsEntities" />

        </DiscoveryTypes>

        <DataSource ID="GroupPopulationDataSource" TypeID="SystemCenter!Microsoft.SystemCenter.GroupPopulator">

          <RuleId>$MPElement$</RuleId>

          <GroupInstanceId>$MPElement[Name="UINameSpaced20b434de436466f835487b6d855bbe2.Group"]$</GroupInstanceId>

          <MembershipRules>

            <MembershipRule>

              <MonitoringClass>$MPElement[Name="MicrosoftWindowsLibrary6163930!Microsoft.Windows.Computer"]$</MonitoringClass>

              <RelationshipClass>$MPElement[Name="MicrosoftSystemCenterInstanceGroupLibrary6163930!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass>

              <Expression>

                <RegExExpression>

                  <ValueExpression>

                    <Property>$MPElement[Name="MicrosoftWindowsLibrary6163930!Microsoft.Windows.Computer"]/NetbiosComputerName$</Property>

                  </ValueExpression>

                  <Operator>ContainsSubstring</Operator>

                  <Pattern>prodsrv</Pattern>

                </RegExExpression>

              </Expression>

            </MembershipRule>

          </MembershipRules>

        </DataSource>

      </Discovery>

The above XML might look a little complicated, but it can be explained.

1 - The discovery target is "UINameSpaced20b434de436466f835487b6d855bbe2.Group". One might ask, but how is this going to work? The class represents the group and we have no discoveries to discover this class. The reason this work is that the class is marked as a singleton and this means that the RMS will automatically create an instance of the class. This is why the discovery is going to work.

2 - The first highlighted line tells us that all that this discovery really discovers is relationships of type Microsoft.SystemCenter.InstanceGroupContainsEntities. We can use the following PS command to find out what does this relationship really represent:

(Get-RelationshipClass -Name:'Microsoft.SystemCenter.InstanceGroupContainsEntities').Base.GetElement().Name

The output of the cmdlet is the following: System.Containment 

So this basically tells us that all that the discovery above do is create containment relationships.  This is interesting because this tells us that the group membership feature is built purely on creating containment relationships between an object that represents a group and the object which is member of the group.

The second highlighted line tells us that this discovery uses a datasource module called "Microsoft.SystemCenter.GroupPopulator". This datasource is at the core of the groups feature in OperationsManager. This datasource uses the configuration that its passed (highlighted in yellow) and generates a T-SQL query which is executed against the Operations Manager DB every 60 seconds. The results of this query are the objects that meet the criteria that the user specified while creating the group. For each one of the objects which the T-SQL query returns, the datasource module creates a containment relationship. The source of the this relationship is the group and the target is the object which met the criteria. One might ask, but how does the datasource know the type of the group to create a containment relationship with? Well that is specified using the GroupInstanceID parameter  (highlighted in green)

So if 50 objects met the user specified criteria, the datasource will return 50 relationships. Then these relationships are stored into the DB by the agent running on the RMS. Now we have a group with 50 members.

In essence, all that it means for an object such as a computer to be a member of a group is to have a containment relation whose source is the group and the target is the object. For the groups created in the UI, you can only use the group calculation datasource module which queries the operational DB and based on the results creates these containment relationships. In a lot of the cases, querying the operational database is sufficient, but sometimes you might need to query a different source of information, for example Active Directory. The goal of such query would be to say "Add all computers that are members of an OU or perhaps meets a more complex LDAP query to a group in Operations Manager". One way I have seen people try to make this work is using the OrganizationalUnit property of a computer. While this works for this particular scenario, there are scenarios where using the property will not help you. In such cases, the natural question to ask is "Can I populate a group using information from another source such as a CSV file, CMDB, Active Directory or some other source?". The answer is "Absolutely Yes!". What you need to do is replace the discovery which queries the Operations Manager DB with a discovery that reads a CSV file or does a more complex LDAP query against AD and then using this information return relationship information from you discovery. As long as the discovery is properly written, it will result in the group being populated with the right objects and you can use this group anywhere you use other groups created in the UI. Here is an example of how such discovery would look like:

 <Discovery ID="ADBasedGroupDemo.SampleDiscovery" Enabled="true" Target="SC!Microsoft.SystemCenter.RootManagementServer" ConfirmDelivery="true" Remotable="true" Priority="Normal">

        <Category>Discovery</Category>

        <DiscoveryTypes>

          <DiscoveryClass TypeID="GroupPopulationDemo.ADBasedGroup" />

        </DiscoveryTypes>

        <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedScript.DiscoveryProvider">

          <IntervalSeconds>300</IntervalSeconds>

          <SyncTime />

          <ScriptName>ADBasedGroupDiscovery.vbs</ScriptName>

          <Arguments>$MPElement$ $Target/Id$</Arguments>

          <ScriptBody><![CDATA[Dim SourceId

Dim ManagedEntityId

Dim oAPI

Dim oDiscoveryData

 

SourceId                = WScript.Arguments(0)

ManagedEntityId         = WScript.Arguments(1)

 

Set oAPI                         = CreateObject("MOM.ScriptAPI")

Set oDiscoveryData         = oAPI.CreateDiscoveryData(0,SourceId,ManagedEntityId)

 

Set objConnection = CreateObject("ADODB.Connection")

 

objConnection.Open "Provider=ADsDSOObject;"

 

Set objCommand = CreateObject("ADODB.Command")

objCommand.ActiveConnection = objConnection

 

objCommand.CommandText = "<LDAP://OU=MS,dc=contoso,dc=com>;(objectCategory=computer);dNSHostName;subtree"

 

Set objRecordSet = objCommand.Execute

 

Set groupInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='GroupPopulationDemo.ADBasedGroup']$")

 

While Not objRecordSet.EOF

 

Set serverInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Windows!Microsoft.Windows.Computer']$")

serverInstance.AddProperty "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$",objRecordSet.Fields("dNSHostName")

 

Set relationshipInstance = oDiscoveryData.CreateRelationshipInstance("$MPElement[Name='GroupPopulationDemo.ADBasedGroupContainsWindowsComputers']$")

 

relationshipInstance.Source = groupInstance

relationshipInstance.Target = serverInstance

 

oDiscoveryData.AddInstance relationshipInstance

 

objRecordSet.MoveNext

Wend

 

objConnection.Close

 

Call oAPI.Return(oDiscoveryData)

                      ]]></ScriptBody>

          <TimeoutSeconds>120</TimeoutSeconds>

        </DataSource>

      </Discovery>

In this case, the discovery is using the Microsoft.Windows.TimedScript.DiscoveryProvider which I am sure many of you used before to do discovery. The only two differences are:

1 - The discovery only returns containment relationship as this is all we need to populate a group

2 - The discovery is targeted to the RMS. I could of targeted the discovery to the type that represents the group, but for this example I targeted to the RMS to explicitly show that the discovery will run on the RMS.

As you can see all this discovery does is execute an LDAP query and then based on the results it creates containment relationships.  In this case the script enumerates all computer objects in the OU called MS and then adds each of these computer objects to my group.

Hopefully this article showed how you can populate groups not only based on information in the Operations Manager DB, but also from other places such as Active Directory or another source of information. Attached to the blog post is a complete MP which shows this example working end to end.

If you have questions or run into any issues making this sample work in your dev/test environment, please let me know.

VladJ is now a blogger

If you are a partner or attended MMS or ITForum or work with OpsMgr for a while I am pretty sure you would recognize the name. The good news is that now is a blogger and has a blog on blogs.msdn.com so I am sure there will be some good stuff posted on his blog. Check it out!

 http://blogs.msdn.com/vladj/default.aspx

 

Configuring rules to run during business hours only

I have heard the question about creating rules that execute only during a certain set of hours many times in the last while. While its not straight forward, it is still possible. Attached to the this blog post is a MHTML file which I wrote that describes the steps of how this can be done and also gives you some clues as to how this can be done for a monitor. The MHTML file includes step by step instructions on how this can be done and also provides screen shots. The first time you do it, it will probably take 10-15 minutes. However the next time you do it, I think it will be pretty quick.

If you have questions about the steps written in the MHTML file, please leave me a comment. If you find this useful, please also leave me a comment and I can put together a sample for a monitor.

Posted by Boris Yanushpolsky | 17 Comments
Filed under:

Attachment(s): Scheduled Rules.mht

What is the state of a particular monitor for all of my objects?

I saw an interesting question today on one of the newsgroups. Basically the question was "How can I find out the state of a particular monitor across all the objects that I have". Unfortunately, a state view in the OpsMgr console doesn’t provide you this information. Instead it provides you the overall state of objects of a particular type (Logical Disks for example). However the SDK has a very convenient function to accomplish this. The attached script takes two parameters:

MonitorName - This is the name of monitor as it appears in the UI

TargetName - This is the name of the target/class as it appears in the UI.

Here is how you run the cmdlet:

1 - Open the OpsMgr CommandShell

2 - Type the following: C:\InstanceMonitorState.ps1 -monitorName:'Logical Disk Free Space' -targetName:'Windows Server 2008 Logical Disk'

Here is the output the you will see:

dc1.contoso.com;E: - Success - 9/11/2008 9:29:50 PM
dc2.contoso.com;C: - Success - 9/11/2008 8:24:17 PM
dc1.contoso.com;C: - Success - 9/11/2008 9:29:49 PM

 

MPViewer 1.7 - Now works with latest E12 MP

Thanks Stefan for reporting that MPViewer export to HTML functionality didn’t work with the latest version of the E12 MP. This was caused by a bug in MPViewer. The new version is attached to this blog post. I also some more minor features such as frequency for performance monitors as well breaking out the monitors by type (unit, dependency, aggregate).

If you see any other issues looking at MPs, please drop me a a message.

Posted by Boris Yanushpolsky | 24 Comments
Filed under:

Attachment(s): MPViewer.zip

Automating port monitoring using PowerShell

A while I wrote a blog entry about how you can automate the creation of URL monitoring logic in OpsMgr using PowerShell. One of the questions I have received is "how do you do the same thing for port monitoring ?". Attached is a script that demonstrates how this can be done.

In order to run the script, you need to open the OpsMgr Command Shell and run the following:

CreatePortMonitoring.ps1 -serverName:'TargetServerName.contoso.com' -portNumber:'80' -pollIntervalSeconds:'120' -watcherNodes:"watcher1.contoso.com", "watcher2.contoso.com" -displayName:'Test URL monitoring' -targetMP:'Port Monitoring MP'

Note: If you specify the interval less than 1 minute, the monitoring should still work but you will not be able to load the configuration page and will see a UI error.....

In one of my future posts I will try to explain how this scripts works for those of you who want to automate execution of MP templates.

MPViewer 1.6 - Exporting to Excel

This updated version of MPViewer will allow you to export data to Excel in addition to the HTML format which was available before. Now that you are able to export to excel, I hope it will make it easier to understand MP contents.

This update also includes my first stab at retrieving configuration of event log rules (collection and alerting). This will retrieve the following properties from "simple" rules:

EventId,EventSource,LogName

What I mean by "simple" rules is rules that filter by one event ID, and one source. I will try to add support for more complex rules in a later version.

As always, feedback is appreciated.

Posted by Boris Yanushpolsky | 9 Comments

Attachment(s): MPViewer.zip

Module Explorer V2

In v1 of module explorer I enumerate code based modules and then populated the tree view with composite module that rely on the code modules. In this version I added another view which instead groups modules by the MP in which the module is defined. This should help in some scenarios where you just want to find a particular module and see its settings and configuration.

 

Posted by Boris Yanushpolsky | 5 Comments

Attachment(s): ModuleExplorer.zip
More Posts Next page »
 
Page view tracker