Categorizing Management Pack Elements

If you are familiar with Management Packs and their elements in Operations Manager, you'll know that there were a few elements that had a "Category" attribute whose value was fixed from an enumeration defined in the schema. While this worked, it was quite limiting. For one, the enumeration itself did not make a lot of sense globally. There were values in the enumeration that only applied to some of the elements that used it. Next, it only allowed for some elements to be categorized and only once. Finally, the enumeration was not extensible.

In Service Manager we've added the ability to categorize any Management Pack element via an extensible mechanism that leverages the new concept of enumerations as defined in management packs. Enumerations are essentially hierarchal extensible lists that are defined in management packs. They can be used both as values for class properties as well as values for categorization of elements. In this article, I'll be discussing the latter.

I've updated the NFL management pack I have been using and introduced a new enumeration and some categories. First, you'll find the following enumeration defined:

 <EnumerationTypes>
        <EnumerationValue ID="NFL.VisibleToCallers" Accessibility="Public" />
</EnumerationTypes>

I can define enumerations to mean just about anything I want as the consumer of these enumerations and subsequent categories defines their behavior. In this case, I am defining an enumeration that categorizes elements as visible to callers via some API that I will be providing.

Once I have defined my enumeration, the next step is to categorize my elements as "in" the value. For this, I need to define category elements:

 <Categories>
    <Category ID="NFL.Visibility1" Target="NFL.Conference" Value="NFL.VisibleToCallers" />
    <Category ID="NFL.Visibility2" Target="NFL.Division" Value="NFL.VisibleToCallers" />
    <Category ID="NFL.Visibility3" Target="NFL.Team" Value="NFL.VisibleToCallers" />
</Categories>

As you can see, I've placed three classes into my enumeration, thus categorizing them. But what does this mean from an API perspective? Really, it doesn't mean anything unless the consumer honors the categorization. As an example, the Service Manager UI uses various enumerations as defined in our management packs to categorize elements, such as console tasks or views, to control their visibility behavior in the UI.

Next, I'll demonstrate how a caller of the API can use this categorization. In the following sample, after importing the attached management pack, I retrieve the defined enumeration and generate criteria from it to filter out the classes I want to retrieve based on the categorization:

             // Connect to the management group
            EnterpriseManagementGroup managementGroup =
                new EnterpriseManagementGroup("localhost");

            // Get the management pack
            ManagementPack nflManagementPack = 
                managementGroup.ManagementPacks.GetManagementPack("NFL", null, new Version("1.0.0.0"));

            // Get the type enumeration value
            ManagementPackEnumeration showToCallersEnumeration =
                nflManagementPack.GetEnumeration("NFL.VisibleToCallers");

            // Create an in statement using the category property
            string classCriteria = string.Format(@"<Criteria xmlns=""https://Microsoft.EnterpriseManagement.Core.Criteria/"">
                                        <Expression>
                                            <In>
                                              <GenericProperty>Category</GenericProperty>
                                              <Values>
                                                <Value>{0}</Value>
                                              </Values>
                                            </In>
                                          </Expression>
                                        </Criteria>", showToCallersEnumeration.Id);

            // Create the criteria object
            ManagementPackClassCriteria classesVisibleToCallersCriteria = new ManagementPackClassCriteria(classCriteria);
            
            // Get classes using criteria
            IList<ManagementPackClass> classesVisibleToCallers = managementGroup.EntityTypes.GetClasses(classesVisibleToCallersCriteria);

Important Note: The criteria behaves in the following way with respect to inclusion and exclusion of categories. If you generate a query as shown earlier, it will return any class that is in this category, regardless if it is in other categories. If you change the query to ask for classes where category is not of a particular id, it will exclude the classes that are ONLY in that particular category; so if a class is in category A and B and you ask for classes not in B, you will still get the class back because A is not in B. If a class is only in category B and you ask for classes not in B, you will not get it back because that class is exclusively in B and thus NOT IN B is false. Even if this didn't make sense to you (I had to read it back several times myself :-) ), essentially what this means is that NOT EQUAL to a particular category queries just don't work the way you would expect so please don't use them or understand how they work before you do. To mitigate this problem, we are planning on caching categories client-side so users can quickly do filtering post-query for "NOT" semantics.

NFL.xml