Saturday, February 18, 2012

Rules Template -- WOW

Okay, I know nothing can replace sex.

But, really,  having a template file that enables you to see around 20 of the most used Managementpack rules is pretty exciting, too.

Let's take a look at what's under the hood:


Okay, that's not very exciting as it looks without expanding one of these. So, let's take a look at the Microsoft.SystemCenter.RuleTemplates.Windows.EventAlert.


As you can see, if you have used this provider before, this template really does cover the bases.

So let's take a look at the mapping of the elements:

ID
Name
Enabled
Description
Target
Category
LocalId
ComputerName
LogName

While below is an example from the 2003 mp, it is also the best way to show you were all the attributes.

<Rule
ID="Microsoft.Windows.Server.2003.OperatingSystem.ServiceOrDriverFailedToStart.Alert" Enabled="false"
Target="Microsoft.Windows.Server.2003.OperatingSystem"
ConfirmDelivery="false"
Remotable="true"
Priority="Normal"
DiscardLevel="100"
>
       <Category>EventCollection</Category>

        <DataSources>
          <DataSource ID="EventDS" TypeID="Windows!Microsoft.Windows.EventProvider">
            <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>
            <LogName>System</LogName>
          </DataSource>
        </DataSources>


Okay, so where does ConfirmDelivery, Remotable, Priority snd DiscardLevel Come from?

The rule properties:

            Dim rule as ManagementPackRule

            rule.ConfirmDelivery = True
            rule.DiscardLevel = "100" 
            rule.Priority = ManagementPackWorkflowPriority.Normal
            rule.Remotable = True

Also notice that the rule.Priority is not the same as the priority and severity used once the alert gets raised.

Typically, the DisplayName, Description, Alert Name, Alert Description are properties designed to create Display strings.  Of course, these strings not only make the mp easier to understand they also serve to explain why the alert occurred.

Now, how can we find out, if we didn't know what the Priority and Severity values come from?


By Going through each of the IncludeSchemaTypes, we find our answer in the System.Health.Library.mp:

<xsd:simpleType name="System.Health.AlertPriority">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Low" />
<xsd:enumeration value="Normal" />
<xsd:enumeration value="High" />       
</xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="System.Health.AlertSeverity">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Information" />
<xsd:enumeration value="Warning" />
<xsd:enumeration value="Error" />
<xsd:enumeration value="MatchMonitorHealth" />
</xsd:restriction>
</xsd:simpleType>

Now, let's take a look at the expression portion of the mp.  Below are the values used in the expression. There's a lot of  "OR" pairs which I've listed below.

PublisherName                Equal     Service Control Manager

EventDisplayNumber      Equal     7000
EventDisplayNumber      Equal     7001


EventDisplayNumber      Equal     7002
EventDisplayNumber      Equal     7003

EventDisplayNumber      Equal     7008
EventDisplayNumber      Equal     7013


EventDisplayNumber      Equal     7014
EventDisplayNumber      Equal     7022


EventDisplayNumber      Equal     7023
EventDisplayNumber      Equal     7025


EventDisplayNumber      Equal     7026
EventDisplayNumber      Equal     7038

To finish the rule up:

<WriteActions>
   <WriteAction ID="GenerateAlert" TypeID="SystemHealth!System.Health.GenerateAlert">
   <Priority>1</Priority>
   <Severity>1</Severity>
   <AlertMessageId>$MPElement[Name="Microsoft.Windows.Server.2003.OperatingSystem.ServiceOrDriverFailedToStart.Alert.AlertMessage"]$</AlertMessageId>
   <AlertParameters>
       <AlertParameter1>$Data/EventDescription$</AlertParameter1>
    </AlertParameters>
    <Suppression>
      <SuppressionValue />
    </Suppression>
  </WriteAction>
</WriteActions>


All of this combined creates this:

<Rule ID="Microsoft.Windows.Server.2003.OperatingSystem.ServiceOrDriverFailedToStart.Alert" Enabled="false" Target="Microsoft.Windows.Server.2003.OperatingSystem">
        <Category>EventCollection</Category>
        <DataSources>
          <DataSource ID="EventDS" TypeID="Windows!Microsoft.Windows.EventProvider">
            <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>
            <LogName>System</LogName>
            <Expression>
              <And>
                <Expression>
                  <SimpleExpression>
                    <ValueExpression>
                      <XPathQuery>PublisherName</XPathQuery>
                    </ValueExpression>
                    <Operator>Equal</Operator>
                    <ValueExpression>
                      <Value>Service Control Manager</Value>
                    </ValueExpression>
                  </SimpleExpression>
                </Expression>
                <Expression>
                  <Or>
                    <Expression>
                      <Or>
                        <Expression>
                          <Or>
                            <Expression>
                              <Or>
                                <Expression>
                                  <SimpleExpression>
                                    <ValueExpression>
                                      <XPathQuery>EventDisplayNumber</XPathQuery>
                                    </ValueExpression>
                                    <Operator>Equal</Operator>
                                    <ValueExpression>
                                      <Value>7000</Value>
                                    </ValueExpression>
                                  </SimpleExpression>
                                </Expression>
                                <Expression>
                                  <SimpleExpression>
                                    <ValueExpression>
                                      <XPathQuery>EventDisplayNumber</XPathQuery>
                                    </ValueExpression>
                                    <Operator>Equal</Operator>
                                    <ValueExpression>
                                      <Value>7001</Value>
                                    </ValueExpression>
                                  </SimpleExpression>
                                </Expression>
                              </Or>
                            </Expression>
                            <Expression>
                              <Or>
                                <Expression>
                                  <SimpleExpression>
                                    <ValueExpression>
                                      <XPathQuery>EventDisplayNumber</XPathQuery>
                                    </ValueExpression>
                                    <Operator>Equal</Operator>
                                    <ValueExpression>
                                      <Value>7002</Value>
                                    </ValueExpression>
                                  </SimpleExpression>
                                </Expression>
                                <Expression>
                                  <SimpleExpression>
                                    <ValueExpression>
                                      <XPathQuery>EventDisplayNumber</XPathQuery>
                                    </ValueExpression>
                                    <Operator>Equal</Operator>
                                    <ValueExpression>
                                      <Value>7003</Value>
                                    </ValueExpression>
                                  </SimpleExpression>
                                </Expression>
                              </Or>
                            </Expression>
                          </Or>
                        </Expression>
                        <Expression>
                          <Or>
                            <Expression>
                              <Or>
                                <Expression>
                                  <SimpleExpression>
                                    <ValueExpression>
                                      <XPathQuery>EventDisplayNumber</XPathQuery>
                                    </ValueExpression>
                                    <Operator>Equal</Operator>
                                    <ValueExpression>
                                      <Value>7008</Value>
                                    </ValueExpression>
                                  </SimpleExpression>
                                </Expression>
                                <Expression>
                                  <SimpleExpression>
                                    <ValueExpression>
                                      <XPathQuery>EventDisplayNumber</XPathQuery>
                                    </ValueExpression>
                                    <Operator>Equal</Operator>
                                    <ValueExpression>
                                      <Value>7013</Value>
                                    </ValueExpression>
                                  </SimpleExpression>
                                </Expression>
                              </Or>
                            </Expression>
                            <Expression>
                              <Or>
                                <Expression>
                                  <SimpleExpression>
                                    <ValueExpression>
                                      <XPathQuery>EventDisplayNumber</XPathQuery>
                                    </ValueExpression>
                                    <Operator>Equal</Operator>
                                    <ValueExpression>
                                      <Value>7014</Value>
                                    </ValueExpression>
                                  </SimpleExpression>
                                </Expression>
                                <Expression>
                                  <SimpleExpression>
                                    <ValueExpression>
                                      <XPathQuery>EventDisplayNumber</XPathQuery>
                                    </ValueExpression>
                                    <Operator>Equal</Operator>
                                    <ValueExpression>
                                      <Value>7022</Value>
                                    </ValueExpression>
                                  </SimpleExpression>
                                </Expression>
                              </Or>
                            </Expression>
                          </Or>
                        </Expression>
                      </Or>
                    </Expression>
                    <Expression>
                      <Or>
                        <Expression>
                          <Or>
                            <Expression>
                              <SimpleExpression>
                                <ValueExpression>
                                  <XPathQuery>EventDisplayNumber</XPathQuery>
                                </ValueExpression>
                                <Operator>Equal</Operator>
                                <ValueExpression>
                                  <Value>7023</Value>
                                </ValueExpression>
                              </SimpleExpression>
                            </Expression>
                            <Expression>
                              <SimpleExpression>
                                <ValueExpression>
                                  <XPathQuery>EventDisplayNumber</XPathQuery>
                                </ValueExpression>
                                <Operator>Equal</Operator>
                                <ValueExpression>
                                  <Value>7025</Value>
                                </ValueExpression>
                              </SimpleExpression>
                            </Expression>
                          </Or>
                        </Expression>
                        <Expression>
                          <Or>
                            <Expression>
                              <SimpleExpression>
                                <ValueExpression>
                                  <XPathQuery>EventDisplayNumber</XPathQuery>
                                </ValueExpression>
                                <Operator>Equal</Operator>
                                <ValueExpression>
                                  <Value>7026</Value>
                                </ValueExpression>
                              </SimpleExpression>
                            </Expression>
                            <Expression>
                              <SimpleExpression>
                                <ValueExpression>
                                  <XPathQuery>EventDisplayNumber</XPathQuery>
                                </ValueExpression>
                                <Operator>Equal</Operator>
                                <ValueExpression>
                                  <Value>7038</Value>
                                </ValueExpression>
                              </SimpleExpression>
                            </Expression>
                          </Or>
                        </Expression>
                      </Or>
                    </Expression>
                  </Or>
                </Expression>
              </And>
            </Expression>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="GenerateAlert" TypeID="SystemHealth!System.Health.GenerateAlert">
            <Priority>1</Priority>
            <Severity>1</Severity>
            <AlertMessageId>$MPElement[Name="Microsoft.Windows.Server.2003.OperatingSystem.ServiceOrDriverFailedToStart.Alert.AlertMessage"]$</AlertMessageId>
            <AlertParameters>
              <AlertParameter1>$Data/EventDescription$</AlertParameter1>
            </AlertParameters>
            <Suppression>
              <SuppressionValue />
            </Suppression>
          </WriteAction>
        </WriteActions>
      </Rule>


Additional features of the templates are shown as below:


As you can see, the library references are listed as well as the layout of the rule, StringResource, and DisplayStrings.

An example of a starter managementpack

With so many people interested in writing managmentpacks,  I thought it wise to add to this blog an example of a barebones managementpack.

With that said, this is what a barebones managementpack looks like:

<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <Manifest>
    <Identity>
      <ID>mp1</ID>
      <Version>1.0.0.0</Version>
    </Identity>
    <Name>mp1</Name>
    <References>
      <Reference Alias="SC">
        <ID>Microsoft.SystemCenter.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Health">
        <ID>System.Health.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="mp1">
          <Name>Management Pack 1</Name>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>

Saturday, February 11, 2012

Why classes are so important

Classes are important for a wide variety of reasons. They create blank open tables in SQL Server. You populate them in a variety of ways, the most popular is the use of a discovery. Hardly the only way, even a rule can fire off a DataSourceModule and the code within can populate the table.

But for that rule to work,  indeed, for anything to happen inside a managementpack, a certain kind of binding must occur. 

So, the combination of a class and a means by which that class's tables get populated creates this kind of binding and enables the rules and monitors to work on the machine where the agent resides and has added the mp to the agent's mangementpack cache.

Ever wondered why every agent has almost every managementpack imported into it on every machine?

That's because the mangementpack has to decide whether or not it should run on that type of machine. For example, the two classes that create the relationship between the 2003 computer and the group are the two below:

<ClassType ID="Microsoft.Windows.Server.2003.Computer" Abstract="false" Accessibility="Public" Base="Windows!Microsoft.Windows.Server.Computer" Hosted="false" Singleton="false" />       
<ClassType ID="Microsoft.Windows.Server.2003.ComputerGroup" Abstract="false" Accessibility="Public" Base="SC!Microsoft.SystemCenter.ComputerGroup" Hosted="false" Singleton="true" />

Notice that neither one has any properties. Again, this is because the two produce the binding between the computer group and the discovered computer.

     
<Discovery ID="Microsoft.Windows.Server.2003.Computer.Discovery" Enabled="onEssentialMonitoring" Target="Windows!Microsoft.Windows.Server.Computer">
<Category>Discovery</Category>
<DiscoveryTypes>
<DiscoveryClass TypeID="Microsoft.Windows.Server.2003.Computer" />
</DiscoveryTypes>
<DataSource ID="DiscoveryDataSource" TypeID="Windows!Microsoft.Windows.FilteredRegistryDiscoveryProvider">
<ComputerName>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>
<RegistryAttributeDefinitions>
<RegistryAttributeDefinition>
<AttributeName>WindowsCurrentVersion</AttributeName>
<Path>SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion</Path>
<PathType>1</PathType>
<AttributeType>1</AttributeType>
</RegistryAttributeDefinition>
</RegistryAttributeDefinitions>
<Frequency>3604</Frequency>
<ClassId>$MPElement[Name="Microsoft.Windows.Server.2003.Computer"]$</ClassId>
<InstanceSettings>
<Settings>
<Setting>
<Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Name>
<Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
</Setting>
</Settings>
</InstanceSettings>
<Expression>
<And>
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery>Values/WindowsCurrentVersion</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value>5.2</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
<Expression>
<SimpleExpression>
<ValueExpression>
<Value>$Target/Property[Type="Windows!Microsoft.Windows.Server.Computer"]/IsVirtualNode$</Value>
</ValueExpression>
<Operator>NotEqual</Operator>
<ValueExpression>
<Value>True</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</And>
</Expression>
</DataSource>
</Discovery>

The above discoveres the computer. The discovery below populates that discover with the group:

<Discovery ID="Microsoft.Windows.Server.2003.AllServersComputerGroupDiscovery" Enabled="onEssentialMonitoring" Target="Microsoft.Windows.Server.2003.ComputerGroup">
<Category>Discovery</Category>
<DiscoveryTypes />
<DataSource ID="DiscoveryDataSource" TypeID="SC!Microsoft.SystemCenter.GroupPopulator">
<RuleId>$MPElement$</RuleId>
<GroupInstanceId>$Target/Id$</GroupInstanceId>
<MembershipRules>
<MembershipRule>
<MonitoringClass>$MPElement[Name="Microsoft.Windows.Server.2003.Computer"]$</MonitoringClass>
<RelationshipClass>$MPElement[Name="SC!Microsoft.SystemCenter.ComputerGroupContainsComputer"]$</RelationshipClass>
</MembershipRule>
</MembershipRules>
</DataSource>
</Discovery>

But this only binds the computer to the group.  What makes the rules work? Just about every other class in the mangementpack does.

The very first rule tells you what class and discover needs to be created and discovered to make it work:
<Rule ID="Microsoft.Windows.Server.2003.OperatingSystem.PerfCounterDataRequestTimeOut.Alert" Enabled="onEssentialMonitoring" Target="Microsoft.Windows.Server.2003.OperatingSystem">

So, this begs, couldn't we have simply started the managementpack from there and not had to worry about the group population?

The answer is both yes and no.  Yes, you can if your managementpack was simply looking for a specific application.  However, in the case of the Windows.Server.2003.mp, no. There is a one to many relationship here with the mp's classes and discoveries.  For example, other classes depend on this class and discovery combination to make the rest of the mp to work and the discovery itself relies on the discovery of  the class: Windows!Microsoft.Windows.Server.Computer.

Meaning, its discovery logic is exactly the same as the Microsoft.Windows.Server.2003.Computer.Discovery:

<Discovery ID="Microsoft.Windows.Server.2003.OperatingSystem.Discovery" Enabled="onEssentialMonitoring" Target="Windows!Microsoft.Windows.Server.Computer">

So, why have both?  Simple, one helps to populate the Group Discovery.  The other binds the rules, monitors and other related targets to Windows!Microsoft.Windows.Server.Computer through the OperatingSystem Discovery.

But it is not the only one:

<ClassType ID="Microsoft.Windows.Server.2003.NetworkAdapter" Abstract="false" Accessibility="Public" Base="WindowsServer!Microsoft.Windows.Server.NetworkAdapter" Hosted="true" Singleton="false" />
<ClassType ID="Microsoft.Windows.Server.2003.Processor" Abstract="false" Accessibility="Public" Base="WindowsServer!Microsoft.Windows.Server.Processor" Hosted="true" Singleton="false" />
<ClassType ID="Microsoft.Windows.Server.2003.PhysicalDisk" Abstract="false" Accessibility="Public" Base="WindowsServer!Microsoft.Windows.Server.PhysicalDisk" Hosted="true" Singleton="false" />
<ClassType ID="Microsoft.Windows.Server.2003.LogicalDisk" Abstract="false" Accessibility="Public" Base="WindowsServer!Microsoft.Windows.Server.LogicalDisk" Hosted="true" Singleton="false" />
<ClassType ID="Microsoft.Windows.Server.2003.DiskPartition" Abstract="false" Accessibility="Public" Base="WindowsServer!Microsoft.Windows.Server.DiskPartition" Hosted="true" Singleton="false" />

Each one gets discovered and the target is:  "Microsoft.Windows.Server.2003.OperatingSystem"

Why spend so much time explaining this?

Because you can create an identity class from the following:

  1. Computer
  2. Server.Computer
  3. Service
    1. Registry
    2. File
  4. Application
    1. Registry
    2. File
  5. Role
    1. Registry
    2. File