com.waveset.provision
Class ProvisionContext

java.lang.Object
  extended bycom.waveset.provision.ThreadContext
      extended bycom.waveset.provision.ProvisionContext

public class ProvisionContext
extends ThreadContext

A class holding the runtime state for a single provisioning operation on a user.

One of these will be created by the Provisioner when it decides to go ahead and push changes to the resources. It maintains a structure of ResourceOp objects and provides a way to iterate over them. Order dependencies declared by Roles/Applications are understood, ResourceOp objects will be returned in the correct order.

The context is designed to be accessed by multiple threads. This allows us to launch several threads to perform a number of ResourceOp operations in parallel.

Besides maintaining the state, we also put the core provisioning implementation methods here too, as well as the methods for determining the resource OPs and calculating the order dependencies.


Field Summary
static java.lang.String code_id
           
protected static Trace trace
           
 
Constructor Summary
ProvisionContext(Provisioner p, ProvisioningOptions options)
           
 
Method Summary
 void buildDeProvisioningOps()
          Build the ops for DEprovisioning.
 void buildOps(boolean deProvision)
          Build the resource ops.
 void buildPolicyOps()
          Build the ops for policy checking.
 void buildProvisioningOps()
          Build the ops for REprovisioning.
 void buildResourceOps(boolean deProvision)
          To implement the "reverse order of creation" rule, any delete dependencies have to be stored in the ResourceInfo object in the _dependentResourceId field.
protected  void calculateRetry(Resource resource, ResourceOp op, GenericObject retryInfo, boolean terminateRetry, java.util.List retWarnings)
          Determine whether or not we need to retry the resource op and when it should be done.
 void checkResources()
          Iterate over the resource ops, performing the "check" function.
 void doResources()
          Iterate over the resource ops, performing the "do" function.
 void dumpFile(java.lang.String file)
           
 int getDesiredThreads()
          Calculate the optimum number of threads that could be launched to perform the ResourceOps in parallel.
 java.util.List getFiltered()
           
 ResourceOp getNextOp()
          Return the next operation that a thread can perform.
protected  java.util.Date getNextRetry(Resource resource, int nextRetryCount)
          Get the date/time of the next retry for the given resource and retry count.
 java.util.List getOps()
          Return the list of ResourceOps.
 OrderedResourceOps getOrderedResourceOps()
           
 Provisioner getProvisioner()
           
 WavesetResult getResult()
           
 boolean isFinished(int thread)
          Returns true once all operations have been performed.
 java.lang.String opsToVerboseString(java.lang.String indent)
           
 void prepare()
          Make any last minute preparations before launching.
 void processOp(ResourceOp op, int thread)
          Called by each thread after it has obtained an operation to perform.
 void setChecking(boolean b)
           
 void setDependencies()
          After the OP buckets have been calculated, make sure that all ResourceInfo objects have any order dependencies recorded, so that they can be deleted in the proper order.
 java.lang.String toVerboseString()
           
 java.lang.String toVerboseString(java.lang.String indent)
           
protected  void updateRetryInfo()
          jsl - added due to the new ProvisioningOptions encapsulation, still needs some rework.
protected  void updateRetryInfo(GenericObject retryInfo)
          Update the retryInfo (stored in the task variables) based on the results in the ResourceOp's.
 
Methods inherited from class com.waveset.provision.ThreadContext
buildResourceUser, buildResourceUser, checkAdapters, generateIdentities, getAdministratorName, getExplicitIdentity, getOp, getOptions, getUser, getUserName, launchThreads, normalizeResourceInfos, overrideResourceAttributes, println, setTrace
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

code_id

public static final java.lang.String code_id
See Also:
Constant Field Values

trace

protected static final Trace trace
Constructor Detail

ProvisionContext

public ProvisionContext(Provisioner p,
                        ProvisioningOptions options)
Method Detail

setChecking

public void setChecking(boolean b)

getProvisioner

public Provisioner getProvisioner()
Overrides:
getProvisioner in class ThreadContext

getOps

public java.util.List getOps()
Description copied from class: ThreadContext
Return the list of ResourceOps. Used internally by some of the utility methods.

Specified by:
getOps in class ThreadContext

getOrderedResourceOps

public OrderedResourceOps getOrderedResourceOps()

getFiltered

public java.util.List getFiltered()

getResult

public WavesetResult getResult()

checkResources

public void checkResources()
                    throws WavesetException
Iterate over the resource ops, performing the "check" function.

Throws:
WavesetException

doResources

public void doResources()
                 throws WavesetException
Iterate over the resource ops, performing the "do" function.

Throws:
WavesetException

prepare

public void prepare()
             throws WavesetException
Make any last minute preparations before launching. Whip through the ops resolving ResourceAdapter references.

Go through each ResourceInfo making sure it has a resource identity. We can't build the identity immediately after buildResourceOps because we won't always have an accountId yet (if we're generating one) and we need build the resource-specific users that contain all of the identity template attributes.

Specified by:
prepare in class ThreadContext
Throws:
WavesetException

getDesiredThreads

public int getDesiredThreads()
Calculate the optimum number of threads that could be launched to perform the ResourceOps in parallel. This number will be used by the Provisioner in determining how many threads to launch. We may end up with substantially fewer threads, here we're just giving the ideal number.

Assuming the sizes are relatively close, each ordered bucket will require its own thread. Could be smarter here if the sizes are radically different. Random ops can all be done in parallel. An optimistic measure would be one thread for every random OP plus the number of buckets.

Delete ops are a little harder since they have their own dependency chains. We'll assume that there can be one thread for each delete OP that does not have a dependency, as these represent the heads of the list.

Specified by:
getDesiredThreads in class ThreadContext

isFinished

public boolean isFinished(int thread)
Returns true once all operations have been performed. This is a signal to the thread that it can terminate.

The thread number is passed here so we can selectively decide to let threads expire even though we're not really done with processing. This might happen if we launched 10 threads to do a bunch of random things in parallel, but we're now down to 2 that have to iterate through 2 ordered lists. Since the other threads have nothing to do, we can let the die.

Specified by:
isFinished in class ThreadContext

getNextOp

public ResourceOp getNextOp()
Return the next operation that a thread can perform. This needs to be synchronized since it will be called by multiple threads. If null is returned, that doesn't necessarily mean we're finished, we may be waititng for dependent operations to finish.

To fix Bug#1598, deletes are processed first. There is an obscure case, where there are two Resource definitions with different names, that both point to the same physical resource. Assume a user is added to one and removed from the other. If you process updates first, we create the new one, but then turn around and delete it when the deletes are processed. By doing deletes first, we still delete the account, but then create it again. Ideally, we would try to recognize that these are the same and not delete it at all, but that requires semantic analysis of the Resource definitions which we really can't do (provide something in ResourceAdapterBase to do this?). So, while the behavior might still be unpleasant, we're arguably better by leaving the fresh account behind.

Specified by:
getNextOp in class ThreadContext

processOp

public void processOp(ResourceOp op,
                      int thread)
               throws WavesetException
Called by each thread after it has obtained an operation to perform. This method must not be synchronized, all the state we need should be in the provided operation. But be careful with global result object and the user object. Prior to 4.1SP2, an error in the check pass would not prevent us from attempting to update that resource in the do pass. This would cause the same error being put into the provisioning result twice. Now if an error happens in the check pass, we'll detect it here and prevent the update. We could try to splice it out of the ops list entirely, but I'd like the option of hanging interesting information on the ResourceOp. While the adapter calls in the check pass are almost always disabled with the provisioner.enableCheckPass option, we still may call getUser in the check pass in order to support the noLink option. If noLink is on, this may mean that the check pass will fail more often than it used to. !! If we get an error with a resource that is in an ordered resource group, we arguably should not attempt to create any of the other resources in this group since the ordering will not be obeyed. Often, the creation of the other accounts would also cause an error because preconditions are not met, but this may not always be the case. This issue is more likely to happen with the introduction of the noLink option which may prevent us from creating an account even when the resource is ok. We'll have to mark our bucket in some way, and prevent getNextOp from returning anything else from it.

Specified by:
processOp in class ThreadContext
Throws:
WavesetException

buildPolicyOps

public void buildPolicyOps()
                    throws WavesetException
Build the ops for policy checking. This is a temporary kludge for the old way of generating passwords. We needed to calculate the full resource list, in order to know what accountId or password policies might be in play. But we don't want this list filtered, resource users built, etc. This should all go away once we sanitize our password generation rules.

Throws:
WavesetException

buildProvisioningOps

public void buildProvisioningOps()
                          throws WavesetException
Build the ops for REprovisioning.

Throws:
WavesetException

buildDeProvisioningOps

public void buildDeProvisioningOps()
                            throws WavesetException
Build the ops for DEprovisioning.

Throws:
WavesetException

buildOps

public void buildOps(boolean deProvision)
              throws WavesetException
Build the resource ops.

Throws:
WavesetException

buildResourceOps

public void buildResourceOps(boolean deProvision)
                      throws WavesetException
To implement the "reverse order of creation" rule, any delete dependencies have to be stored in the ResourceInfo object in the _dependentResourceId field.

I tried to come up with a optimized bucket-oriented implementation for deletion, but it started getting too complicated and error prone. Instead, we'll just keep all delete OPs in one bucket, and check delete dependencies on the fly in getNextOp. In theory, this could be more expensive since we'll be performing the same tests multiple times rather than once up front. But the code is much simpler this way.

Throws:
WavesetException

setDependencies

public void setDependencies()
                     throws WavesetException
After the OP buckets have been calculated, make sure that all ResourceInfo objects have any order dependencies recorded, so that they can be deleted in the proper order.

Recalculate this each time, in case someone wants to correct a previously specified order. Note that if you have more than one account on a resource, we will have selected one at random to "satisfy" the ordered assignment. This may not be the one you want, but trying to solve that will significantly complicate things.

Throws:
WavesetException

updateRetryInfo

protected void updateRetryInfo()
                        throws WavesetException
jsl - added due to the new ProvisioningOptions encapsulation, still needs some rework. If the _ops list could be returned as part of the provisioning result we could do it outside.

Throws:
WavesetException

updateRetryInfo

protected void updateRetryInfo(GenericObject retryInfo)
                        throws WavesetException
Update the retryInfo (stored in the task variables) based on the results in the ResourceOp's. For operations that failed, the next retry time will be determined (if the max retries hasn't been reached). The retryInfo.retryTimeout is set to the number of seconds to wait for the resource(s) that need to be retried next. It is set to 0, if there are no more retries needed.

Throws:
WavesetException

calculateRetry

protected void calculateRetry(Resource resource,
                              ResourceOp op,
                              GenericObject retryInfo,
                              boolean terminateRetry,
                              java.util.List retWarnings)
Determine whether or not we need to retry the resource op and when it should be done.


getNextRetry

protected java.util.Date getNextRetry(Resource resource,
                                      int nextRetryCount)
Get the date/time of the next retry for the given resource and retry count.


dumpFile

public void dumpFile(java.lang.String file)

opsToVerboseString

public java.lang.String opsToVerboseString(java.lang.String indent)

toVerboseString

public java.lang.String toVerboseString()

toVerboseString

public java.lang.String toVerboseString(java.lang.String indent)