In this installment, we're going to dive into one of the tricker areas of CIM called associations.  They're extremely powerful, and used heavily by the standard profiles.  In many cases, you can simply ignore them and get 90% of what you need, but for that last 10%, you'll need to do some association traversals to make sense of how things relate. We'll use this to figure out what Memory and Processor slots you havethat are unoccupied vs. occupied.

So what is an association?  In CIM an association is an object that relates two other objects together.  Lets use a simple real world analogy to make the concept clear:  I have a car.  It has 4 wheels.  If I were to model this in CIM, I might have a Car class, a Wheel class, and an association class that I could call AttachedTo which connects instances of those two classes.  In our system if we had 2 cars, we might want to know which wheels were on which car.  Simply enumerating instances of Wheel would net 8 instances, which doesn't really tell us which car they're on, until we use the association.  What we want to do is ask for wheels (or cars) that are "associated" to one another.  Roughly speaking, this would looking something like:

   myWheels = client.Associators(myCar, AssocClass = "AttachedTo")

The results in "myWheels" would be the 4 wheels attached to myCar, not the other 4 attached to the other car.

If we go back to our database analogy, the associations are basically joins across multiple tables.  Where CIM adds some complexity is that it models the association itself as a class with distinct instances for each relationship between distinct endpoints, instead of just a simple linkage between the two endpoints.  Lets look at why that extra complexity is there.

CIM allows association classes to have their own properties, that might add additional information to the relationship between the two endpoints.  Keeping with our example above, lets say we wanted to model the spare tire as well.  We might add a property on the AttachedTo class "bool isSpare" that would be set to true if the tire was a spare.  Now the problem is, with the Associators call we looked at above, we start with one endpoint, and get a list of the other endpoints, but we never see the association instances in the middle.  We'd get 5 results, and not know which one is acting as the spare tire at that moment. To figure this out, we use a different CIM routine called References.

   myAttachedTo = client.References(myCar, ResultClass = "AttachedTo")

The results of the References call are actually the association instances themselves.  If you look at the association class, you'll see at least two properties that are "reference" properties that contain the object path pointing to the endpoints – Car and Wheel in our example. If you wanted to, you could iterate over the results, filter out what you want, and then call GetInstance with the Wheel references you have.

So with that  foundation, lets take a look at some examples on the system where associations are necessary to understand what's going on. Here's some sample code that will start by looking at all the CIM_Slot instances and then see which ones have something in them.

   list = client.EnumerateInstances('CIM_Slot')

   if len(list) == 0:

      print 'Error: Unable to locate any slots'


      for instance in list:

         packages = getPackages(client, instance)

         if len(packages) == 0:

            contains = 'Slot is Empty'


            contains = 'Slot is Populated'

         print '%s%30s' % (instance.classname, contains)

         printInstance(client, instance)

         for package in packages:

            indent = '      '

            print '%s%30s' % (indent, package.classname)

            printInstance(client, package, )

If you run that against an ESX system, two interesting slot types you'll see are Memory slots and Processor slots.  If your system isn't fully populated, this will show you what slots are empty.  Here's some example output:

OMC_MemorySlot             Slot is Populated

               ConnectorLayout = 7 (Slot)

             CreationClassName = OMC_MemorySlot

                   ElementName = DIMM 6B

                        Number = 6

                           Tag = 32.5


                   CreationClassName = OMC_MemoryPhysicalPackage

                         ElementName = DIMM 6B

                         PackageType = 13 (Memory)

                                 Tag = 32.5

OMC_MemorySlot                 Slot is Empty

               ConnectorLayout = 7 (Slot)

             CreationClassName = OMC_MemorySlot

                   ElementName = DIMM 7C

                        Number = 7

                           Tag = 32.6

The full example is attached.