How to extend and populate a CI class in SCSM 2012

A fairly common requirement from customers is to extend work item or configuration item classes and pull values from other systems (like Active Directory or some database) and put it into a new property of an existing class. Service Manager is very extendable and has some great feature to help you with that. To achieve a goal like this, you *just* need to “author” your own management pack and do some scripting or System Center Orchestrator magic.

Sounds complicated? Follow this blog post and you will see that it’s not that hard at all.

Here’s the high level overview of what to do:

  1. Identify the class you want to extend
  2. Create a management pack to extend the class
  3. Create a script (or Orchestrator runbook) to populate the new property/properties of your extended class

1. Identifying the class to extend

In this example I demonstrate how to extend the Active Directory User class (which is used and populated by the AD connector) to have a dedicated property for the primary email address. In case you wonder why I do this, you should know that SCSM handles email addresses using relationships and dedicated objects which makes it hard to just get a view of all users with a column showing the primary email address (as set in AD). With SCSM you cannot do this easily.

My fellow MVP colleague Anton Gritsenko is working on a tool called “Advanced View Editor for SCSM 2012” which will allow you to create a view to display the email addresses in a column. At this point it’s still beta but you should definitely check it out as you can do much, much more with this awesome tool!

Still, this blog post should be more like a demonstration on how to solve a problem like this in general: pulling some data from somewhere and populate an extended class. Take a look at this Technet Library page to see how the AD connector is mapping objects to Service Manager: http://technet.microsoft.com/en-us/library/hh524307.aspx

As you can see, it seems that the mail property from AD is synchronized with the Microsoft.AD.User property but if you try to create a view showing the Email property, you are out of luck:

At least, the Technet page gives us a clue what class we should extend: “Active Directory User” (ID = Microsoft.AD.User). In case you do not have a Technet page which is showing you the class ID, the easy way to find the ID (= Name) for the class is a PowerShell command like this:

Get-SCSMClass | where {$_.DisplayName –eq ‘Active Directory User’}

2. Create a management pack to extend the class

To extend a class we need to “author” a management pack. Since a management pack basically some XML definitions you could use a tool like notepad but it would require you to know the schema and exact syntax on how to create a management pack. A much easier way to create management packs is either the use of Service Manager Authoring Tool or the Visual Studio Authoring Extension (which allows you to not only create Service Manager management packs but also allows you to create Operations Manager management packs). Note, the Service Manager authoring tool was released for SCSM 2010 SP1 but it will also work for SCSM 2012 management packs. Since we are only extending a class, I will use the Visual Studio Authoring Extension (which requires at least Visual Studio 2010 Professional). If you want to customize forms, I recommend you use the Service Manager Authoring Tool as this one has a graphical, designer like interface to do so. Once I’ve installed Visual Studio 2010 and the Authoring Extensions, I create a new Project with the type: “Service Manager 2012 Management Pack”:

Next, we need to add a reference to the management pack which holds the original class we want to extend. The Get-SCSMClass command above will also show the management pack name: “Microsoft.Windows.Library”

Right-click on the “References” node in the Solution Explorer and select “Add Reference”. Navigate to the SCSM installation folder and browse for the file Microsoft.Windows.Library.mp:

Next, click on the project in the Solution Explorer and right-click to select Add –> New Item…:

Now, select Class and type a name like ADUserExtension.mpx:

In the management pack fragment, paste the following code:

<ManagementPackFragment SchemaVersion="SM2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        <ClassType ID="code4ward.SCSM.ADUser.Extension.ADUserExtension" 
                   Base="Windows!Microsoft.AD.User" 
                   Extension="true"
                   Accessibility="Public" 
                   Abstract="false" 
                   Hosted="false" 
                   Singleton="false">
          <Property ID="PrimaryEmailAddress" Key="false" Type="string" />
        </ClassType>
      </ClassTypes>
    </EntityTypes>
  </TypeDefinitions>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="code4ward.SCSM.ADUser.Extension.ADUserExtension">
          <Name>Active Directory User (Extended)</Name>
          <Description></Description>
        </DisplayString>
        <DisplayString ElementID="code4ward.SCSM.ADUser.Extension.ADUserExtension" SubElementID="PrimaryEmailAddress">
          <Name>Primary Email Address</Name>
          <Description></Description>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

The code snippet above looks basically almost the same as the code snippet you find after adding the new class item. Here’s what I changed and why:

  1. The class type ID was adjusted to be unique (usually you add those dot-separated naming like company.application.thing[.subthing] to uniquely identify your class).
  2. The base class is changed to the Microsoft.AD.User class in the Windows (alias for Microsoft Windows Library) management pack.
  3. The extension attribute is added to tell SCSM that we do not want a new class, instead we want to extend an existing class. This also ensures that all inherited classes get the new property/properties.
  4. The property id was changed to something meaningful: PrimaryEmailAddress.
  5. The display strings (here only English/ENU) were updated.

That’s it. Build the management pack and import it into your management group.
Note that for this demo I didn’t seal the MP. MPs with extensions or class definitions should be sealed when used in production.
After you have imported the MP you will see that the new property “Primary Email Address” is now available for the Active Directory User class (and all inherited classes):

Also note that creating a new or editing an existing user would already allow you to use the new property:

Because we didn’t adjust the user form, you will find all additional, custom properties on theExtensions tab.

3. Automatically populate the new property

Now, that we have successfully extended a class, we want to have it filled with data – preferably using a script or something which can be automated. In this example I will write a simple PowerShell script which can be executed on demand, using a scheduled task or invoked by a runbook.

$UserCIs = Get-SCClassInstance -class (Get-SCClass -name 'Microsoft.AD.User')
foreach ($UserCI in $UserCIs)
{
    $ADUser = Get-ADUser -Filter "SamAccountName -eq '$($UserCI.UserName)'" -Server $UserCI.Domain -Properties EmailAddress
    Write-Host Processing CI $UserCI.UserName
    Write-Host CI Email: $UserCI.PrimaryEmailAddress
    Write-Host AD Email: $ADUser.EmailAddress
    if ($ADUser.EmailAddress -ne $UserCI.PrimaryEmailAddress)
    {
        Write-Host CI and AD email address does not match!
        $UserCI.PrimaryEmailAddress = $ADUser.EmailAddress
        $UserCI | Update-SCSMClassInstance
        Write-Host CI was updated.
    }
    Write-Host ----------
} 

Let me explain the above script above:

  1. The approach here is to get all CIs from SCSM and compare each found entry with the one in Active Directory. You could go through the AD users and compare it with the CI classes but this should be much more efficient and better because you may not import all your AD users into the CMDB.
  2. For each CI object we get the corresponding AD user (note that you may need to specify which properties to load; in this case we just need the EmailAddress).
  3. Then we compare the email address from AD with the one from the CI (note that you just can refer to our extended property using $UserCI.PrimaryEmailAddress.
  4. The Update-SCSMClassInstance will commit the change of the CI object to the database.

Conclusion

As you can see, it’s not too hard to extend classes with additional properties and fill and update them automatically using some simple script. Please bear in mind that the content of this blog post is roughly a proof of concept and should be carefully tested, adapted and extended before you put it into production.

If you have any suggestions or feedback, let me know.

cheers,
Stefan

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