I spent yesterday seeing if virt-builder could be used to safely build or test packages in custom virtual machines. It’s a bit complicated, but the answer is yes.
Building a libvirt RPM takes 6 minutes, versus about 2 minutes when run locally. Most of the overhead is fixed, ie. it would be the same overhead whatever package you were building. Virt-builder takes just over 2 minutes to run.
The whole script is at the bottom, but I’ll just talk about the virt-builder command itself. Here is the command with my comments added:
I’m running virt-builder from git because I added a few features to make this easier:
$guest_type is the base guest, eg. fedora-19:
Select the size and temporary output file:
Don’t bother relabelling as we’re not going to use SELinux:
/home/build directory which contains the SRPM, the build script (a small wrapper around rpmbuild), and a configuration file that has the name of the SRPM file for the build script.
--write options are new features which are not in any released version of virt-builder yet:
Install the basic build system and the build dependencies of the SRPM:
--run-command "yum-builddep -y /home/build/$srpm"
When the guest boots, we create a builder user account, run rpmbuild, and then power off the machine:
--firstboot-command 'useradd -m -p "" builder'
--firstboot-command 'chown builder.builder /home/build'
--firstboot-command 'su - builder -c /home/build/build-it.sh'
The entire build script runs virt-builder as above, then runs qemu to boot the VM, then copies out the resulting RPMs.
# Use a homebrew compile of libguestfs from git.
# This is the Fedora platform we want to build on.
# The SRPM we want to build.
# The build script.
# Because virt-builder copies the build script permissions too.
chmod +x $build_script
# How much guest memory we need for the build:
# Run virt-builder.
# Use a long build path to work around RHBZ#757089.
$d/run $d/builder/virt-builder \
--size 20G \
--output /tmp/$guest_type.img \
--delete /.autorelabel \
--mkdir /home/build \
--upload $srpmdir/$srpm:/home/build \
--upload $build_script:/home/build \
--write "/home/build/config:srpm=$srpm" \
--install /usr/bin/yum-builddep,/usr/bin/rpmbuild,@buildsys-build,@development-tools \
--run-command "yum-builddep -y /home/build/$srpm" \
--firstboot-command 'useradd -m -p "" builder' \
--firstboot-command 'chown builder.builder /home/build' \
--firstboot-command 'su - builder -c /home/build/build-it.sh' \
# Run qemu directly. Could also use virt-install --import here.
-machine accel=kvm:tcg \
-cpu host \
-m 2048 \
-smp 4 \
-net user \
-serial stdio \
# The build ran OK if this contains the magic string (see $build_script).
virt-cat -a /tmp/$guest_type.img /root/virt-sysprep-firstboot.log
# Copy out the SRPMs & RPMs.
rm -rf /tmp/result
virt-copy-out -a /tmp/$guest_type.img /home/build/RPMS /home/build/SRPMS \
# Leave the guest around so you can examine the /home/build dir if you want.
# Or you could delete it.
The build-it script is just a small wrapper around rpmbuild:
# This runs inside the throwaway guest at first boot.
# Build from SRPM.
rpmbuild --define '_topdir /home/build' --rebuild /home/build/$srpm
# If we get this far, everything built successfully.
# This string is detected in the guest afterwards.
echo '=== BUILD FINISHED OK ==='