MP authoring samples - NT service based discovery

One of the things that I have been wanting to cover in this blog is advanced MP authoring. Lately I have been spending a fair bit of time doing MP related work so I am going to start blogging on this subject. My main focus will be to provide samples as well as share some thoughts that come to my mind when doing MP related work.

One of the problems that I see pretty frequently is people only want to target a particular set of computers when creating a new rule or monitor. A lot of times these computers perform a common function. Perhpas the most correct way to do this is define a new type and the discover instances of this type. This can be done using the Authoring Console or using raw XML. In this blog post I will show how you can do this by checking if a particular service is installed and not disabled on a computer as in many cases this is a easy way to identify a server as performing a particular function. 

One the goals of providing the XML is so that you can easily tweak this to your needs and use it.

If you find this sort of samples usefull, please let me know and I will post more. If you have questions about the MP below please post comments and I will try to address them.

<ManagementPack ContentReadable="true" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsl="https://www.w3.org/1999/XSL/Transform">

  <Manifest>

    <Identity>

      <ID>NTServiceBasedDiscoverySample.MP</ID>

      <Version>2.0.0.0</Version>

    </Identity>

    <Name>NTServiceBasedDiscoverySample.MP</Name>

    <References>

      <Reference Alias="SC">

        <ID>Microsoft.SystemCenter.Library</ID>

        <Version>6.0.5000.0</Version>

        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>

      </Reference>

      <Reference Alias="System">

        <ID>System.Library</ID>

        <Version>6.0.5000.0</Version>

        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>

      </Reference>

      <Reference Alias="Windows">

        <ID>Microsoft.Windows.Library</ID>

        <Version>6.0.5000.0</Version>

        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>

      </Reference>

      <Reference Alias="Health">

        <ID>System.Health.Library</ID>

        <Version>6.0.5000.0</Version>

        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>

      </Reference>

    </References>

  </Manifest>

  <TypeDefinitions>

    <EntityTypes>

      <ClassTypes>

        <ClassType ID="Sample.ServerRole" Accessibility="Public" Abstract="false" Base="Windows!Microsoft.Windows.ComputerRole" Hosted="true" Singleton="false"/>

      </ClassTypes>

      <RelationshipTypes>

      </RelationshipTypes>

    </EntityTypes>

    <ModuleTypes>

      <!--

      This data source is composed of three module:

      Scheduler - This will kick off the discovery which uses this datasource every N seconds

      Probe - This will check if the specified service exists and is not disabled

      Mapper - This will cause discovery data to be created

      -->

      <DataSourceModuleType ID="Sample.Discovery.DataSource" Accessibility="Internal" Batching="false">

        <Configuration>

          <xsd:element name="IntervalSeconds" type="xsd:unsignedInt" />

        </Configuration>

        <OverrideableParameters>

          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />

        </OverrideableParameters>

        <ModuleImplementation Isolation="Any">

          <Composite>

            <MemberModules>

              <DataSource ID="Scheduler" TypeID="System!System.Discovery.Scheduler">

                <Scheduler>

                  <SimpleReccuringSchedule>

                    <Interval Unit="Seconds">$Config/IntervalSeconds$</Interval>

                  </SimpleReccuringSchedule>

                  <ExcludeDates />

                </Scheduler>

              </DataSource>

              <ProbeAction ID="Probe" TypeID="Sample.Discovery.Probe">

                <ComputerName>$Target/Property[Type='Windows!Microsoft.Windows.Computer']/NetworkName$</ComputerName>

          <!--

                This is where we specify which service to look for.

                In this case its the Alerter service.

                -->

                <ServiceName>Alerter</ServiceName>

              </ProbeAction>

              <ConditionDetection ID="Mapper" TypeID="System!System.Discovery.ClassSnapshotDataMapper">

                <ClassId>$MPElement[Name="Sample.ServerRole"]$</ClassId>

                <InstanceSettings>

                  <Settings>

                    <Setting>

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

                      <Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>

                    </Setting>

         <Setting>

                      <!--This is going to be the display name of the object created. As an example I am putting in the computer on which its running-->

                      <Name>$MPElement[Name="System!System.Entity"]/DisplayName$</Name>

                      <Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>

                    </Setting>

                  </Settings>

                </InstanceSettings>

              </ConditionDetection>

            </MemberModules>

            <Composition>

              <Node ID="Mapper">

                <Node ID="Probe">

                  <Node ID="Scheduler" />

                </Node>

              </Node>

            </Composition>

          </Composite>

        </ModuleImplementation>

        <OutputType>System!System.BaseData</OutputType>

      </DataSourceModuleType>

      <!--This composite probe module consists of two modules:

      1 - Probe module which queries the service control manager for info about the specified service

      2 - Condition detection module which checks whether the startup type of the service is not set to "Disabled"

      See https://blogs.msdn.com/sampatton/archive/2008/03/10/win32serviceinformation-modules.aspx for more info

      -->

      <ProbeActionModuleType ID="Sample.Discovery.Probe" Accessibility="Public" Batching="false" PassThrough="false">

        <Configuration>

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

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

        </Configuration>

        <ModuleImplementation Isolation="Any">

          <Composite>

            <MemberModules>

              <ProbeAction ID="Probe" TypeID="Windows!Microsoft.Windows.ExistingWin32ServiceInformationProbe">

                <ComputerName>$Config/ComputerName$</ComputerName>

                <ServiceName>$Config/ServiceName$</ServiceName>

              </ProbeAction>

              <ConditionDetection ID="CD" TypeID="System!System.ExpressionFilter">

                <Expression>

                <!--

                This is where we specify that we only care if the service startup mode is not disabled

                -->

                <SimpleExpression>

                  <ValueExpression>

                    <XPathQuery Type="Integer">Property[@Name='StartMode']</XPathQuery>

                  </ValueExpression>

                  <Operator>NotEqual</Operator>

            <ValueExpression>

                    <Value Type="Integer">4</Value>

                  </ValueExpression>

                </SimpleExpression>

                </Expression>

              </ConditionDetection>

            </MemberModules>

            <Composition>

              <Node ID="CD">

                <Node ID="Probe" />

              </Node>

            </Composition>

          </Composite>

        </ModuleImplementation>

        <OutputType>System!System.PropertyBagData</OutputType>

        <InputType>System!System.BaseData</InputType>

      </ProbeActionModuleType>

    </ModuleTypes>

  </TypeDefinitions>

  <Monitoring>

    <Discoveries>

      <Discovery ID="Sample.Discovery" Enabled="true" Target="Windows!Microsoft.Windows.Computer" ConfirmDelivery="false" Remotable="true" Priority="Normal">

        <Category>Discovery</Category>

        <DiscoveryTypes>

          <DiscoveryClass TypeID="System!System.Entity">

            <Property TypeID="System!System.Entity" PropertyID="DisplayName"/>

          </DiscoveryClass>

          <DiscoveryClass TypeID="Sample.ServerRole"/>

        </DiscoveryTypes>

        <DataSource ID="DiscoveryDataSource" TypeID="Sample.Discovery.DataSource">

          <IntervalSeconds>120</IntervalSeconds>

        </DataSource>

      </Discovery>

    </Discoveries>

  </Monitoring>

  <Presentation>

    <Views>

      <View ID="Sample.View" Accessibility="Public" Enabled="true" Target="Sample.ServerRole" TypeID="SC!Microsoft.SystemCenter.StateViewType" Visible="true">

        <Category>Operations</Category>

        <Criteria>

          <InMaintenanceMode>false</InMaintenanceMode>

        </Criteria>

        <Presentation>

          <ColumnInfo Index="0" SortIndex="0" Width="100" Grouped="false" Sorted="true" IsSortable="true" Visible="true" SortOrder="Descending">

            <Name>State</Name>

            <Id>Sample.ServerRole</Id>

          </ColumnInfo>

          <ColumnInfo Index="1" SortIndex="-1" Width="100" Grouped="false" Sorted="false" IsSortable="true" Visible="true" SortOrder="Ascending">

            <Name>Maintenance Mode</Name>

            <Id>InMaintenanceMode</Id>

          </ColumnInfo>

          <ColumnInfo Index="2" SortIndex="-1" Width="100" Grouped="false" Sorted="false" IsSortable="true" Visible="true" SortOrder="Ascending">

            <Name>Name</Name>

            <Id>Name</Id>

          </ColumnInfo>

          <ColumnInfo Index="3" SortIndex="-1" Width="100" Grouped="false" Sorted="false" IsSortable="true" Visible="true" SortOrder="Ascending">

            <Name>Path</Name>

            <Id>Path</Id>

          </ColumnInfo>

          <ColumnInfo Index="4" SortIndex="-1" Width="100" Grouped="false" Sorted="false" IsSortable="true" Visible="false" SortOrder="Ascending">

            <Name>Display Name</Name>

            <Id>DisplayName</Id>

          </ColumnInfo>

        </Presentation>

        <Target />

      </View>

    </Views>

    <Folders>

      <Folder ID="Sample.Folder" Accessibility="Public" ParentFolder="SC!Microsoft.SystemCenter.Monitoring.ViewFolder.Root" />

    </Folders>

    <FolderItems>

      <FolderItem ElementID="Sample.View" Folder="Sample.Folder" />

    </FolderItems>

  </Presentation>

  <LanguagePacks>

    <LanguagePack ID="ENU" IsDefault="true">

      <DisplayStrings>

        <DisplayString ElementID="NTServiceBasedDiscoverySample.MP">

          <Name>NT Service Based Discovery Sample MP</Name>

        </DisplayString>

        <DisplayString ElementID="Sample.ServerRole">

          <Name>Sample Server Role</Name>

        </DisplayString>

        <DisplayString ElementID="Sample.Discovery">

          <Name>Sample NT Service based discovery</Name>

        </DisplayString>

        <DisplayString ElementID="Sample.Folder">

          <Name>Sample MP</Name>

        </DisplayString>

        <DisplayString ElementID="Sample.View">

          <Name>Sample objects state (will be unmonitored as there are no monitors in the MP)</Name>

          <Description />

        </DisplayString>

      </DisplayStrings>

    </LanguagePack>

  </LanguagePacks>

</ManagementPack>