-
Notifications
You must be signed in to change notification settings - Fork 14
Writing BtrPlace extensions
BtrPlace is already bundled with several Views and constraints to accomodate with common concerns. In some circumstances, the library may however lack of solutions. We discuss here how to create extensions.
BtrPlace is designed around the bridge pattern to dissociate the user API which expresses a constraint or a view and the solver API which expresses the enforcement algorithm using the choco API. Furthermore, it is pretty sweet to be able to serialise an instance into JSON to be able to replay it for debugging purpose.
As a result, when you develop a view or a constraint, you will have to develop 3 components:
- the user-side code. For a view, this exhibits a part of a cluster state. For a constraint, this will exhibit the desired state.
- The serialisation code to produce a JSON version of your component.
- the solver-side code. This consists in customizing the default Choco CSP to express your requirements
The mapping between a user-level constraint or view and the choco-level equivalent is done using the ChocoMapper that is accessible from any ChocoScheduler Parameters. Internally, the Reflection API is used to instantiate the Choco object.
The Choco CSP is generated incrementally from a core problem called the ReconfigurationProblem
- The
ReconfigurationProblemis created. It models that the nodes are free to change their state using NodeTransitions. The next state for every VM is however forced. By default, their state is unchanged but constraints derived from VMTransitions can force the state-change. The basic model is in charge of accounting the number of VMs per node and scheduling the actions so that they succeed according to the element states. - The ChocoViews associated to the ModelView are instantiated.
- The CSP code for the ChocoView is created through their
inject()method. Usually the views create variables and some relations between them. The injection ordering satisfies the [declared dependencies] (http://www.btrplace.org/apidocs/org/btrplace/scheduler/choco/view/ChocoView.html#getDependencies--). Once injected, you will be able to access them from ReconfigurationProbleem.getView(). - The CSP code for the constraints is injected through their
inject()method. At this moment, it is then safe to access anyChocoViewvariable. - The Choco views are queried a second time using their
beforeSolve()method. This enables to some code optimisation. Again the dependencies between the views are considered.
A view deserves the purpose of declaring a new dimension or concern for a cluster. For example, to state the resource usage for a specific component (Network, GPU, etc.) that are not present by default.
Every view derives from ModelView.
- It must provide an identifier
- It must be Copyable
- It must implements
equals()andhashcode()
It is also convenient to implement a static get() method to access the view inside a model once attached (example)
Remember that a view reports the initial cluster state. Accordingly, there is no notion of interpretation about the current situation.
The Choco version of a constraint implements ChocoView. It expects the user-side view as a unique constructor parameter.
- Implement the
inject()view to provide here the view specific variables and basic relations between them. - If the view requires variables from another view, declare the dependencies in
getDependencies() - If some late optimisation is possible, implement
beforeSolve() - If the view can perform some problem simplification in the repair mode, it must implements
getMisplaced()to state the supposed mis-placed VMs. Be careful, if this method returns all the VMs in the problem, then the repair mode will be counter-effective as it will prevent any optimisation. -
insertAction()may be implemented if, once a solution computed, this view may modify the reconfiguration plan with view specific events.
- Implement ModelViewConverter. Use the JSONs utility class to reduce the (de)serialisation code.
- Map the Converter to the user-level view using the ModelConverter that can be accessed from InstanceConverter
An instance may be composed of any number of satisfaction-oriented constraints and one optimisation constraint.
Each constraint derives from SatConstraint but SimpleConstaint can be used to reduce the code to write.
- Implements
equals()andhashcode()to provide comparison capabilities - Write a constraint that manipulates the minimum number of elements. For example, while it would make sense to have a VM-host anti-affinity that can take multiple VM into parameters, the underlying semantic is still per VM.
- Make the constraint as stateless as possible (there is a known caveat with the continuous mode). Typically, it should not be possible to change the set of managed VMs or nodes.
- Each constraint provides a Checker that will be called to analyse a
Modeland state if the constraint is satisfied. If the constraint is discrete, it is enough to implementendsWith(). If the constraint is continuous, it is also required to implement every method signalling the beginning or the end of an action that may alter the constraint satisfaction.
- An optimisation constraint is not focusing any particular elements.
- By design, there is no need to provide any viability checker
- just implement at minimum
equals()andhashcode()to ease comparison - The constraint should be stateless
- The constructor must take the user-level constraint as a unique parameter to be instantiable by the ChocoMapper
- The
inject()method will be called with theReconfigurationProblemthat can be customized - The
getMisplacedVMs()should be implemented to reduce the problem size in the repair mode - Remember the restriction mode of the constraint. If it is continuous, it must be satisfied at any moment of time, including the initial state.
- Along with the regular injection, it matters to declare the objective variable that will have to be maximised or minimised using the ReconfigurationProblem#setObjective() method
- It matters to provide a branching heuristic that will state all the decision variables. Choco considers that a problem is solved only if all the decision variables are instantiated. If some meaningful variables are not instantiated once a solution computed, the generation of the
ReconfigurationPlanmay fail
- Implement ConstraintConverter. Use the JSONs utility class to reduce the (de)serialisation code.
- Map the Converter to the user-level view using the ConstraintsConverter that can be accessed from InstanceConverter
The choco library is well documented and provide a wide range of documentations, from tutorials for beginners to technical information for developers.
- Have a look to Choco documentation and tutorials before starting the modelling process
- Avoid creating variables when un-needed as they will consume memory
-
ReconfigurationProblem contains a few helpers (
make*methods) to create context-specific variables that will be properly initialised. - Provide meaningful variable names to help debugging. However, with tens of thousands of variable, the variable labels will use a significant amount of memory. Use ReconfigurationProblem#makeVarLabel() to create them lazily, only when the scheduler verbosity is at least 1.