Building VM images using Danube Cloud Factory (part 1)

Danube Cloud on SmartOS
22. February 2017
Building VM images using Danube Cloud Factory (part 2)
2. March 2017

Building VM images using Danube Cloud Factory (part 1)


Let’s start with some theory:

  • An image is a copy of virtual machine’s disk. It is used to quickly spawn virtual machines without the need to install an operating system or configure services.
  • In the case of Danube Cloud (and other SmartOS-related software), an image is a ZFS data stream (usually compressed) + an image manifest (metadata).
  • Images are served by an image server (usually via HTTP(S)) and imported directly to a compute node’s zpool. The image server should be compatible with Image API (IMGAPI).
  • Each Danube Cloud installation uses by default its local (intermediate) image server (esdc-shipment).
  • Images used in Danube Cloud are compatible with images from or

At Erigones, we are building images daily. Mainly because some images are part of our headnode USB image. And of course, we do this automatically by using our Ansible-based project – esdc-factory. The hardest thing when creating images is that you have to take care of them and release new versions periodically. That’s why automation is so important here. And the best thing with esdc-factory is that by using Ansible roles and tasks, image build scripts can share a lot of code and the code can be re-used for making other images as well.

In this part of the two-part tutorial, we will first prepare the esdc-factory environment for creating images and build one of the images. In the second part, we will create a playbook for a new VM image (GitLab CE on CentOS) and build it.


The prerequisites are listed in the README.rst in the esdc-factory repo, but let’s quickly go through them. You will need one or two network-connected Linux/Unix machines:

  • buildnode remote host – this must be a SmartOS or Danube Cloud compute node capable of running KVM machines and/or zones (depends on what kind of images are you going to build). If you are going to use SmartOS, please make sure that you have Python installed and available on the node.
  • builder local host – this is a Linux/Unix machine that has the esdc-factory repo checked out. This can be the same machines as the buildnode. The following software must be installed on the system:
    • git
    • Ansible >= 2.0
    • GNU make
    • sshpass
    • OpenSSH client
    • a working ssh-agent with loaded build_ssh_key (for running git clone on the remote host, see below)
    • a running web server serving build_base_url (this can be a simple web server, see below)


You don’t have to configure anything on the buildnode; all configuration steps are performed on builder host:

Web server
[user@builder ~]$ mkdir data; cd data
[user@builder ~/data]$ python -m SimpleHTTPServer 8000
SSH agent
[user@builder ~]$ ssh-keygen -t rsa; eval "$(ssh-agent)"; ssh-add
[user@builder ~]$ git clone; cd esdc-factory/etc
[user@builder ~/esdc-factory/etc]$ cp hosts.sample.cfg hosts.cfg
[user@builder ~/esdc-factory/etc]$ cp config.sample.yml config.yml

Let’s edit both configuration files:


This is file has only three lines (including the [build] configuration group). You have to set the IP addresses of builder and buildnode and optionally set the ansible_python_interpreter if Python is in a non-standard PATH.

builder ansible_ssh_host= ansible_connection=local
buildnode ansible_ssh_host= ansible_python_interpreter=/opt/local/bin/python


You have to adjust these configuration variables to reflect your reality:

  • build_base_url: '' – URL pointing to the web server you have previously configured
  • build_base_dir: '/home/user/data' – Full path to the doc root directory served by the web server
  • build_ssh_key: 'ssh-rsa blabla user@host' – The SSH key on builder
  • build_image_password: 'passw0rd' – Password set for the root user in base images
  • build_disk_compression: lz4
  • build_nic_tag: admin – NIC tag of the interface on buildhost which will be used by VMs to access the network
    • The network configuration below depends on your network setup
  • build_gateway: – Network gateway of VMs for the time of image building
  • build_netmask: – Network mask of VMs for the time of image building
  • build_resolvers: [ '', '']
  • build_ips: – This is a dictionary, which can be used to configure a custom IP address for every built VM image. It has to be here even if it is empty
  • build_ip: – Default IP address of every VM
  • build_vnc_ports: – This is a dictionary, which can be used to configure a custom VNC port for every built VM image. It has to be here even if it is empty
  • build_vnc_port: 60000 – Default VNC port of every virtual machine


The main part of the esdc-factory repo is the ansible directory, which contains all the build playbooks, roles, tasks, and variables. For now, let’s just test whether everything is working fine. There is a comfortable script and Makefile for running the build playbooks. Just type make help to see all options:

[user@builder ~/esdc-factory]$ make help

First, you have to initialize the build_base_dir directory structure:

[user@builder ~/esdc-factory]$ make init

Now you can build an image. Let us test it by building a KVM CentOS 7 base image:

[user@builder ~/esdc-factory]$ make base-centos-7

In the next part of this tutorial, we will dive deeper into the Ansible playbooks, tasks and roles and create a custom build playbook.

Daniel Kontšek
Daniel Kontšek
CTO, Danube Cloud

Leave a Reply

Your email address will not be published. Required fields are marked *