This section includes the following information:
There are situations when facts with static or even simple dynamic values don’t provide adequate data to enable implementation of more complex policy constraints. In such cases, Cloud Manager Orchestration can use “computed facts” whose values are dynamically and programmatically calculated using more sophisticated scripted l
A computed fact is meant to be used in a policy’s constraint. When applied through the execution of a Jython thread, the computed fact calculates values on demand and returns them to the Orchestration logic (Job Definition Language or “JDL”) which evaluates the job context and extends the built-in factsets for a Grid Object. This methodology lets you create facts that represent other metrics on the system that are not necessarily available in the default factset.
A computed fact implementation uses the ComputedFactContext class to access the evaluation context. This context contains the Grid Objects that the constraint engine uses to evaluate constraints, so this class could access the current job instance, deployed job, User, Resource, vBridge, and Repository Grid Objects if they are available within the context of the policy constraint consuming the computed fact's value.
Some computed facts are bundled with the product and used to handle more complex scenarios relating to provisioning adapter actions. However, computed facts can also be used by jobs which are not related to provisioning adapters or virtual machines in any way. More specifically, the VM host, vBridge and Repository grid objects are in the context only to evaluate provisioning constraints, such as vmHost, whereasthe Job and Job Instance objects are in the context only to evaluate resource or allocation constraints.
The following computed fact example illustrates how you can use a computed fact to calculate how many instances of the job named “foo” that the user in the current job context is running. The value of this computed fact can be used in a constraint to limit the number of instances of a particular job that a user can run:
class ActiveFooJobs(ComputedFact): def compute(self): count = 0 ctx = self.getContext() if ctx == None: print "No context" else: jobInstance = ctx.getJobInstance() if jobInstance == None: print "No job instance in context" else: activejobs = getMatrix().getActiveJobs() for j in activejobs: state = j.getFact("jobinstance.state.string") if j.getFact("job.id") == "foo" and \ j.getFact("user.id") == ctx.getFact("user.id") and \ (state == "Running" or state == "Starting"): count+=1 return count
Example 4-1 Example of a Computed Fact
The following is an actual computed fact used by the xen and vsphere provisioning adapters:
""" Computed Fact to check whether vmHost in given context has access to all shared repositories. This fact is to be used in a vmhost constraint. The vmhostDefault policy can be augmented to evaluate on this fact. First you must define the usage of the computed fact on the grid object by creating a linked fact. Create a policy with the following text and apply the new policy to any repository objects you want to constrain (or for simplification apply this new policy to All repositories) <policy> <resource> <fact name="candidateHost" type="Boolean" cfactvalue="cfact.resource"/> </resource> </policy> This creates a new fact in the repository namespace that links to the computed fact. Second, create a constraint that uses the new repository fact. Example constraint to add to the vmhostDefault policy: <eq fact="resource.candidateHost" value="True" reason="vmHost doesn't have access to all shared repositories" /> To test: Select a VM and choose "Check Host Assignment". This brings up a dialog of what host/repository plans match. In this case, all the plans will not match unless they have access to shared repositories. """ class resource(ComputedFact): def compute(self): context = self.getContext() if context is not None: #Get vm resource and vmhost Info object resource = context.getResource() vmhost = context.getVmHost() if resource == None: print "no resource" return False elif vmhost == None: print "no vmhost" return False else: #get the vm disks list vmdisks = resource.getFact("resource.vm.vdisks") #print 'disk info is ',vmdisks for diskId in vmdisks: disk = getMatrix().getGridObject(TYPE_VDISK,diskId) if disk != None and disk.factExists("vdisk.moveable) and not disk.getFact(vdisk.moveable"): # If the disk is not moveable, get repository where it is stored if disk.factExists("vdisk.repository"): repo = disk.getFact("vdisk.repository") #Get list of repositories to which vmhost has access to repos = vmhost.getFact("vmhost.repositories") #If vmhost doesn't have access to disk repo, return False if not repo in repos: return False #vmhost in context has access to all shared repositories return True # no context (console fact table) return False
ComputedFact is the base class for creating custom computed Facts. To create a new computed fact, you need to subclass the ComputedFact class with the .cfact extension.
You can create a standard fact to include the cfact just as you would in a policy structure. For example:
<fact name="network.score" type="Integer" cfactvalue="cfact.networkScore"/>
To use a computed fact you must deploy to the server the file with the .cfact extension referred to above. The ComputedFact subclass name is not required to match the computed fact file name. The file name is the computed fact name that you define. To use the Computed Fact, create a linked fact that references the deployed ComputedFact class. Cloud Manager Orchestration uses the linked fact in constraints.
The following is an example you would use to retrieve the current job instance where a computed fact is being executed in a resource constraint:
class myComputedFact(ComputedFact): def compute(self): ctx = self.getContext() if ctx == None: print "No context" ... else: jobInstance = ctx.getJobInstance() if jobInstance == None: print "No job instance in context" ... else: print "jobInstance.id=%s" % (jobInstance.getFact("jobinstance.id")) ...
Due to spawning of Jython threads, cfacts place a considerably higher load on the server than normal dynamic fact computations. You should enable caching when an excess load occurs, such as when a fact is associated with a large number of resources. An example of this is using the vmbuilderPXEBoot cfact when the grid is large, to avoid performance degradation.
To enable caching of cfacts,
In the Explorer treee of the Orchestration Console, expand the
group object and select to open the admin view.In the admin view, select the
tab to open the page.On the
page, select the check box and enter an amount of time greater than 30 seconds (for example, enter 10 minutes).Click the
icon in the main toolbar to save the new settings.Use this procedure only on Orchestration resources that are also VMs – for example, on Xen VMs where the agent is installed.
NOTE:The caching setting is unselected by default because Cloud Manager Orchestration requires some facts to be evaluated frequently for VM host plans. As an administrator, you should also be aware of and select the amount of time for cache refresh. The vmbuilderPXEBoot fact does not change, so setting the cache for this fact has no undesirable effects.