Using Packer with Zetta.IO

From version 0.8.x, packer supports Zetta.IO and other modern Openstack clouds with multi-tenant/domain support. We contributed to the Packer project with the first working builder for the platform. The code was used as a base for the new Openstack builder in 0.8.0. Visit the Official Packer page and download the binaries.

To configure Packer you need a JSON template and environment variables with authentication data.

Setting Environment Variables

Let's start with making a simple script that sets the environment variables. This example works for Linux and OS X. You can download an rc file from our dashboard under Overview -> API and modify it for this.

File : openrc-zettaio-mydomainname-myproject-myuser.sh

export OS_AUTH_URL=https://identity.api.zetta.io/v3 export OS_DOMAIN_NAME="mydomainname.com" export OS_TENANT_NAME="Standard" export OS_USERNAME="myusername" export OS_PASSWORD="mypassword"

Note that the TENANT_NAME is the name of the project you want to create the image in. If you only have one project it would normally be named called "Standard".

JSON Template

File : zetta_test.json

{ "builders": [{ "type": "openstack", "image_name": "packer-test-image", "source_image": "d0a89aa8-9644-408d-a023-4dcc1148ca01", "flavor": "6", "floating_ip_pool": "Public", "security_groups": ["default"], "ssh_username": "ubuntu" } ], "provisioners": [{ "type": "shell", "inline": [ "sleep 30", "sudo apt-get update", "sudo apt-get install -y nginx" ] }] }

This template will create an image named "packer-test-image" based on a public Ubuntu 14.04 image and installs Ngix with a simple shell provisioner. The selected flavor is m3.medium (6).

Running Packer

Set the environment variables in the script :

$ source openrc-zettaio-mydomainname-myproject-myuser.sh

Run the template :

$ packer build zetta_test.json

The output :

==> openstack: Discovering enabled extensions... ==> openstack: Loading flavor: 6 openstack: Verified flavor. ID: 6 ==> openstack: Creating temporary keypair for this instance... ==> openstack: Launching server... openstack: Server ID: 22deb62c-a888-4c76-9523-66816c35cac0 ==> openstack: Waiting for server to become ready... ==> openstack: Creating floating IP... openstack: Pool: Public openstack: Created floating IP: X.X.X.X ==> openstack: Associating floating IP with server... openstack: IP: X.X.X.X openstack: Added floating IP X.X.X.X to instance! ==> openstack: Waiting for SSH to become available... ==> openstack: Connected to SSH! ==> openstack: Provisioning with shell script: /var/folders/m3/xy78sqz160g_722vt047721r0000gn/T/packer-shell733544044 openstack: (runs apt-get update) <SNIP> openstack: Setting up nginx-core ... ==> openstack: Stopping server... openstack: Waiting for server to stop... ==> openstack: Creating the image: packer-test-image openstack: Image: 4862f351-511b-4fd7-9ec2-00e605597d57 ==> openstack: Waiting for image to become ready... ==> openstack: Deleted temporary floating IP X.X.X.X ==> openstack: Terminating the source server... ==> openstack: Deleting temporary keypair... Build 'openstack' finished.

You should now be able to find the image in your project. It's ready to launch whenever you need it. This is a fairly basic example just to get started. There are so many ways to run provisioning, and if you're already using provisioning tools, it probably works with packer already. Please see the official documentation for more details. It's also worth stopping by their Github page page.

Additional Notes

The supported environment variables for authentication is :

OS_AUTH_URL OS_USERNAME OS_USERID OS_PASSWORD OS_TENANT_ID OS_TENANT_NAME OS_DOMAIN_ID OS_DOMAIN_NAME

See : https://github.com/rackspace/gophercloud/blob/master/openstack/auth_env.go (Packer is using the Gophercloud API for all communication to Openstack)

Builder Steps

It can be practical to know what the Openstack builder does step by step. The goal is to successfully create an image after running provisioners and possibly post-processors.

Authentication. The user is authenticated and scoped to a project in their domain.

Extension Check. The builder checks what extensions are available.

Flavor Check. Checks if the flavor id for the server actually exists.

Keypair Creation. Creates a temporary keypair for SSH communication.

Launch Server. Starts a server with the supplied image id and flavor with the security groups listed in the template.

Allocate IP. Attempts to release an IP from the pool and set the ower to your project. Then the server is given this public IP. (There are other options for IP allocation as well)

Wait for SSH. Keep trying to ssh to the server. It might not be done booting. This is the most common step to fail initially becuse of too strict security groups or wrong ip pool name. (You could also provision in the local network, so public IPs are structly not needed. Then this step will be skipped)

Run Provisioners. Run whatever provisioner(s) you have configured. The possibilities here are endless. This step will wait until provisioning is completed before it continues.

Stop Server. The server is stopped so we safely create an image.

Create Image. An image creation is queued. We wait for it to complete.

Delete Server. The server is deleted.

Delete Keypair. The temporary keypair is deleted.

Post-Processor. Run post-processors on the final image (optional)