Network devices dynamic group membership #sysctr #scom


The scenario

As a System Center solution provider and consultant I often face complex scenarios where multi tenancy and administrative delegation is a must. One of the latest challenges I faced has been about Operations Manager console scoping in a complex and distributed architecture. The customer used to have gateways and sites to partition the OpsMgr infrastructure and to scope the console on a regional support basis. The approach has been:

          For every region set the appropriate gateways and define a site

          Scope the console using sites so that each regional support center can take care of the appropriate devices

Lastly the customer added support for *nix systems and network devices (SNMP) monitoring. For both categories the site relationship doesn’t work, so they had to find a way to add the*nix and SNMP devices to the pictures and asked for help.

I need to add a couple of requirements:

          They don’t want, as much as possible, to deal with low level MP authoring and/or XML customizations

          They want to be autonomous in adding and modifying sites and scopes

This blog post is about a possible solution to the above scenario, it is probably not a common scenario, but it can be used as a basic idea to solve similar problems.

It will focus on network devices for a couple of reasons:

          The xplat systems are limited in number and pretty static

          The xplat systems monitoring requires a group the runas account distribution and the population of the group as already been written

On the other hand network devices are in the hundreds and potentially much more dynamic, so the customer doesn’t want to have a static instance based group.

A possible solution

I started working on two of ideas:

          Add a site relationship to the objects, so that the site scoping will just include the missing objects

          Create a dynamic group based on resource pool monitoring relationship, then add the proper group to the user role

Both ideas ended up with issues:

          In the first case I was fearing collateral effects

          In the second case I didn’t find a way to specify the relationship in the group populator data source

Eventually I decided to use the discovery rule as the seed of the dynamic group, so I will have one group per discovery rule and then I can add the group to the console scoping. The discovered devices have a containment relationship with the discovery rule, so in the group populatore datasource I can use the contained operator. Alas the operator is not exposed in the UI so a custom management pack needed to be written, but the customer wanted to be autonomous and not have to “develop” custom management pack.

In the end, I created a base management pack and a powershell script that using the SDK adds the proper classes and sicovery rules: one for each network discovery rule. The customer can run the script every time a new discovery rule is added and the script will create the corresponding dynamic group. The group can then be added to the proper user role for console scoping.

The management pack defines the network device group base class and the relationship between the group and the network devices:

XML

  <TypeDefinitions>

    <EntityTypes>

      <ClassTypes>

 

        <!– In this section, you can edit the Base attribute to derive from other non-generic

             group types. Depending on your requirements and how you or your users will use this

             group, you may need to populate this group with instances by creating a Discovery

             that uses a script or the GroupPopulator module: http://msdn.microsoft.com/en-us/library/ff472328.aspx –>

        <ClassType ID=QND.NetDevGroup.Class Accessibility=Internal Base=System!System.Group Abstract=true Hosted=false Singleton=false>

        </ClassType>

 

      </ClassTypes>

      <RelationshipTypes>

        <RelationshipType ID=QND.NetDevGroup.GroupContainsNode Abstract=false Accessibility=Internal  Base=System!System.Containment>

          <Source ID=Group Type=QND.NetDevGroup.Class></Source>

          <Target ID=Device Type=SNL!System.NetworkManagement.Node/>

        </RelationshipType>

      </RelationshipTypes>

    </EntityTypes>

  </TypeDefinitions>

 

The management pack must be imported before the powershell script can be run. The script takes in input the management pack name and the sdk server name, then:

          Enumerates all the network discovery rules

$netdiscoserver = get-scomclassinstance -class (get-scclass -DisplayName ‘Network Discovery Server’)

          For each rule checks if a group exists, if not creates a new one

     $grp = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackClass ($mp, $groupClassName, [Microsoft.EnterpriseManagement.Configuration.ManagementPackAccessibility]::Public) 

          It then creates a new discovery rule

$discovery = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackDiscovery ($mp, $groupDiscoveryName)    

          With the proper membership

          <RuleId>$MPElement$</RuleId>

          <GroupInstanceId>$Target/Id$</GroupInstanceId>

          <MembershipRules>

            <MembershipRule>

              <MonitoringClass>$MPElement[Name=”SNL!System.NetworkManagement.Node”]$</MonitoringClass>

              <RelationshipClass>$MPElement[Name=”QND.NetDevGroup.GroupContainsNode”]$</RelationshipClass>

              <Expression>

                <Contained>

                  <MonitoringClass>$MPElement[Name=”SNL!System.NetworkManagement.NetworkDiscoveryServer”]$</MonitoringClass>

                  <Expression>

                    <SimpleExpression>

                      <ValueExpression>

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

                      </ValueExpression>

                      <Operator>Equal</Operator>

                      <ValueExpression>

                        <Value>//NetworkDiscoveryServerDisplayName//</Value>

                      </ValueExpression>                     

                    </SimpleExpression>

                  </Expression>

                </Contained>

              </Expression>

            </MembershipRule>

          </MembershipRules>

The whole powershell script follows:

Powershell

<#

.Synopsis

   Batch generates Operations Manager Groups for network devices based network discovery rule membership

  

.DESCRIPTION

Using a pre-imported base management pack creates one group of network devices per network discovery rule.

The groups are dynamically populated and can be used as any other standard group.

Requirements

 – SCOM Operations Console console must be installed on the system used to run the script

 – the account used to execute the script must be an Operations Manager Admin

 – the base management pack must be pre imported in the management group

 

.EXAMPLE

   .\QND-CreateNetGroups.ps1 -ManagementServer ‘localhost’ -MPName ‘QND.NetDevGroup’

 

 

#>

    [CmdLetBinding()]

param(

    [Parameter(Mandatory=$True,HelpMessage=“Please Enter the management server name”)]

                    [string] $ms,

    [Parameter(Mandatory=$False,HelpMessage=“Please Enter the base managament pack name”)]

                    [string] $mpName=‘QND.NetDevGroup’

)

 

#init session

try

{

    $error.Clear()

    if (!(Get-Module OperationsManager))

    {

        Import-Module OperationsManager

    }

 

    [System.Reflection.Assembly]::LoadWithPartialName(‘Microsoft.EnterpriseManagement.Monitoring’)

    [System.Reflection.Assembly]::LoadWithPartialName(‘Microsoft.EnterpriseManagement.Configuration’)

    [System.Reflection.Assembly]::LoadWithPartialName(‘Microsoft.EnterpriseManagement’)

 

    New-SCManagementGroupConnection -ComputerName $ms

    $mg = Get-SCOMManagementGroup

}

catch {

    Write-Error ‘An Error accured initializing the session. Exiting’

    Write-Error $error

    Exit 1;

}

 

#check for MP existence

try

{

    $mp = $mg.GetManagementPacks($mpName)[0]

    $scmp = $mg.GetManagementPacks(‘Microsoft.SystemCenter.Library’)[0]

}

catch {

    Write-Error “$mpName not found in Management Group $($mg.Name)”

    exit 1

}

 

#constants

$config = @’

          <RuleId>$MPElement$</RuleId>

          <GroupInstanceId>$Target/Id$</GroupInstanceId>

          <MembershipRules>

            <MembershipRule>

              <MonitoringClass>$MPElement[Name=”SNL!System.NetworkManagement.Node”]$</MonitoringClass>

              <RelationshipClass>$MPElement[Name=”QND.NetDevGroup.GroupContainsNode”]$</RelationshipClass>

              <Expression>

                <Contained>

                  <MonitoringClass>$MPElement[Name=”SNL!System.NetworkManagement.NetworkDiscoveryServer”]$</MonitoringClass>

                  <Expression>

                    <SimpleExpression>

                      <ValueExpression>

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

                      </ValueExpression>

                      <Operator>Equal</Operator>

                      <ValueExpression>

                        <Value>//NetworkDiscoveryServerDisplayName//</Value>

                      </ValueExpression>                     

                    </SimpleExpression>

                  </Expression>

                </Contained>

              </Expression>

            </MembershipRule>

          </MembershipRules>

‘@

 

$netdiscoserver = get-scomclassinstance -class (get-scclass -DisplayName ‘Network Discovery Server’)

 

foreach ($nd in $netdiscoserver)

{

    $groupDisplayName = $nd.DisplayName + ‘ Group’

    $groupClassName = $mpName + ‘.’ + $nd.Name

    $groupDiscoveryName = $mpName + ‘.’ + $nd.Name + ‘.Discovery’

    $groupDiscoveryDisplayName = ‘Discovers ‘ + $groupDisplayName

    try

    {

        $groupClass = $mp.GetClass($groupClassName)

        #if we get here the group has already been defined so you have finished

        Write-Output “Group $groupClassName already defined, skipping”

        continue;

    }

    catch [System.Management.Automation.MethodInvocationException] {

        Write-Output “Group $groupClassName not found, going to create one”

        $Error.Clear()

    }

    catch {

        Write-Error “Uncaught exception, skipping $groupDisplayName”

        Write-Error $Error

        $Error.Clear()

        continue;

    }

    try {

        $grp = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackClass ($mp, $groupClassName, [Microsoft.EnterpriseManagement.Configuration.ManagementPackAccessibility]::Public)  

        $grp.DisplayName = $groupDisplayName

        $grp.LanguageCode = ‘ENU’

        $grp.Abstract = $false

        $grp.Singleton = $true

        $grp.Base = $mp.GetClass(‘QND.NetDevGroup.Class’)

        Write-Output “Group $groupDisplayName created, adding discovery rule”

        $discovery = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackDiscovery ($mp, $groupDiscoveryName)    

        $discovery.DisplayName = $groupDiscoveryDisplayName

        $discovery.LanguageCode = ‘ENU’

        $discovery.Category=[Microsoft.EnterpriseManagement.Configuration.ManagementPackCategoryType]::Discovery

        $discovery.ConfirmDelivery = $false

        $discovery.Remotable = $true

        $discovery.Priority = [Microsoft.EnterpriseManagement.Configuration.ManagementPackWorkflowPriority]::Normal

        $discovery.Target = $grp

        $discovery.Enabled = [Microsoft.EnterpriseManagement.Configuration.ManagementPackMonitoringLevel]::true

       

        #the ManagementPackDiscovery property DiscoveryClassCollection is marked as readonly so I cannot add the class and relationship documentation

        #$discoveryClass = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackDiscoveryClass

        #$discoveryClass.TypeID =$mp.GetClass(‘QND.NetDevGroup.Class’)

        #$t = new-object ‘System.Collections.Generic.List[Microsoft.EnterpriseManagement.Configuration.ManagementPackDiscoveryClass]’

        #$t.Add($discoveryClass)

       

        $ds = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackDataSourceModule( $discovery,‘DS’)

        $ds.TypeId = $scmp.GetModuleType(‘Microsoft.SystemCenter.GroupPopulator’)

        $newConfig = $config.Replace(‘//NetworkDiscoveryServerDisplayName//’, $nd.DisplayName)

        $ds.Configuration = $newConfig

        $discovery.DataSource = $ds

     }

     catch {

        Write-Error “Error generating class and disocvery, skipping $groupDisplayName”

        Write-Error $Error

        $Error.Clear()

        continue;

     }

}

     try {

        $mp.Verify()

        $mp.AcceptChanges()

     }

     catch {

        Write-Error “Fatal Error saving management pack, exiting”

        Write-Error $Error

        Exit 2

     }

The base management pack and the script can be found on Technet Gallery here.

Final considerations

I could have used the SDK to build the management pack from scratch, but I found it easier for testing purposes to have a pre-imported base management pack.

– Daniele

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

Advertisements
  1. #1 by Aleem on December 4, 2014 - 4:54 pm

    Hi there,
    I am trying our your solution of Dynamically creating Group MP with Discovery, but the PowerShell scripts fails where it tries to create the Group ManagementPack with the following error

    $grp = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackClass($mp, $groupClassName,
    [Microsoft.EnterpriseManagement.Configuration.ManagementPackAccessibility]::Public)

    Error generating class and disocvery, skipping ClassName Group
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,TestGroupPopulator2.ps1

    Write-Error : Cannot convert ‘System.Collections.ArrayList’ to the type ‘System.String’ required by parameter ‘Message’. Specified method is not
    supported.

    Any clue what i am missing or doing wrong?

    Thanks in advance

    • #2 by Aleem on December 4, 2014 - 5:07 pm

      May be your solution only works with unsealed Management Pack. I have a sealed MP.
      Is it possible to add discovery rules via powershell to an already existing Dynamically created Group?

      $ds = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackDataSourceModule( $discovery,‘DS’)
      $ds.TypeId = $scmp.GetModuleType(‘Microsoft.SystemCenter.GroupPopulator’)
      $newConfig = $config.Replace(‘//NetworkDiscoveryServerDisplayName//’, $nd.DisplayName)
      $ds.Configuration = $newConfig
      $discovery.DataSource = $ds

      • #3 by Daniele Grandini on December 5, 2014 - 8:48 am

        Hi Aleem,
        you need an unselaed MP to store the group and its rules, afaik you cannot add a dynamic rule to a group contained in a sealed MP.

  2. #4 by Jonathan Almquist on May 3, 2014 - 4:26 am

    Thanks for posting this. It was helpful.

    Regarding the commented part for adding discovered types to the discovery:

    #the ManagementPackDiscovery property DiscoveryClassCollection is marked as readonly so I cannot add the class and relationship documentation
    #$discoveryClass = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackDiscoveryClass
    #$discoveryClass.TypeID =$mp.GetClass(‘QND.NetDevGroup.Class’)
    #$t = new-object ‘System.Collections.Generic.List[Microsoft.EnterpriseManagement.Configuration.ManagementPackDiscoveryClass]‘
    #$t.Add($discoveryClass)

    I was able to get this working with the following:

    $discovery_class = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackDiscoveryClass
    $discovery_class.TypeID = $mp.GetClass(‘YourClassId’)
    $discovery.DiscoveryClassCollection.Add($discovery_class)

    • #5 by Daniele Grandini on May 3, 2014 - 9:26 am

      Thx Jonathan,
      I banged my head on this issue :-). With this hint it’s possible to build the MP without the XML snippet.

      -Daniele

    • #6 by Aleem on December 8, 2014 - 6:25 pm

      Thanks Daniele. Your post is very helpful. I am able to create an unsealed MP and after some modification, i am able to create dynamic groups with Expression filters. Thanks for sharing.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: