ddd59e4d7b
Utility for adding patch metadata to the iso. Debian patches are sequential and uses ostree so any patch will produce an updated iso, this utility injects the patch metadata into the iso. During install the kickstart will copy the metadata into the right location and the sw-patch query command will output the correct patch level. Test: Pass: build iso and patch Pass: patch iso Pass: install iso (with modified kickstart) Pass: sw-patch query returns metadata information Story: 2009969 Task: 46467 Signed-off-by: Luis Sampaio <luis.sampaio@windriver.com> Change-Id: I455a72c4c2140ec3a7426ba78976123c601984f3
263 lines
6.2 KiB
Bash
263 lines
6.2 KiB
Bash
#!/bin/bash
|
|
#
|
|
# Copyright (c) 2022 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
# Utility for adding patch metadata to the iso
|
|
# Debian patches are sequential and uses ostree
|
|
# so any patch will produce an updated iso, this
|
|
# utility injects the patch metadata into the iso.
|
|
# During install the kickstart will copy the metadata
|
|
# into the right location and the sw-patch query
|
|
# command will output the correct patch level
|
|
#
|
|
|
|
source "$(dirname $0)/image-utils.sh"
|
|
|
|
if [ -z "${STX_BUILD_HOME}" ]; then
|
|
echo "Required environment variable STX_BUILD_HOME is not set"
|
|
exit 1
|
|
fi
|
|
|
|
REPO_ROOT="${STX_BUILD_HOME}"/repo
|
|
DEPLOY_DIR="${STX_BUILD_HOME}/localdisk/deploy"
|
|
|
|
RELEASE_INFO="$(get_release_info)"
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: failed to find a release info file."
|
|
exit 1
|
|
fi
|
|
|
|
PLATFORM_RELEASE=$(source $RELEASE_INFO && echo $PLATFORM_RELEASE)
|
|
|
|
function usage() {
|
|
echo ""
|
|
echo "Usage: "
|
|
echo " $(basename $0) -i <input filename.iso> -o <output filename.iso> [ -u ] <patch> ..."
|
|
echo " -i <file>: Specify input ISO file"
|
|
echo " -o <file>: Specify output ISO file"
|
|
echo " -p <file>: Patch file"
|
|
echo ""
|
|
}
|
|
|
|
function extract_metada() {
|
|
local patchesdir=${BUILDDIR}/patches
|
|
local patchfile=$1
|
|
local patchid=$(basename $patchfile .patch)
|
|
local ostree_ref=$(cat ${BUILDDIR}/ostree_repo/refs/heads/starlingx)
|
|
|
|
# Extract it
|
|
tar xf ${patchfile} -O metadata.tar | tar x -O > ${patchesdir}/${patchid}-metadata.xml
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to extract metadata from ${patchfile}"
|
|
exit 1
|
|
fi
|
|
|
|
# Verify if ostree_repo ref matches the metadata.xml
|
|
xml_base=$(xmllint --xpath "string(//contents/ostree/base/commit)" ${patchesdir}/${patchid}-metadata.xml)
|
|
if [ "$xml_base" != "$ostree_ref" ]; then
|
|
echo "Error, ostree head ref and patch xml base commit does not match."
|
|
echo "ostree head: ${ostree_ref}"
|
|
echo "patch base: ${xml_base}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
declare INPUT_ISO=
|
|
declare OUTPUT_ISO=
|
|
declare ORIG_PWD=$PWD
|
|
declare DO_UPGRADES=1
|
|
|
|
while getopts "i:o:p:" opt; do
|
|
case $opt in
|
|
i)
|
|
INPUT_ISO=$OPTARG
|
|
;;
|
|
o)
|
|
OUTPUT_ISO=$OPTARG
|
|
;;
|
|
p)
|
|
PATCH_FILE=$OPTARG
|
|
;;
|
|
*)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$INPUT_ISO" -o -z "$OUTPUT_ISO" ]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f ${INPUT_ISO} ]; then
|
|
echo "Input file does not exist: ${INPUT_ISO}"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -f ${OUTPUT_ISO} ]; then
|
|
echo "Output file already exists: ${OUTPUT_ISO}"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f ${PATCH_FILE} ]; then
|
|
echo "Patch file dos not exists: ${PATCH_FILE}"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! ${PATCH_FILE} =~ \.patch$ ]]; then
|
|
echo "Specified file ${PATCH_FILE} does not have .patch extension"
|
|
exit 1
|
|
fi
|
|
|
|
shift $((OPTIND-1))
|
|
|
|
declare MNTDIR=
|
|
declare BUILDDIR=
|
|
|
|
function check_requirements {
|
|
local -a required_utils=(
|
|
rsync
|
|
mkisofs
|
|
isohybrid
|
|
implantisomd5
|
|
ostree
|
|
xmllint
|
|
)
|
|
if [ $UID -ne 0 ]; then
|
|
# If running as non-root user, additional utils are required
|
|
required_utils+=(
|
|
guestmount
|
|
guestunmount
|
|
)
|
|
fi
|
|
|
|
local -i missing=0
|
|
|
|
for req in ${required_utils[@]}; do
|
|
which ${req} >&/dev/null
|
|
if [ $? -ne 0 ]; then
|
|
echo "Unable to find required utility: ${req}" >&2
|
|
let missing++
|
|
fi
|
|
done
|
|
|
|
if [ ${missing} -gt 0 ]; then
|
|
echo "One or more required utilities are missing. Aborting..." >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function mount_iso {
|
|
if [ $UID -eq 0 ]; then
|
|
# Mount the ISO
|
|
mount -o loop ${INPUT_ISO} ${MNTDIR}
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to mount ${INPUT_ISO}" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
# As non-root user, mount the ISO using guestmount
|
|
guestmount -a ${INPUT_ISO} -m /dev/sda1 --ro ${MNTDIR}
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
# Add a retry
|
|
echo "Call to guestmount failed with rc=$rc. Retrying once..."
|
|
|
|
guestmount -a ${INPUT_ISO} -m /dev/sda1 --ro ${MNTDIR}
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
echo "Call to guestmount failed with rc=$rc. Aborting..."
|
|
exit $rc
|
|
fi
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function unmount_iso {
|
|
if [ $UID -eq 0 ]; then
|
|
umount ${MNTDIR}
|
|
else
|
|
guestunmount ${MNTDIR}
|
|
fi
|
|
rmdir ${MNTDIR}
|
|
}
|
|
|
|
function cleanup() {
|
|
if [ -n "$MNTDIR" -a -d "$MNTDIR" ]; then
|
|
unmount_iso
|
|
fi
|
|
|
|
if [ -n "$BUILDDIR" -a -d "$BUILDDIR" ]; then
|
|
chmod -R +w $BUILDDIR
|
|
\rm -rf $BUILDDIR
|
|
fi
|
|
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
|
|
MNTDIR=$(mktemp -d -p $PWD patchiso_mnt_XXXXXX)
|
|
if [ -z "${MNTDIR}" -o ! -d ${MNTDIR} ]; then
|
|
echo "Failed to create mntdir. Aborting..."
|
|
exit $rc
|
|
fi
|
|
|
|
BUILDDIR=$(mktemp -d -p $PWD patchiso_build_XXXXXX)
|
|
if [ -z "${BUILDDIR}" -o ! -d ${BUILDDIR} ]; then
|
|
echo "Failed to create builddir. Aborting..."
|
|
exit $rc
|
|
fi
|
|
|
|
# Mount the ISO
|
|
mount_iso
|
|
|
|
rsync -a ${MNTDIR}/ ${BUILDDIR}/
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
echo "Call to rsync ISO content. Aborting..."
|
|
exit $rc
|
|
fi
|
|
|
|
unmount_iso
|
|
|
|
# Fix for permission denied if not running as root
|
|
chmod +w ${BUILDDIR}
|
|
chmod -R +w ${BUILDDIR}/isolinux
|
|
# Extract patch xml
|
|
mkdir ${BUILDDIR}/patches
|
|
extract_metada $PATCH_FILE
|
|
|
|
# Repack the ISO
|
|
mkisofs -o "${OUTPUT_ISO}" \
|
|
-A 'instboot' -V 'instboot' \
|
|
-quiet -U -J -joliet-long -r -iso-level 2 \
|
|
-b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot \
|
|
-boot-load-size 4 -boot-info-table \
|
|
-eltorito-alt-boot \
|
|
-e efi.img \
|
|
-no-emul-boot \
|
|
"${BUILDDIR}"
|
|
|
|
isohybrid --uefi ${OUTPUT_ISO}
|
|
implantisomd5 ${OUTPUT_ISO}
|
|
|
|
# Sign the .iso with the developer private key
|
|
# Signing with the formal key is only to be done for customer release
|
|
# and is a manual step afterwards, as with the GA ISO
|
|
openssl dgst -sha256 \
|
|
-sign ${STX_BUILD_HOME}/repo/cgcs-root/build-tools/signing/dev-private-key.pem \
|
|
-binary \
|
|
-out ${OUTPUT_ISO/%.iso/.sig} \
|
|
${OUTPUT_ISO}
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
echo "Call to $(basename ${SETUP_PATCH_REPO}) failed with rc=$rc. Aborting..."
|
|
exit $rc
|
|
fi
|
|
|
|
echo "Patched ISO: ${OUTPUT_ISO}"
|