Working with Management Pack Templates

Management pack templates provide a powerful way to create single or a collection of management pack objects. Essentially, you author the fragment of a management pack you want created, with some missing values that become configuration to your template, and upon execution of the template the missing values are provided and the finished management pack object(s) are materialized and imported.

Templates show up in the UI under the Authoring pane. In order for your own custom template to show up there, you need to create a folder for it and place the template in the folder as a folder item. It will show up without the folder, but won't work quite right. Enabling executing the template via the UI is outside the scope of this post, but should be eventually available as a tutorial on www.authormps.com.

I've attached a sample management pack that essentially recreates the instance group template we use for creating groups.

If you take a look at the template defined there, you will see that the configuration section is very similar to other management pack elements. The configuration schema here specifies what values must be provided to the template processor.

The second section is the references for the actual template. The references refer to the references section of the management pack the template is in, by alias. There is one special alias defined, 'Self', which refers to the management pack the template is in.

Finally, under the implementation section is the fragment of the management pack you want your template to create. You can have the configuration values replace any part of the implementation by referring to the values via the $TemplateConfig/<configuration variable name>$ format.

In the templates management pack you will also notice that I put the sample templates in a newly created folder. This will ensure the UI behaves properly with any template output I produce. What happens is that the template output can be placed in a folder, and the UI will treat these folders as individual instances of execution of the template, such that they can be managed as homogenous units, even though they may have created a wide variety of management pack objects.

The code below runs my template using the SDK.

First you will notice that I need to get the management pack the template is in and the template itself. I need the management pack for two reasons. First, I need a management pack to run the template against; all the objects produced by the template will be placed in this management pack. Second, I need this particular management pack because it is not sealed and thus any templates defined in it, must be run against it. If you seal the management pack that contains the template, you can run it against any non-sealed management pack.

Next, I have to build the configuration for my template. This is just XML that matches the schema of my template. You will also notice that within my configuration I have to referenced some management packs. This will be reflected by adding additional references as a parameter to processing the template. Note that if I want to use references that already exist in the management pack the template output will be put in, these aliases must match the already existing aliases for the same management packs.

Finally, when I process my template, I provide additional information that will be used to name the folder the template output is put into. This is optional, but required if you want the output to show up in the UI and want to be able to delete it easily (by deleting everything in this folder). The method actually returns the folder the output was put in.

 using System;
using System.Collections.ObjectModel;
using System.Text;
using System.Xml;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Configuration;

namespace Jakub_WorkSamples
{
    partial class Program
    {
        static void ProcessTemplate()
        {
            // Connect to the local management group
            ManagementGroup localManagementGroup = new ManagementGroup("localhost");

            // Get template management pack. This is where we will store out template output since 
            // the sample template management pack is not sealed and the output needs to be 
            // in the same management pack as the template in this case.
            ManagementPack templateManagementPack =
                localManagementGroup.GetManagementPacks(
                "Template.Sample")[0];

            // Get the template you want to process
            MonitoringTemplate sampleTemplate = 
                localManagementGroup.GetMonitoringTemplates(
                    new MonitoringTemplateCriteria("Name = 'Sample.Template'"))[0];

            // Populate the configuration for the template
            string formula =
               @"<MembershipRule>
                <MonitoringClass>$MPElement[Name=""Windows!Microsoft.Windows.Computer""]$</MonitoringClass>
                <RelationshipClass>$MPElement[Name=""InstanceGroup!Microsoft.SystemCenter.InstanceGroupContainsEntities""]$</RelationshipClass>
                </MembershipRule>";
            
            StringBuilder stringBuilder = new StringBuilder();
            XmlWriter configurationWriter = XmlWriter.Create(stringBuilder);
            configurationWriter.WriteStartElement("Configuration");
            configurationWriter.WriteElementString("Namespace", "Sample.Namespace");
            configurationWriter.WriteElementString("TypeName", "MyClass");
            configurationWriter.WriteElementString("LocaleId", "ENU");
            configurationWriter.WriteElementString("GroupDisplayName", "My Class");
            configurationWriter.WriteElementString("GroupDescription", "My Class Description");
            configurationWriter.WriteStartElement("MembershipRules");
            configurationWriter.WriteRaw(formula);
            configurationWriter.WriteEndElement();
            configurationWriter.WriteEndElement();
            configurationWriter.Flush();

            // Get the management packs for references
            ManagementPack windowsManagementPack = localManagementGroup.
                GetManagementPack(SystemManagementPack.Windows);
            ManagementPack instanceGroupManagementPack = localManagementGroup.
                GetManagementPack(SystemManagementPack.Group);
            ManagementPackReferenceCollection newReferences =
                new ManagementPackReferenceCollection();
            newReferences.Add("Windows", windowsManagementPack);
            newReferences.Add("InstanceGroup", instanceGroupManagementPack);

            templateManagementPack.ProcessMonitoringTemplate(sampleTemplate,
                stringBuilder.ToString(),
                newReferences,
                "MyTemplateRunFolder",
                "My Template Run",
                "This is the folder for my sample template output");
        }
    }
}

Template.Sample.xml