Welcome to MSDN Blogs Sign in | Join | Help

Now that we are aware of the internals of syslog module, internals of managed discovery data mapper module, this blog-post aims at providing an example of how various modules in OM 2007 can be connected, configured and leveraged for various purposes.

Let us define the health of a host such that any syslog message generated by it with a severity less than 4 indicates something bad. So, how do we make this happen in OM 2007? We would first need a managed type. So, lets define that:

<ClassType ID="Demo.Syslog.IP" Accessibility="Public" Base="System!System.LogicalEntity" Hosted="false" Abstract="false">

  <Property ID="IP" Type="string" Key="true" CaseSensitive="false" />

</ClassType>

 

Now, that we have this managed type, we need a discovery rule to submit various discovery instances of it. Let's add that to our demo MP too.

 

<Discovery ID="Demo.Syslog.Discovery" Target="SCLibrary!Microsoft.SystemCenter.RootManagementServer" Enabled="true" ConfirmDelivery="true">

  <Category>Discovery</Category>

  <DiscoveryTypes>

    <DiscoveryClass TypeID="Demo.Syslog.IP" />

  </DiscoveryTypes>

  <DataSource ID="DS" TypeID="Demo.Syslog.Discovery.ModuleType" />

</Discovery>

 

The data source module 'Demo.Syslog.Discovery.ModuleType' used above would basically be a combination of 2 modules: Syslog and Discovery Data Mapper. The syslog receiver module outputs syslog data which has the hostName element which is used by discovery data mapper module to convert it into discovery data for 'Demo.Syslog.IP' class type. See attached MP for details.

Now, that instances are available in OM 2007, they can be viewed by creating a state view targeted towards the new type 'Demo.Syslog.IP' defined. The attached MP already defines one in a new folder 'Syslog Views' and so importing it into an existing installation of OM 2007 should suffice.

Next is addition of a monitor type and monitor to compute the health of the ''Demo.Syslog.IP' class type. For computation of the state, we would need information about the last message generated by the host. Let us add a few more properties to the class type then:

<ClassType ID="Demo.Syslog.IP" Accessibility="Public" Base="System!System.LogicalEntity" Hosted="false" Abstract="false">

  <Property ID="IP" Type="string" Key="true" CaseSensitive="false" />

  <Property ID="LastFacility" Type="int" Key="false" />

  <Property ID="LastSeverity" Type="int" Key="false" />

  <Property ID="LastPriority" Type="int" Key="false" />

  <Property ID="LastPriorityName" Type="string" Key="false" />

  <Property ID="LastTimeStamp" Type="string" Key="false" />

  <Property ID="LastMessage" Type="string" Key="false" />

</ClassType>

 

Discovery data submitted by the discovery data mapper module will retreive information of the above extra fields from syslog message itself. We define the monitor type 'Demo.Syslog.MonitorType' to do a comparison such that the last facility value is greater than or equal to a least facility value, and that the priority name value matches a regular expression, and so on. See the attached MP for more details.

Now, that such a monitor type is defined, let us see how we use this to define a monitor associated with the 'Demo.Syslog.IP' class type.

<UnitMonitor ID="Demo.Syslog.Monitor" TypeID="Demo.Syslog.MonitorType" Target="Demo.Syslog.IP" Accessibility="Public" Enabled="true" ParentMonitorID="Health!System.Health.AvailabilityState" ConfirmDelivery="true">

  <Category>Alert</Category>

  <AlertSettings AlertMessage="Demo.Syslog.AlertMessage">

    <AlertOnState>Error</AlertOnState>

    <AutoResolve>true</AutoResolve>

    <AlertPriority>High</AlertPriority>

    <AlertSeverity>Error</AlertSeverity>

    <AlertParameters>

      ...

    </AlertParameters>

  </AlertSettings>

  <OperationalStates>

    <OperationalState HealthState="Success" MonitorTypeStateID="Healthy" ID="Regular"/>

    <OperationalState HealthState="Error" MonitorTypeStateID="Unhealthy" ID="Iregular"/>

  </OperationalStates>

  <Configuration>

    <LastFacility>$Target/Property[Type="Demo.Syslog.IP"]/LastFacility$</LastFacility>

    <LastSeverity>$Target/Property[Type="Demo.Syslog.IP"]/LastSeverity$</LastSeverity>

    <LastPriority>$Target/Property[Type="Demo.Syslog.IP"]/LastPriority$</LastPriority>

    <LastPriorityName>$Target/Property[Type="Demo.Syslog.IP"]/LastPriorityName$</LastPriorityName>

    <LastTimeStamp>$Target/Property[Type="Demo.Syslog.IP"]/LastTimeStamp$</LastTimeStamp>

    <IP>$Target/Property[Type="Demo.Syslog.IP"]/IP$</IP>

    <LastMessage>$Target/Property[Type="Demo.Syslog.IP"]/LastMessage$</LastMessage>

    <MinutesFrequency>10</MinutesFrequency>

    <LeastFacility>0</LeastFacility>

    <LeastSeverity>4</LeastSeverity>

    <LeastPriority>0</LeastPriority>

    <PriorityNameRegexPattern>.*</PriorityNameRegexPattern>

    <TimeStampRegexPattern>.*</TimeStampRegexPattern>

    <HostNameRegexPattern>.*</HostNameRegexPattern>

    <MessageRegexPattern>.*</MessageRegexPattern>

  </Configuration>

</UnitMonitor> 

In the above monitor definition, we also specified an alert to be generated when the state of an entity goes unhealthy. The above configuration means generate an alert and compute the state of an entity of class type 'Demo.Syslog.IP' as unhealthy when

  • the facility is less than 0 or
  • severity is less than 4 or
  • priority is less than 0 or
  • priority name/time stamp/host name/message doesn't match the regular expression ".*".

Overrides are defined for these threshold values which can be modified in the authoring pane of OM 2007 Console.

To summarize, the attached DEMO MP once imported into the system enables syslog listening on root management server and creates instances of various host names it discovers. At the same time, it computes health of each host which can be overridden using overrides for the 'Demo.Syslog.MonitorType' monitor type.

SCOM 2007 resource kit tools has been released and can be found here

Two of these are of particular interest for AEM:

AEM Validation: This tool can help validate that AEM is working once it has been enabled on a SCOM 2007 installation. This tool can be found here.

AEM Generic Mapping: This tool maps a lot of unknown application errors to more specific information. This tool basically comprises of a new MP that needs to be imported into the SCOM system.

I have posted a few updates to the MPs attached to the 2 blogs:

 Kindly look at them if you have used the prior MPs before.

In the last blog post, it was described how overrides for AEM applications/error groups can be changed via submitting discovery data for Microsoft.SystemCenter.CM.AEM.MonitorOverride through a management pack. Same can be achieved via writing code against the SDK service. Below is a snippet of code that can help achieve the same.

namespace AEM_Samples

{

  using System;

  using ObjectModel = System.Collections.ObjectModel;

 

  using Microsoft.EnterpriseManagement;

  using Configuration = Microsoft.EnterpriseManagement.Configuration;

  using ConnectorFramework = Microsoft.EnterpriseManagement.ConnectorFramework;

  using Monitoring = Microsoft.EnterpriseManagement.Monitoring;

 

  public class AEMDemoClass

  {

 

    private void SetOverrides()

    {

      // Connect to the sdk service on the local machine

      ManagementGroup localManagementGroup = new ManagementGroup("komalk-test");

 

      // Retrieving information about ClientMonitoring library MP

      Configuration.ManagementPack aemLibraryMp = localManagementGroup.GetManagementPack(

          "Microsoft.SystemCenter.ClientMonitoring.Library",

          "9396306c2be7fcc4",

          new Version("6.0.5000.0"));

 

      // We need to create as many CustomMonitoringObjects as we have overrides

      // to be defined

      // So, let's figure out how many applications as of now the

      // OpsMgr system knows that meet the given requirement (appName = 'sample.exe'

      // appVersion like '%'.

 

      // Let's 1st get class type for application

      Configuration.ManagementPackClass applicationClass =

          aemLibraryMp.GetClass("Microsoft.SystemCenter.CM.AEM.Application");

 

      Configuration.MonitoringClass applicationMonitoringClass =

          localManagementGroup.GetMonitoringClass(applicationClass.Id);

 

      ObjectModel.ReadOnlyCollection<Monitoring.MonitoringObject> apps =

          localManagementGroup.GetMonitoringObjects(

          new Monitoring.MonitoringObjectCriteria(

              "ApplicationName = 'sample.exe'",

              applicationMonitoringClass));

 

      if (apps.Count == 0)

      {

        // there are no Apps whose override value can be set;

        return;

      }

 

      // Let's get class type id for Microsoft.SystemCenter.CM.AEM.MonitorOverride

      // defined in MP: Microsoft.SystemCenter.ClientMonitoring.Library

      Configuration.ManagementPackClass monitorOverrideClass =

          aemLibraryMp.GetClass("Microsoft.SystemCenter.CM.AEM.MonitorOverride");

 

      Configuration.MonitoringClass monitorOverrideMonitoringClass =

          localManagementGroup.GetMonitoringClass(monitorOverrideClass.Id);

 

      // Let's get information about various elements on this class

      Configuration.MonitoringClassProperty managedEntityIdProperty =

          monitorOverrideMonitoringClass.GetMonitoringProperty("ManagedEntityId");

 

      Configuration.MonitoringClassProperty errorCountProperty =

          monitorOverrideMonitoringClass.GetMonitoringProperty("HitCountThresholdValue");

 

      Configuration.MonitoringClassProperty userCountProperty =

          monitorOverrideMonitoringClass.GetMonitoringProperty("UniqueUserThresholdValue");

 

      Configuration.MonitoringClassProperty computerCountProperty =

          monitorOverrideMonitoringClass.GetMonitoringProperty("UniqueComputerThresholdValue");

 

      // For all these applications, lets set new override values for all 3

      // basic threshold parameters

      // we achieve this by submitting a MonitorOverride information about each

      // to submit we need to add each instance of CustomMonitoringObject to

      // discovery data below

 

      // Discovery Data would contain class Instance for AEM Crash Listener

      ConnectorFramework.IncrementalMonitoringDiscoveryData discoveryData =

          new ConnectorFramework.IncrementalMonitoringDiscoveryData();

 

      for (Int32 idx = 0; idx < apps.Count; idx++)

      {

        Monitoring.CustomMonitoringObject aemMonitorOverride =

            new Monitoring.CustomMonitoringObject(monitorOverrideMonitoringClass);

 

        // Key:

        aemMonitorOverride.SetMonitoringPropertyValue(

            managedEntityIdProperty,

            apps[idx].Id);

 

        // Non-Keys:

        aemMonitorOverride.SetMonitoringPropertyValue(errorCountProperty, 100);

        aemMonitorOverride.SetMonitoringPropertyValue(userCountProperty, 150);

        aemMonitorOverride.SetMonitoringPropertyValue(computerCountProperty, 200);

 

        discoveryData.Add(aemMonitorOverride);

      }

 

      // Committing makes sure the data is submitted to the system now

      discoveryData.CommitForUserDiscoverySource(localManagementGroup);

    }

  } // end of class

} // end of namespace

More about inserting discovery data can be read here.

 

It should be noted that this approach only takes care of submitting overrides for applications that are known to OpsMgr and match given criteria. Where as the MP approach takes care of applications new to OpsMgr have overrides defined/submitted periodically.

 

Various error groups and applications that report crashes over period of time can be seen in AEM Views.

The state of each error group is controlled by 3 thresholds: error/crash/hit count, unique users affected, unique computers affected. By default, the threshold value for all these 3 parameters is 50. In other words, if any error group has a error count and/or unique users affected count and/or unique computers affected count exceeding 50 then the health of corresponding error group goes red affecting it's availability aspect.

The state of each application is also controlled by 3 direct thresholds: error/crash/hit count, unique users affected, unique computers affected. But it is also affected by state of any of the error groups it hosts/encompasses. The threshold for the 3 basic thresholds is 50 here too.

These basic threshold values can be changed by submitting an instance of Microsoft.SystemCenter.CM.AEM.MonitorOverride for each error group/application whose threshold values need to be changed. This class type has 4 properties: ManagedEntityId and new value for the 3 thresholds. The ManagedEntityId can correspond to either ID of a watson bucket/application error group or ID of an application.

Attached is a sample/demo MP that shows how to change the threshold values. Let's analyze various parts of the MP.

<Discovery ID="ChangeMyAppThresholdValue" Target="AEMLib!Microsoft.SystemCenter.CM.AEM.CrashListener">

  <Category>Discovery</Category>

  <DiscoveryTypes>

    <DiscoveryClass TypeID="AEMLib!Microsoft.SystemCenter.CM.AEM.MonitorOverride" />

  </DiscoveryTypes>

  <DataSource ID="DS" TypeID="ApplicationThresholdDefiner">

    <!-- Properties for Application(s) whose threshold value needs to be changed -->

    <ApplicationName>= 'Foo.exe'</ApplicationName>

    <ApplicationVersion>like '%'</ApplicationVersion>

    <HitCountThresholdValue><!-- the new value-->100</HitCountThresholdValue>

    <UniqueUserThresholdValue><!-- the new value -->100</UniqueUserThresholdValue>

    <UniqueComputerThresholdValue><!-- the new value -->100</UniqueComputerThresholdValue>

  </DataSource>

</Discovery>

The above discovery tells us that the new threshold values for all the 3 basic monitors is going to be 100 for all applications whose applicationName is foo.exe irrespective of their applicationVersion.

Let's look at the composition of the module type ApplicationThresholdDefiner used above.

      <Composition>

        <Node ID="DiscoveryMapper">

          <Node ID="Filter">

            <Node ID="OleDbProbe">

              <Node ID="Scheduler" />

            </Node>

          </Node>

        </Node>

      </Composition>

There are 4 modules used: Scheduler (System.Scheduler from System.Library MP) followed by OleDbProbe, followed by Filter (System.ExpressionFilter from System.Library MP) and then followed by DiscoveryMapper.

The Scheduler module is configured to 15 minutes in the MP and can be changed. What does this indicate? This indicates that if new applications are discovered by the system which meet the criteria defined by user, then in 15 minutes (worst case), a threshold override would also be submitted to the system.

The OleDbProbe module retrieves the managed entity id for one or more applications meeting given criteria.

The Filter module ensures that there's at least one application known to OpsMgr via AEM that meets given criteria.

The DiscoveryMapper module is responsible for submitting override data to the system in form of instances of the class Microsoft.SystemCenter.CM.AEM.MonitorOverride defined in Microsoft.SystemCenter.ClientMonitoring.Library MP.

Similar composition has been provided in attached MP to change threshold values for 1 or more error groups.

It should be noted that the state change for all error groups and applications is computed every 15 minutes. As a result, with the attached sample MP, it can take upto 30 minutes to reflect the override changes in the OpsMgr console.

This max. value can be reduced to 15 minutes by reducing the configuration of scheduler module from 15 minutes to 30 seconds or something like that. However, reducing the configuration for scheduler module would have an impact on performance as that determines how frequently the OpsMgr DB is hit with queries as defined in the compositions in the sample MP.

However, based on user requirements, the value can even be bumped up or changed to a schedule basis as well.

The earlier post on Ole-Db module was all about what the module does. This post is more about what one can do with the module. Specifically, this post would talk about how connection strings can be constructed dynamically using RunAs accounts. This post will also demonstrate (with examples) how other modules can use data generated by Ole-Db module.

A new RunAs profile is defined in MP (Management Pack) as follows and using OpsMgr Console, one should be able to add various RunAs accounts for different machines to it.

<SecureReferences>

  <SecureReference ID="Demo.OleDB.ActionAccount" Accessibility="Public" Context="System!System.Entity" />

</SecureReferences>

The above RunAs profile can be used to make connections to DB in a couple of ways:

1. An easy way to this is to specify credentials explicitly in the ConnectionString configuration element of Ole-Db Probe module as follows:

<ConnectionString>Provider=msdaora;Data Source=MyOracleDB;User Id=$RunAs[Name="Demo.OleDB.ActionAccount"]/UserName$;Password=$RunAs[Name="Demo.OleDB.ActionAccount"]/Password$</ConnectionString>

2. Another way is to create a composite module type and associating the RunAs profile to that module type. This way one can use trusted connections, i.e., 'Integrated Security=true'. 

See attached MP for more information.

In order to use output from OleDb module as configuration for other module, one should first understand the structure of OleDb data. More about it can be found here. OleDb module can be connected to any module that takes either System.BaseData or System.OleDbData as its input type (both datatypes defined in System.Library MP). Some example modules from System.Library MP that can be connected to OleDb would be System.Secure.CommandExecuterProbe, System.ExpressionFilter, System.Event.GenericDataMapper, etc.

Suppose, if we need the result of 1st column and 2nd row to be passed to the next module, it can be referred in the configuration as:

$Data/Columns[2]/Column[1]$

The configuration for System.ExpressionFilter module would look something like:

<Expression>

  <SimpleExpression>

    <ValueExpression>

      <XPathQuery Type="String">Columns[2]/Column[1]</XPathQuery>

    </ValueExpression>

    <Operator>NotEqual</Operator>

    <ValueExpression>

      <Value Type="String">foo</Value>

    </ValueExpression>

  </SimpleExpression>

</Expression>

The configuration for System.Secure.CommandExecuterProbe module would look something like:

<ApplicationName>%windir%\system32\cscript.exe</ApplicationName>

<WorkingDirectory/>

<CommandLine>//nologo $file/DemoOleDb.vbs$ $Data/Columns[2]/Column[1]$</CommandLine>

<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>

<RequireOutput>true</RequireOutput>

<Files>

  <File>

    <Name>DemoOleDb.vbs</Name>

    <Contents>

      <![CDATA[  

'*************************************************************************

' Script Name - Demo Ole Db Script

'

' Purpose     - Demonstrate how output from OleDbProbe module can be used

'

'*************************************************************************

 

Dim val

val = oArgs(0)    ' "$Data/Columns[2]/Column[1]$"

]]>

    </Contents>

    <Unicode>1</Unicode>

  </File>

</Files>

The AEM feature in Operations Manager 2007 is next step from CER 2.0. A training video is available here.

As such, AEM falls under the umbrella of Client Monitoring which in its current state also emcompasses other features like Customer Experience Improvement Program (CEIP). A white paper on Client Monitoring can be read here.

Operations Manager SDK contains helper classes for programming with AEM under Microsoft.EnterpriseManagement.Monitoring.ClientMonitoring namespace.

There's a lot available online to read about AEM (one such read is here) and so the next few blogs on AEM would focus on how you can customize AEM as per your needs.

The Ole-DB module is a probe action module. It is defined in System.Library Management Pack (MP) as System.OleDbProbe. This module takes in the following as various configuration elements:

  • ConnectionString
    • This is a mandatory string element used for establishing a connection.
    • Example Value: Provider=SQLOLEDB;Database=master;Server=.;IntegratedSecurity=SSPI
  • Query
    • This is an optional string element which when provided is used to query against the provider (info purveyed above).
    • Example Value: SELECT COUNT(*) FROM SYSCOLUMNS
  • GetValue
    • This is an optional boolean element indicating whether the result set from query should be outputted or not.
    • Example Value: true
  • IncludeOriginalItem
    • This is an optional boolean element. Since this module is a probe-action module, it basically needs a trigger in most cases. However, in some scenarios, the input item data needs to be preserved and this element indicates that. A value of true would cause the input item's xml to be outputted.
    • Example Value: true
  • OneRowPerItem
    • If multiple rows are returned by the query string, then setting this optional boolean element would cause multiple items to be outputted each having only one row.
    • Example Value: true
  • DatabaseNameRegLocation
    • This is an optional string element. There might be cases where the database name is not available to you and needs to be read from a registry location (based off HKLM). In short, the DatabaseName is not provided in ConnectionString and the registry location information can be provided here.
    • Example Value: SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup\DatabaseName
  • DatabaseServerNameRegLocation
    • This is an optional string element. And just like DatabaseNameRegLocation, this element allows listing a registry location under HKLM from where Server information can be read from and not from ConnectionString.
    • Example Value: SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup\DatabaseServerName

The output from this module is OleDb data defined in the System.Library MP as System.OleDbData and has the following elements in it:

XML Tag

Meaning

HRResult

indicating if everything went fine

Result

Detailed result in string representation,

"Success"

"Fetch Failed"

"Execution of query failed"

"Session could not be opened"

"Data Source could not be initialized"

 

ResultLength

Length of Result string above

InitializationTime

time that took for initialization with given ConnectionString (in ms)

OpenTime

time that took for opening a session (in ms)

ExecutionTime

time that took for executing query, if provided, else it is 0 (in ms)

FetchTime

time that took for fetching the resultSet, if it was fetched, else it is 0 (in ms)

RowLength

# of rows in resultSet

Columns

There are as many column tags as there is # of rows (RowLength).

Column

There are as many Column tags inside each Columns tag, as there is # of columns.

OriginalDataLength

GetItemXml() is called on original data and the length of returned string is captured here

OriginalData

GetItemXml() is called on original data and the result is captured here

Attached is a demo MP demonstrating how Ole-Db module can be used to generate alerts associated with management server when it takes too long to execute a query.

Posted Tuesday, May 01, 2007 2:10 PM by Komal | 7 Comments
Filed under:

Attachment(s): Demo.OleDB.MP.xml

The Syslog module is a data source module. It listens to syslog datagrams (UDP packets) on specified port (default being 514 as per IETF standards.). It is defined in System.ApplicationLog Management Pack (MP) as System.ApplicationLog.SysLogReader.

The output from this module is Syslog data defined in the ApplicationLog MP as System.ApplicationLog.SysLogData and has the following elements in it:

  • Facility
  • Severity
  • Priority
  • PriorityName
  • TimeStamp
  • HostName
  • Message

Each syslog packet received by the module contains a max of 1024 bytes and they are to be interpreted as ASCII characters. A best effort is made to parse these characters into the above xml elements. The module needs only one piece of configuration: the port number at which the syslog module should be listening.

Attached is a demo MP demonstrating how syslog module can be used to generate alerts when it receives a high severity syslog message.

Read about Syslog in MOM2000/2005 here.

The aim of this posting is to explain with examples how discovery data can be created out of any other data-item produced by modules and be submitted to OpsMgr.

Let us assume that we have an application that acts as a server for various agents deployed in our system. We would like to collect information about various agents that contact the server and run monitoring rules against them. These agents need to be modeled as a class whose instances/objects identify various agents.

The class could be defined in Management Pack (MP) as follows:

<ClassType ID="MyAgent" Accessibility="Public" Base="System!System.Entity" Hosted="false" Abstract="false">

  <Property ID="AgentID" Type="int" Key="true" />

  <Property ID="AgentName" Type="string" Key="false" CaseSensitive="false" />

  <Property ID="AgentVersion" Type="string" Key="false" CaseSensitive="false" />

  <Property ID="AgentOwner" Type="string" Key="false" CaseSensitive="false" />

  <Property ID="LastMessageReceived" Type="string" Key="false" CaseSensitive="false" />

  <Property ID="Comments" Type="string" Key="false" CaseSensitive="false" />

</ClassType>

Table 1: Sample Class

 

As can be seen above, class MyAgent has one key Property ‘AgentID’ of type int and 5 non-key properties of type string: AgentName, AgentVersion, AgentOwner, LastMessageReceived and Comments.

To submit instances (discovery data) for this class, we would have the following section in MP:

<Monitoring>

  <Discoveries>

    <Discovery ID="AgentDiscoverer" Target="System!System.Computer" Enabled="true" ConfirmDelivery="true">

      <Category>Discovery</Category>

      <DiscoveryTypes>

        <DiscoveryClass TypeID="MyAgent" />

      </DiscoveryTypes>

      <DataSource ID="AgentDiscovererDS" TypeID="AgentDataGenerator" />

    </Discovery>

  </Discoveries>

</Monitoring>

Table 2: Sample Data Generator

 

The above text in MP tells that there would be a discovery rule running targeted towards System.Computer that would generate instances of type ‘MyAgent’. These instances would be submitted to the system by an instance of AgentDataGenerator module.

A discovery rule expects DiscoveryData. Therefore, output of AgentDataGenerator module should be System!System.Discovery.Data and nothing else. If we have a module that outputs a different type, how do we convert it to DiscoveryData/instance of MyAgent?

Let’s look at our module first.

<DataSourceModuleType ID="AgentExplorer" Accessibility="Public">

  <Configuration />

  <ModuleImplementation>

    <Managed>

      <Assembly>ServerAssembly</Assembly>

      <Type>ServerNamespace.MyServer</Type>

    </Managed>

  </ModuleImplementation>

  <OutputType>AgentData</OutputType>

</DataSourceModuleType>

Table 3: Sample Module

 

From the above definition looks like AgentExplorer is implemented as class MyServer in namespace ServerNamespace in ServerAssembly and it outputs AgentData. AgentData being defined as follows:

<DataType ID="AgentData" Base="System!System.BaseData" Accessibility="Public">

  <Implementation>

    <Assembly>ServerAssembly</Assembly>

    <Type>ServerNamespace.AgentData</Type>

  </Implementation>

</DataType>

Table 4: Sample Data

 

AgentData is implemented as AgentData in ServerAssembly. AgentData would definitely be inheriting from DataItemBase defined in Microsoft.EnterpriseManagement.HealthService.dll. As a result of this inheritance, AgentData would also provide serialization/deserialization of the contents into/from xml.

Let’s assume the xml representation (serialized version of the datatype) looks like below:

<AgentData>

  <ID>0</ID>

  <Name>Sample Agent</Name>

  <MajorVersion>1.0</MajorVersion>

  <MinorVersion>0.0</MinorVersion>

  <OwnerInfo>

    <Name>AgentOwner1</Name>

    <Name>AgentOwner2</Name>

  </OwnerInfo>

  <Message>Client 0 pinging server.</Message>

</AgentData>

Table 5: Sample Data (Serialized)

 

Now, let us look as to how we can connect the above module to a managed discovery data mapper module and generate discovery data. In short, we would be defining the module from table 2.

<DataSourceModuleType ID="AgentDataGenerator" Accessibility="Public">

  <Configuration /

  <ModuleImplementation>

    <Composite>

      <MemberModules>

        <DataSource ID="AgentExplorerDS" TypeID="AgentExplorer" />

        <ProbeAction ID="DiscoveryMapper" TypeID="MapperLibrary!Microsoft.SystemCenter.CM.DiscoveryMapperPA">

          <!-- To Add More Here Later -->

        </ProbeAction>

      </MemberModules>

      <Composition>

        <Node ID="DiscoveryMapper">

          <Node ID="AgentExplorerDS" />

        </Node>

      </Composition>

    </Composite>

  </ModuleImplementation>

  <OutputType>System!System.Discovery.Data</OutputType>

</DataSourceModuleType>

Table 6: Sample Discovery Data Generator

 

Now, let us look at configuration for DiscoveryMapper module (defined in above table) closely. (Schema is defined in a previous blog posting).

<ManagedEntity><Detailed>

  <TimeGenerated UseCurrent="true" />

  <DiscoveryType>AddUpdate</DiscoveryType>

  <DiscoverySourceType>Rule</DiscoverySourceType>

  <SourceObjectId>$MPElement$</SourceObjectId>

  <SourceManagedEntityId>$Target/Id$</SourceManagedEntityId>

  <Properties>

    <Evaluate If=".">

      <Property ID="IDValue">//AgentData/ID</Property>

      <Property ID="NameValue">//AgentData/Name</Property>

      <Property ID="VersionValue">concat(//AgentData/MajorVersion, “.”, //AgentData/MinorVersion)</Property>

      <Property ID="OwnerValue">//AgentData/OwnerInfo/Name</Property>

      <Property ID="MessageValue">//AgentData/Message</Property>

    </Evaluate>

  </Properties>

  <PropertySets />

  <ClassInstances>

    <ClassInstance If=".">

      <TypeId>$MPElement[Name="MyAgent"]$</TypeId>

      <Properties>

        <Property>

          <Name>$MPElement[Name="MyAgent"]/AgentID$</Name>

          <Value>IDValue</Value>

        </Property>

        <Property>

          <Name>$MPElement[Name="MyAgent"]/AgentName$</Name>

          <Value>NameValue</Value>

        </Property>

        <Property>

          <Name>$MPElement[Name="MyAgent"]/AgentVersion$</Name>

          <Value>VersionValue</Value>

        </Property>

        <Property>

          <Name>$MPElement[Name="MyAgent"]/AgentOwner$</Name>

          <Value>OwnerValue[0]</Value>

        </Property>

        <Property>

          <Name>$MPElement[Name="MyAgent"]/LastMessageReceived$</Name>

          <Value>MessageValue</Value>

        </Property>

        <Property Optional="true">

          <Name>$MPElement[Name="MyAgent"]/Comments$</Name>

          <Value>No Comments!</Value>

        </Property>

      </Properties>

    </ClassInstance>

  </ClassInstances>

  <RelationshipInstances />

</Detailed></ManagedEntity>

Table 7: Configuration for Generic Data Mapper

 

The TimeGenerated element specifies the time stamp associcated with discovery data.

DiscoveryType element can be AddUpdate/Snapshot/Remove based on kind of discovery operations performed.

DiscoverySourceType element specified source of discovery data submitted to the system. In the sample case, it’s a rule. However, discovery data can be submitted via task/user/system as well.

SourceId is also required besides the DiscoverySourceType. $MPElement$ retrieves the Id of rule in which it is being used.

SourceManagedEntityId is managed entity Id of the target in this case, which is System!System.Computer.

The Properties element section in configuration allows to evaluate a bunch of xpath expressions from serialized data item (e.g., see table 5). The evaluation can be conditional as well. The ‘If’ attribute requires an xpath expression whose evaluates to a non-empty string will cause the included properties to be evaluated. There can be multiple Evaluate element sections. The mapper would build a list of property elements (as permitted by the ‘Evaluate/if’ attribute) referenced by an ID associated with xpath expressions. Xpath functions are permitted. (See VersionValue). ID can refer to a list as well here (See OwnverValue).

Explanation for PropertySets element is not required for this sample case.

The ClassInstances section allows creation of multiple class instances based on evaluation of ‘If’ attribute. If the ‘If’ attribute permits, then instance for specified ‘TypeId’ will be created. The Properties associated with it are defined as name-value pairs. Name takes an Id to the property of the class whose value needs to be populated. The Value element can take values either from configuration, values from propertyID’s defined earlier (see IDValue, NameValue, etc), values hard-coded (See Comments) and values from a member of ID referencing a list (See AgentOwner).

Also, make note of Optional attribute defined on Property element (See  Comments). When set to true, the mapper would not include that particular property in submission list if the value evaluates to an empty string.

RelationshipInstances can be discovered similarly. See schema for more info.

See all the pieces combined together in attached MP.

Following is the schema of configuration for discovery data managed mapper module.

 

<SchemaType ID="Microsoft.SystemCenter.CM.DiscoveryMapperConfiguration" Accessibility="Public">

  <xsd:complexType name="PropertyInclusion">

    <xsd:sequence>

      <xsd:element name="Name" type="xsd:string" />

      <xsd:element name="Value" type="xsd:string" />

    </xsd:sequence>

    <xsd:attribute name="Optional" type="xsd:boolean" use="optional" />

    <xsd:attribute name="GenNewInstance" type="xsd:boolean" use="optional" />

  </xsd:complexType>

  <xsd:complexType name="DiscoveryMapperConfigType">

    <xsd:choice>

      <xsd:element name="Simple">

        <xsd:complexType>

          <xsd:sequence>

            <xsd:element name="TimeGenerated">

              <xsd:complexType>

                <xsd:simpleContent>

                  <xsd:extension base="xsd:string">

                    <xsd:attribute name="IsXpath" type="xsd:boolean" />

                    <xsd:attribute name="UseCurrent" type="xsd:boolean" use="optional" />

                  </xsd:extension>

                </xsd:simpleContent>

              </xsd:complexType>

            </xsd:element>

            <xsd:element name="XmlBlob">

              <xsd:complexType>

                <xsd:simpleContent>

                  <xsd:extension base="xsd:string">

                    <xsd:attribute name="IsXpath" type="xsd:boolean" />

                  </xsd:extension>

                </xsd:simpleContent>

              </xsd:complexType>

            </xsd:element>

          </xsd:sequence>

        </xsd:complexType>

      </xsd:element>

      <xsd:element name="Detailed">

        <xsd:complexType>

          <xsd:sequence>

            <xsd:element name="TimeGenerated">

              <xsd:complexType>

                <xsd:simpleContent>

                  <xsd:extension base="xsd:string">

                    <xsd:attribute name="IsXpath" type="xsd:boolean" />

                    <xsd:attribute name="UseCurrent" type="xsd:boolean" use="optional" />

                  </xsd:extension>

                </xsd:simpleContent>

              </xsd:complexType>

            </xsd:element>

            <xsd:element name="DiscoveryType">

              <xsd:simpleType>

                <xsd:restriction base="xsd:string">

                  <xsd:enumeration value="Snapshot" />

                  <xsd:enumeration value="AddUpdate" />

                  <xsd:enumeration value="Remove" />

                </xsd:restriction>

              </xsd:simpleType>

            </xsd:element>

            <xsd:element name="DiscoverySourceType">

              <xsd:simpleType>

                <xsd:restriction base="xsd:string">

                  <xsd:enumeration value="Rule" />

                  <xsd:enumeration value="Task" />

                  <xsd:enumeration value="User" />

                  <xsd:enumeration value="System" />

                </xsd:restriction>

              </xsd:simpleType>

            </xsd:element>

            <xsd:element name="SourceObjectId" type="xsd:string" />

            <xsd:element name="SourceManagedEntityId" type="xsd:string" />

            <xsd:element name="Properties">

              <xsd:complexType>

                <xsd:sequence>

                  <xsd:element name="Evaluate" minOccurs="0" maxOccurs="unbounded">

                    <xsd:complexType>

                      <xsd:sequence>

                        <xsd:element name="Property" minOccurs="1" maxOccurs="unbounded">

                          <xsd:complexType>

                            <xsd:simpleContent>

                              <xsd:extension base="xsd:string">

                                <xsd:attribute name="ID" type="xsd:string" />

                              </xsd:extension>

                            </xsd:simpleContent>

                          </xsd:complexType>

                        </xsd:element>

                      </xsd:sequence>

                      <xsd:attribute name="If" type="xsd:string" />

                    </xsd:complexType>

                  </xsd:element>

                </xsd:sequence>

              </xsd:complexType>

            </xsd:element>

            <xsd:element name="PropertySets">

              <xsd:complexType>

                <xsd:sequence>

                  <xsd:element name="Set" minOccurs="0" maxOccurs="unbounded">

                    <xsd:complexType>

                      <xsd:sequence>

                        <xsd:element name="Property" minOccurs="1" maxOccurs="unbounded" type="PropertyInclusion" />

                      </xsd:sequence>

                      <xsd:attribute name="ID" type="xsd:string" />

                    </xsd:complexType>

                  </xsd:element>

                </xsd:sequence>

              </xsd:complexType>

            </xsd:element>

            <xsd:element name="ClassInstances">

              <xsd:complexType>

                <xsd:sequence>

                  <xsd:element name="ClassInstance" minOccurs="0" maxOccurs="unbounded">

                    <xsd:complexType>

                      <xsd:sequence>

                        <xsd:element name="TypeId" type="xsd:string" />

                        <xsd:element name="Properties">

                          <xsd:complexType>

                            <xsd:sequence>

                              <xsd:element name="Property" minOccurs="0" maxOccurs="unbounded" type="PropertyInclusion" />

                              <xsd:element name="PropertySet" minOccurs="0" maxOccurs="unbounded">

                                <xsd:complexType>

                                  <xsd:attribute name="Name" type="xsd:string" />

                                </xsd:complexType>

                              </xsd:element>

                            </xsd:sequence>

                          </xsd:complexType>

                        </xsd:element>

                      </xsd:sequence>

                      <xsd:attribute name="If" type="xsd:string" />

                    </xsd:complexType>

                  </xsd:element>

                </xsd:sequence>

              </xsd:complexType>

            </xsd:element>

            <xsd:element name="RelationshipInstances">

              <xsd:complexType>

                <xsd:sequence>

                  <xsd:element name="RelationshipInstance" minOccurs="0" maxOccurs="unbounded">

                    <xsd:complexType>

                      <xsd:sequence>

                        <xsd:element name="TypeId" type="xsd:string" />

                        <xsd:element name="SourceTypeId" type="xsd:string" />

                        <xsd:element name="TargetTypeId" type="xsd:string" />

                        <xsd:element name="SourceProperties">

                          <xsd:complexType>

                            <xsd:sequence>

                              <xsd:element name="Property" minOccurs="0" maxOccurs="unbounded" type="PropertyInclusion" />

                              <xsd:element name="PropertySet" minOccurs="0" maxOccurs="unbounded">

                                <xsd:complexType>

                                  <xsd:attribute name="Name" type="xsd:string" />

                                </xsd:complexType>

                              </xsd:element>

                            </xsd:sequence>

                          </xsd:complexType>

                        </xsd:element>

                        <xsd:element name="TargetProperties">

                          <xsd:complexType>

                            <xsd:sequence>

                              <xsd:element name="Property" minOccurs="0" maxOccurs="unbounded" type="PropertyInclusion" />

                              <xsd:element name="PropertySet" minOccurs="0" maxOccurs="unbounded">

                                <xsd:complexType>

                                  <xsd:attribute name="Name" type="xsd:string" />

                                </xsd:complexType>

                              </xsd:element>

                            </xsd:sequence>

                          </xsd:complexType>

                        </xsd:element>

                        <xsd:element name="Properties">

                          <xsd:complexType>

                            <xsd:sequence>

                              <xsd:element name="Property" minOccurs="0" maxOccurs="unbounded" type="PropertyInclusion" />

                              <xsd:element name="PropertySet" minOccurs="0" maxOccurs="unbounded">

                                <xsd:complexType>

                                  <xsd:attribute name="Name" type="xsd:string" />

                                </xsd:complexType>

                              </xsd:element>

                            </xsd:sequence>

                          </xsd:complexType>

                        </xsd:element>

                      </xsd:sequence>

                      <xsd:attribute name="If" type="xsd:string" />

                    </xsd:complexType>

                  </xsd:element>

                </xsd:sequence>

              </xsd:complexType>

            </xsd:element>

          </xsd:sequence>

        </xsd:complexType>

      </xsd:element>

    </xsd:choice>

  </xsd:complexType>

</SchemaType>

Hi there,

This is Komal Kashiramka and I am here to help you with/give you more insight into some of the cool features in System Center Operations Manager 2007.

Specifically, I can help in depth with:

  • Client Monitoring (AEM [Agentless Exception Monitoring], SQM, etc.)
  • Ole Db Template/Module
  • Syslog Module
  • Computer Verification Module
  • Generic Managed Modules: Discovery-data Mapper, Event Mapper, Http-Listener/Uploader

Keep reading and have fun! This is just the beginning...

 
Page view tracker