JBoss Community Archive (Read Only)

RHQ 4.9

Design - Policy

Policy now has its own design page. See Design - Provisioning for the provisioning design page.

There is a Bundles Sprint Demo available


This is the design for a basic "configuration/provisioning/policy engine" for RHQ. We'll use the term "bundle" when talking about this new subsystem. Keep in mind the three objectives to this subsystem:

  • pushing a bundle of content to remote machines ("provisioning")

  • tweaking the settings found in the configuration files that are associated with the bundle ("configuration")

  • periodically checking that the bundle's content to ensure it hasn't changed without permission ("policy")

The goal will be to support many bundle types, but for the first version the design will implement basic file templating. For the purpose of this design, policy will be defined as "the configuration and content which should be on the machine". This is different from other RHQ configuration views in that they represent what "is" on the machine. The name policy for this is really not great - any feedback is welcome.

The design is for the actual policy rules to be enforced on the machine which is at the edge. Ideally, a central server is not pushing out each command, but rather pushing out all the commands (i.e. a "recipe") and letting the agent do the real work.

An interesting side-effect of this model, is that:

  • basic JBoss provisioning will also be supported since dropping a container and configuring it are integral to this design

  • support for Cobbler profiles and provisioning with koan will also be supportable (with some custom plugin coding)

Relationship to Other RHQ Systems

Bundle management will be a separate RHQ subsystem.  It will use the content system to store files. There is no plans to connect the configuration subsystem's representation of the file to that which is in the bundle system. Where the connection will be seen is in looking at the audit history of a resource. The user will be able to correlate when the policy engine ran with changes on the machine.

Use Cases

The main story which cross cuts these use cases is that a user can upload bundles either as a single archive file, or as a collection of files. These will be stored within a repository in the content system. When the bundle plugin is run, it will check for the latest version of the files and then will lay down the files and extract them from archives if necessary. The file-template bundle plugin will support doing macro substitution of files so that they can be generic in the content system, but made specific during the deployment.

Design Overview

Data Model

The design will introduce the following entities to the core RHQ model. The non-greyed out entities in the diagram below will be added:

Unable to render embedded object: File (bundle-schema-4.png) not found.


  • rhq_bundle_type: This entity defines a bundle type/format. We will initially support two bundle types - FileTemplate and Puppet. Plugins on both the Server and Agent side will check a bundle's type to determine how to parse and validate that bundle's recipe file. Each bundle type is associated with a singleton ResourceType whose ResourceComponent implements the BundleFacet, which contains the logic for checking and installing (if needed) a recipe.

  • rhq_bundle: This entity will contain the configuration data which should be be deployed onto a machine. Bundles can be versioned, so the real data is stored in rhq_bundle_version

  • rhq_bundle_version: This entity is a specific point in time of bundle configuration data.

  • rhq_bundle_file: This entity is a file which is part of a bundle and is used in the deployment process.

  • rhq_bundle_deploy: An entity which contains the bundle to deploy and all the variable substitutions defined as a config (rhq_bundle_version has a configuration definition associated with it that defines what variables need to be defined). The config is immutable after creation. It also contains a flag which specifies whether automatic policy enforcement is enabled.

  • rhq_bundle_res_deploy: This entity represents an actual deployment of the bundle onto a given resource. The deployment could have been either user-initiated or system-initiated (if policy enforcement was enabled). System-initiated deployments will only be created if one or more changes were necessary to bring the system into conformance with the recipe.

  • rhq_bundle_res_dep_hist: This entity represents an audit trail for the deployment of the bundle onto a given resource (a platform). It will (minimally) record start and end times for deployment, as well as policy failures.

  • rhq_bundle_group_deploy: This entity represents an aggregate of resource deployments to the group members.

  • rhq_tagging: This entity represents a tagging relationship users can use to reflect their provisioning processes. (Best practices to be published for this?)


The following relationships are shown on this design:

  • (a): A bundle may require that a target resource be subscribed to several repositories for content. For example, this bundle requires the machine to be subscribed to a RHEL6 repo. This relationship models that need. Only eligible platforms can be provisioned to.

  • (b): Each bundle will have its own repo for owning content associated with the bundle that is not pulled from an existing repo. Note, the repo in this relationship is completely independent of those described in (a).

  • (c): A bundle file may link to a specific version of a file which is stored in the content system, or to the most recent version of that file. If choosing the most recent version the relation to the rhq_package will be non-null. The relation to the relevant rhq_package_version will always be defined. The system will ensure it always points to the most recent version, if necessary.

  • (d): When defining a deployment, the user can opt to pick a specific bundle version, or the most recent version of the bundle. If choosing the most recent version the relation to the rhq_bundle will be non-null. The relation to the relevant rhq_bundle_version will always be defined. The system will ensure it always points to the most recent version, if necessary.

  • (e): Bundles are versioned. This is the version relationship.

  • (f): Bundles are not hierarchical. Therefore, a user needs to be able to guide more that one bundle to a given resource.

  • (g): Multiple configuration templates can be associated with a bundle version. If any templates are defined on the bundle version's config def, when the user creates a new deployment definition, they can select a template as a base for the def's configuration.

  • (h): Each bundle will have its own package type. Files uploaded for the bundle will have their package types set to the bundle's package type and the package versions will be associated with the bundle's repo (see (b)).

Bundle Subsystem

To support the bundle provisioning/configuration and ongoing policy enforcement, a new plugin subsystem will be created. The common scenarios for execution are below.

Schedule Driven Updates

  1. The user configures the agent plugin container to update the bundle every X minutes

  2. The agent plugin container retrieves a summary of the bundle from the server. This includes enough data to determine if the bundle which is installed is out of date. The data should include things like:

    1. Bundle Version and last updated time

    2. Bundle Recipe MD5

    3. Bundle Variable MD5

    4. MD5 Sum and Timestamp for every Bundle File

  3. The agent plugin container passes this data, and a call back object, to the plugin to tell it to perform an update.

  4. The plugin will be responsible for interrogating state data in the data directory with the md5 sum and version information which was passed down.

  5. If the plugin needs the actual file, then it can call back to the server via the callback

    1. The plugin can request all the files for the bundle, or individual files.

  6. The agent plugin container then records the event that the update occurred.

  7. The agent plugin container then notifies the server that the update is complete.

User Driven Updates

This is the same Use Case as schedule driven, with the following changes:

  1. Instead of time kicking off the process in step 1 above, it is a manual user action.

  2. The event which is recorded notes the user who requested the update.

Future Dates Updates

This is the same use case as schedule driven, with the following changes:

  1. Instead of a recurring job kicking off the process in step 1 above, the user selects a specific time for the change to occur.

New Bundle Creation

  1. The user does development work on a bundle, and combines them all into a single archive file.

  2. The user uploads the file and notes the "type" of bundle (puppet, file, etc)

  3. The Bundle Subsystem locates a custom Bundle Parser (via a bundle server-side plugin) based on the type which will expand the archive file and create the new data structure items in the database.

Policy Perspective

The UI will probably be complex enough that a custom perspective will be warranted.

File Template Engine

A core agent engine will need to be created which will allow files which are templated with simple macros (e.g. <% rhq.ip_address %>) to be placed onto the file system with the macros expanded. Some of the these macros (like ip_address) should be facts which the engine discovers from the machine, or from the RHQ deployment. Others should be user defined. This engine will also be used by the raw config plugins, since the same feature of facts and substitution will be required when pushing one file out to a group of machines.

The following can be used as examples of macros to support:

Detail Design

The following sections provide more detailed information about the design summary above.

Data Model

Bundles and Bundle Versions

A bundle is a named collection of content and configuration. A bundle can be versioned. Each version can contain the following bits of information:

  1. The repositories which a machine should be subscribed to.

  2. The type of bundle which it is (e.g. FileTemplate, Puppet, etc)

  3. An optional recipe

    1. The recipe content will be stored in an instance of rhq_package_version.

    2. The recipe should not change for a bundle version - if a recipe changes, it must be considered a new bundle version - therefore, the recipe must be hardlinked to its bundle_version - the recipe content will be stored as a CLOB in the bundle_version table.

  4. An Collection of template variables which need to be filled out by a deployment.

    1. Stored in configuration definitions / configuration templates

  5. A collection of default values for the template variables

  6. A version number, and last modified date to help determine if an update needs to be run.

  7. An md5 sum and last modified data for the recipe.

Bundle Files

Bundle files represent the actual files which should be included in the bundle. When creating a bundle file, the user can decide to either pull in the latest version of the file, or to pull in an exact version of the file. Base on this selection, the entity will  contain a reference to either a rhq_package or to a rhq_package_version.

Archive Bundle Files

One use case for the subsystem will be to deploy JBoss containers which are uploaded as a Zip File.  This Zip File will be the rhq_bundle_file associated with the bundle. At deployment time, items in the zip file could potentially be realized with macro expansion, as the recipe dictates.


The deployment should be reusable, so the deployment is broken up into 2 entities. These are:

  • rhq_bundle_deploy_def: This entity will hold the user defined values which are required to complete the deployment. For example, the templated file has the ability to substitute in a "wiki_name" variable, then his object will contain a key-value pair which is wiki_name = "My Wiki". This is done via the  rhq_config Configuration subsystem.

  • rhq_bundle_deploy: This entity provides a mapping between one deployment and many systems. For each platform where a bundle is deployed, there will be one rhq_bundle_deploy entity.

The Deployments, when mapped to a resource, they will need to be ordered. The user will want to ensure that certain bundles are deployed before or after others.

Bundle Subsystem

Agent Plugin Container

The Agent Plugin Container's Bundle Manager (org.rhq.core.pc.bundle.BundleManager) will support the bundle subsystem on the agent side. It will interface with those plugins that support the BundleFacet.

Agent / Server Communication

The Agent / Server communication will follow the standard format for RHQ subsystems. The specific APIs are below.

Agent API

The Agent API will support the following functions:

  • update: Update will be called with a summarized set of the bundle data and instructs the agent to do an update of policy immediately.

Server API

The server API will support the following functions:

  • getAllFiles: Retrieves all the files for a bundle

  • getFile: Returns a single file for a bundle

  • getFilesSince: Returns all files which have changed for a bundle since a given time or version

  • updateComplete: Tells the server that the update is complete

Bundle Facet API

The Bundle plugin facet will need to expose the following APIs. Each will need to take in a Callback object to expose the server side calls to the plugin:

  • update: Determines if an update needs to occur based on the summarized bundle data, and performs the update if required.

Bundle Decomposition Server Side Plugin

The subsystem will need to support a model for uploading new bundles and new bundle recipes. A server side plugin should be able to parse the recipe and archive file when they are uploaded. This plugin should create/update the bundle data to be in sync with the recipe / archive.

Bundle Update Job

A new Quartz Stateful Job will need to be created which will update bundles in the database, based on changes in the content system. This new job, org.rhq.enterprise.server.bundle.BundleUpdateJob, will be launched via the org.rhq.enterprise.gui.startup.StartupServlet. The job will be responsible to look for BundleFiles which are configured to use the most recent version of he file. If a new version of the file is found, the batch job will update the timestamp on both the bundle_file and the bundle_version to ensure that the next time an agent checks in the agent will see a recently updated bundle timestamp.


We probably need to create a new permission ("Bundle" or whatever). This would restrict a person to be able to create/manage/deploy bundles. The first cut of the implementation probably won't have anything along the lines of permissions/security. We'll add that once we get the API and UI flushed out and thus we will see where security will be needed.


  1. The content system will need to support storing archive files (zip, gzip, tar, jar, war, etc) not tied to any specific resource.

File Template Bundle Type Design

Bundle DSL

The Bundle contains a single script which is the set of actions or "recipe commands" to be taken on a given machine in order to deploy the Bundle. The DSL will consist of the following recipe commands:

  • script: Takes as a parameter a command line which is executed on the machine. This represents a script file that is explicitly included in the bundle - it is an uploaded bundle file.

  • command: Takes as a parameter a shell command line which is executed on the machine. The executable/shell command must already exist on the machine.

  • deploy: Takes 2 parameters, an archive name (-file) and a path (-directory). The archive is assumed to be one of the bundle_files. At deployment time, the archive is unzipped into the path location. The MD5 version of the file will need to be stored on the machine to ensure that the a second deployment is not done unless the version changes.

  • file: Takes in 2 parameters, a file name (-source) and a destination path (-destination). The file is assumed to be one of the bundle files. At deployment time, the file is copied in the specified path. If you want replacement variables to be substituted with their realized values in this file, use the realize command afterwards.

  • realize: Realize perform macro substitution on a file which is already on the filesystem (--file). This can be used to substitution replacement variables.

  • configdef: Defines one configuration definition, or "replacement variable". The name provided to this configdef will be assumed to be a replacement variable that may exist in bundle files that are to be realized. The user that deploys the bundle will need to provide a value for this config def or let the agent provide the value (by looking up the value in the agent's template engine or looking up the value as a simple Java system property).

the following recipe commands are not supported yet

  • service: Takes in 2 parameters, a service name and a command (start|stop|restart).

  • repo: Takes as a parameter a repository name so the server will be able to check that the proper subscriptions are in order prior to deploying the bundle.

  • package: Takes as a parameter a packge name. It will cause a specific package to be installed or updated.

An example DSL would then be:

  repo -n rhel-x86_64-5 (_not supported yet_)
  package -n foo-1.25.rpm (_not supported yet_)
  package -n bar-1.25.rpm (_not supported yet_)
  configdef -n listener.port
  script foo.bash -c some parameter
  deploy -f jboss.tar -d <%jboss.home.directory%>
  realize -f <%jboss.home.directory%>/server/default/setting.xml
  file -s example.setting -d /etc/some/setting.ini
  service example restart (_not supported yet_)

There must be a server-side plugin that must be defined that can parse the different kinds of recipes that are supported. For example, a file-template server side plugin must be able to parse a file-template DSL as shown above so it can:

  • create the bundle version config def so a UI will know what questions to ask a user

  • create relationships between the bundle version and its related repos, distributions and packages

ANT Bundle Type Design

The "file template" bundle type supports a easy recipe style that lets you quickly build simple bundles for deployment to your agent boxes. While the DSL supported by that file template bundle type can do many of the basic things you'd want to do when pushing out content, you may find that you need a more advanced featureset. If you need to write a recipe with more functionality than what the file template DSL can give you, you have the option to write your "recipe" as an ANT script. When you create a ANT bundle, the recipe you provide is a standard ANT script that is executed on the agent machine.

RHQ adds additional custom ANT tasks for use within your ANT scripts to help model your bundle's behavior and metadata. Read about those ANT tasks in order to properly write a RHQ Ant Bundle Recipe.


this will change in the next implementation due to design changes recently decided upon - for the real design - see Design-Bundle Ant Tasks

If you need to associate bundle files to your bundle, you do so using the standard ANT <property> tag, but to inform RHQ that you need to upload a file with your bundle, assign that property tag with a reference ID that starts with "_bundlefile.". If you need to have the user provide the values for custom configuration properties (which then get passed to your ANT script), again set a reference ID to the <property> tag but have the ID start with "_bundleconfig.". For example:

<property id="_bundlefile.1" name="jboss.distro" value="jbossas.zip"></property>
<property id="_bundleconfig.1" name="listener.port" value="8080"></property>

When you create the bundle, RHQ will ask you to upload the "jbossas.zip" file. When you go to deploy the bundle (more specifically when you go to create the deployment definition), RHQ will ask you for the value of "listener.port" that you want set.

For some reason, if you file upload a ANT script as the recipe, you can't use XML notation like <property name="a" /> - you need to explicitly provide the ending tag like this: <property name="a"></property>. If you don't want to be forced into using that notation, just copy-n-paste the ANT script content directly in the text field, as opposed to using the file upload mechanism.


The following are Java classes and other resources that have been added to the core server and agent as part of the "bundle subsystem". This is the plumbing that now exists (in the bundle branch). All that needs to happen is to fill out the meat of these stubs to implement bundle functionality.



the remote endpoint that the agent talks to. In other words, when the agent sends a bundle API message to the server, this is the class that receives and processes that message.


the API interface that the agent calls. This defines the API that the agent compiles against.


the EJB3 SLSB that performs the business logic for the bundle subsystem. The BundleServerServiceImpl calls this SLSB to perform transactional db operations.


the local EJB3 SLSB interface


the remote EJB3 SLSB interface that is exposed as a web service and can be invoked by the remote CLI


the server-side plugin container that manages all bundle server side plugins (there is an associated plugin manager, but this plugin container will probably be the class that will need to be enhanced)


contains the plugin manager and validator for bundle server side plugins - the important class is the plugin container class though


the XML schema that defines what a bundle server side plugin descriptor looks like.

The first server-side plugin implementation to support our RHQ FileTemplate bundle type:


the stateful server-side plugin component that performs the job of the plugin. This will be where the DSL is parsed, and where it determines the domain model relationships for a given bundle


the filetemplate bundle server plugin descriptor



the manager within the plugin container that performs tasks for the bundle subsystem. This is also the remote endpoint that the server talks to. In other words, when the server sends a bundle API message to the agent, this is the class that receives and processes that message. It will also be the one to schedule policy checks - probably via a thread pool executor.


the API interface that the server calls. This defines the API that the server compiles against.


The plugin facet that bundle plugins must implement. This will provide the common/generic API interface that the plugin container will call when it needs to ask a bundle plugin to process a bundle.


This package contains data transfer objects that are required as per the BundleAgentService interface. In other words, these are objects that both the server and agent need to know about and use because it is these objects that the server and agent hand off to one another when sending messages back and forth

The first agent plugin implementation to support our RHQ FileTemplate bundle type:


the stateful agent plugin component that performs the job of the plugin. It implements the BundleFacet and will process bundles of a specific bundle type


the agent plugin descriptor


Bundle domain objects that match the data model described earlier can be found in modules/core/domain within the package org.rhq.core.domain.bundle. There are already some unit tests but they just test the basics.


Here are some of the APIs that we will need to implement.

Server-side SLSB

  • BundleManagerBean should support the following API for CLI/GUI usage

  • RecipeParseResults verifyRecipe(String bundleTypeName, String recipe)

  • Bundle createBundle(String bundleName)

    • Creates the Repo under the covers

  • BundleVersion createBundleVersion(Bundle bundle, String Recipe)

    • Implicit package creation for each bundle file in recipe

    • Implicit create of config def based on recipe

    • Auto-increment version

  • List<Package> getBundleVersionPackages( BundleVersion bundleVersion )

    • note, maybe get this as fetch from BundleVersion criteria?

  • BundleFile addBundleFile( BundleVersion bundleVersion, PackageVersion pkgVersionPojo, boolean pinToPackage )

    • Calls content subsystem's "createPackageVersion" under the covers

  • void attachPackageBitsToBundleFile(BundleFile bf, byte[] bits)

  • void attachPackageBitsToBundleFile(BundleFile bf, InputStream bits)

  • Convienence method to combine the addBundleFile and attachPackageBitsToBundleFile:

    • BundleFile addBundleFile( BundleVersion bundleVersion, PackageVersion pkgVersion,boolean pinToPackage, byte[] bits )

    • BundleFile addBundleFile( BundleVersion bundleVersion, PackageVersion pkgVersion,boolean pinToPackage, InputStream bits )

  • BundleDeployDefinition createBundleDeployDefinition(BundleDeployDefinition def)

  • void deployBundle(int bundleDeployDefinitionId, int[] resourceIds)

    • Question: Does this generate the BundleDeployment records (the mapping table) Answer: Probably, although it may not be needed until the deployment actually starts (if it is scheduled for the future). History records hang off this and get generated on each tracked action.

  • List<BundleDeploymentHistory> getBundleDeploymentHistory(BundleDeploy deploy)

  • List<BundleDeploymentHistory> findBundleDeploymentHistoryByCriteria(BundleDeploymentHistoryCriteria bc)

    • bc.addFilterBundleId( id )

  • List<BundleDeploymentHistory> getBundleDeploymentHistory(int bundleId,int platformResourceId);

    • gets history for a specific bundle deployment

  • List<BundleDeploymentHistory> getBundleDeploymentHistory(int platformResourceId);

    • gets history for ALL bundles deployed on this platform

Server-side plugin

  • interface BundleServerPluginFacet is what all bundle server side plugins must implement. We need to fill out this interface with the API described in this section

  • RecipeParseResults parseRecipe(String recipe)

  • class RecipeParseResults needs to contain all information that can be gleened from the recipe:

    • ConfigurationDefinition configurationDefinitionAndTemplates

    • Do we need a separate ConfigurationTemplate? or can they be in ConfigurationDefinition?

    • List<Package> bundleFiles

Agent-side Plugin Container/Manager

  • interface BundleAgentService (and the impl BundleManager) needs to support the API in this section

  • BundleDeployResults deployBundle(BundleDeployRequest request)

    • request has to have things like "getBundleDeployDefinition"

Agent-side bundle plugin

  • all agent bundle plugins must implement the BundleFacet. This facet should support the API described in this section

  • BundleDeployResults deployBundle(BundleDeployRequest request)

    • Note: plugins never get resource IDs, nor to they typically get the detailed data that server sends to agents (for several reasons - don't forget we want the plugin dev API to be simple). Thus I think the BundleFacet probably won't be a one-to-one mapping of the BundleAgentService interface - e.g. plugin dev won't need to know about BundleDeployResults/Request but a more simple API.

    • The package org.rhq.core.clientapi.[server,agent].bundle will have interfaces and DTOs for agent-server comm APIs - NO agent plugin interfaces/DTOs go in here. Plugin devs do not even have access to client-api classes.

    • The package org.rhq.core.pluginapi.bundle has the plugin developer API such as BundleFacet and all its supporting objects. The server side does not have access to these classes - its only for agent side plugin container-plugin communication.

Properties Available

In the file template recipe, you can provide <% var %> replacement variables, where "var" is one of the below. For an ANT recipe, the below properties will be automatically set and can be used as a ${var} expression:

These have the values as specified by their corresponding SystemInfo API:

























These have the values of 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

Issues / Questions


  1. If a bundle knows about repos, then guiding a bundle to a resource is an explicit subscription (rhq_repo_resource_map entry). If the policy engine sets this, can the core UI respect and not change it?

  2. Can tagging be used to make this any easier?

    • This was Eve's concern about "make it easy to manage repos and content and bundles and packages"

  3. There is no notion of "undeploy"

  4. Should the policy plugin create resource items which are "what is installed on the machine?"

  5. What additional work needs to be done to expose this to the CLI?

  6. How does search fit into this?

  7. This desgin does not have much in the way of permissions. Is that acceptable for the first release?

  8. How do we handle updates when some data (e.g. credentials for starting/stopping jboss) are already entered in the plugin config.


  1. The DSL seems like "puppet lite". Is that a good thing? ANSWER: yes - we are not re-writing puppet - we will in the future support a puppet integration. However, we are providing a way to perform provisioning and policy-based deployment without requiring puppet to be installed and without requiring to know how to configure/setup puppet or write the more complex puppet recipes



A "Bundle" contains 3 things:

  1. a deployment script called a "recipe"

  2. a group of 0, 1 or more files

  3. a set of 0, 1 or more configuration property definitions


A "recipe" is a small piece of text that describes what a bundle contains and how it should be deployed. It could also be called a "script" - the name isn't important, but you must know that it is core element of a bundle because it defines what files and configuration property definitions belong to the bundle as well as how the bundle should be deployed.

Configuration Property Definition

A configuration property definition defines a named configuration setting whose value is required in order to be able to successfully deploy a bundle.

Templatized File, Token, Realize

A "templatized" file is a text file that has one or more "tokens" (aka "replacement variables") that need to be replaced (aka "realized") when the file is deployed. A "token" usually represents a configuration property (see above) but it could represent agent-side "facts" (like hostname or operating system name). When a file is "realized", that means its content is re-written with all tokens replaced with their actual values. Here's a simple example:

  • This is a templatized file for my applications configuration file:

        <port number="<% listener.port %>" />
  • And here is that file in its realized form:

        <port number="8080" />

High Level Use-Case Summary In One Picture

Unable to render embedded object: File (bundle-usecase.png) not found.

JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-13 08:07:28 UTC, last content change 2013-09-18 19:41:38 UTC.