55fdee2aee
- 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
413 lines
11 KiB
Bash
Executable File
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]}
|