RHQ provides the ability to provision a versioned bundle of files to a destination of a group of resources on a destination directory that is relative to a base location based on rules (and perhaps script code) defined in a recipe. You tell RHQ about the bundle of files and its recipe by zipping them up into a single bundle distribution file and uploading it to RHQ. Before continuing, here's a quick glossary of terms used throughout the provisioning documentation:
A "group of resources" is nothing more than a normal compatible group of resources whose resource type supports bundle deployments. If you create a compatible group whose member resources can be bundle targets (e.g. platform resources where an agent is running), you can provision bundles to that group.
A "base location" is a named location that is applicable for the target resources. For example, platform resources support a single base location for bundles - that being the Root File System (i.e. the "/" directory). Other resources may have different base locations to choose from. For example, if you are deploying a bundle to a JBossAS Server resource, you can deploy bundles under the Install Directory or the Profile Directory.
A "destination directory" is simply a location on a file system where the files are copied on the agent machine. This directory is relative to the base location. In other words, given a base location and a relative destination directory, you can figure out what the absolute directory path is where the bundle will be deployed for any individual resource in the group of resources.
A "destination" is the combination of a group of resources along with a base location and a destination directory which are associated with a bundle (specifically all versions of a bundle). When you say you want to deploy a bundle to a "destination", you are identifying which machines the bundle will be deployed to and in which directory on those machines the files will be copied to. A "destination" is only ever associated with one bundle (for example, a destination for bundle "Banking App" can only have versions of the Banking App bundle deployed to it).
A "bundle" refers to versioned file content bundled together that is to be copied to a destination. Usually when "bundle" is mentioned in the docs, it more technically refers to a "bundle version" - that is to say, a specific version of a specific bundle like "Banking App version 1.5". However, in some cases "bundle" may refer to all versions - for example, bundle "Banking App" refers to all of its versions (e.g. "Banking App v1.5" and "Banking App v2.0").
To "provision" a bundle means to push bundle files to a remote machine and copy those files to their desired locations on the remote file system.
A "recipe" defines the rules and metadata that describe the files associated with the bundle, where those files need to be placed on the remote machines and what files (if any) are templatized and thus need to be run through the template engine (otherwise called "realizing the file").
A "Bundle Distribution File" is simply a zip file that contains all the bundle's files and its recipe.
A good blog is available that further discusses what these terms mean along with an example use-case to further illustrate how they are used. There is also a flash demo that shows you the basics of provisioning bundles. Read that blog and watch that demo to get a clearer picture on what this bundle stuff is all about and what it is used for.
RHQ 4.0.1 and below supported bundles on platform resource only. If you are using such a version of RHQ, realize that you can only deploy bundles to groups of platforms. Later versions do support provisioning bundles to non-platform resources.
A bundle can contain zero, one or more files (called, appropriately enough, "bundle files"). A bundle is versioned, thus one can more technically call it a "bundle version". Versioning bundles allows you to define several related bundles, each having different content (e.g. the "JBossAS 4.3" bundle and the "JBossAS 5.0" bundle). A bundle version is associated with a "recipe" that defines metadata describing the bundle files and where the bundle files should be placed on the remote resources.
When provisioning a bundle version to a destination, all bundle files are copied to one or more remote machines' file systems according to the rules defined in the recipe. The main directory where the bundle files are copied to is located in the relative "destination directory" which is found under the "base location". During provisioning, the file content may be passed through a template engine that will replace tokens found in the file content with actual values that are either pre-defined by a user or automatically defined by the agent running on the remote platform where the bundle is being provisioned. When a templatized bundle file is passed through the template engine to obtain its real content, it is called "realizing the file".
A "recipe" defines the rules that describe the files associated with the bundle, where those files need to be placed on the remote machines and what files (if any) are templatized and thus need to be run through the tempate engine. A recipe may include some script commands that need to be invoked to help complete the provisioning task. RHQ can understand different types of recipes based on the type of bundle that is to be provisioned. The provisioning subsystem within RHQ is pluggable which allows developers to write their own provisioning mechanisms and plug them into RHQ, thus allowing you to define different "bundle types". Out of box, there are two bundle types (and thus two types of recipes) that are supported - "Ant" and "File Template". The "Ant Bundle Type" is the one you are most likely going to use; its recipe is a Ant script that contains RHQ-specific tasks that define metadata about your bundle. The "File Template Bundle Type" provides a simple recipe syntax that allows you to perform simple provisioning use-cases, but it does not support complex or advanced provisioning requirements (which is why it is only used mainly for testing, development and for very simple use-cases in production).
How is this bundle provisioning feature to be used? What happens when you provision a bundle? To answer these questions, it is best to go over some example use cases. But keep in mind the overriding purpose of bundles - we have a set of files that we want to be deployed to remote file systems and any files that are different than those declared in the bundle are to be removed. In other words, in general, what your bundle content looks like should be exactly what your destination directory should look like after the bundle is deployed.
Now let's go over some possible use-cases.
Suppose you have a standalone application that you want to install on a group of machines. By "standalone application", we mean a complete set of file content that constitute an entire application installation. You can package this file content within a bundle distribution file along with the bundle recipe that contains the instructions for how to install that file content. In this example, because it is a full, standalone application, you will want to install this in a new or empty destination directory on the target file system.
As a concrete example, suppose you have a JBoss Application Server prebuilt with your own .war web application deployed inside of it. You can put the entire app server installation (that is, all the files that make up the app server installation including your deployed .war content) along with the deploy.xml recipe in a zip file. This is your bundle distribution file. When you provision this bundle distribution file, you will want to provision it to a new or empty destination directory on your target file system. In other words, you'll want to define your bundle destination with an unused destination directory such as "/opt/my-application" or something similar. After the bundle is provisioned, you will have a full JBoss Application Server with your .war web application deployed in it located in /opt/my-application.
Because your bundle is a full application, it has declared all files that are to be provisioned to that destination directory. The /opt/my-application directory will be fully managed by the bundle subsystem - once the bundle is deployed, only the bundle files found in your bundle distribution file will be located in that directory. The bundle subsystem will ensure no other files are left "hanging around" in that destination directory (that is, any unknown files found in that destination directory or its subdirectories will be removed at the time your bundle is provisioned).
Suppose you already have an application server pre-installed through some other provisioning mechanism (that is, suppose you have a JBoss Application Server already installed by some means outside of the RHQ bundle provisioning subsystem). But now suppose you want to use RHQ to provision your own web application to that pre-existing JBoss Application Server. In this case, your bundle distribution file will only have your .war web application inside of it (along with the RHQ recipe of course). In other words, your bundle distribution file will only have the .war content in it, not the entire JBoss Application Server itself.
Given such a bundle distribution file, you can deploy that bundle to a destination whose destination directory is the JBoss Application Server's "deploy" directory (here we are assuming the JBoss Application Server version is 4.x or 5.x where the web applications are deployed directly inside the application server's <jboss>/server/default/deploy directory).
But note that we do not want the RHQ bundle subsystem to fully manage that destination directory (unlike our first use-case example above). This is because that "deploy" directory has other content inside of it - there are other applications in there! Your war bundle does not specify, provide or manage this additional content. We don't want this "deploy" destination directory to have this content removed when the war bundle is deployed - we just want to add the war bundle content to this "deploy" directory. In this case, you must make sure your bundle recipe specifies "manageRootDir=false" in the <rhq:deployment-unit> element. When you do this, the bundle files in the bundle distribution file are deployed in the "deploy" destination directory (including any subdirectories and their files found in the bundle distribution file) but any other files already existing in that root "deploy" directory are left as-is. This means your war web application will be deployed next to the already existing web applications that may have already been deployed in your JBoss Application Server. Note that if your war bundle declares subdirectories, those subdirectories are managed by your bundle and any extra files found to be in the way are removed. For example, if your war bundle comes with a file "my-app.war/WEB-INF/web.xml", then any files found in the "deploy/my-app.war" or "deploy/my-app.war/WEB-INF" directories will be removed, because your bundle has declared it will manage the content in those directories.
You can only deploy a single bundle to any one destination directory. If you wish to deploy more than one war to your application server's "deploy" directory, you must bundle them all in a single bundle distribution file.
Consider again the case where you have already installed a JBoss Application Server through some other means other than through RHQ. Now consider the case where you want to deploy some configuration files to this application server installation. For example, you want to deploy new login configuration settings (<jboss-install>/server/default/conf/login-config/xml) along with new JMX console users (<jboss-install>/server/default/conf/props/jmx-console.properties).
Now, notice the difference in this use-case from the others: there are other configuration files located in this "conf" directory and more specifically its subdirectory "conf/props". The issue here is, when RHQ sees that a bundle ships with files in subdirectories (like this "props" subdirectory), RHQ will expect the bundle the fully manage all the content in those subdirectories. The "manageRootDir" setting described in the previous use-case only affects those files in the top root directory (aka the destination deployment directory). A bundle will always have to manage files in those subdirectories that are shipped with the bundle.
Therefore, in this case, the bundle must not only set "manageRootDir=false" in its recipe (so that all files already found in the "conf" directory are left alone) but the bundle must also ship with all files that are expected to be in the conf/props directory (this means the bundle must ship all files that are expected to be in here, not just the one jmx-console.properties).
The bundle subsystem within RHQ is pluggable, meaning it can support multiple types of bundles and recipes. Today, there are two bundle types that can be supported, if you choose to deploy their respective agent/server plugins:
For more information on the specifics of preparing bundle distribution files of those types, please see their individual pages.
When you import a platform into inventory, you automatically get with it several child resources. Some of these children represent hardware services on that platform (e.g. CPUs, file systems and network adapters). Along with those hardware services, you will also see bundle handler services - one for each supported bundle type (e.g. the "Ant Bundle Handler" child resource supports the Ant Bundle type). These bundle handler resources are used to facilitate the provisioning of bundles on the agent machine. You do not have to directly interact with a bundle handler resource once in inventory; however, a handler does need to be in inventory for the provisioning subsystem to support its associated bundle type. This is why the bundle handers are automatically imported for you.
Only some resource types can support bundle deployments. In earlier versions of RHQ, only platforms could be targets of bundle deployments. In later versions, you can now target bundles to be deployed on non-platforms like JBoss AS Server resources. Each individual agent plugin deployed in RHQ needs to define metadata if it wants to support bundle deployments for one of its resource types.
When provisioning a bundle version, you first must build the bundle distribution file. You do this by placing all the bundle files into a single zip file (typically you just have one main bundle file, but you can have more than one bundle file associated with a single bundle version). Within that bundle distribution zip file, you also add the recipe. Once you have a bundle distribution file that contains a recipe and zero, one or more bundle files, you can upload that to the RHQ Server and provision it to your remote resources.
If you are packaging an Ant Bundle, you can use the standalone Ant Bundle Deployer tool to help you test your bundle distribution file before uploading it to RHQ and deploying it.
You have the option to store your bundle distribution files in a URL-addressable remote repository. If you do this, you can simply give your bundle distribution file's URL to the RHQ Server and it will download the bundle distribution file from there. This will allow you to, for example, store all your bundle distributions to an Apache Web Server or a git repository and let the RHQ Server pick up the bundle distributions directly from there, rather than asking users to file-upload the bundle distributions to the RHQ Server from their browser.
Each bundle file can be "templatized". This means it can contain one or more tokens that will be replaced with real values at the time it is deployed on the remote resource. A token consists of two @ symbols, following by a replacement variable name, followed by another two @ symbols - for example, @@listener.port@@.
Replacement variable names (the string between the @ symbols) must consist solely of alphanumeric (A-Z, a-z, 0-9), underscore (_) or period (.) characters.
Some replacement variables will be predefined by a user. For example, the token @@listener.port@@ defines a replacement variable that must be defined by a user when the bundle is scheduled to be provisioned - in other words, the user must provide the value that the template engine will use to replace that token.
Some replacement variables will not be predefined by the user but they will be automatically determined by the remote agent that is performing the bundle provisioning. The names of the replacement variables whose values will be automatically determined are fixed and defined below (note that the API column is for developers only - it indicates the Java API that is used to determine the replacement value):
Replacement Variable |
API |
rhq.system.hostname |
SystemInfo.getHostname() |
rhq.system.os.name |
SystemInfo.getOperatingSystemName() |
rhq.system.os.version |
SystemInfo.getOperatingSystemVersion() |
rhq.system.os.type |
SystemInfo.getOperatingSystemType().toString() |
rhq.system.architecture |
SystemInfo.getSystemArchitecture() |
rhq.system.cpu.count |
SystemInfo.getNumberOfCpus() |
rhq.system.interfaces.java.address |
InetAddress.getByName(SystemInfo.getHostname()).getHostAddress() |
rhq.system.interfaces.<network-adapter-name>.mac |
NetworkAdapterInfo.getMacAddress() |
rhq.system.interfaces.<network-adapter-name>.type |
NetworkAdapterInfo.getType() |
rhq.system.interfaces.<network-adapter-name>.flags |
NetworkAdapterInfo.getAllFlags() |
rhq.system.interfaces.<network-adapter-name>.address |
NetworkAdapterInfo.getUnicastAddresses().get(0).getHostAddress() |
rhq.system.interfaces.<network-adapter-name>.multicast.address |
NetworkAdapterInfo.getMulticastAddresses().get(0).getHostAddress() |
These replacement variables are also supported - their values are determined by their corresponding standard Java System Property:
rhq.system.sysprop.java.io.tmpdir |
rhq.system.sysprop.file.separator |
rhq.system.sysprop.line.separator |
rhq.system.sysprop.path.separator |
rhq.system.sysprop.java.home |
rhq.system.sysprop.java.version |
rhq.system.sysprop.user.timezone |
rhq.system.sysprop.user.region |
rhq.system.sysprop.user.country |
rhq.system.sysprop.user.language |
To deploy a bundle, go to the main Bundle view and click the "Deploy" button. You will be shown the Bundle Deploy Wizard - you pick the bundle you want to deploy, the destination where you want the bundle to go to, and the values for any configuration settings the bundle requires. If you are already viewing a bundle, clicking the "Deploy" button will implicitly know you want to deploy the bundle are viewing. Similarly, if you are viewing a destination, RHQ will implicitly know which bundle you want to deploy and which destination you want to deploy to.
After completing the wizard, the bundle deployment schedule is created and RHQ will begin deploying the bundle files to all resources in your bundle destination's group of resources.
Once the deployments are kicked off, you can view the deployment from the GUI to track its progress (see the image below). Once complete, the deployment view will show the audit trail of all that happened on each machine where the bundle was deployed (or where the bundle was attempted to be deployed to).
Upgrading a bundle is nothing more than simply deploying a bundle to a destination that already had a previous bundle deployed to it. RHQ will handle updating files on the remote systems.
In the Bundle Deploy Wizard, there is a checkbox which you can set to tell RHQ to "clean" the destination directory. This is used if you want to make sure no old files exist in the destination directory before the new bundle files are deployed. Use this to ensure that your new bundle deployment looks exactly as your bundle distribution expects it to be.
You may have deployed a bundle, but no longer want that bundle on your remote machine. From the deployment view, press the "Purge" button to completely wipe the bundle deployment from the remote file system.
After you have performed an upgrade, you may discover that the bundle you deployed isn't working as you want (perhaps it has a bug for which there is no patch available). In that case, you may want to "revert" back to the previously installed version of the bundle. You can ask RHQ to revert to the previously deployed bundle version via the "Revert" button.
When you revert, RHQ will take the previously installed bundle version and re-deploy it. If there were any files that were backed up during the previous bundle upgrade, those backed up files will also be restored.
Not all bundles can be reverted using this mechanism. Only bundle plugins that support the revert feature can do this. Specifically, the Ant Bundle Plugin does support this revert feature, however, the File Template Bundle Plugin does not.
Here's an example for how this can work. Suppose you have two versions of bundle "My App", let's call them versions 1 and 2. If you installed version 1, and then upgraded to version 2, your current live version is version 2. But suppose you don't like version 2 and you want to go back to what you had previously deployed. The previous version you had deployed was version 1. So, during a revert, RHQ will re-deploy version 1. Any files that were backed up when version 2 was installed will be restored. At this point, your old version 1 should be back and it will again be considered the current live deployment.