Build with packer qcow2 images (e.g. for OpenStack)

First of all, what is Packer?

Packer is an opensource tool for automated creation of identical machine images
for multiple platforms from a single source configuration. That means OpenStack, Vagrant, VirtualBox, Amazon E2 or even docker container.

Packer handles the different virtualization platforms with the integration of plugins, which are then called by the build scripts for the desired virtualization platform .

So here I use the kvm build environment to build a qcow2 image for my OpenStack environment. Think about it, you can easily build up a Jenkins or Go job for automated builds, integrate a checked out source code and deploy a complete … e.g. Test environment for performance Tests … that’s quite cool … or behind LBaaS … start a new instance in OpenStack from latest stable Release … let’s start …

Install a basic Ubuntu 14.04 LTS, with ssh-server, vim (because it’s my basic) and in addition the needed tools as a packer build machine (you should have enabled virtualization):

sudo su

apt-get -y install openssh-server vim qemu qemu-kvm unzip virtinst

Download packer/ get the Link:

Go to the download page: and get the download link:


unzip the packer direct to /usr/local/bin

unzip -d /usr/local/bin/

Test if everything was okay by typing:


First packer needs a config file to handle the process of image creation (which includes the instructions of the used hypervisor what Image file should be
used, trigger provision stages…) this is done – in our case – by the file centos.json. If you want to
use another Hypervisor and/or another OS you have to create a different .json file.

Second we need a Kickstarter file for the installation of CentOS itself this file contains
instructions how and what to install. This file gets provisioned to the installer via http by
the buildin http Server included in the packer process (it’s the same like on Spacewalk or RedHat Satellite server).
This file is in our case named centos6-ks.cfg and is placed in the httpdir.

So let’s start again after theory session 🙂 we should have all in one folder under /root/ (in real world I would suggest a own User like packer and build everything in /home/packer and just give sudo access to needed commands, but here its just a simple example for understanding) I also install cloud-init for later usage inside OpenStack, to get ssh-keys, ip and flavour from openstack.

1. Create needed folders including subfolder:

mkdir -pv /root/packer/httpdir
cd /root/packer/

2. Prepare a user key for build user for later inhouse support (you must be inside of folder /root/packer/):

ssh-keygen -t rsa -b 2048 -f id_rsa_cloud-user -q -N ""
openssl rsa -in id_rsa_cloud-user -outform pem > id_rsa_cloud-user.pem
chmod 600 id_rsa_cloud-user.pem

Later on you can easily login (also from other hosts which having the pem file) with:
ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -i
id_rsa_cloud-user.pem build-user@IP_or_HOSTNAME

3. build up packer build file:

vim /root/packer/centos.json


      "type": "qemu",
      "iso_url": "",
      "iso_checksum": "0d9dc37b5dd4befa1c440d2174e88a87",
      "iso_checksum_type": "md5",
      "output_directory": "output_centos_qcow2",
      "ssh_wait_timeout": "30s",
      "shutdown_command": "shutdown -P now",
      "disk_size": 5000,
      "format": "qcow2",
      "headless": true,
      "accelerator": "kvm",
      "http_directory": "httpdir",
      "http_port_min": 10082,
      "http_port_max": 10089,
      "ssh_host_port_min": 2222,
      "ssh_host_port_max": 2229,
      "ssh_username": "root",
      "ssh_password": "MySecretPassword",
      "ssh_port": 22,
      "ssh_wait_timeout": "900m",
      "vm_name": "tbade_test",
      "net_device": "virtio-net",
      "disk_interface": "virtio",
      "boot_wait": "5s",
      "qemuargs": [ "-serial", "file:serial.out" ],
        " append console=ttyS0,115200n8 ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg",
      "type": "shell",
      "inline": [
        "sleep 3",
        "rpm -ivh",
        "yum -y update",
        "yum -y install cloud-init cloud-utils-growpart dracut-modules-growroot",
        "echo \"NOZEROCONF=yes\" >> /etc/sysconfig/network",
        "adduser build-user",
        "echo 'build-user:MySecretPassword' |chpasswd",
        "mkdir /home/build-user/.ssh",
        "chown build-user:build-user /home/build-user/.ssh",
        "chmod 700 /home/build-user/.ssh",
        "echo \"build-user ALL=(ALL) ALL\" >> /etc/sudoers",
	"yum clean cache",
	"yum clean all"
      "type": "file",
      "source": "centos.json",
      "destination": "/root/centos.json",
      "source": "httpdir/centos6-ks.cfg",
      "destination": "/root/centos6-ks.cfg"
      "type": "file",
      "source": "",
      "destination": "/home/build-user/.ssh/authorized_keys"
     "type": "shell",
      "inline": [
        "chmod 600 /home/build-user/.ssh/authorized_keys",
        "chown build-user:build-user /home/build-user/.ssh/authorized_keys",
        "sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config",
	"echo package_upgrade: true >>/etc/cloud/cloud.cfg"

4. create the kickstarter file:

vim /root/packer/httpdir/centos6-ks.cfg 

and copy following inside (modify it for your needs e.g. lvm or classic hdd layout)

# url of CentOS Mirror
url --url=
repo --name=base --baseurl=
repo --name=updates --baseurl=
repo --name=epel --baseurl=
repo --name=cloud-init --baseurl=

#url --url
#repo --name=updates --baseurl=
lang en_US.UTF-8
keyboard us
rootpw MySecretPassword
# enable firewall, allow ssh
firewall --enabled --ssh
authconfig --enableshadow --passalgo=sha512
# selinux can be disabled during installation, please reenable thereafter
selinux --disabled
timezone Etc/UTC
%include /tmp/kspre.cfg
services --enabled=network,sshd/sendmail
# because of dependency problems we can not use --nobase (some essencial are missing)
#%packages --nobase
%packages --nobase
if [ -f "/dev/$bootdrive" ] ; then
  exec < /dev/tty3 > /dev/tty3
  chvt 3
  echo "ERROR: Drive device does not exist at /dev/$bootdrive!"
  sleep 5
  halt -f
cat >/tmp/kspre.cfg <> /etc/ssh/sshd_config
# at last to clean the image -->
yum clean all

5. Now I build a small bash script for automation (maybe you should download the centos iso and build it all the time against local iso, otherwise he downloads it all the time from repo):

vim /root/packer/

copy following inside:


if [ "$#" -ne 1 ]; then
    echo "Illegal number of parameters"
    echo "Please start script with:"
    echo "$0 imagename"
    echo "e.g. $0 my_first_image"
    exit 1

if [ -e /root/packer/output_centos_qcow2/ ];
    \rm -rf /root/packer/output_centos_qcow2/

if [ ! -e /root/packer/final_qcow2/ ];
    \mkdir -pv /root/packer/final_qcow2/

sed -i "s/\"vm_name\".*/\"vm_name\": \"$1\",/g" /root/packer/centos.json

export PACKER_LOG="yes" && export PACKER_LOG_PATH="packer.log" && packer build centos.json 

qemu-img convert -c /root/packer/output_centos_qcow2/"$1".qcow2 -O qcow2 /root/packer/final_qcow2/"$1".qcow2

now make the script executable:

chmod 775 /root/packer/

and execute it by typing (inside /root/packer)

./ testvm

to check the process you can type all the time one of the two log files (one for packer, one for installation):

tail -f serial.out


tail -f packer.log

Hopefully there are no errors 🙂 … enjoy

3 Gedanken zu „Build with packer qcow2 images (e.g. for OpenStack)“

  1. Hi,

    Thanks for the great write up.. It really useful to build a openstack image..

    Few corrections in your script,

    fi [ ! -e /root/packer/final_qcow2/ ];
    mkdir -pv /root/packer/final_qcow2/

    It should be,

    if [ ! -e /root/packer/final_qcow2/ ];
    mkdir -pv /root/packer/final_qcow2/

  2. I keep getting following error.

    qemu: Downloading or copying ISO
    qemu: Downloading or copying: file:///devops/packer/images/rhel-server-6.6-x86_64-dvd.iso
    ==> qemu: Creating hard drive…
    ==> qemu: Starting HTTP server on port 10084
    ==> qemu: Found port for communicator (SSH, WinRM, etc): 2226.
    ==> qemu: Looking for available port between 5900 and 6000
    ==> qemu: Found available VNC port: 5921
    ==> qemu: Starting VM, booting from CD-ROM
    qemu: WARNING: The VM will be started in headless mode, as configured.
    qemu: In headless mode, errors during the boot sequence or OS setup
    qemu: won’t be easily visible. Use at your own discretion.
    ==> qemu: Overriding defaults Qemu arguments with QemuArgs…
    ==> qemu: Waiting 5s for boot…
    ==> qemu: Connecting to VM via VNC
    ==> qemu: Typing the boot command over VNC…
    ==> qemu: Waiting for SSH to become available…

    Logs :
    2017/02/06 14:42:43 packer: 2017/02/06 14:42:43 [INFO] Attempting SSH connection…
    2017/02/06 14:42:43 packer: 2017/02/06 14:42:43 reconnecting to TCP connection for SSH
    2017/02/06 14:42:43 packer: 2017/02/06 14:42:43 handshaking with SSH

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.