Thursday, August 19, 2010

Scripted Provisioning with RHQ 3.0 and JON 2.4

The new JBoss Operations Network (JON) 2.4.0, and its upstream project RHQ 3.0.0, introduce provisioning. Users can now begin to manage content distribution via RHQ by deploying bundles to managed platforms, and laying them down with flexible Ant scripting. RHQ can help manage and track different bundle versions on different destinations with varied configuration. Deployments can be upgraded and reverted as well, on groups of mixed platforms. And all deployments generate extensive auditing. For more information on provisioning see the docs.

For a gui-based demo, check out Mazz's blog entry. (note, the gui has been improved since this demo was recorded.)

I want to discuss RHQ provisioning via CLI scripting. RHQ has a powerful CLI for interactive use or for executing scripts via the Rhino Javascript engine.

Most of what you can do via the RHQ GUI can also be done via scripting, allowing IT managers to automate their processes. RHQ's Remote API is fully accessible as well as CLI features that can further simplify your scripting. The RHQ Git repository houses the following four sample scripts that I'll talk through. For the full set of commented, repeatable scripts go here. I'll just cover the snippets that do the provisioning work...

By the way, here are instructions to install the CLI.

A Bundle is basically some logical content, like an application, that you want to deploy out to your RHQ managed platforms. This example will use a bundle named sample-bundle.

Script 1: Create version 1.0 of sample-bundle
       // create bundleVersion 1.0 for the sample bundle
var distributionFile = new java.io.File(bundleDistroV1Path);
[1] distributionFile = new java.io.File(distributionFile.getAbsolutePath());
[2] var bundleVersion1 = BundleManager.createBundleVersionViaFile(
distributionFile);
print("\nCreated " + bundleVersion1 + "!")

  1. Get the bundle distribution file path. This is a zip file containing the Ant deploy recipe and the files to be deployed. In this an example, a simple WAR file. The recipe let's us know this is V1.0 of sample-bundle. The distribution files are provided along with the scripts in the git repo link above.
  2. Call the RHQ Server and have it create the new bundle, starting with bundle version 1.0. Note that in this case the bundle file is small so we just send it in one shot, the API provides for streaming alternatives for larger distributions.


Script 2: Deploy version 1.0 of sample-bundle

[1]    // get the bundle
var bundleName = 'sample-bundle';
var bc = new BundleCriteria();
bc.addFilterName(bundleName);
bc.fetchBundleVersions( true );
var bundles = BundleManager.findBundlesByCriteria(bc);
var bundle = bundles.get(0);
var bundleVersion = bundle.getBundleVersions().get(0);

[2] // get the "platforms" group
var rgc = new ResourceGroupCriteria();
rgc.addFilterName("platforms");
var groups = ResourceGroupManager.findResourceGroupsByCriteria(rgc);
var groupId = groups.get(0).getId();

[3] // create a destination for the deployment
var dest = BundleManager.createBundleDestination(
bundle.getId(),
"sample destination",
"sample destination",
"/tmp/sample-bundle",
groupId);

[4] // create a config for the V1.0 deployment
// setting the required properties for recipe in distro 1.0
var config1 = new Configuration();
var property11 = new PropertySimple("sample.name", "V1 Name");
config1.put( property11 );
var property12 = new PropertySimple("sample.port", "11111");
config1.put( property12 );

[5] // create a deployment for sample bundle 1.0 using the 1.0 config
var deployment = BundleManager.createBundleDeployment(
bundleVersion.getId(),
dest.getId(),
"Deploying Sample Ant Bundle V1",
config1);
deployment = BundleManager.scheduleBundleDeployment(
deployment.getId(),
true);
  1. Use a criteria find to locate sample-bundle and retrieve it's BundleVersion info.
  2. Again, use a criteria find to locate the group of platforms to which we want to deploy this bundle.
  3. A bundle is deployed to a *Destination*, which is basically a combination of a platform group and a deploy directory. The deploy directory is where the deployment will be rooted on each of the target platforms. Note that the platform group can be of mixed platform types.
  4. A bundle *Deployment* is basically a combination of a bundle version, a destination, and a *Configuration*. Here we define the configuration that will be used for this deployment. The same bundle version may need to be provisioned to different platforms with different configuration. In this case we have name and port values that will be applied on the target deployments.
  5. Finally, we create the BundleDeployment and then schedule it for execution. Note that in the first release only immediate schduling is available. The sample-bundle, version 1.0 will be provisioned to the /tmp/sample-bundle directory on each member of the platforms group, and configured with name="V1 Name" and port 11111.


Script 3: Upgrade to version 2.0 of sample-bundle to the same Destination.

[1]    //get the bundle if it exists
var bc = new BundleCriteria();
bc.addFilterName(bundleName);
bc.fetchDestinations( true );
var bundles = BundleManager.findBundlesByCriteria(bc);
var bundle = bundles.get(0);
var dest = bundle.getDestinations().get(0);

[2] //create bundleVersion 2.0 for the sample bundle
var distributionFile = new java.io.File(bundleDistroV2Path);
distributionFile = new java.io.File(distributionFile.getAbsolutePath());
var bundleVersion2 = BundleManager.createBundleVersionViaFile(
distributionFile);

[3] //create a config for the V2.0 deployment
var config2 = new Configuration();
var property21 = new PropertySimple("sample.name", "V2 Name");
config2.put( property21 );
var property22 = new PropertySimple("sample.port", "22222");
config2.put( property22 );
var property23 = new PropertySimple("sample.new", "V2.0 ONLY!");
config2.put( property23 );

[4] // upgrade the deployment to 2.0 using the 2.0 config
var deployment = BundleManager.createBundleDeployment(
bundleVersion2.getId(),
dest.getId(),
"Upgrading Sample Ant Bundle to V2",
config2);
deployment = BundleManager.scheduleBundleDeployment(
deployment.getId(),
false);
  1. Again, using criteria fetch, get the Bundle and it's destination.
  2. Just like script 1, now create a new BundleVersion, 2.0, with a distribution fil
  3. Showing the different versions can have different configuration needs, a new property is added.
  4. Just like script 2, deploy to the same destination, this time version 2.0. The sample-bundle will be upgraded on each member of the platforms group, same directory, new configuration applied.

Script 4. Revert back to version 1.0

[1]     //revert the live V2 deployment to the replaced V1 deployment
var deployment = BundleManager.scheduleRevertBundleDeployment(
dest.getId(),
"Reverting Sample Ant Bundle from V2 to V1",
false);

  1. Omitted is a criteria search for the bunde information, as shown in script 3. here we ask to revert the live deployment, version 2.0, to the version it had replaced, version 1.0.

All of this can be done via the RHQ GUI as well. The GUI of course can show details of everything involved, including the audits for the individual resource deployments. The API can also provide this information to the CLI, mainly via criteria fetches asking for various data to be supplied with the results.

Provisioning is a major new feature in RHQ 3.0.0 and JON 2.4, check it out!