Skip to content

Creating Images with libguestfs

The first step in building a marketplace app for HyperCloud is building the disk image that will be used to deploy the VM running your app.

We'll go over the process of building an image with libguestfs.

The final image will contain an operating system, customized to include the following:

  • A contextualization package ( one-context )

    When a VM is instantiated, it will be contextualized by HyperCloud. This is when the VM's individual configuration is applied, such as networking and SSH Keys.

    We will use the latest one-context package from the addon-context-linux repository.

  • A firstboot script

    This script will be executed when the VM is first booted up after being instantiated in HyperCloud.

    This can be used to perform any configuration or setup that cannot be applied at build time, such as editing VM's config files with any input provided by the user during setup.

  • App files

    Anything needed for your app, such as packages, code, templates, configuration files etc.

Preparation

To keep things simple, we'll create a Debian image with one-context and Grafana installed. The Grafana admin username & password will be set in HyperCloud.

Write a build.sh script.

It's not really a script

It's mostly a virt-builder command broken into multiple lines for readability, convenience, and reproducible results.

app_name='grafana'
root_password="correcthorsebatterystaple"

base_image='debian-11'
context_package='https://github.com/OpenNebula/addon-context-linux/releases/download/v6.6.0/one-context_6.6.0-1.deb'

image_format='qcow2'
output_file="$app_name-$base_image.$image_format"

virt-builder $base_image \
--format $image_format \
--install curl,gnupg \
--run-command "wget $context_package" \
--run-command 'apt update ; dpkg -i /root/one-context_*deb || apt-get install -fy' \
--run-command 'curl https://packages.grafana.com/gpg.key | apt-key add -' \
--run-command 'echo "deb https://packages.grafana.com/oss/deb stable main" | tee -a /etc/apt/sources.list.d/grafana.list' \
--install grafana \
--upload local-config/grafana.ini:/etc/grafana/grafana.ini \
--firstboot firstboot.sh \
--root-password password:$root_password \
--output $output_file && echo "Successfully built image: $output_file at $(date)"

This script refers to some files that don't exist yet, so we'll make them:

firstboot.sh

This runs when the image first boots up, after being instantiated in HyperCloud.

With the user's inputs during setup, we can finish configuring the app.

The output of this script will be written to /root/virt-sysprep-firstboot.log

#!/usr/bin/env bash

# Wait until one_env has been populated and source it to get the user's inputs
while [[ ! -s "/run/one-context/one_env" ]]; do
    echo "Waiting for one_env to be populated..."
    sleep 1
done

source /run/one-context/one_env

sed -i "s/admin_user =.*#MANAGED-BY-HC/admin_user = $GRAFANA_ADMIN_USERNAME #MANAGED-BY-HC/g" /etc/grafana/grafana.ini
sed -i "s/admin_password =.*#MANAGED-BY-HC/admin_password = $GRAFANA_ADMIN_PASSWORD #MANAGED-BY-HC/g" /etc/grafana/grafana.ini

systemctl enable grafana-server --now

systemctl status grafana-server | cat

There is another option.

The firstboot script is only run once, and in this example we use it to configure the Grafana username and password,

If the VM is already running and the password is changed in hypercloud, that change will not be reflected in the VM, as this script has already been run.

one-context-refresh is able to keep the configuration updated with new changes in hypercloud, Refer to instructions at Integration into HyperCloud App Image

local-config/grafana.ini

[security]
admin_user = admin #MANAGED-BY-HC
admin_password = hypercloud?m0nitoring #MANAGED-BY-HC

Build

With all our files in place, we can run the build script:

build.sh

Successful output:

[   1.0] Downloading: http://builder.libguestfs.org/debian-11.xz
[   1.6] Planning how to build this image
[   1.6] Uncompressing
[   5.5] Converting raw to qcow2
[   6.3] Opening the new disk
[   9.6] Installing packages: curl gnupg
[  30.7] Running: wget https://github.com/OpenNebula/addon-context-linux/releases/download/v6.6.0/one-context_6.6.0-1.deb
[  31.3] Running: apt update ; dpkg -i /root/one-context_*deb || apt-get install -fy
[  32.2] Running: curl https://packages.grafana.com/gpg.key | apt-key add -
[  32.7] Running: echo "deb https://packages.grafana.com/oss/deb stable main" | tee -a /etc/apt/sources.list.d/grafana.list
[  32.7] Installing packages: grafana
[  39.2] Uploading: local-config/grafana.ini to /etc/grafana/grafana.ini
[  39.3] Installing firstboot script: firstboot.sh
[  39.4] Setting passwords
[  40.0] Finishing off
                   Output file: grafana-debian-11.qcow2
                   Output size: 6.0G
                 Output format: qcow2
            Total usable space: 6.4G
                    Free space: 5.0G (77%)
Successfully built image: grafana-debian-11.qcow2 at Wed 22 Feb 13:57:19 GMT 2023

You can now upload the built image to HyperCloud, and Create your VM Template