Packer OVA

Recently I have started using Packer to build AMI images. It works like a champ, but then I tried to make VMWare images and it produced machine images, not machine exports. This makes the exports nearly useless. However, with a little post-processing magic this can be fixed.

There is a GoLang based ovftool post processor that already does this, but it needs to be compiled and put into the packer plugins dir. Nothing that the plugin does requires GoLang, so I whipped up a quick bash version that I could include with the packer script.

VMWare comes bundled with a tool called ovftool which will convert a machine image into a OVA file. It has a lot of useful options so I recommend you reading the manual page. Basically it take a vmx file and its associated files and makes a OVA: ovftool sourc.vmx dest.ova.

I turned this into a script that can be called as a post processor from packer. There are a number of protections, but the important items are:

  1. line 5: Ensures ovftool is on the path
  2. line 19: This avoids an interesting behavior (read bug) of Packer where the the inline script is called multiple times; once per file in the output directory.
  3. line 33: Removes the floppy which is used to install some VMWare drivers.
  4. line 37: Removes the CD-Room that is also used to install some VMWare drivers.
  5. line 42: Uses ovftool to create an OVA.
 1 #!/bin/bash
 2 
 3 # Make sure ovftool is in the path.
 4 # On the mac:
 5 PATH=/Applications/VMware\ Fusion.app/Contents/Library/VMware\ OVF\ Tool/:$PATH
 6 
 7 # I need to be given the output path and vmname.
 8 if [ -z "$1" -o -z "$2" ]; then
 9   echo "output path and vm-name are required"
10   exit 1
11 fi
12 
13 DIR=$1
14 NAME=$2
15 
16 cd $DIR
17 
18 # I may be called multiple times.  If so bail early
19 if [ -f "${NAME}.ova" ]; then
20   echo "OVA already created, skipping"
21   exit 0
22 fi
23 
24 if [ ! -f "${NAME}.vmx" ]; then
25   echo "no ${NAME}.vmx file found"
26   exit 1
27 fi
28 
29 # bail on error
30 set -e
31 
32 # remove floppy
33 sed '/floppy0\./d' ${NAME}.vmx > 1.tmp
34 echo 'floppy0.present = "FALSE"' >> 1.tmp
35 
36 # remove CD
37 sed '/ide1:0\.file/d' 1.tmp | sed '/ide1:0\.present/d' > 2.tmp
38 echo 'ide1:0.present = "FALSE"' >> 2.tmp
39 
40 mv 2.tmp ${NAME}.vmx
41 
42 ovftool -dm=thin --compress=1 ${NAME}.vmx ${NAME}.ova

Add this script to the packer JSON files.

{
    "variables": {
        "output_path": "output",
        "vm_name": "data-collector",
        ...
    },

    "builders": [{
        "output_directory": "{{ user `output_path` }}",
        "vm_name": "{{ user `vm_name` }}",
        ...
    }],

    "_comment": "Create an OVA because packer cannot.",
    "post-processors": [{
        "type": "shell-local",
        "inline": ["post-ova.sh {{user `output_path`}} {{user `vm_name`}}"]
    }]
}

The following isn’t necessary, but I like to move the ova after creation.

#!/bin/bash

mkdir -p dist &&
packer build ubuntu.json &&
mv output/*.ova dist &&
rm -rf output

comments powered by Disqus