From 8e53c77a11ef304be74c1f3be00531d0af0e411a Mon Sep 17 00:00:00 2001 From: Robert C Jennings Date: Thu, 7 Jun 2018 17:35:12 -0700 Subject: [PATCH] snap: Alternate fix for snap pre-seeding (LP: #1775710) * Backport: Refactor functions out of ubuntu-cpc and ubuntu-server hooks. * Backport: Add dependency on distro-info for snap preseeding --- debian/changelog | 4 +- live-build/auto/config | 4 +- live-build/{ubuntu-cpc => }/functions | 141 ++++++++++++++++-- live-build/functions.snaps | 126 ---------------- .../ubuntu-cpc/hooks/032-disk-image.binary | 5 +- .../hooks/033-disk-image-uefi.binary | 9 +- .../hooks/034-disk-image-ppc64el.binary | 7 +- .../ubuntu-cpc/hooks/042-vagrant.binary | 2 + .../ubuntu-cpc/hooks/999-cpc-fixes.chroot | 2 +- live-build/ubuntu-cpc/hooks/999-extras.binary | 4 + 10 files changed, 161 insertions(+), 143 deletions(-) rename live-build/{ubuntu-cpc => }/functions (67%) delete mode 100644 live-build/functions.snaps diff --git a/debian/changelog b/debian/changelog index 4e12d4db..dc21cc19 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ livecd-rootfs (2.408.32) xenial; urgency=medium * snaps: Fixes for snap pre-seeding (LP: #1775710) - * Add dependency on distro-info for snap preseeding - * Move snap-related functions to avoid conflicts with ubuntu-cpc functions + * Backport: Refactor functions out of ubuntu-cpc and ubuntu-server hooks. + * Add dependency on distro-info for snap preseeding -- Robert C Jennings Thu, 07 Jun 2018 14:12:26 -0700 diff --git a/live-build/auto/config b/live-build/auto/config index 875f5ea3..ff0c4307 100755 --- a/live-build/auto/config +++ b/live-build/auto/config @@ -33,8 +33,10 @@ if [ -z "$MIRROR" ]; then esac fi +mkdir -p config +cp -af /usr/share/livecd-rootfs/live-build/functions config/functions + mkdir -p config/package-lists -cp -af /usr/share/livecd-rootfs/live-build/functions.snaps config/functions.snaps add_task () { diff --git a/live-build/ubuntu-cpc/functions b/live-build/functions similarity index 67% rename from live-build/ubuntu-cpc/functions rename to live-build/functions index 0af43d94..a4c0593a 100644 --- a/live-build/ubuntu-cpc/functions +++ b/live-build/functions @@ -1,7 +1,8 @@ # vi: ts=4 expandtab syntax=sh -CLOUD_IMG_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process" -IMAGE_SIZE=$((2252*1024**2)) # 2.2G (the current size we ship) +#imagesize=${IMAGE_SIZE:-$((2252*1024**2))} # 2.2G (the current size we ship) +imagesize=${IMAGE_SIZE:-2361393152} # 2.2G (the current size we ship) +fs_label="${FS_LABEL:-rootfs}" rootfs_dev_mapper= loop_device= @@ -39,13 +40,13 @@ clean_loops() { create_empty_disk_image() { # Prepare an empty disk image - dd if=/dev/zero of="$1" bs=1 count=0 seek="${IMAGE_SIZE}" + dd if=/dev/zero of="$1" bs=1 count=0 seek="${imagesize}" } make_ext4_partition() { device="$1" - - mkfs.ext4 -F -b 4096 -i 8192 -m 0 -L cloudimg-rootfs -E resize=536870912 "$device" + label=${fs_label:+-L "${fs_label}"} + mkfs.ext4 -F -b 4096 -i 8192 -m 0 ${label} -E resize=536870912 "$device" } mount_image() { @@ -56,7 +57,7 @@ mount_image() { # Find the loop device loop_p1="$(echo -e ${kpartx_mapping} | head -n1 | awk '{print$3}')" - loop_device="/dev/loop$(echo ${loop_p1} | cut -b5)" + loop_device="/dev/${loop_p1%p[0-9]*}" if [ ! -b ${loop_device} ]; then echo "unable to find loop device for ${backing_img}" exit 1 @@ -129,7 +130,7 @@ mount_disk_image() { # such as updating grub and installing software cat > $mountpoint/usr/sbin/policy-rc.d << EOF #!/bin/sh -# ${CLOUD_IMG_STR} +# ${IMAGE_STR} echo "All runlevel operations denied by policy" >&2 exit 101 EOF @@ -264,7 +265,7 @@ convert_to_qcow2() { replace_grub_root_with_label() { # When update-grub is run, it will detect the disks in the build system. - # Instead, we want grub to use the cloudimg-rootfs labelled disk + # Instead, we want grub to use the right labelled disk CHROOT_ROOT="$1" # If boot by partuuid has been requested, don't override. @@ -273,7 +274,7 @@ replace_grub_root_with_label() { then return 0 fi - sed -i -e "s,root=[^ ]*,root=LABEL=cloudimg-rootfs," \ + sed -i -e "s,root=[^ ]*,root=LABEL=${fs_label}," \ "$CHROOT_ROOT/boot/grub/grub.cfg" } @@ -318,3 +319,125 @@ undivert_grub() { chroot "$CHROOT_ROOT" dpkg-divert --remove --local \ --rename /usr/bin/systemd-detect-virt } + +release_ver() { + # Return the release version number + distro-info --series="$LB_DISTRIBUTION" -r | awk '{ print $1 }' +} + +_snap_preseed() { + # Download the snap/assertion and add to the preseed + local CHROOT_ROOT=$1 + local SNAP=$2 + local SNAP_NAME=${SNAP%/*} + local CHANNEL=${3:?Snap channel must be specified} + + local seed_dir="$CHROOT_ROOT/var/lib/snapd/seed" + local snaps_dir="$seed_dir/snaps" + local seed_yaml="$seed_dir/seed.yaml" + local assertions_dir="$seed_dir/assertions" + + # Download the snap & assertion + local snap_download_failed=0 + chroot $CHROOT_ROOT sh -c " + set -x; + cd /var/lib/snapd/seed; + SNAPPY_STORE_NO_CDN=1 snap download \ + --channel=$CHANNEL \"$SNAP_NAME\"" || snap_download_failed=1 + if [ $snap_download_failed = 1 ] ; then + echo "If the channel ($CHANNEL) includes '*/ubuntu-##.##' track per " + echo "Ubuntu policy (ex. stable/ubuntu-18.04) the publisher will need " + echo "to temporarily create the channel/track to allow fallback during" + echo "download (ex. stable/ubuntu-18.04 falls back to stable if the" + echo "prior had been created in the past)." + exit 1 + fi + + mv -v $seed_dir/*.assert $assertions_dir + mv -v $seed_dir/*.snap $snaps_dir + + # Add the snap to the seed.yaml + ! [ -e $seed_yaml ] && echo "snaps:" > $seed_yaml + cat <> $seed_yaml + - + name: ${SNAP_NAME} + channel: ${CHANNEL} +EOF + + case ${SNAP} in */classic) echo " classic: true" >> $seed_yaml;; esac + + echo -n " file: " >> $seed_yaml + (cd $snaps_dir; ls -1 ${SNAP_NAME}_*.snap) >> $seed_yaml +} + +snap_prepare_assertions() { + # Configure basic snapd assertions + local CHROOT_ROOT=$1 + # A colon-separated string of brand:model to be used for the image's model + # assertion + local CUSTOM_BRAND_MODEL=$2 + + local seed_dir="$CHROOT_ROOT/var/lib/snapd/seed" + local snaps_dir="$seed_dir/snaps" + local assertions_dir="$seed_dir/assertions" + local model_assertion="$assertions_dir/model" + local account_key_assertion="$assertions_dir/account-key" + local account_assertion="$assertions_dir/account" + + mkdir -p "$assertions_dir" + mkdir -p "$snaps_dir" + + local brand="$(echo $CUSTOM_BRAND_MODEL | cut -d: -f 1)" + local model="$(echo $CUSTOM_BRAND_MODEL | cut -d: -f 2)" + + if ! [ -e "$model_assertion" ] ; then + snap known --remote model series=16 \ + model=$model brand-id=$brand \ + > "$model_assertion" + fi + + if ! [ -e "$account_key_assertion" ] ; then + local account_key=$(sed -n -e's/sign-key-sha3-384: //p' \ + < "$model_assertion") + snap known --remote account-key \ + public-key-sha3-384="$account_key" \ + > "$account_key_assertion" + fi + + + if ! [ -e "$account_assertion" ] ; then + local account=$(sed -n -e's/account-id: //p' < "$account_key_assertion") + snap known --remote account account-id=$account \ + > "$account_assertion" + fi +} + +snap_prepare() { + # Configure basic snapd assertions and pre-seeds the 'core' snap + local CHROOT_ROOT=$1 + # Optional. If set, should be a colon-separated string of brand:model to be + # used for the image's model assertion + local CUSTOM_BRAND_MODEL=${2:-generic:generic-classic} + + local seed_dir="$CHROOT_ROOT/var/lib/snapd/seed" + local snaps_dir="$seed_dir/snaps" + + snap_prepare_assertions "$CHROOT_ROOT" "$CUSTOM_BRAND_MODEL" + + # Download the core snap + if ! [ -f $snaps_dir/core_[0-9]*.snap ] ; then + _snap_preseed $CHROOT_ROOT core stable + fi +} + +snap_preseed() { + # Preseed a snap in the image + local CHROOT_ROOT=$1 + local SNAP=$2 + # Per Ubuntu policy, all seeded snaps (with the exception of the core + # snap) must pull from stable/ubuntu-$(release_ver) as their channel. + local CHANNEL=${3:-"stable/ubuntu-$(release_ver)"} + + snap_prepare $CHROOT_ROOT + _snap_preseed $CHROOT_ROOT $SNAP $CHANNEL +} diff --git a/live-build/functions.snaps b/live-build/functions.snaps deleted file mode 100644 index 4772c28b..00000000 --- a/live-build/functions.snaps +++ /dev/null @@ -1,126 +0,0 @@ -# vi: ts=4 expandtab syntax=sh - -#imagesize=${IMAGE_SIZE:-$((2252*1024**2))} # 2.2G (the current size we ship) -imagesize=${IMAGE_SIZE:-2361393152} # 2.2G (the current size we ship) - -release_ver() { - # Return the release version number - distro-info --series="$LB_DISTRIBUTION" -r | awk '{ print $1 }' -} - -_snap_preseed() { - # Download the snap/assertion and add to the preseed - local CHROOT_ROOT=$1 - local SNAP=$2 - local SNAP_NAME=${SNAP%/*} - local CHANNEL=${3:?Snap channel must be specified} - - local seed_dir="$CHROOT_ROOT/var/lib/snapd/seed" - local snaps_dir="$seed_dir/snaps" - local seed_yaml="$seed_dir/seed.yaml" - local assertions_dir="$seed_dir/assertions" - - # Download the snap & assertion - local snap_download_failed=0 - chroot $CHROOT_ROOT sh -c " - set -x; - cd /var/lib/snapd/seed; - SNAPPY_STORE_NO_CDN=1 snap download \ - --channel=$CHANNEL \"$SNAP_NAME\"" || snap_download_failed=1 - if [ $snap_download_failed = 1 ] ; then - echo "If the channel ($CHANNEL) includes '*/ubuntu-##.##' track per " - echo "Ubuntu policy (ex. stable/ubuntu-18.04) the publisher will need " - echo "to temporarily create the channel/track to allow fallback during" - echo "download (ex. stable/ubuntu-18.04 falls back to stable if the" - echo "prior had been created in the past)." - exit 1 - fi - - mv -v $seed_dir/*.assert $assertions_dir - mv -v $seed_dir/*.snap $snaps_dir - - # Add the snap to the seed.yaml - ! [ -e $seed_yaml ] && echo "snaps:" > $seed_yaml - cat <> $seed_yaml - - - name: ${SNAP_NAME} - channel: ${CHANNEL} -EOF - - case ${SNAP} in */classic) echo " classic: true" >> $seed_yaml;; esac - - echo -n " file: " >> $seed_yaml - (cd $snaps_dir; ls -1 ${SNAP_NAME}_*.snap) >> $seed_yaml -} - -snap_prepare_assertions() { - # Configure basic snapd assertions - local CHROOT_ROOT=$1 - # A colon-separated string of brand:model to be used for the image's model - # assertion - local CUSTOM_BRAND_MODEL=$2 - - local seed_dir="$CHROOT_ROOT/var/lib/snapd/seed" - local snaps_dir="$seed_dir/snaps" - local assertions_dir="$seed_dir/assertions" - local model_assertion="$assertions_dir/model" - local account_key_assertion="$assertions_dir/account-key" - local account_assertion="$assertions_dir/account" - - mkdir -p "$assertions_dir" - mkdir -p "$snaps_dir" - - local brand="$(echo $CUSTOM_BRAND_MODEL | cut -d: -f 1)" - local model="$(echo $CUSTOM_BRAND_MODEL | cut -d: -f 2)" - - if ! [ -e "$model_assertion" ] ; then - snap known --remote model series=16 \ - model=$model brand-id=$brand \ - > "$model_assertion" - fi - - if ! [ -e "$account_key_assertion" ] ; then - local account_key=$(sed -n -e's/sign-key-sha3-384: //p' \ - < "$model_assertion") - snap known --remote account-key \ - public-key-sha3-384="$account_key" \ - > "$account_key_assertion" - fi - - - if ! [ -e "$account_assertion" ] ; then - local account=$(sed -n -e's/account-id: //p' < "$account_key_assertion") - snap known --remote account account-id=$account \ - > "$account_assertion" - fi -} - -snap_prepare() { - # Configure basic snapd assertions and pre-seeds the 'core' snap - local CHROOT_ROOT=$1 - # Optional. If set, should be a colon-separated string of brand:model to be - # used for the image's model assertion - local CUSTOM_BRAND_MODEL=${2:-generic:generic-classic} - - local seed_dir="$CHROOT_ROOT/var/lib/snapd/seed" - local snaps_dir="$seed_dir/snaps" - - snap_prepare_assertions "$CHROOT_ROOT" "$CUSTOM_BRAND_MODEL" - - # Download the core snap - if ! [ -f $snaps_dir/core_[0-9]*.snap ] ; then - _snap_preseed $CHROOT_ROOT core stable - fi -} - -snap_preseed() { - # Preseed a snap in the image - local CHROOT_ROOT=$1 - local SNAP=$2 - # Per Ubuntu policy, all seeded snaps (with the exception of the core - # snap) must pull from stable/ubuntu-$(release_ver) as their channel. - local CHANNEL=${3:-"stable/ubuntu-$(release_ver)"} - - snap_prepare $CHROOT_ROOT - _snap_preseed $CHROOT_ROOT $SNAP $CHANNEL -} diff --git a/live-build/ubuntu-cpc/hooks/032-disk-image.binary b/live-build/ubuntu-cpc/hooks/032-disk-image.binary index f4b7a86d..64183258 100755 --- a/live-build/ubuntu-cpc/hooks/032-disk-image.binary +++ b/live-build/ubuntu-cpc/hooks/032-disk-image.binary @@ -1,9 +1,12 @@ #!/bin/bash -ex -. config/functions +IMAGE_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process" +FS_LABEL="cloudimg-rootfs" . config/binary +. config/functions + BOOTPART_START= BOOTPART_END= BOOT_MOUNTPOINT= diff --git a/live-build/ubuntu-cpc/hooks/033-disk-image-uefi.binary b/live-build/ubuntu-cpc/hooks/033-disk-image-uefi.binary index 3447ca54..a15faa64 100755 --- a/live-build/ubuntu-cpc/hooks/033-disk-image-uefi.binary +++ b/live-build/ubuntu-cpc/hooks/033-disk-image-uefi.binary @@ -9,6 +9,11 @@ case $ARCH in ;; esac +IMAGE_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process" +FS_LABEL="cloudimg-rootfs" + +. config/binary + . config/functions create_partitions() { @@ -88,7 +93,7 @@ install_grub() { esac cat << EOF >> mountpoint/etc/default/grub.d/50-cloudimg-settings.cfg -${CLOUD_IMG_STR} +${IMAGE_STR} # For Cloud Image compatability GRUB_PRELOAD_MODULES="${GRUB_PRELOAD_MODULES:-$grub_modules}" EOF @@ -104,7 +109,7 @@ EOF if [ -f mountpoint/boot/efi/EFI/BOOT/grub.cfg ]; then sed -i "s| root| root hd0,gpt1|" mountpoint/boot/efi/EFI/BOOT/grub.cfg - sed -i "1i${CLOUD_IMG_STR}" mountpoint/boot/efi/EFI/BOOT/grub.cfg + sed -i "1i${IMAGE_STR}" mountpoint/boot/efi/EFI/BOOT/grub.cfg # For some reason the grub disk is looking for /boot/grub/grub.cfg on # part 15.... chroot mountpoint mkdir -p /boot/efi/boot/grub diff --git a/live-build/ubuntu-cpc/hooks/034-disk-image-ppc64el.binary b/live-build/ubuntu-cpc/hooks/034-disk-image-ppc64el.binary index 7bafd9e0..b97ef55b 100755 --- a/live-build/ubuntu-cpc/hooks/034-disk-image-ppc64el.binary +++ b/live-build/ubuntu-cpc/hooks/034-disk-image-ppc64el.binary @@ -7,6 +7,11 @@ case $ARCH in ;; esac +IMAGE_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process" +FS_LABEL="cloudimg-rootfs" + +. config/binary + . config/functions create_partitions() { @@ -32,7 +37,7 @@ install_grub() { # set the kernel commandline to use hvc0 mkdir -p mountpoint/etc/default/grub.d cat << EOF > mountpoint/etc/default/grub.d/50-cloudimg-settings.cfg -${CLOUD_IMG_STR} +${IMAGE_STR} # Set the recordfail timeout GRUB_RECORDFAIL_TIMEOUT=0 diff --git a/live-build/ubuntu-cpc/hooks/042-vagrant.binary b/live-build/ubuntu-cpc/hooks/042-vagrant.binary index 7a1b1ff4..2d0513e5 100755 --- a/live-build/ubuntu-cpc/hooks/042-vagrant.binary +++ b/live-build/ubuntu-cpc/hooks/042-vagrant.binary @@ -44,6 +44,8 @@ case $ARCH in exit 0;; esac +IMAGE_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process" + . config/functions # Lets be safe about this diff --git a/live-build/ubuntu-cpc/hooks/999-cpc-fixes.chroot b/live-build/ubuntu-cpc/hooks/999-cpc-fixes.chroot index 91fdc554..88905ca5 100755 --- a/live-build/ubuntu-cpc/hooks/999-cpc-fixes.chroot +++ b/live-build/ubuntu-cpc/hooks/999-cpc-fixes.chroot @@ -47,7 +47,7 @@ respawn script exec /sbin/getty -L CONDEV 115200 vt102 end script -${CLOUD_IMG_STR} +${IMAGE_STR} EOF sed -i "s/CONDEV/${condev}/g" "$idir/${condev}.conf" } diff --git a/live-build/ubuntu-cpc/hooks/999-extras.binary b/live-build/ubuntu-cpc/hooks/999-extras.binary index 2dd1dbd3..108063a9 100755 --- a/live-build/ubuntu-cpc/hooks/999-extras.binary +++ b/live-build/ubuntu-cpc/hooks/999-extras.binary @@ -8,6 +8,10 @@ if [ ! -d ${my_dir}/extra ]; then exit 0 fi +export IMAGE_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process" +export CLOUD_IMG_STR="$IMAGE_STR" +export FS_LABEL="cloudimg-rootfs" + # Export the common functions to the extras . config/functions