Discovery: identifying the device [SNMP MP Chap 2] #sysctr #scom


Update

My first device discovery method implied a new SNMP GET to be able to identify the device, as my fellow MVP Alexey Zhuravlev pointed out it’s not necessary. Since the OID is already discovered by the standard OpsMgr discovery we just need to iterate through the discovered device and get our own device from the existing OID. Thanks Alex for pointing this out and making me feel like an idiot ;-).

In any case I will keep the old discovery method for future reference at the bottom of the article.

Identifying the device

The very first step to monitor a generic device is to get a unique identifier for the device itself. This is important since we need to discover the device in order to apply the proper monitoring policies. The first id to check for is sysObjectID (.1.3.6.1.2.1.1.2), the id is returned by OpsMgr discovery itself.

The easy way is to add the generic device IP to our discovery rule and let Operations Manager to perform the basic discovery, if this doesn’t work it’s useless to go forward, the device needs to be discovered by standard Operations manager discovery before we can do anything with it. Once it has been discovered we just need to step in the administration space and, under network devices, select the properties of the device:

 There are obviously other methods to get to this OID for example snmpwalk from SharpSnmpLib can be used (see references in chapter 1), for an SNMP v2 device the syntax is something like this:

snmpget -v=2 -c=public localhost .1.3.6.1.2.1.1.2

where “localhost” must be substituted with the device IP and the community set accordingly, but this is more a troubleshooting technique then something useful at this stage: remember the device must be first discovered by Operations Manager.

Discovering the device

One we have the the device id we can write our discovery. To do this:

1.       We must define a new class derived by System.NetworkManagement.Node. If our device is a switch we can use the System.NetworkManagement.Switch class as well. What if it is a router, easy System.NetworkManagement.Router.

QND.MyNetwork.Device class

    <EntityTypes>

      <ClassTypes>

        <!– In this section, modify the attributes based on your needs. Ensure the

             Base attribute matches the application you are modeling.

             More information can be found in the Management Pack Development Kit:

             http://msdn.microsoft.com/en-us/library/ee533867.aspx –>

        <ClassType ID=QND.MyNetwork.Device Accessibility=Public Abstract=false Base=Network!System.NetworkManagement.Node Hosted=false Singleton=false Extension=false” />

        </ClassType>

</EntityTypes>

 

2.       Let’s define the discovery datasource. We just use the FilteredClassSnapshotDataMapper to get our device

XML

<DataSourceModuleType ID=QND.MyNetwork.Device.Discovery.DS Accessibility=Internal Batching=false>

        <Configuration>

          <xsd:element minOccurs=1 name=IntervalSeconds type=xsd:integer />

          <xsd:element minOccurs=0 name=SyncTime type=xsd:string />

          <xsd:element minOccurs=0 maxOccurs=1 name=Version type=xsd:string />

          <xsd:element name=DisplayName type=xsd:string />

          <xsd:element name=Model type=xsd:string />

        </Configuration>

        <OverrideableParameters>

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

          <OverrideableParameter ID=SyncTime ParameterType=string Selector=$Config/SyncTime/>

        </OverrideableParameters>

        <ModuleImplementation Isolation=Any>

          <Composite>

            <MemberModules>

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

                <Scheduler>

                  <SimpleReccuringSchedule>

                    <Interval>$Config/IntervalSeconds$</Interval>

                    <SyncTime>$Config/SyncTime$</SyncTime>

                  </SimpleReccuringSchedule>

                  <ExcludeDates />

                </Scheduler>

              </DataSource>

              <ConditionDetection ID=MapToDiscovery TypeID=System!System.Discovery.FilteredClassSnapshotDataMapper>

                <Expression>

                  <SimpleExpression>

                    <ValueExpression>

                      <Value>$Target/Property[Type=”Network!System.NetworkManagement.Node”]/SystemObjectID$</Value>

                    </ValueExpression>

                    <Operator>Equal</Operator>

                    <ValueExpression>

                      <Value Type=String>.1.3.6.1.4.1.41091.1.1</Value>

                    </ValueExpression>

                  </SimpleExpression>

                </Expression>               

                <ClassId>$MPElement[Name=’QND.MyNetwork.Device’]$</ClassId>

                <InstanceSettings>

                  <Settings>

                    <Setting>

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

                      <Value>$Config/DisplayName$</Value>

                    </Setting>

                    <Setting>

                      <Name>$MPElement[Name=’Network!System.NetworkManagement.Node’]/DeviceKey$</Name>

                      <Value>$Target/Property[Type=”Network!System.NetworkManagement.Node”]/DeviceKey$</Value>

                    </Setting>

                    <Setting>

                      <Name>$MPElement[Name=’Network!System.NetworkManagement.Node’]/Model$</Name>

                      <Value>$Config/Model$</Value>

                    </Setting>

                    <Setting>

                      <Name>$MPElement[Name=’Network!System.NetworkManagement.Node’]/Vendor$</Name>

                      <Value>QND</Value>

                    </Setting>

                    <Setting>

                  </Settings>

                </InstanceSettings>

              </ConditionDetection>

            </MemberModules>

            <Composition>

              <Node ID=MapToDiscovery>

                <Node ID=Scheduler />

              </Node>

            </Composition>

          </Composite>

        </ModuleImplementation>

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

      </DataSourceModuleType>

 

3.       Finally we must define our discovery rule targeted at the generic System.Network.Node class

MyNetwork.Device discovery rule

  <Discovery ID="QND.MyNetwork.Device.Discovery" Enabled="true" ConfirmDelivery="false" Remotable="true" Priority="Normal" Target="Network!System.NetworkManagement.Node">
    <Category>Discovery</Category>
    <DiscoveryTypes>
      <DiscoveryClass TypeID="QND.MyNetwork.Device" />
    </DiscoveryTypes>
    <DataSource ID="DS" TypeID="QND.MyNetwork.Device.Discovery.DS">
      <IntervalSeconds>43200</IntervalSeconds>
      <SyncTime />
      <DisplayName>$Target/Property[Type="Network!System.NetworkManagement.Node"]/sysName$</DisplayName>
      <Model>MyNetwork Device Model XYZ</Model>
    </DataSource>
  </Discovery>

 

This is it. But let’s review the key points here to make this process really generic. The QND.MyNetwork.Device.Discovery.DS is a composition of a standard scheduler and a filtered snapshot class data mapper. The filter is used to actually filter our device by sysObjectID. Basically this module, at the scheduled time, enumerates all the NetworkNode discovered devices and maps the ones with the corresponding sysObjexctID to our device class. All this is done without any network traffic.

From here we can go on building our specific monitor, but this is the topic for another post.

The Old way

The following is the old discovery data source, it basically gets the system object ID via SNMP, this is not needed since OpsMgr already discovered it for us.

4.       Using the System.NetworkManagement.SnmpProbe we must define a new data source module type to feed our discovery rule. To make code reusable I will define a generic datasource that does the match and a specific datasource that perform the actual mapping

Generic datasource to match on device sysObjectID

  <DataSourceModuleType ID="QND.NetLibrary.MatchOID.DS" Accessibility="Public" Batching="false">
    <Configuration>
      <IncludeSchemaTypes>
        <SchemaType>System!System.ExpressionEvaluatorSchema</SchemaType>
        <SchemaType>Snmp!System.SnmpVarBindsSchema</SchemaType>
      </IncludeSchemaTypes>
      <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" />
      <xsd:element minOccurs="0" name="SyncTime" type="xsd:string" />
      <xsd:element minOccurs="0" maxOccurs="1" name="NoOfRetries" type="xsd:unsignedInt" default="3" />
      <xsd:element minOccurs="0" maxOccurs="1" name="Timeout " type="xsd:unsignedInt" default="500" />
      <xsd:element minOccurs="0" maxOccurs="1" name="Port" type="xsd:unsignedInt" default="161" />
      <xsd:element name="IP" type="xsd:string" />
      <xsd:element name="CommunityString" type="xsd:string" />
      <xsd:element minOccurs="0" maxOccurs="1" name="Version" type="xsd:string" />
      <xsd:element name="ObjectOID" type="xsd:string" />
    </Configuration>
    <ModuleImplementation Isolation="Any">
      <Composite>
        <MemberModules>
          <DataSource ID="Scheduler" TypeID="System!System.Discovery.Scheduler">
            <Scheduler>
              <SimpleReccuringSchedule>
                <Interval>$Config/IntervalSeconds$</Interval>
                <SyncTime>$Config/SyncTime$</SyncTime>
              </SimpleReccuringSchedule>
              <ExcludeDates />
            </Scheduler>
          </DataSource>
          <ProbeAction ID="Probe" TypeID="Network!System.NetworkManagement.SnmpProbe">
            <Walk>false</Walk>
            <WalkReturnMultipleItems>false</WalkReturnMultipleItems>
            <NoOfRetries>3</NoOfRetries>
            <Timeout>500</Timeout>
            <Port>$Config/Port$</Port>
            <SNMPv3UserName>$RunAs[Name="Network!System.NetworkManagement.SnmpV3.MonitoringAccount"]/UserName$</SNMPv3UserName>
            <SNMPv3AuthProtocol>$RunAs[Name="Network!System.NetworkManagement.SnmpV3.MonitoringAccount"]/AuthenticationProtocol$</SNMPv3AuthProtocol>
            <SNMPv3AuthPassword>$RunAs[Name="Network!System.NetworkManagement.SnmpV3.MonitoringAccount"]/AuthenticationKey$</SNMPv3AuthPassword>
            <SNMPv3PrivProtocol>$RunAs[Name="Network!System.NetworkManagement.SnmpV3.MonitoringAccount"]/PrivacyProtocol$</SNMPv3PrivProtocol>
            <SNMPv3PrivPassword>$RunAs[Name="Network!System.NetworkManagement.SnmpV3.MonitoringAccount"]/PrivacyKey$</SNMPv3PrivPassword>
            <SNMPv3ContextName>$RunAs[Name="Network!System.NetworkManagement.SnmpV3.MonitoringAccount"]/ContextName$</SNMPv3ContextName>
            <IsWriteAction>false</IsWriteAction>
            <IP>$Config/IP$</IP>
            <CommunityString>$Config/CommunityString$</CommunityString>
            <Version>$Config/Version$</Version>
            <SnmpVarBinds>
              <SnmpVarBind>
                <OID>.1.3.6.1.2.1.1.2.0</OID>
                <Syntax>0</Syntax>
                <Value VariantType="8" />
              </SnmpVarBind>
            </SnmpVarBinds>
            <OutputOnError>false</OutputOnError>
          </ProbeAction>
          <ConditionDetection ID="FilterOnObjectID" TypeID="System!System.ExpressionFilter">
            <Expression>
              <SimpleExpression>
                <ValueExpression>
                  <XPathQuery Type="String">SnmpVarBinds/SnmpVarBind[OID=".1.3.6.1.2.1.1.2.0"]/Value</XPathQuery>
                </ValueExpression>
                <Operator>Equal</Operator>
                <ValueExpression>
                  <Value Type="String">$Config/ObjectOID$</Value>
                </ValueExpression>
              </SimpleExpression>
            </Expression>
          </ConditionDetection>
        </MemberModules>
        <Composition>
          <Node ID="FilterOnObjectID">
            <Node ID="Probe">
              <Node ID="Scheduler" />
            </Node>
          </Node>
        </Composition>
      </Composite>
    </ModuleImplementation>
    <OutputType>Snmp!System.SnmpData</OutputType>
  </DataSourceModuleType>

 

Specific discovery datasource for QND.MyNetwork.Device

  <DataSourceModuleType ID="QND.MyNetwork.Device.Discovery.DS" Accessibility="Internal" Batching="false">
  <Configuration>
    <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" />
    <xsd:element minOccurs="0" name="SyncTime" type="xsd:string" />
    <xsd:element minOccurs="0" maxOccurs="1" name="NoOfRetries" type="xsd:unsignedInt" default="3" />
    <xsd:element minOccurs="0" maxOccurs="1" name="Timeout " type="xsd:unsignedInt" default="500" />
    <xsd:element minOccurs="0" maxOccurs="1" name="Port" type="xsd:unsignedInt" default="161" />
    <xsd:element name="IP" type="xsd:string" />
    <xsd:element name="CommunityString" type="xsd:string" />
    <xsd:element minOccurs="0" maxOccurs="1" name="Version" type="xsd:string" />
    <xsd:element name="DisplayName" type="xsd:string" />
    <xsd:element minOccurs="1" name="DeviceKey" type="xsd:string" />
    <xsd:element name="Model" type="xsd:string" />
    <xsd:element name="Vendor" type="xsd:string" />
  </Configuration>
  <ModuleImplementation Isolation="Any">
    <Composite>
      <MemberModules>
        <DataSource ID="Seed" TypeID="QND.NetLibrary.MatchOID.DS">
          <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
          <SyncTime>$Config/SyncTime$</SyncTime>
          <Port>$Config/Port$</Port>
          <IP>$Config/IP$</IP>
          <CommunityString>$Config/CommunityString$</CommunityString>
          <Version>$Config/Version$</Version>
          <ObjectOID>.1.3.6.1.4.1.41091.1.1</ObjectOID>
        </DataSource>
        <ConditionDetection ID="MapToDiscovery" TypeID="System!System.Discovery.ClassSnapshotDataMapper">
          <ClassId>$MPElement[Name='QND.MyNetwork.Device']$</ClassId>
          <InstanceSettings>
            <Settings>
              <Setting>
                <Name>$MPElement[Name='System!System.Entity']/DisplayName$</Name>
                <Value>$Config/DisplayName$</Value>
              </Setting>
              <Setting>
                <Name>$MPElement[Name='Network!System.NetworkManagement.Node']/DeviceKey$</Name>
                <Value>$Config/DeviceKey$</Value>
              </Setting>
              <Setting>
                <Name>$MPElement[Name='Network!System.NetworkManagement.Node']/Model$</Name>
                <Value>$Config/Model$</Value>
              </Setting>
              <Setting>
                <Name>$MPElement[Name='Network!System.NetworkManagement.Node']/Vendor$</Name>
                <Value>$Config/Vendor$</Value>
              </Setting>
            </Settings>
          </InstanceSettings>
        </ConditionDetection>
      </MemberModules>
      <Composition>
        <Node ID="MapToDiscovery">
          <Node ID="Seed" />
        </Node>
      </Composition>
    </Composite>
  </ModuleImplementation>
  <OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>

 

But let’s review the key points here to make this process really generic. The QND.NetLibrary.MatchOID.DS is a composition of a standard scheduler, with the generic SNMP probe configured to SNMP GET (<Walk>false</Walk>) the RFC standard sysObjectID, the result is filtered to return just the devices with a matching OID ($Config/ObjectOID$). It can be underlined the isolation of SNMPv3 parameters, since it’s highly improbable we will use different credentials when running our workflows from the credential used to discover the device. This will make our subsequent workflows easier to read. This is a generic module that, if this series will continue, will add to a generic Network Library management pack.

The actual discovery datasource builds on the QND.NetLibrary.MatchOID.DS sets the OID to be matched and maps the resulting SNMP data to the QND.MyNetwork.Device class. As you can read this is where we can add some more data to the discovered properties (for example the model information). The mapping is done using a standard System.Discovery.ClassSnapshotDataMapper.

Finally the actual discovery rule, this rule will hit every single network device discovered so far so I would suggest to schedule it once or twice a day, for every device it will perform a SNMP GET and check if the returned OID is the MyNetwork.Device one, if so the device is discovered.

 

– Daniele

This posting is provided “AS IS” with no warranties, and confers no rights.

  1. #1 by Chris Rivera on November 2, 2015 - 9:18 pm

    daniel,
    I’m going to follow your instructions to create an SNMP management pack for Sophos UTM network devices. I’ll let you know how it goes. I will provide the management pack once it is completed. Let me know if there is anything addtional you could use to help your documentation for this blog.

    • #2 by Erik Leutscher on February 11, 2016 - 2:23 pm

      Hi Chris, Did you finished making an MP for Sophos UTM? I am looking for one.

  2. #3 by Gabe on July 3, 2014 - 11:01 pm

    Hi Daniele,

    Thanks for the great write up. I enjoyed reading your blog series and decided to do a fun little project to create an MP to monitor my DDWRT Router that I currently have in my Lab/Home environment.

    Unfortunately I cannot get the MP to create in Visual Studio Pro 2013 using the System Center Extensions. I’m getting several errors when running a code analysis on my project and I’m hoping you can help as this is my first attempt at MP creation using VS. Up till this point I’ve been mostly creating MP’s in the console and would like to expand my skills into advanced MP creation. Thought starting out by adding my router at home would be a good start.

    Below are the errors I’m receiving when running the code analysis.

    C:\Program Files (x86)\MSBuild\Microsoft\VSAC\Microsoft.SystemCenter.OperationsManager.targets(255,5): error : Failed to verify module reference [Type=ManagementPackElement=System.Discovery.FilteredClassSnapshotDataMapper in ManagementPack:[Name=System.Library, KeyToken=31bf3856ad364e35, Version=7.5.8501.0], ID=MapToDiscovery] in the MemberModules list.
    : Incorrect XPATH reference: DisplayName.

    I’m thinking this has to do with this line in my Datasource module. Verified ‘System!System.Entity’]/DisplayName$ exists in the System.Library reference in my project, but for the life of me I cannot figure out why i’m getting this error.

    C:\Program Files (x86)\MSBuild\Microsoft\VSAC\Microsoft.SystemCenter.OperationsManager.targets(255,5): error : The configuration specified for Module DS is not valid.
    : Schema validation failed.
    The element ‘Configuration’ has incomplete content. List of possible elements expected: ‘IntervalSeconds’. (Path = DDWRTRouter.Discovery.Router/DS)

    Note sure why I’m getting the Schema validation failed error.

    I can zip the project up and send it to you or past the code into the comment if that helps. I’m fairly new to VS MP creation so any help would be greatly appreciated.

    Thanks
    Gabe

    • #4 by Daniele Grandini on July 4, 2014 - 7:19 am

      Hi Gabe 99% there’s a typo when you refer to DisplayName in the configuration section of your data source, if you send the code I would be more than happy to take a look at it, but I’m sure that if you carefully review the code you’ll find the typo yourself. :-)

  3. #5 by Steve Burkett on October 19, 2013 - 2:55 pm

    Not sure if it’s my browser or Sergei’s code in his comment was removed. Anyhow, in the two OverrideableParameter lines, add a dollar sign to the end of the IntervalSeconds and SyncTime in the Selector part of these lines?

    • #6 by Daniele Grandini on October 22, 2013 - 8:29 am

      Yes Steve, you’re correct there’s a typo in the pasted code where the final $ sign is missing.
      Daniele

  4. #7 by Sergei on July 30, 2013 - 12:55 pm

    I had build errors with your OverrideableParameters
    i’d replaced them with:

    and build succeded

  5. #8 by Sergei on June 6, 2013 - 8:58 pm

    Great post series,
    but are U shure we need to use snmp v1/2 account in discovery rule for v3 discovery?
    “$RunAs[Name=”Network!System.NetworkManagement.Snmp.MonitoringAccount”]/CommunityString$$Target/Property[Type=”Network!System.NetworkManagement.Node”]/VirtualCommunitySuffix$”

    • #9 by Daniele Grandini on June 7, 2013 - 8:49 am

      Hi Sergei,
      I’m not sure to understand what you’re asking. The discovery I’m presenting are SNMP version indipendent, I don’t know in advance if the device will use SNMP v2c or v3, so I must spend all the possible security information on the data source. The OPsMgr discovery module will take care of setting the proper values based on the discovery rules defined.
      Where am I wrong?
      – Daniele

      • #10 by Sergei on July 12, 2013 - 2:56 pm

        Hi,
        U already know snmp version (v2 or v3), device is using, because u specify this in scom when doing discovery, but yes, if u want to create universal discovery, not the linked one to specific version, i agree with you

  1. Writing a custom class for your network devices – Kevin Holman's Blog
  2. NeWay Technologies – Weekly Newsletter #44 – May 24, 2013 | NeWay
  3. Creating SNMP monitoring Management Packs for System Center 2012 Operations Manager [SNMP MP Chap 2] #scom #sysctr | Quae Nocent Docent

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.