Add image boot testing to pipeline

This patchset will ensure pipeline fails if any of the images built are
not bootable.

Use qcow snapshots for testing so the original image is not altered or
tainted for publication.

Change-Id: Ide7be563c5951151694057ab66980821c95336cd
This commit is contained in:
Anderson, Craig (ca846m) 2021-09-07 10:48:05 -07:00
parent ed0be4e13d
commit bfbe3d6c1f
2 changed files with 74 additions and 8 deletions

View File

@ -37,6 +37,7 @@ SKIP_LIVECDCONTENT_ROLE ?=
IMAGE ?= ${DOCKER_REGISTRY}/${IMAGE_PREFIX}/${IMAGE_NAME}:${IMAGE_TAG}-${DISTRO}
PROXY ?=
NO_PROXY ?= localhost,127.0.0.1
BOOT_TIMEOUT ?= 300 # Image boot validation timeout. Set to 0 to disable to make console available for manual debugging.
.PHONY: help build images cut_image package_qcow run clean
@ -109,7 +110,7 @@ ifneq ($(PROXY), )
export NO_PROXY=$(NO_PROXY)
endif
ifeq ($(IMAGE_TYPE), iso)
sudo -E tools/cut_image.sh $(IMAGE_TYPE) $(WORKDIR)/iso $(IMAGE) "$(PROXY)" "$(NO_PROXY)"
sudo -E tools/cut_image.sh $(IMAGE_TYPE) $(WORKDIR)/iso $(IMAGE) $(BOOT_TIMEOUT) "$(PROXY)" "$(NO_PROXY)"
else
# Assemble all images based on configs defined in each subdirectory
# Trailing / allows proper function with symlinks
@ -124,7 +125,7 @@ else
export qcow_params="$(QCOW_BUNDLE)/$$subdir/qcow-vars.yaml"
# Image name
export img_name=$$subdir.qcow2
sudo -E tools/cut_image.sh $(IMAGE_TYPE) $(QCOW_BUNDLE) $(IMAGE) "$(PROXY)" "$(NO_PROXY)"
sudo -E tools/cut_image.sh $(IMAGE_TYPE) $(QCOW_BUNDLE) $(IMAGE) $(BOOT_TIMEOUT) "$(PROXY)" "$(NO_PROXY)"
done
endif
@ -169,4 +170,5 @@ clean:
sudo -E tools/multistrap.sh clean
find $(WORKDIR) -name "*.iso" -exec rm {} \; >& /dev/null
find $(WORKDIR) -name "*.qcow2" -exec rm {} \; >& /dev/null
find $(WORKDIR) -name "*.snapshot" -exec rm {} \; >& /dev/null
find $(WORKDIR) -name "*.md5sum" -exec rm {} \; >& /dev/null

View File

@ -15,10 +15,12 @@ build_type="${1:-qcow}"
host_mount_directory="${2:-$BASEDIR/../manifests}"
# Docker image to use when launching this container
image="${3:-port/image-builder:latest-ubuntu_focal}"
# boot timeout for image validation
boot_timeout="${4:-300}"
# proxy to use, if applicable
proxy="$4"
proxy="$5"
# noproxy to use, if applicable
noproxy="$5"
noproxy="$6"
workdir="$(realpath ${host_mount_directory})"
@ -54,6 +56,7 @@ install_pkg libvirt-daemon-system
install_pkg libvirt-clients
install_pkg cloud-image-utils
install_pkg ovmf
install_pkg util-linux
type docker >& /dev/null || (echo "Error: You do not have docker installed in your environment." && exit 1)
sudo docker version | grep Community >& /dev/null || (echo "Error: Could not find Community version of docker" && \
echo "You must uninstall docker.io and install docker-ce. For instructions, see https://docs.docker.com/engine/install/ubuntu/" && \
@ -121,9 +124,11 @@ outputFileName: $img_name" > ${qcow_config}
--env no_proxy=$noproxy \
--env NO_PROXY=$noproxy \
${image} < ${qcow_config}
# Create cloud-config ISO for testing
cloud_init_config_dir='assets/tests/qcow/cloud-init'
sudo -E cloud-localds -v --network-config="${cloud_init_config_dir}/network-config" "${workdir}/${img_name}_config.iso" "${cloud_init_config_dir}/user-data" "${cloud_init_config_dir}/meta-data"
disk1="--disk path=${workdir}/${img_name}"
snapshot_path="${workdir}/${img_name}.snapshot"
disk1="--disk path=${snapshot_path}"
disk2="--disk path=${workdir}/${img_name}_config.iso,device=cdrom"
network='--network network=default'
else
@ -131,30 +136,67 @@ else
exit 1
fi
logfile=/var/log/${img_name}.log
imagePath=$(echo $disk1 | cut -d'=' -f2 | cut -d',' -f1)
echo Image successfully written to $imagePath
sudo -E virsh destroy ${img_name} 2> /dev/null || true
sudo -E virsh undefine ${img_name} --nvram 2> /dev/null || true
# Use snapshot so original image is not altered during testing
if [[ $build_type == qcow ]]; then
# Clean previous snapshot
if [ -f "${snapshot_path}" ]; then
sudo -E rm "${snapshot_path}"
fi
sudo -E qemu-img create -f qcow2 -b "${workdir}/${img_name}" "${snapshot_path}"
fi
cpu_type=''
kvm-ok >& /dev/null && cpu_type='--cpu host-passthrough' || true
virt_type=qemu
if kvm-ok >& /dev/null; then
cpu_type='--cpu host-passthrough'
virt_type=kvm
fi
if ! sudo -E virsh net-list | grep default | grep active > /dev/null; then
network='--network none'
fi
# Default to 4 vcpus
num_vcpus=4
# Reduce the vcpu count in the event physical cpu count is less
num_pcpus=$(($(lscpu -e | wc -l) - 1))
if [[ ${num_pcpus} -lt ${num_vcpus} ]]; then
echo Reducing num_vcpus to ${num_pcpus}
num_vcpus=${num_pcpus}
fi
# Exit if the number of vcpus is less than 1, i.e. there is a problem
if [[ ${num_vcpus} -lt 1 ]]; then
echo ERROR: num_vcpus of ${num_vcpus} is less than 1
exit 1
fi
serial=''
perform_boot_test="false"
# User may set boot_timeout to 0 to skip boot test and allow for manual "virsh console" debugging
if [ $boot_timeout -gt 0 ]; then
serial="--serial file,path=${logfile}"
perform_boot_test="true"
fi
xml=$(mktemp)
sudo -E virt-install --connect qemu:///system \
--name ${img_name} \
--memory 1536 \
${network} \
${cpu_type} \
--vcpus 4 \
--vcpus ${num_vcpus} \
--import \
${serial} \
${disk1} \
${disk2} \
${virt_type} \
--virt-type ${virt_type} \
${uefi_boot_arg} \
--noautoconsole \
--graphics vnc,listen=0.0.0.0 \
@ -164,3 +206,25 @@ virsh define $xml
echo Virsh definition accepted
echo Image artifact located at $imagePath
if [[ $perform_boot_test = "true" ]]; then
echo Starting ${img_name} ...
virsh start ${img_name}
successful_boot=false
time_waited=0
while [ $time_waited -lt $boot_timeout ]; do
if sudo cat ${logfile} | grep "login:" >& /dev/null; then
echo ${img_name} boot test SUCCESS after $time_waited seconds.
successful_boot=true
break
fi
sleep 5
time_waited=$(($time_waited + 5))
done
echo Stopping ${img_name} ...
virsh destroy ${img_name}
if [ $successful_boot != "true" ]; then
echo ${img_name} boot test FAIL after $boot_timeout second timeout.
exit 1
fi
fi