Integrating CloudForms with Puppet (Quru)

The guys at Quru have done some really cool stuff with Puppet and CloudFORMS. Here is a re-blog of what they have done,

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!

SIMPLE!

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 http://docs.puppetlabs.com/guides/external_nodes.html.

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.

#!/bin/bash

# settings

export PGUSER=”puppet_enc”
export PGPASSWORD=”YOUR_PASSWORD”
export PGHOST=”YOUR_HOST FQDN or IP ADDRESS”
export PGDATABASE=”vmdb_production”

# retrieve the tags

_sql=”select replace(ltrim(tags.name, ‘/’), ‘/’, ‘_’) from tags join taggings on taggings.tag_id = tags.id join vms on taggings.taggable_id = vms.id join hardwares on vms.id = hardwares.vm_or_template_id join networks on hardwares.id = networks.hardware_id where taggings.taggable_type = ‘VmOrTemplate’ and tags.name 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}
do
echo ” ${_tag}:”
done

echo

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: http://docs.puppetlabs.com/puppet/2.7/reference/modules_fundamentals.html

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 {

realize(Htaccess[‘_var_www_html_htaccess_auth’])
}
/etc/puppetlabs/puppet/modules/managed_department_presales/manifest/init.pp

class managed_department_presales {

	realize(Htaccess['_var_www_html_htaccess_no-auth'])

}

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.

www.quru.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s