Custom Cloud Images for OpenStack pt3

Hi folks,

In the last 2 posts we covered creating a custom cloud image for RHEL, then editing it with “guest fish”. Today, I’ll introduce you to another tool called “oz” as we continue our journey into creating custom cloud images. The way we did things last time using “virt-manager” is fine if you’re doing an image here or there.. but let’s face it, walking through anaconda is cumbersome. Granted, I showed you how to do things using the CLI and kickstart, but I think you’ll like this way even better.

Let me clear one one thing, and this is really good – this method works for RHEL, Fedora, and CentOS. You’ll see how as we move along. 🙂

I seem to remember that the “oz” tool was included in RHEL-OSP, at least in the older versions, but it does not seem to be part of the current release. That’s ok, it’s easy enough to put things together. Much like the previous example from the first post, we do want a sandbox environment. If you’re going to be building mostly RHEL-based cloud images, then build a RHEL-based KVM host. In addition to the packages that I suggested in part 1 of this series, you’ll need to install 2 more packages. In my case, this pulled in additional packages for dependency. No problem:

# yum -y install git rpm-build

Next, pull in the git environment relevant to oz

# git clone https://github.com/clalancette/oz.git

Then go into the oz directory, and create the RPM:

# cd oz 
# make rpm

And you’ll find your shiny new oz RPM here – go ahead and install it:

# cd ~/rpmbuild/RPMS/noarch
# rpm -ivh oz-*

NOTE: I still ended up having to add one more package (python-libguestfs) for dependency, but no big deal.

Next, we need to create or edit an existing template. Chris Lalancette (the git link above for oz is his) has created several templates that you can use and/or edit. I’m going to take things just a little further than basic, as that is where we left things last week. Lets look at the following template:

rhel-7-cloud-base.tdl

<template>
 <name>rhel-7_x86_64</name>
 <description>RHEL 7.1 template</description>
 <os>
   <name>RHEL-7</name>
   <version>1</version>
   <arch>x86_64</arch>
   <rootpw>Ch4ng3M3S00n!</rootpw>
   <install type='iso'>
     <iso>file:///path/to/rhel7.iso</iso>
   </install>
 </os>
 <commands>
   <command name='console'>
      sed -i 's/ rhgb//g' /boot/grub2/grub.cfg
      sed -i 's/ quiet//g' /boot/grub2/grub.cfg
      sed -i '/linux16/ s/$/ console=tty0 console=ttyS0,115200n8/' /boot/grub2/grub.cfg
   </command>
   <command name='update'>
      echo -n > /etc/udev/rules.d70-persistent-net.rules
      echo 'NOZEROCONF=yes' >> /etc/sysconfig/network
   </command>
 </commands>
</template>

It should actually be fairly easy to follow. We have a filename with a “.tdl” extension. We a markup language that is easy enough to follow. Note that there can be several “command” sections. They don’t need to be limited to single lines – they can be highly complex BASH scripts.

To create our custom cloud image we type the following:

# oz-install -d3 -u rhel-7-cloud-basic.tdl

NOTE: If you get any kind of parsing error or XML related error, then you’ll likely need to copy and paste from one of the original tdl files on git, then edit. The XML parsing is the only finicky part of this method.

That will create an image with the most basic of deployments. It will take several minutes, so kick it off right before a break or meeting. When you’re done, you would then convert the image from its current “raw” disk format to qcow2 format:

qemu-img convert /var/lib/libvirt/images/rhel-7.dsk -O qcow2 /tmp/rhel-7.qcow2

Then repeat the final steps as defined in part 1 of this series:

  1. Upload the image to OpenStack (test run only, not final)
  2. Test the image to be sure services are started/stopped/installed and that networking comes up properly. I find that I have to change my network interface from whatever it gives me to “eth0”. The networking won’t come up for me with eth0 on the sandbox network, but it comes up as expected on the OpenStack network.
  3. Remove the image from OpenStack once you’ve either verified that it works as needed or you’ve verified the few edits to be made.
  4. Use “virt-sysprep” to make the image generic & “virt-sparsify” to make the image as small as possible
    # virt-sysprep -a /tmp/rhel-7.qcow2
    # virt-sparsify —compress /tmp/rhel-7.qcow2 /tmp/rhel-7-cloud-base.qcow
  5. Upload the final version of the image to OpenStack

Ok, so that’s pretty cool. But what if you want just a little more control over some things. Like say, packages. Ah, well, the template file still has you covered! We can place “repositories” and “packages” sections in just before the “commands” section (and after the </os>):

<repositories>
    <repository name=‘rhel-7-server-rh-common-rpms'>
       <url>http://path/to/repo</url>
       <signed>yes</signed>
    </repository>
 </repositories>
 <packages>
   <package name='cloud-init'/>
 </packages>

Not enough control? Ok, that’s fine. Lets add in our old friend kickstart. Lets edit our template first, though.

Let’s change the install section from this:

 <install type='iso'>
    <iso>file:///path/to/rhel7.iso</iso>
 </install>

to this:

 <install type='url'>
    <url>http://path/to/install/tree</url>
 </install>

(If you have a kickstart file, you likely have your package media available over HTTP.. If not, you can keep it as ISO.)

Then create your kickstart file. Remember though, this is a cloud image. Keep it simple and small, like the following:

rhel-7-base.ks

install
text
key --skip
keyboard us
lang en_US.UTF-8
skipx
network --device eth0 --bootproto dhcp
rootpw Ch4ng3M3S00n!
firewall --disabled
authconfig --enableshadow --enablemd5
selinux —enabled
timezone --utc America/New_York
bootloader --location=mbr --append="console=tty0 console=ttyS0,115200"
zerombr yes
clearpart --all
part /boot --fstype ext4 --size=200
part swap --size=512
part / --fstype ext4 --size=1024 --grow

reboot

%packages
@core
@base

%post
echo “oz is the coolest” >> /etc/motd

Obviously, the kickstart will allow you absolute control over the install. The command to build the image from the kickstart file is:

# oz-install -p -u -d3 -a rhel7-cloud.ks rhel-7-cloud-basic.tdl

And just like before, once you kick that off, go make a sandwich or cup of coffee or whatever. It’s going to take a few minutes. How long? It depends on your sandbox host. But it’s not horrible. Once it’s complete, go through the finalization steps that I outlined above (virt-sysprep, virt-sparsify) and then upload the image to Glance.

Hopefully you’ve also seen that the only adjustments that you would need to make for Fedora or CentOS would be to swap out the ISO images and adjust the repo paths. Everything else is the same.

Hope this helps,

Captain KVM

2 thoughts on “Custom Cloud Images for OpenStack pt3”

  1. Hi Jon,
    First, I think this is a great video (https://www.youtube.com/watch?v=rw44DCbj0WE). I have been looking around for installation guide and this is great.unfortunately, your screen is too small to read 🙁
    Also I am trying to do the same but running into foreman-proxy.service failure even when my hostname and facter fqdn are the same. Any suggestions?

    1. Hi Uma,

      When viewing the video, view it in “full screen mode”. That should help tremendously. As for the proxy failure, watch /var/log/messages (and other relevant log files) while the process and failure is going on.

      Captain KVM

Agree? Disagree? Something to add to the conversation?