June, 2009

  • Jakub@Work

    Object Templates

    • 0 Comments

    In Service Manager, we have a variety of scenarios where we needed to capture partial object state and apply that state at a later time. The state captured is usually all or part of some IT process. For example, when creating a Change Request from the UI, the user is prompted with a set of templates to choose from, each representing a different kind of change request. These templates are stored as Object Templates in MPs and pre-define a set of values to populate the change request form with.

    Object templates can be used to store data about classes as well as projections. They are neither classes, nor objects, but rather blueprints (stored in management packs) for creating or modifying objects. In the attached MP you will find three different object templates.

    1.     <ObjectTemplate ID="NFL.NFCDivision.Template" TypeID="NFL.Division" >
    2.       <Property Path="$Target/Property[Type='NFL.Conference']/Name$">NFC</Property>
    3.     </ObjectTemplate>

    The first two set properties of a class. The Path notation is the same as used in projections, with the exception that you specify the particular property you want to set as well. You can specify as many or as few properties as you want, these objects don’t need to be complete, but we do verification to ensure property values make sense.

    Projections can also be defined:

    1.     <ObjectTemplate ID="NFL.New.Template" TypeID="NFL.Conference.All" >
    2.       <Property Path="$Target/Property[Type='NFL.Conference']/Name$">New Conference</Property>
    3.       <Object Path="$Target/Path[Relationship='NFL.ConferenceHostsDivision']$">
    4.         <Property Path="$Target/Property[Type='NFL.Conference']/Name$">New Conference</Property>
    5.         <Property Path="$Target/Property[Type='NFL.Division']/Name$">New Division 1</Property>
    6.         <Object Path="$Target/Path[Relationship='NFL.DivisionContainsTeam' TypeConstraint='NFC.Team']$">
    7.           <Property Path="$Target/Property[Type='NFC.Team']/Name$">New Team</Property>
    8.         </Object>
    9.       </Object>
    10.       <Object Path="$Target/Path[Relationship='NFL.ConferenceHostsDivision']$">
    11.         <Property Path="$Target/Property[Type='NFL.Conference']/Name$">New Conference</Property>
    12.         <Property Path="$Target/Property[Type='NFL.Division']/Name$">New Division 2</Property>
    13.       </Object>
    14.     </ObjectTemplate>


    These are similar, but allow you to define a hierarchy of objects that conform to the projection definition the object template references. Whenever you want to define a new object, you need to ensure the endpoint of the relationship is concrete, or you need to specify the TypeConstraint to indicate what class you want to create, as in the example above.

    In code, you can use these templates to create new objects or update existing objects:

    1.             // Connect to the management group
    2.             EnterpriseManagementGroup managementGroup =
    3.                 new EnterpriseManagementGroup("localhost");
    4.             // Get the management pack
    5.             ManagementPack nflManagementPack =
    6.                 managementGroup.ManagementPacks.GetManagementPack("NFL", null, new Version("1.0.0.0"));
    7.             // Get the object templates
    8.             ManagementPackObjectTemplate nfcDivisionTemplate =
    9.                 nflManagementPack.GetObjectTemplate("NFL.NFCDivision.Template");
    10.             ManagementPackObjectTemplate afcDivisionTemplate =
    11.                 nflManagementPack.GetObjectTemplate("NFL.AFCDivision.Template");
    12.             ManagementPackObjectTemplate nflTemplate =
    13.                 nflManagementPack.GetObjectTemplate("NFL.New.Template");
    14.             // Create a new NFC division using the template
    15.             CreatableEnterpriseManagementObject newNfcDivision =
    16.                 new CreatableEnterpriseManagementObject(managementGroup, nfcDivisionTemplate);
    17.             // Change it to an AFC division
    18.             newNfcDivision.ApplyTemplate(afcDivisionTemplate);
    19.             // Create a new projection from a template
    20.             EnterpriseManagementObjectProjection newNfl =
    21.                 new EnterpriseManagementObjectProjection(managementGroup, nflTemplate);
    22.             // You can also apply a template to an existing projection
    23.             newNfl.ApplyTemplate(nflTemplate);
  • Jakub@Work

    Categorizing Management Pack Elements

    • 1 Comments

    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=""http://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.

Page 1 of 1 (2 items)