Digging Deep with diskimage-builder pt 1

Digging Deep with diskimage-builder pt 1

I’d like to dig deep, on diskimage-builder – the OpenStack tool for creating customized images to boot. In this three part series, I’ll be primarily doing this to create UEFI bootable baremetal images. We’ll start with RHEL 7.5, as this is my favorite. Join me!

Down with the DIB

So you want to UEFI boot bare metal nodes in OpenStack? You want to build a customized image of RHEL to do this?  There are many ways to achieve this, from the janky to the kinda janky – to the fully automated and rocking way.  We’re going for the later here. We don’t have much time for jank, we’re looking to build a RHEL 7.5 image with diskimage-builder. For the sake of my fingers, I have a lot of jazz to play after this, let’s just refer to diskimage-builder as DIB.  Plus – we all know there aren’t enough acronyms in this field.

DIB has a fairly large scope, as it portends to be able to allow you to build bootable images for the following Linux distros:Centos 6, 7

   Debian 8 (“jessie”)
   Fedora 26, 27
   RHEL 6, 7
   Ubuntu 12.04 (“precise”), 14.04 (“trusty”)
   openSUSE Leap 42.2, 42.3 and Tumbleweed (opensuse-minimal only)

That’s a whole-lotta Linux there. Of course, here, we only really care about Fedora, CentOS and RHEL. I may be able to show you the Ubuntu version of this, but let’s see how far we can get.

Ordinarily, you’d think this process would be pretty straight forward, but as with many open source tools, the amount of complexity is directly proportionate to the amount of options you get. And here, my dear Linux friends, we have a ton of options.

It’s nice to have goals

So I’m thinking the best way to approach this is to scope this to a few specific goals. Here’s what I have in mind:

  1. Create a bootable UEFI RHEL 7 image
  2. Register it with the Red Hat customer portal during the build
  3. Subscribe to some repos
  4. Install some packages
  5. Run some custom code therein
  6. Create a baremetal instance – booting off of UEFI

These are our goals, let’s get to them and see where this leads us. Our voodoo will be strong, as we have lot of ground to cover — and many elements to explore.

The Creator

First up,  let’s make sure we start in the right place. I’m building here from my Red Hat OpenStack 13  Director environment. DIB is part of this environment, so building here won’t require us to install anything. Additionally, we’ll be uploading our images into glance in the undercloud, and just booting a baremetal node with ironic to test.

Let’s start by creating a working directory in the stack user’s home:

Next, we’ll just create a simple bash script to run our build:

Ok – let’s step through this:

  1. We’re sourcing our portal credentials, which should be in an external file called secret.sh, in the following format:
  2. Next, we set the set the REG_METHOD variable to  portal
  3. We create a comma separated list of repos we’d like to enable using the REG_REPOS variable – these are examples of the bare minimum for RHEL 7
  4. We set REG_AUTO_ATTACH to true. This sets our image up to use the pool-id and repos
  5. Next, we want to get the latest RHEL 7.5 KVM image from https://access.redhat.com, save it locally, and refer to it using the DIB_LOCAL_IMAGE variable.
  6. Set the subscription’s registered machine name for this image using the REG_MACHINE_NAME variable
  7. Finally, we kick off the build using the openstack overcloud image build command, referencing our custom rhel7.yamlheat template.

Our rhel7.yaml template looks like this:

This is yaml, so it’s important that you obey the yaml syntax structure. Let’s go over each of the attributes:

imagename – This is what your resulting image will be called

type – the ouput format of your image – we wan’t qcow2 for OpenStack

arch – this is the architecture you’ll be booting this image on – amd64 is ours

distro – this is a DIB keyword that specifically refers to Red Hat Enterprise Linux 7

elements – A list of elements you’d like to enable for your image. DIB uses this construct to modify your image and customize it. The full list of available elements can be found here: https://docs.openstack.org/diskimage-builder/latest/elements.html

Rather than go into detail on each one of these, I’ll leave it to the reader to do so in their spare time. This is quite a lot of information, some of which is specific to the distrothat you’re using. I suggest you look at some of these to gain better insight into this process. Suffice it to say that grub2and baremetal are key elements here. Specifically, baremetalwill build three binaries for us – a qcow2 image, a vmlinuz image and an initrd image. We’ll load all of these into glance and use them to UEFI boot our baremetal node.

packages –  A list of package names we’d like to install into the image. These are synonymous with yum install package-name

options – A list of options to pass to DIB's disk-image-create command. Here, we set the minimum in GB that the tool will use in tmpfs to build the image.

environment – These will set specific environment variables for us – in this case, our filesystem and python version. For this image, these are safe defaults.

Time to build

So, we have our yaml, our build script and our base image. Let’s go ahead and run build-rhel.sh to build our image.

I prefer to run tmux before I do this, in case anything happens to our terminal session, be it local or remote. You can also use screen, if you’re more accustomed to it.

Once this image builds, and it will take a while, you should end up with a few files:

rhel-7.5.qcow2 – this is the actual image of the filesystem

rhel-7.5.initrd – the initial ramdisk image you’ll boot on your baremetal uefi boot

rhel-7.5.vmlinuz – the compressed linux kernel image, used on your baremetal node

Get thee into Glance

So we have our image, and we’re ready to test it on a baremetal node. What need to do first, is to load it into glance in the undercloud. Additionally, we’ll need to associate our initrd and vmlinuz images with our qcow2 as well. This can be accomplished thusly:

NOTE: I’m loading these into my undercloud here – you can do the same with your overcloud, just be sure to source the right rc file in the stack user’s home directory

Let’s start with the kernel:

We’re setting the variable KERNEL_ID to be our rhel-7.5.vmlinuz file.

Next, let’s work with the initial ramdisk:

This will set the RAMDISK_ID to our newly created rhel-7.5.initrd file.

Finally, we’ll load our image into glance:

We should see something list return, or using the command openstack image list

Boot me up, Scotty

Ok, so we’re ready to boot with our image and test UEFI booting a baremetal node in Red Hat OpenStack 13. I’m going to use our compute flavor, as I’ve already introspected my baremetal node and tagged it as a compute node:

You should now be able to see this boot at the console. Good times!


I’d be remiss if I didn’t mention a couple of items –

  1. If you kill your build, or if it fails on you,  you will end up with a bunch of tmpfs filesystems taking up all of your memory. If you don’t unmount these prior to re-starting your next build, you’ll end up in a world of hurt. I actually took down my undercloud by doing this. Your best course of action is lazy unmount them like so – sudo umount -l /tmp/dib*
  2. Watch your disk space here – you don’t want to fill up your root partition on the undercloud. This can cause all sorts of whacky stuff to happen and potentially destroy your undercloud. df -h is your friend
  3. Chmod 0600 your secrets file. As we’re doing this with bash and have this file with your secrets as an open text file – at least chmod it with reasonable defaults to keep it unreadable to prying eyes. Better yet, remove it after your build.

Closing Thoughts

There’s a lot to take in here, and a lot more to come. I’ve decided to break this into three different posts. This is just an introduction of sorts. Stay tuned with a post on developing your own elements for DIB, as well as a final post about integrating Ansible – Red Hat’s awesome orchestration tool.


Leave a Reply

%d bloggers like this: