The ModiPY Architecture
ModiPY has the following major compoents:
- The ChangeController
- Devices
- Provisioners
- Changes, and ChangeTemplates
- Iterators
The ChangeController
The ChangeController is the central processor that manages loading the changeset configuration, Change dependencies, scheduling and all the other glue required to make changes happen. It gets started by the modipy program when you run it. It manages all the other objects in the system.
Devices
Devices are things you want to manage via changes. They can be anything with a command and control interface. Usually they will be an IP addressable device like a computer, a switch, router, storage array, or something similar.
Devices are managed with Provisioners to implement Changes.
Provisioners
Provisioners all inherit from a base class call Provisioner that defines the method for implementing Changes. Each subclass implements a way of communicating with remote Devices. The inbuilt CommandProvisioner provides for a way of running arbitrary commandline programs or scripts. The ZAPIProvisioner used the NetApp XML-RPC style mechanism for communicating with NetApp storage arrays.
ModiPy can be extended to communicate with any device by implementing a Provisioner that knows how to set up a session with the remote Device.
Each Provisioner is linked to particular Change types. This is done because implementing a change via commandline is very different to the method used with ZAPI, or some other protocol. ModiPy handles the linkage for you, though. All you need to do is define a Change of the appropriate type, and so long as a Provisioner that supports that Change type has also been defined, ModiPy will use it. ModiPy won't try to implement a commandline change over ZAPI.
Changes and ChangeTemplates
Changes and ChangeTemplates are the core of the system. You use them to define what needs to happen when you run ModiPy.
Changes
Changes consist of a sequence of stages. Every Change goes through a minimum of 3 stages:
- Pre-implementation - where checks can be made to see if a change should be applied
- Implementation - where the change is applied
- Post-implementation - where other checks can be made to ensure the change was applied correctly
If something should go wrong, there are other stages that a Change can go through:
- Pre-backout - where checks can be made to see if a change can, and should, be backed out
- Backout - where a change is backed out
- Post-Backout - where other checks can be made to ensure the change was backed out correctly
Changes may also have one or more dependencies. These define other Changes that must complete successfully before the Change is allowed to run. You can define dependency trees that are as simple or as complex as you like.
Changes can also be defined as an implementation of a more generic ChangeTemplate.
Change Templates
ChangeTemplates provide a way to define common changes once, to build up a library of standard change procedures. A specific changeset must have a specific set of changes defined, but these Changes can be based on ChangeTemplates that define most of what needs to happen.
Your ChangeTemplates might have the full change procedure, including backout procedures, but lack the specific targets that you plan to apply the changes to. Or, you might want to use a pre-defined template, but change its dependencies for a particular change run. Changes can override anything defined in their ChangeTemplate.
Iterators
Iterators are used to define a set of variables that can be used by a change in a loop.
For example, you might want to create a set of directories on a unix server. You could define a single change that creates all of them in one go, but this would have some limitations:
- the change would only be useful once
- the change can't create different sets of directories on different devices
- the change is not generic enough.
A better way would be to create a change definition that create a single directory, with a name to be supplied later. In essence, a good change should define the how, but as little of the what as possible.
With our new change (or ChangeTemplate, preferably) defined, we can call this change with an Iterator that contains a list of the directories we want to create. You can have different iterators for different devices, or a smarter Iterator that can provide different values depending on which device the change is being applied to.
