The last couple of months I have been assigned to a project dedicated to deployment automation including several levels and types of technologies: database, middleware, services and portals. The selected deployment tool is XL Deploy from XebiaLabs.
One of the main challenges was to determine the proper order of the steps within the deployment plan considering the dependencies between the several artifacts.
1 Basic features for orchestration
Deployment with XL Deploy is a joined activity between its core process and its plugins. This diagram from the Customization Manual shows this cooperation (puzzle pieces represent plugin jobs):
Each plugin defines its own artifact types derived from their base UDM type in hierarchy.
The core process defines default orders, related to the base types.
XL Deploy uses the following default orders:
• PRE_FLIGHT (0)
• STOP_ARTIFACTS (10)
• STOP_CONTAINERS (20)
• UNDEPLOY_ARTIFACTS (30)
• DESTROY_RESOURCES (40)
• CREATE_RESOURCES (60)
• DEPLOY_ARTIFACTS (70)
• START_CONTAINERS (80)
• START_ARTIFACTS (90)
• POST_FLIGHT (100)
Each plugin, either distribution or community, is defaulting each of its types’ create, modify and destroy order property into one of these values. However, these are just ranges. Individual artifact types may be refined easily without implementing a new plugin
2 The Case
The largest set of artifacts consists of Oracle Service Bus resources and SOA services, including metadata service (MDS) and service component architecture (SCA).
SB resources are separated by their “nature” into project categories:
1. Common definitions, which are shared among multiple services
2. Service contract elements (WSDL, schema definitions)
3. Service implementations (business and proxy services)
Logically, 2 and 3 may have elements of which deployment depend on 1 and also 3 may depend on 2. Each category should have no internal dependency.
1. Metadata services (MDS) with schema definitions, service contracts and mappings
2. Composite archives (SCA) of SOA or BPM processes
Based on service definitions, 2 strongly depends on 1 since the propagated entry point as well as all external service references need their entire schema and operation definition present.
In principle, group 1 may have internal dependencies. However, importing metadata before service implementation would succeed with missing referenced schema.
3 SOA and Service Bus plugin type definitions
For Service Bus, the XL Deploy plugin comes with one generic type: osb.Configuration. It contains a configuration archive with optional customization file(s). If we provide a set of such artifacts, the generated deployment plan will show up just in lexicographical order as they are assigned with the default deployment order value 60. This way we cannot have any influence on the sequence. Furthermore, the order property is defined as hidden so manual adjustment of the mapped artifact is excluded too.
For SOA Suite, the plugin defines the two related types: soa.MdsSOADeployableSpec, soa.CompositeSOADeployableSpec. This would support the sequencing. Yet, the defaulted order (70) and the hidden property still prevents us from the adjustment.
According to the dependencies, SharedOsbResources should precede OsbResources otherwise latter would fail. For the same reason SchemaDefinitions_mds should precede SampleSCA. Let’s take care of that.
4 Customization by Type Modification
Let’s touch the SOA types first. The only criteria is that all MDS artifacts get imported before any composite deployment. This involves references from updated services to new contracts and from new services to updated contracts. Therefore we have to specify the order at the modification stage as well.
Our entry point is the XLD_dir/ext/synthetic.xml file. We modify the type definitions just putting distinct order values in place:
<property name=”createOrder” kind=”integer” default=”75″ hidden=”true”/>
<property name=”modifyOrder” kind=”integer” default=”76″ hidden=”true”/>
<property name=”createOrder” kind=”integer” default=”77″ hidden=”true”/>
<property name=”modifyOrder” kind=”integer” default=”78″ hidden=”true”/>
Keep in mind we used the type definitions of the artifacts in the target container (environment), not the ones in the application.
To take the change into effect, we need to restart XL Deploy server (command line or service, whichever variant is running in place).
Analyze the deployment of the same application. This time, SchemaDefinitions_mds stands above SampleSCA. The dependency criteria is fulfilled.
5 Customization by Type Definition
For Service Bus the job is a bit more complex and a little „invasive”. As we have only one type, we cannot distinct the order values. We have to artificially cast SharedOsbResources into category 2 and OsbResources into category 3 and then modify their order properties.
The Service Bus plugin is distributed with the XL Deploy product. It is better to keep it opaque.
For our new types we will use the virtual plugin name „custom”. We use again the synthetic.xml the CI definition but we do not define new deployment rules.
At first, we define three „clones” of osb.Configuration type:
1. custom.OsbCommonConfiguration: schema definitions for shared use
2. custom.OsbServiceCommonConfiguration: service definitions
3. custom.OsbServiceConfiguration: service implementations
In the XML it will look like:
<type type=”custom.OsbCommonConfiguration” extends=”osb.Configuration”/>
<type type=”custom.OsbServiceCommonConfiguration” extends=”osb.Configuration”/>
<type type=”custom.OsbServiceConfiguration” extends=”osb.Configuration”/>
As you see, the base type here is the application CI type, not the targeted type. In order to customize their order we link each of them to a deployed type, which extends the deployed variant of the original type:
<type type=”custom.DeployedOsbCommonConfiguration” extends=”osb.DeployedConfiguration” deployable-type=”custom.OsbCommonConfiguration” container-type=”osb.Domain”>
<property name=”createOrder” kind=”integer” default=”60″ hidden=”true”/>
<property name=”modifyOrder” kind=”integer” default=”61″ hidden=”true”/>
<type type=”custom.DeployedOsbServiceCommonConfiguration” extends=”osb.DeployedConfiguration” deployable-type=”custom.OsbServiceCommonConfiguration” container-type=”osb.Domain”>
<property name=”createOrder” kind=”integer” default=”62″ hidden=”true”/>
<property name=”modifyOrder” kind=”integer” default=”63″ hidden=”true”/>
<type type=”custom.DeployedOsbServiceConfiguration” extends=”osb.DeployedConfiguration” deployable-type=”custom.OsbServiceConfiguration” container-type=”osb.Domain”>
<property name=”createOrder” kind=”integer” default=”64″ hidden=”true”/>
<property name=”modifyOrder” kind=”integer” default=”65″ hidden=”true”/>
The story behind the chosen numbers is:
1. The shared resources get absolute precedence to the rest at each scenario (new deployment or update).
2. New service implementations may refer to modified messages and operations (of different services).
3. Modified service implementations may refer to new messages and operations (of different services).
Same way, restarting of the server is necessary for the customization to take effect.
6 Applying the New Types
This time, due to the new types, we would not be able to achieve the goal with just a redeployment of the same package.
Thus, we create a new application, ProperOrder using the same artifacts but associated with freshly defined types. The corresponding part of the deployit-manifest.xml is:
<custom.OsbServiceConfiguration name=”OsbResources” file=”OsbResources/OsbResources”>
<custom.OsbServiceCommonConfiguration name=”SharedOsbResources” file=”SharedOsbResources/SharedOsbResources”>
Let’s analyze the deployment of the new application. This time, SharedOsbResources stands above OsbResources. The dependency criteria is fulfilled.