One of the great strengths of cloud computing is the ability to set up virtual machines in a repeatable way, using appropriate tools to inject information into them as they boot in order to configure them for your exact needs. In this tutorial, we will look at how to insert OpenStack's native Heat agents into an image to allow the use of Heat for application setup.

Most images for OpenStack are cloud-init enabled. This means that every instance this image creates can run the cloud-init script on early boot in order to do some configurations. The directory /var/lib/cloud contains the cloud-init specific subdirectories. In these subdirectories, you'll find the current instance ID, previous instance ID (it could be different than the current one), current and previous data sources, start and end time, errors (if they exist), custom scripts (in the scripts/ subdirectory) downloaded or created by the corresponding handlers (in the handlers/ subdirectory), user data downloaded from metadata service, and more.

But what if we want some configurations/actions on different parts of the instance's life cycle and not just at early boot? For example, if we're using the OpenStack autoscaling service, our servers will be added and deleted automatically without human intervention. "When any of these servers are determined to be ended, they need some time to clean themselves and need some configuration (e.g. ending active sessions, closing active connections to other services, etc.).

This is the value of Heat-based software deployment, which facilitates communication between the OpenStack Heat unit and the instance to configure the instance on different life cycles. This feature has been available since OpenStack's Icehouse release. To use it, we need to install some agents on the image, as well as some definitions in the Heat template (mainly based on the OS::Heat::SoftwareDeployment and OS::Heat::SoftwareConfig resource types).

The agents can be installed on boot (via a script that installs the agents on boot, or with definitions in Heat template). Here I'll discuss how to install the agents in the image. The agents we will use in this example are: heat-config, os-collect-config, os-refresh-config, os-apply-config, heat-config-cfn-init, heat-config-puppet, heat-config-salt, and heat-config-script.

Preparing for image building

For this example, I am assuming that you have your own OpenStack-ready image and you want to add the Heat agents to your image. I will use the Diskimage-builder to build the image. Diskimage-builder (DIB) is an open source project managed by HP, Red Hat, and Cisco and licensed under the Apache License (version 2.0). My operating system is Fedora 21, and in this example I will build a CentOS 7 custom image with Heat support.

If your image is already on the cloud, you can download it using Glance client after you provide your credentials. To install the Glance client on Fedora, type:

# yum install python-devel libffi-devel

# pip install python-glanceclient

To download the image, execute:

# glance image-download --file outputImageFilename imageID



By doing this, you will get the file outputImageFilename on the local disk.

The Diskimage-builder needs enough RAM for caching. If your image is big and you do not have enough memory, you can use /tmp for caching on disk. See instructions for doing so further down the article.

Now we need to clone the repositories: Diskimage-builder, image elements, and heat-templates:

# git clone https://git.openstack.org/openstack/diskimage-builder.git

# git clone https://git.OpenStack.org/OpenStack/tripleo-image-elements.git

# git clone https://git.openstack.org/openstack/heat-templates.git

Some environment variables need to be exported:

DIB_LOCAL_IMAGE : This variable contains the path to the local image (in my case my_image.qcow2). If this variable is not set, the Diskimage-builder will go to the Internet and bring a generic image. If you don't have any image just don't export this variable to keep the default.

: This variable contains the path to the local image (in my case my_image.qcow2). If this variable is not set, the Diskimage-builder will go to the Internet and bring a generic image. If you don't have any image just don't export this variable to keep the default. DIB_CLOUD_IMAGES (HTTP address): If your image is public on the Internet, you can export this variable.

(HTTP address): If your image is public on the Internet, you can export this variable. ARCH : This variable contains the architecture. In my case “amd64”: # export ARCH="amd64" . This will be converted to x86_64.

In my case with CentOS 7, the source file which use this variable is ".../Diskimage-builder/elements/centos7/root.d/10-centos7-cloud-image". I recommend you check the corresponding file for your choice (Go to the root.d directory in your OS choice directory and check what is supported for ARCH ). Check this file also for DIB_CLOUD_IMAGES variable and others.

Then we need to install some packages:

# yum install qemu or # yum install qemu-img

# yum install python-pip git

# pip install git+git://git.openstack.org/openstack/dib-utils.git

Image building

Next I am going to add the Heat agents to my image using Diskimage-builder so that the instances created from my image can interact with Heat on different life cycles. Write the following in bash script and execute it or take it line by line. Note: You need to be in the directory where you have cloned the repositories, or use absolute paths.

export ELEMENTS_PATH=tripleo-image-elements/elements:heat-templates/hot/software-config/elements

# customize this line. Possible values: fedora centos7, debian, opensuse, rhel, rhel7, or ubuntu

export BASE_ELEMENTS="centos7 selinux-permissive"

export AGENT_ELEMENTS="os-collect-config os-refresh-config os-apply-config"

export DEPLOYMENT_BASE_ELEMENTS="heat-config heat-config-script"

# For any other chosen configuration tool(s). e.g. heat-config-cfn-init, heat-config-puppet, or heat-config-salt. NOT IN MY CASE.

export DEPLOYMENT_TOOL=""

export IMAGE_NAME=software-deployment-image-gold

diskimage-builder/bin/disk-image-create vm $BASE_ELEMENTS $AGENT_ELEMENTS $DEPLOYMENT_BASE_ELEMENTS $DEPLOYMENT_TOOL -o $IMAGE_NAME.qcow2

(Note the variable IMAGE_NAME determines the image name.)

Image uploading

After building the image, you'll get the file software-deployment-image-gold.qcow2. If your image is big, you can compress it before uploading it to OpenStack (Glance unit):

# tar -zcvf gw-software-deployment-gold.qcow2.tar.gz gw-software-deployment-gold.qcow2

You can also pass the option "-t tar" to the command diskimage-builder/bin/disk-image-create to have the image compressed by the Diskimage-builder. Also use this option "-a i386|amd64|armhf" for the ARCH mentioned above. See the full documentation for more details.

To upload the compressed image, execute:

# glance image-create --name "gw-software-deployment-gold" --is-public false --disk-format qcow2 --file gw-software-deployment-gold.qcow2.tar.gz

I've had troubling using Firefox to upload large files (like images), but Chrome usually seems to work. I recommend uploading your image from the OpenStack control panel (Horizon) using Chrome browser.

You may also need to tune the performance parameters of the operating system (i.e. you may need to update system files) and the application itself so the servers created from the image are already tuned. You can do the tuning on the live server before taking a snapshot or you can update the system files of the local image using guestfish before uploading.

Now you can create an instance from the new uploaded image where you can start working with software deployment on different lifecycle in your Heat template.

Using "/tmp" for caching on disk

If your computer lacks enough RAM to complete the image building process, you'll need to increase the size of /tmp. For example (with 15GB):

# dd if=/dev/zero of=/usr/tmp-dir bs=1024M count=15

# mke2fs -j /usr/tmp-dir; chmod 777 /usr/tmp-dir

# mount /usr/tmp-dir /tmp>

Notes

During image building, if you run into problems related to packages update, you can temporarily disable repositories that cause the problems by using yum-config-manager --disable repositoryName in the live server before creating the image (The image that you will download from the cloud to work on).

in the live server before creating the image (The image that you will download from the cloud to work on). Commenting out the line yum -y update in the file "..../heat-templates/hot/software-config/heat-container-agent/scripts/configure_container_agent.sh" could solve the problems that arise on update, such as conflicts between different versions of packages.

in the file "..../heat-templates/hot/software-config/heat-container-agent/scripts/configure_container_agent.sh" could solve the problems that arise on update, such as conflicts between different versions of packages. You could do the process many times with different updates until the image creation process completed successfully. If you are using the default, you shouldn't have any problems.

You can specify package dependencies. In my case I'm using the CentOS 7 defaults at ".../diskimage-builder/elements/centos7/element-deps": If you like, you can add more here so it will be installed.

For more information, you may wish to view "Creating Custom Elements For Diskimage-builder" from the recent OpenStack Summit in Vancouver.

An earlier version of this article was previously published on VOIP Magazine. Republished with permission.