From 5194a5b0aa515f6a196fafab29e4bd4be19a8451 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 4 Feb 2022 16:54:02 +0100 Subject: [PATCH] CI: use a custom cirros partition image instead of the default Cirros partition images are not compatible with local boot since they don't ship grub (nor a normal root partition). This change adds a script that builds a partition image with UEFI artifacts present. It still cannot be booted in legacy mode, but it's a progress. Set the tempest plugin's partition_netboot option. We need it to inform the tempest plugin about the ability to do local boot. This option already exists but is never set. Also set the new default_boot_option parameter, which will be introduced and used in Iaba563a2ecbca029889bc6894b2a7f0754d27b88. Remove netboot from most of the UEFI jobs. Conflicts: devstack/files/bindep.txt zuul.d/ironic-jobs.yaml Change-Id: I15189e7f5928126c6b336b1416ce6408a4950062 (cherry picked from commit bbceca562e0b552cd2fc33b2833931ab3cbbfce5) --- bindep.txt | 6 +- devstack/files/debs/ironic | 1 + devstack/files/rpms/ironic | 1 + devstack/lib/ironic | 49 +++++++++++++ .../tools/ironic/scripts/cirros-partition.sh | 69 +++++++++++++++++++ zuul.d/ironic-jobs.yaml | 5 +- 6 files changed, 128 insertions(+), 3 deletions(-) create mode 100755 devstack/tools/ironic/scripts/cirros-partition.sh diff --git a/bindep.txt b/bindep.txt index 70797ab892..8da5ea1f44 100644 --- a/bindep.txt +++ b/bindep.txt @@ -85,9 +85,13 @@ docker-io [platform:rpm imagebuild] gnupg [imagebuild] squashfs-tools [platform:dpkg platform:redhat imagebuild] squashfs [platform:suse imagebuild] +# For custom partition images +kpartx [devstack] libguestfs0 [platform:dpkg imagebuild] -libguestfs [platform:rpm imagebuild] +libguestfs [platform:rpm imagebuild devstack] +libguestfs-tools [platform:dpkg devstack] python-guestfs [platform:dpkg imagebuild] +qemu-img [platform:rpm devstack] # for TinyIPA build wget [imagebuild] python-pip [imagebuild] diff --git a/devstack/files/debs/ironic b/devstack/files/debs/ironic index 49b0689d71..455bf0dfef 100644 --- a/devstack/files/debs/ironic +++ b/devstack/files/debs/ironic @@ -17,6 +17,7 @@ ipxe ipxe-qemu isolinux jq +kpartx libguestfs-tools libguestfs0 libvirt-bin # dist:bionic diff --git a/devstack/files/rpms/ironic b/devstack/files/rpms/ironic index 469f7fe6b0..41847aadef 100644 --- a/devstack/files/rpms/ironic +++ b/devstack/files/rpms/ironic @@ -3,6 +3,7 @@ ipmitool iptables ipxe-bootimgs gnupg +kpartx libguestfs libguestfs-tools libvirt diff --git a/devstack/lib/ironic b/devstack/lib/ironic index 5f39e97b70..6669e4b57b 100644 --- a/devstack/lib/ironic +++ b/devstack/lib/ironic @@ -2811,6 +2811,44 @@ function build_ipa_dib_ramdisk { rm -rf $tempdir } +function upload_image_if_needed { + if [[ "$IRONIC_PARTITIONED_IMAGE_NAME" =~ cirros ]] \ + && [[ "$IRONIC_DEFAULT_BOOT_OPTION" == local ]] \ + && is_service_enabled glance; then + echo Building a Cirros image suitable for local boot + + local dest + IRONIC_PARTITIONED_IMAGE_NAME=cirros-${CIRROS_VERSION}-x86_64-partition + dest="$IRONIC_DATA_DIR/$IRONIC_PARTITIONED_IMAGE_NAME.img" + + # Export some variables that the script is using. + CIRROS_ARCH=$CIRROS_ARCH CIRROS_VERSION=$CIRROS_VERSION \ + IRONIC_TTY_DEV=$IRONIC_TTY_DEV VERBOSE=$VERBOSE \ + $IRONIC_SCRIPTS_DIR/cirros-partition.sh "$dest" + + # TODO(dtantsur): stop uploading kernel/ramdisk when image_type support + # lands. + local kernel_id + kernel_id=$(openstack image list -f value -c ID -c Name \ + | awk '/cirros.*kernel/ { print $1; exit 0; }') + die_if_not_set $LINENO kernel_id "Cannot find cirros kernel" + + local ramdisk_id + ramdisk_id=$(openstack image list -f value -c ID -c Name \ + | awk '/cirros.*ramdisk/ { print $1; exit 0; }') + die_if_not_set $LINENO ramdisk_id "Cannot find cirros ramdisk" + + openstack image create $IRONIC_PARTITIONED_IMAGE_NAME \ + --public --disk-format raw --container-format bare \ + --property kernel_id=$kernel_id --property ramdisk_id=$ramdisk_id \ + --file "$dest" + + if [[ "$IRONIC_TEMPEST_WHOLE_DISK_IMAGE" != True ]]; then + IRONIC_IMAGE_NAME=$IRONIC_PARTITIONED_IMAGE_NAME + fi + fi +} + # download EFI boot loader image and upload it to glance # this function sets ``IRONIC_EFIBOOT_ID`` function upload_baremetal_ironic_efiboot { @@ -2975,6 +3013,8 @@ function prepare_baremetal_basic_ops { upload_baremetal_ironic_efiboot fi + upload_image_if_needed + configure_tftpd configure_iptables } @@ -3097,6 +3137,13 @@ function ironic_configure_tempest { iniset $TEMPEST_CONFIG baremetal partition_image_ref $image_uuid fi + # Our cirros images cannot do local boot in legacy mode. + if [[ "${IRONIC_PARTITIONED_IMAGE_NAME}" =~ cirros && "${IRONIC_BOOT_MODE}" == "bios" ]]; then + iniset $TEMPEST_CONFIG baremetal partition_netboot True + else + iniset $TEMPEST_CONFIG baremetal partition_netboot False + fi + if [[ "$IRONIC_IP_VERSION" == "6" ]]; then iniset $TEMPEST_CONFIG baremetal whole_disk_image_url "http://$IRONIC_HOST_IPV6:$IRONIC_HTTP_PORT/${IRONIC_WHOLEDISK_IMAGE_NAME}.img" else @@ -3119,6 +3166,8 @@ function ironic_configure_tempest { # Driver for API tests iniset $TEMPEST_CONFIG baremetal driver fake-hardware + iniset $TEMPEST_CONFIG baremetal default_boot_option $IRONIC_DEFAULT_BOOT_OPTION + local adjusted_root_disk_size_gb if [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then adjusted_root_disk_size_gb=$(( ${IRONIC_VM_SPECS_DISK} - ${IRONIC_VM_EPHEMERAL_DISK} )) diff --git a/devstack/tools/ironic/scripts/cirros-partition.sh b/devstack/tools/ironic/scripts/cirros-partition.sh new file mode 100755 index 0000000000..40c87b19e9 --- /dev/null +++ b/devstack/tools/ironic/scripts/cirros-partition.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +set -eu -o pipefail + +VERBOSE=${VERBOSE:-True} +if [[ "$VERBOSE" == True ]]; then + set -x + guestfish_args="--verbose" +fi + +CIRROS_VERSION=${CIRROS_VERSION:-0.5.2} +CIRROS_ARCH=${CIRROS_ARCH:-x86_64} +# TODO(dtantsur): use the image cached on infra images in the CI +DISK_URL=http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-disk.img +OUT=$(realpath ${1:-rootfs.img}) + +IRONIC_TTY_DEV=${IRONIC_TTY_DEV:-ttyS0,115200} +# rdroot : boot from the ramdisk present on the root partition instead of +# mounting the root partition. +# dslist : disable Nova metadata support, it takes a long time on boot. +KARGS=${KARGS:-nofb nomodeset vga=normal console=${IRONIC_TTY_DEV} rdroot dslist=configdrive} + +workdir=$(mktemp -d) +root_mp=$workdir/root +efi_mp=$workdir/efi +dest=$workdir/dest + +cd $workdir + +curl -Lf -o disk.qcow2 $DISK_URL +qemu-img convert -O raw disk.qcow2 disk.img +rm disk.qcow2 + +# kpartx automatically allocates loop devices for all partitions in the image +device=$(sudo kpartx -av disk.img | grep -oE 'loop[0-9]+p' | head -1) + +function clean_up { + set +e + sudo umount $efi_mp + sudo umount $root_mp + sudo kpartx -d $workdir/disk.img + sudo rm -rf $workdir +} +trap clean_up EXIT + +# TODO(dtantsur): some logic instead of hardcoding numbers 1 and 15? +rootdev=/dev/mapper/${device}1 +efidev=/dev/mapper/${device}15 + +mkdir -p $root_mp $efi_mp $dest/boot/efi +sudo mount $rootdev $root_mp +sudo mount $efidev $efi_mp + +sudo cp -aR $root_mp/* $dest/ +sudo cp -aR $efi_mp/EFI $dest/boot/efi/ + +# These locations are required by IPA even when it does not really run +# grub-install. +sudo mkdir -p $dest/{dev,proc,run,sys} + +# The default arguments don't work for us, update grub configuration. +sudo sed -i "/^ *linux /s/\$/ $KARGS/" $dest/boot/efi/EFI/ubuntu/grub.cfg + +LIBGUESTFS_BACKEND=direct sudo -E \ + virt-make-fs --size +50M --type ext3 --label cirros-rootfs \ + ${guestfish_args:-} "$dest" "$OUT" + +sudo chown $USER "$OUT" +qemu-img info "$OUT" diff --git a/zuul.d/ironic-jobs.yaml b/zuul.d/ironic-jobs.yaml index a1c09c6d18..761c9d22cd 100644 --- a/zuul.d/ironic-jobs.yaml +++ b/zuul.d/ironic-jobs.yaml @@ -224,6 +224,7 @@ vars: devstack_localrc: IRONIC_BOOT_MODE: uefi + IRONIC_DEFAULT_BOOT_OPTION: local IRONIC_ENABLED_BOOT_INTERFACES: redfish-virtual-media SWIFT_ENABLE_TEMPURLS: True SWIFT_TEMPURL_KEY: secretkey @@ -250,6 +251,7 @@ tempest_test_regex: test_baremetal_introspection devstack_localrc: IRONIC_BOOT_MODE: bios + IRONIC_DEFAULT_BOOT_OPTION: netboot IRONIC_INSPECTOR_MANAGED_BOOT: True IRONIC_INSPECTOR_NODE_NOT_FOUND_HOOK: '' IRONIC_AUTOMATED_CLEAN_ENABLED: False @@ -316,7 +318,6 @@ IRONIC_BOOT_MODE: uefi IRONIC_VM_SPECS_RAM: 4096 IRONIC_AUTOMATED_CLEAN_ENABLED: False - IRONIC_DEFAULT_BOOT_OPTION: netboot - job: name: ironic-tempest-ipa-partition-pxe_ipmitool @@ -324,6 +325,7 @@ parent: ironic-base vars: devstack_localrc: + IRONIC_BOOT_MODE: bios IRONIC_DEFAULT_BOOT_OPTION: netboot IRONIC_AUTOMATED_CLEAN_ENABLED: True @@ -614,7 +616,6 @@ IRONIC_BOOT_MODE: uefi IRONIC_RAMDISK_TYPE: tinyipa IRONIC_AUTOMATED_CLEAN_ENABLED: False - IRONIC_DEFAULT_BOOT_OPTION: netboot IRONIC_VM_SPECS_RAM: 4096 - job: