Integrating CloudForms with Puppet

Red Hat's CloudForms enables you to provision, manage and tag virtualized servers in a Cloud. To ensure that the VMs are configured correctly, most people rely on the configuration management automation tool Puppet. Puppet is normally configured to use the server's domain name, providing configuration according to preset needs associated with that name. This limits CloudForms' ability to be quickly used to manage the server's function. This paper describes how CloudForms and Puppet can be integrated so that a new VM can be correctly and automatically configured by Puppet according to tags assigned to it in CloudForms. The integration of Cloudforms and Puppet can enable you to manage and configure your server cloud from a single pane of glass.

The Concept

We thought it would be quite useful to be able to pass tags from CloudForms to our Puppet Master. This would help us provide an end to end provisioning and configuration mechanism whereby we could automate the whole VM life cycle through a 'single pane of glass'.

A little background on the two tools and how they fit together:

Red Hat CloudForms - Enables you to provision, manage and automatically tag your VMs in a cloud infrastructure across different hypervisors i.e. KVM, RHEV, HyperV, VMware and also AWS.

Puppet - Enables you to manage your server configurations based on classes and manifests and also to report on configuration changes.

The idea is to use CloudForms to identify and manage your Hybrid Cloud infrastructure, with any changes made within CloudForms being passed immediately on to Puppet to ensure configurations are enforced seamlessly. This would also mean that the whole process of bringing up a new VM, or even changing an existing VMs 'tag' in CloudForms would apply any configuration changes through using Puppet.

Taking the concept a bit further, we can create/identify/change and configure workloads in one action, giving us our own version of end-to-end Cloud Automation.

So, the three main 'players' in this setup are:

  • VM Manager (RHEV-M, vCenter etc) - Provisioning/Creating/Managing VMs
  • CloudForms - Managing/Maintaining/Identifying VMs
  • Puppet - Enforcing configuration policies on the VMs

The Technology

Looking at how Puppet and CloudForms work, we came up with the following steps to achieve an end-to-end provisioning and configuration mechanism:

  1. Puppet Agent from within a Client goes to the Puppet Master with their Hostname.
  2. Puppet Master runs an external script to interact with CloudForms. This script uses the Client FQDN as the first argument, in return receives a list of applicable Classes.
  3. The script simply searches the CloudForms database and retrieves the Tags. It strips out the leading slash character and converts the rest to underscores. So, for the Tag Workload: Database, the Class name is managed_function_database .
  4. If Puppet finds modules/classes with this name present in the manifests, it applies that Class to the Client!

For the Puppet side, we have written a script that acts as Puppet External Node Classifier (ENC) to extend Puppet beyond the Puppet Master (we won't get into the detail of ENC's for Puppet here).What we had to do was point the configuration in Puppet Master to this script. Note: You will have to update some config settings within the script itself to fit your environment in the top section of the script.

NOTE: Information Puppet ENC documentation can be found at

You may notice a nice, long SQL query in the script. It is not entirely optimal since indices on certain columns do not exist in the CloudForms database Schema. Also, we had to take this approach as the CloudForms API doesn't currently have inquiry by hostname of the client, this should emerge in the next few iterations to the API.

In summary, we take the tags from the CloudForms database, prime them up and present them in YAML format so that Puppet understands it and can apply configuration tasks accordingly.

NOTE: Before you run the script, create a Postgres user on the CloudForms database called 'puppet_enc' and give it 'SELECT' permissions.

The Script

Make sure your script is saved in the same path as you identified in the Puppet.conf for ENC configuration and is given 755 permissions so that it can be executed.


# settings

export PGUSER="puppet_enc"
export PGDATABASE="vmdb_production"

# retrieve the tags

_sql="select replace(ltrim(, '/'), '/', '_') from tags join taggings on taggings.tag_id = join vms on taggings.taggable_id = join hardwares on = hardwares.vm_or_template_id join networks on = networks.hardware_id where taggings.taggable_type = 'VmOrTemplate' and not like '/managed/folder_path_%' and networks.hostname = '${1}'"

_tags=$(psql --quiet --tuples-only --command="${_sql}")

# mimic yaml

echo '---'
echo 'classes:'

for _tag in ${_tags}
echo "    ${_tag}:"


The Application

In order to test this, we set up two VMs running HTTPD. We then wrote a Puppet class to create an '.htaccess' file to see if there is a match from the tag in CloudForms. So, we have two departmental tags in CloudForms: Finance - Requires httpd authentication\\ Presales - Doesn't require httpd authentication

Setting up Puppet Manifest

We added the following to our main Puppet manifest (located at /etc/puppetlabs/puppet/manifests/site.pp):

## cloudforms

define htaccess($auth) {

	if $auth == 'true' {

	file {'/var/www/html/.htaccess':
		ensure => present,
		source => 'puppet:///files/htaccess-auth.txt',


	elsif $auth == 'false' {

	file {'/var/www/html/.htaccess':
		ensure => present,
		source => 'puppet:///files/htaccess-no-auth.txt',



@htaccess {'_var_www_html_htaccess_auth':
		auth => 'true',

@htaccess {'_var_www_html_htaccess_no-auth':
		auth => 'false',

Setting up Puppet Modules

When using Puppet Enterprise you can use the following command to determine your modulepath

puppet config print modulepath

Information: The 'Modules' tutorial in Puppet can be found here: Then we create two modules in Puppet accordingly at the following paths: /etc/puppetlabs/puppet/modules/managed_department_finance/manifest/init.pp

class managed_department_finance {



class managed_department_presales {



Lastly, we have to create the 'htaccess-auth.txt' and the 'htaccess-no-auth.txt' file we mentioned in the main Puppet manifest.

cd /etc/puppetlabs/puppet/files
echo -e 'AuthName "Finance Login" \nAuthType basic \nRequire valid-user' > htaccess-auth.txt
touch htaccess-no-auth.txt

That's it! Now you should be able to change tags in CloudForms and Puppet will apply the configuration. You can either wait for this to happen automatically, or login to your Puppet Enterprise Dashboard and do a 'run once' to force the configuration. To test, browse to the server and see if it requires authentication, and then change the tags for each VM to 'FINANCE' in CloudForms and it will then ask you for authentication to access the HTML content.

Watch it in action

At Quru we're very excited about open source and are always working on unique ways to integrate different open source technologies into new solutions that make life easier and simpler.

Our QuruLab is a portable, mobile datacentre that we use to demonstrate the technology we are passionate about. We can bring it to your offices in a small case and have it running in a couple of minutes.

We have all sorts of interesting Red Hat, EnterpriseDB and Puppet Labs use cases running so if you'd like to see the above solution in action, or any of the other use cases we have developed, swing by the offices or we can come to you!

Call us on 0207 160 2883 or email [email protected]

About Quru

Quru is a market leader in the technical development, deployment and support of Linux and open source solutions that help organisations to reduce costs and increase operational agility and capability. We have also developed multiple award-winning software solutions ranging from mobile phone apps to global enterprise systems. Quru is based in Somerset House on the banks of the Thames, right in the centre of London. More...

Quru :: inspired open source solutions