root/build-tools/build-guest
Davlet Panech 55fdee2aee build-guest: accept extra RPMs on command line
- Accept additional RPM file names or package names to be installed into
  the guest image
- Don't fail if build-info/release-info.inc doesn't exist

Story: 2009108
Task: 42968

Signed-off-by: Davlet Panech <davlet.panech@windriver.com>
Change-Id: Id532f3cfcd7bb16d8ca4c6bdf7615fe6d79f41b1
2021-08-16 09:29:05 -04:00

413 lines
11 KiB
Bash
Executable File

#!/bin/env bash
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# Build the tis-centos-image.img or tis-centos-image-rt.img file
#
BUILD_GUEST_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )"
source "${BUILD_GUEST_DIR}/image-utils.sh"
PROGNAME=$(basename "$0")
# NOTE: TMP_DIR must end in '/'
# NOTE: /tmp/ is now tmpfs like. Can't be trusted across multiple mock commands
# TMP_DIR=/tmp/
TMP_DIR=/
# Use RPMs from the std build only, for now
export BUILD_TYPE=std
export MY_BUILD_DIR_TOP=$MY_BUILD_DIR
function init_vars {
# Output path (current dir unless MY_WORKSPACE defined)
OUTPUT_DIR="$PWD/export"
if [ ! -z "$MY_WORKSPACE" ] && [ -d "$MY_WORKSPACE" ] ; then
OUTPUT_DIR="$MY_WORKSPACE/export"
CGCS_REPO_DIR="$MY_WORKSPACE/rpmbuild/RPMS"
fi
if [ -n "$MY_GUEST_DIR" ]; then
GUEST_DIR=$MY_GUEST_DIR
else
GUEST_DIR=$MY_WORKSPACE/guest
fi
MOCK=/usr/bin/mock
if [ $VERBOSE -eq 0 ]; then
MOCK="$MOCK -q"
fi
# Path to guest configuration
GUEST_BUILD_DIR="${BUILD_GUEST_DIR}/build_guest"
GUEST_BUILD_CMD=$GUEST_BUILD_DIR/build-guest-image.py
if [ $VERBOSE -eq 1 ]; then
GUEST_BUILD_CMD="$GUEST_BUILD_CMD -x"
fi
if [ $BUILD_MODE == 'std' ]; then
OUTPUT_FILE=$OUTPUT_DIR/tis-centos-guest.img
elif [ $BUILD_MODE == 'rt' ]; then
OUTPUT_FILE=$OUTPUT_DIR/tis-centos-guest-rt.img
else
printf " Error -- unknown BUILD_MODE '$BUILD_MODE'\n";
exit 1
fi
}
function check_vars {
# Where to store data
printf "Finding cgcs-root\n"
printf " Checking \$MY_REPO (value \"$MY_REPO\")\n"
if [ ! -z "$MY_REPO" ] && [ -d "$MY_REPO" ] ; then
INTERNAL_REPO_ROOT=$MY_REPO
printf " Found!\n"
fi
if [ -z "$INTERNAL_REPO_ROOT" ] ; then
printf " No joy -- checking \$MY_REPO_ROOT_DIR (value \"$MY_REPO_ROOT_DIR\")\n"
if [ ! -z "$MY_REPO_ROOT_DIR" ] && [ -d "$MY_REPO_ROOT_DIR/cgcs-root" ] ; then
INTERNAL_REPO_ROOT=$MY_REPO_ROOT_DIR/cgcs-root
printf " Found!\n"
fi
fi
if [ -z "$INTERNAL_REPO_ROOT" ] ; then
printf " No joy -- checking for \$MY_WORKSPACE/cgcs-root\n"
if [ -d "$MY_WORKSPACE/cgcs-root" ] ; then
INTERNAL_REPO_ROOT=$MY_WORKSPACE/cgcs-root
printf " Found!\n"
fi
fi
if [ -z "$INTERNAL_REPO_ROOT" ] ; then
printf " Error -- could not locate cgcs-root repo.\n"
exit 1
fi
STX_DIR=$INTERNAL_REPO_ROOT/stx
if [ "x$MY_BUILD_CFG" == "x" ];then
printf " Error -- reqiure MY_BUILD_CFG to be defined.\n"
exit 1
fi
RELEASE_INFO="$(get_release_info)"
if [ $? -ne 0 ]; then
echo "WARNING: failed to find a release info file."
else
export PLATFORM_RELEASE=$(source "$RELEASE_INFO" && echo $PLATFORM_RELEASE)
fi
}
function create_rootfs {
printf "\nCreating guest file system\n"
mkdir -p $GUEST_DIR
if [ $? -ne 0 ]; then
printf " Error -- Could not create $GUEST_DIR\n";
exit 1
fi
# Place build-time environment variables in mock configuration
GUEST_ENV="${MY_BUILD_ENVIRONMENT}-guest"
GUEST_CFG=$GUEST_DIR/$MY_BUILD_ENVIRONMENT_FILE
MY_BUILD_ENVIRONMENT=$GUEST_ENV "${BUILD_GUEST_DIR}/modify-build-cfg" $GUEST_CFG
if [ $? -ne 0 ]; then
printf " Error -- Could not update $GUEST_CFG\n";
exit 1
fi
# Setup mock directories for the guest
if [ -d /localdisk/loadbuild/mock ]; then
LNK=/localdisk/loadbuild/mock/$GUEST_ENV
if [ ! -L $LNK ]; then
ln -s $GUEST_DIR $LNK
fi
fi
if [ -d /localdisk/loadbuild/mock-cache ]; then
mkdir -p $GUEST_DIR/cache
LNK=/localdisk/loadbuild/mock-cache/$GUEST_ENV
if [ ! -L $LNK ]; then
ln -s $GUEST_DIR/cache $LNK
fi
fi
# Setup mock chroot environment
$MOCK -r $GUEST_CFG --clean && $MOCK -r $GUEST_CFG --init
if [ $? -ne 0 ]; then
printf " Error -- Failed to setup guest mock chroot\n";
exit 1
fi
# Install the RPMs to the root filesystem
# Note that the "rt" build needs access to both local-std and local-rt repos
local EXTRA_REPOS=""
if [ $BUILD_MODE == 'std' ]; then
INC_RPM_LIST=$(grep -v '^#' ${GUEST_BUILD_DIR}/rpm-install-list.txt)
TIS_RPM_LIST=$(image_inc_list guest std centos)
elif [ $BUILD_MODE == 'rt' ]; then
INC_RPM_LIST=$(grep -v '^#' ${GUEST_BUILD_DIR}/rpm-install-list-rt.txt)
TIS_RPM_LIST=$(image_inc_list guest rt centos)
EXTRA_REPOS="--enablerepo local-rt"
else
printf " Error -- unknown BUILD_MODE '$BUILD_MODE'\n";
exit 1
fi
$MOCK -r $GUEST_CFG ${EXTRA_REPOS} --install ${INC_RPM_LIST} ${TIS_RPM_LIST} "$@"
if [ $? -ne 0 ]; then
printf "=====\n"
cat $GUEST_DIR/mock/result/root.log | sed -n '/Error:/,$p' | sed '/Child return code was:/q'
printf "=====\n"
printf " Error -- Failed to install RPM packages\n";
exit 1
fi
# Make sure all requested packages are installed
MISSING=$(
extra_rpm_names="$(
for p in "$@" ; do
# skip URLs
if [[ "$p" =~ :// ]] ; then
continue
fi
# if it contains a slash or ends with .rpm, assume its a local file
# and read its embedded package name
if [[ "$p" =~ / || "$p" =~ [.]rpm$ ]] ; then
rpm -q --qf '%{name}\n' -p "$p"
# otherwise assume its a package name already
else
echo "$p"
fi
done
)"
$MOCK -r $GUEST_CFG --chroot -- rpm -q --whatprovides ${INC_RPM_LIST} ${TIS_RPM_LIST} $extra_rpm_names \
| sed -n 's/^no package provides //p' \
| sort -u
)
if [ -n "$MISSING" ]; then
printf "=====\n"
printf "WARNING: The following RPMs are missing or could not be installed:\n"
local p
for p in $MISSING ; do
echo " [$p]"
done
printf "=====\n"
fi
# Remove RPMs that are not required in image (pruned package list)
# NOTE: these are automatically installed from the mock init not
# through dependencies.
EXC_RPM_LIST=$(grep -v '^#' ${GUEST_BUILD_DIR}/rpm-remove-list.txt)
$MOCK -r $GUEST_CFG --remove ${EXC_RPM_LIST}
if [ $? -ne 0 ]; then
printf " Error -- Failed to remove RPM packages\n";
exit 1
fi
printf " Done\n"
}
function update_rootfs {
printf "\nCustomizing guest file system\n"
# Copy over skeleton configuration files
for GUEST_ROOTFS in $GUEST_BUILD_DIR/rootfs $GUEST_BUILD_DIR/rootfs-$BUILD_MODE;
do
for f in $(cd $GUEST_ROOTFS && find . -type f | cut -c3-);
do
echo "$MOCK -r $GUEST_CFG --copyin $GUEST_ROOTFS/$f $f"
$MOCK -r $GUEST_CFG --copyin $GUEST_ROOTFS/$f $f
if [ $? -ne 0 ]; then
printf " Error -- Failed to copyin file $f\n";
exit 1
fi
done
done
# Run the root file system setup script inside the chroot
ROOTFS_SETUP=rootfs-setup.sh
$MOCK -r $GUEST_CFG --copyin $GUEST_BUILD_DIR/$ROOTFS_SETUP $TMP_DIR && \
if [ $BUILD_MODE == 'rt' ]; then
ROOTFS_SETUP_CMD="$TMP_DIR$ROOTFS_SETUP --rt"
elif [ $BUILD_MODE == 'std' ]; then
ROOTFS_SETUP_CMD="$TMP_DIR$ROOTFS_SETUP --std"
else
ROOTFS_SETUP_CMD="$TMP_DIR$ROOTFS_SETUP"
fi
$MOCK -r $GUEST_CFG --chroot "$ROOTFS_SETUP_CMD"
if [ $? -ne 0 ]; then
printf " Error -- Failed to run guest $ROOTFS_SETUP\n";
exit 1
fi
$MOCK -r $GUEST_CFG --chroot "rm -f $TMP_DIR$ROOTFS_SETUP"
if [ $? -ne 0 ]; then
printf " Error -- Failed to delete $ROOTFS_SETUP from guest\n";
exit 1
fi
printf " Done\n"
}
function build_image {
# Build the image
printf "\nBuilding guest image $OUTPUT_FILE\n"
mkdir -p $OUTPUT_DIR
if [ $? -ne 0 ]; then
printf " Error -- Could not create $OUTPUT_DIR\n";
exit 1
fi
# Build guest rootfs archive
ROOTFS_SPACE=$((500*1024*1024))
ROOTFS_TAR=rootfs.tar
ROOTFS_EXCLUDE=rootfs-exclude.txt
$MOCK -r $GUEST_CFG --copyin $GUEST_BUILD_DIR/$ROOTFS_EXCLUDE $TMP_DIR
$MOCK -r $GUEST_CFG --chroot -- tar -cf $TMP_DIR$ROOTFS_TAR -X $TMP_DIR$ROOTFS_EXCLUDE --exclude=$TMP_DIR$ROOTFS_TAR --numeric-owner /
$MOCK -r $GUEST_CFG --copyout $TMP_DIR$ROOTFS_TAR $GUEST_DIR
$MOCK -r $GUEST_CFG --chroot -- rm -f $TMP_DIR$ROOTFS_TAR
$GUEST_BUILD_CMD -i $GUEST_DIR/$ROOTFS_TAR -o $OUTPUT_FILE -s $ROOTFS_SPACE
if [ $? -ne 0 ]; then
printf " Error -- Failed to build guest image\n";
exit 1
fi
printf " Done\n"
}
function clean_guest {
printf "\nCleaning the guest $GUEST_DIR\n"
if [ ! -e $GUEST_DIR ]; then
printf " Done...nothing to do\n";
exit 0
fi
# Place build-time environment variables in mock configuration
GUEST_ENV="${MY_BUILD_ENVIRONMENT}-guest"
GUEST_CFG=$GUEST_DIR/$MY_BUILD_ENVIRONMENT_FILE
if [ ! -e $GUEST_CFG ]; then
MY_BUILD_ENVIRONMENT=$GUEST_ENV "${BUILD_GUEST_DIR}/modify-build-cfg" $GUEST_CFG
if [ $? -ne 0 ]; then
printf " Error -- Could not update $GUEST_CFG\n";
exit 1
fi
fi
$MOCK -r $GUEST_CFG --clean
$MOCK -r $GUEST_CFG --scrub=cache
rm -rf $GUEST_DIR
if [ $? -ne 0 ]; then
printf " Error -- Failed to remove guest $GUEST_DIR\n";
exit 1
fi
printf " Done\n"
}
#############################################
# Main code
#############################################
usage () {
echo ""
echo "Usage: "
echo " build-guest [--rt | --std] [--verbose] [EXTRA_RPMS...]"
echo " build-guest [--help]"
echo " build-guest [--clean]"
echo ""
echo "EXTRA_RPMS are either package names or full RPM file paths"
}
# Default argument values
HELP=0
CLEAN=0
VERBOSE=0
BUILD_MODE='std'
# read the options
TEMP=`getopt -o h --long clean,rt,std,verbose,help -n "$PROGNAME" -- "$@"` || exit 1
eval set -- "$TEMP"
# extract options and their arguments into variables.
while true ; do
case "$1" in
-h|--help) HELP=1 ; shift ;;
--clean) CLEAN=1 ; shift ;;
--verbose) VERBOSE=1 ; shift ;;
--rt) BUILD_MODE='rt' ; shift ;;
--std) BUILD_MODE='std' ; shift ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
if [ $HELP -eq 1 ]; then
usage
exit 0
fi
if [[ $CLEAN -eq 1 && "$#" -gt 0 ]] ; then
echo "Too many arguments!" >&2 ; exit 1
else
# make sure extra RPM files exist
for p in "$@" ; do
# skip URLs
if [[ "$p" =~ :// ]] ; then
continue
fi
# if it contains a slash or ends with .rpm assume its a local file name
if [[ "$p" =~ / || "$p" =~ [.]rpm$ ]] ; then
# make sure it exists and is an RPM file
true <"$p" || exit 1
if ! file --brief --mime-type "$p" | grep -q "^application/x-rpm$" ; then
echo "$p: not an RPM file" >&2
exit 1
fi
fi
done
unset p
fi
(
printf "\n*****************************\n"
printf "Create Titanium Cloud/CentOS Guest Image\n"
printf "*****************************\n\n"
init_vars
check_vars
if [ $CLEAN -eq 1 ]; then
clean_guest
exit 0
fi
create_rootfs "$@"
update_rootfs
build_image
) 2>&1 | stdbuf -o0 awk '{ print strftime("%H:%M:%S"), $0; fflush(); }' ; exit ${PIPESTATUS[0]}