Files
OpenNetworkLinux/builds/any/installer/installer.sh.in
Carl D. Roth f761378827 Use a longer wait during debug installs
- else the serial console speed gets in the way
2018-05-02 16:37:16 -07:00

603 lines
14 KiB
Bash

#!/bin/sh
############################################################
# <bsn.cl fy=2013 v=none>
#
# Copyright 2013, 2014 BigSwitch Networks, Inc.
#
#
#
# </bsn.cl>
############################################################
#
# Open Network Linux Installation Script
#
############################################################
IARCH="@ARCH@"
ARCH=`uname -m`
if test "$ARCH" != "$IARCH"; then
# identify mappings between kernel arch and debian arch
case "$IARCH:$ARCH" in
armel:armv7l) ;;
arm64:aarch64) ;;
powerpc:ppc) ;;
*)
echo
echo "------------------------------------"
echo "Installer Architecture: $IARCH"
echo "Target Architecture: $ARCH"
echo
echo "This installer cannot be used on this"
echo "target."
echo
echo "------------------------------------"
sleep 5
exit 1
;;
esac
fi
case "$ARCH" in
ppc|powerpc)
ARCH_PPC=$ARCH
;;
x86*|amd*|i?86*)
ARCH_X86=$ARCH
;;
arm*|aarch64)
ARCH_ARM=$ARCH
;;
*)
echo "Invalid Architecture: $ARCH"
sleep 5
exit 1
;;
esac
############################################################
#
# Installation Main
#
# Installation is performed as follows:
#
# 1. Detect whether we are running under ONIE or SwitchLight
# and perform the appropriate setup.
#
# 2. Unpack the installer files.
#
# 3. Source the installer scriptlet for the current platform.
# 4. Run the installer function from the platform scriptlet.
#
# The platform scriptlet determines the entire installation
# sequence.
#
# Most platforms will just call the installation
# utilities in this script with the approprate platform settings.
#
############################################################
set -e
installer_script=${0##*/}
installer_dir=${0%/*}
installer_dir=$(cd $installer_dir && pwd)
installer_zip=$1
installer_tmpfs=
installer_tmpfs_opts=
# installer_tmpfs=??*, installer_tmpfs_opts= --> temporary mount
# installer_tmpfs=??*, installer_tmpfs_opts=??* --> temporary remount
installer_tmpfs_kmin=1048576
# minimum tmpfs/ramfs size to run this installer
# (conservative, could be based on actual installer size)
BOOTDIR=/mnt/onie-boot
# initial boot partition (onie)
# Replaced during build packaging with the current version.
onl_version="@ONLVERSION@"
initrd_archive="@INITRD_ARCHIVE@"
initrd_offset="@INITRD_OFFSET@"
initrd_size="@INITRD_SIZE@"
CR="
"
cd $installer_dir
has_grub_env()
{
local tag
tag=$1; shift
test -f $BOOTDIR/grub/grubenv || return 1
case "`grub-editenv $BOOTDIR/grubenv list` 2>/dev/null" in
*${tag}*) return 0 ;;
esac
return 1
}
has_uboot_env()
{
local tag
tag=$1; shift
test -x /usr/sbin/fw_printenv || return 1
test -f /etc/fw_env.config || return 1
/usr/sbin/fw_printenv $tag 1>/dev/null 2>&1 && return 0
return 1
}
has_boot_env()
{
local tag
tag=$1; shift
has_grub_env $tag && return 0
has_uboot_env $tag && return 0
return 1
}
# Check installer debug option from the boot environment
if has_boot_env onl_installer_debug; then installer_debug=1; fi
if test "$installer_debug"; then
echo "Debug mode"
set -x
installer_wait=30
else
installer_wait=3
fi
# Pickup ONIE defines for this machine.
if test "$onie_platform"; then
:
else
onie_platform=$(onie-sysinfo -p 2>/dev/null) || :
fi
if test "$onie_arch"; then
:
else
onie_arch=$(onie-sysinfo -c 2>/dev/null) || :
fi
if test "$onie_platform"; then
:
elif test -r /etc/machine.conf; then
. /etc/machine.conf
fi
visit_proc_mounts() {
local ifs line dummy fn rest sts
fn=$1; shift
rest="$@"
ifs=$IFS; IFS=$CR
for line in $(cat /proc/mounts); do
IFS=$ifs
if eval $fn $line $rest; then
:
else
sts=$?
if test $sts -eq 2; then break; fi
return $sts
fi
done
IFS=$ifs
return 0
}
#
# Installation environment setup.
#
installer_umount() {
local cwd mpt tdir
cwd=$PWD
cd /
tdir=${TMPDIR-"/tmp"}
for mpt in $(cat /proc/mounts | cut -d' ' -f2 | sort -r); do
case "$mpt" in
"$tdir"/*)
installer_say "Unmounting $mpt"
umount "$mpt"
;;
esac
done
# handle installer_tmpfs specially
if test "$installer_tmpfs"; then
if grep -q " $installer_tmpfs " /proc/mounts; then
if test "$installer_tmpfs_opts"; then
# remount if still mounted
case ",$installer_tmpfs_opts," in
*,size=*,*) ;;
*)
# default if unspecified is 50% of physical memory
installer_tmpfs_opts=${installer_tmpfs_opts},size=50%
;;
esac
installer_say "Remounting $installer_tmpfs with options $installer_tmpfs_opts"
mount -o remount,$installer_tmpfs_opts $installer_tmpfs
elif test "$installer_tmpfs" != "/tmp"; then
# else unmount if still mounted
installer_say "Unmounting $installer_tmpfs"
umount "$installer_tmpfs"
rmdir "$installer_tmpfs"
fi
fi
fi
cd $cwd || :
return 0
}
if test "${onie_platform}"; then
# Running under ONIE, most likely in the background in installer mode.
# Our messages have to be sent to the console directly, not to stdout.
installer_say()
{
echo "$@" > /dev/console
}
# Installation failure message.
installer_cleanup()
{
installer_say "Install failed."
cat /var/log/onie.log > /dev/console
installer_say "Install failed. See log messages above for details"
installer_umount
if installer_reboot $installer_wait; then
:
else
sync
sleep 3
reboot
fi
}
else
if test "$ARCH_X86"; then
echo "Missing onie_platform (invalid or missing onie-sysinfo or /etc/machine.conf)" 1>&2
exit 1
fi
#
# Assume we are running in an interactive environment
#
installer_say()
{
echo
echo "* $@"
echo
}
installer_cleanup()
{
installer_say "Install failed."
installer_umount
exit 1
}
fi
trap "installer_cleanup" 0 1
# Find a suitable location for TMPDIR
scan_tmpfs() {
local dev mpt fstype opts tdir
dev=$1; shift
mpt=$1; shift
fstype=$1; shift
opts=$1; shift
shift
shift
tdir="$1"
case "$fstype" in
ramfs|tmpfs) ;;
*) return 0 ;;
esac
case "$tdir" in
"$mpt"|"$mpt"/*)
d1=$(stat -c '%D' "$tdir")
d2=$(stat -c '%D' $mpt)
if test "$d1" = "$d2"; then
installer_say "Found installer $fstype on $installer_dir ($mpt) using opts $opts"
installer_tmpfs=$mpt
installer_tmpfs_opts=${opts:-"defaults"}
return 2
fi
;;
esac
return 0
}
# maybe installer script was unpacked to a tmpfs/ramfs filesystem
if test -z "$installer_tmpfs" -a "$installer_dir"; then
visit_proc_mounts scan_tmpfs "$installer_dir"
if test "$installer_tmpfs"; then
TMPDIR="$installer_dir"
export TMPDIR
fi
fi
# maybe TMPDIR is on a tmpfs/ramfs filesystem
if test -z "$installer_tmpfs" -a "$TMPDIR"; then
visit_proc_mounts scan_tmpfs "$TMPDIR"
if test "$installer_tmpfs"; then
:
else
installer_say "TMPDIR $TMPDIR is not actually tmpfs, ignoring"
unset TMPDIR
fi
fi
# else, hopefully /tmp is a tmpfs/ramfs
if test -z "$installer_tmpfs"; then
visit_proc_mounts scan_tmpfs /tmp
if test "$installer_tmpfs"; then
TMPDIR=/tmp
export TMPDIR
fi
fi
if test "$installer_tmpfs"; then
set dummy $(df -k $installer_tmpfs | tail -1)
if test $3 -lt $installer_tmpfs_kmin; then
installer_say "Resizing tmpfs $installer_tmpfs to ${installer_tmpfs_kmin}k"
mount -o remount,size=${installer_tmpfs_kmin}k $installer_tmpfs
else
# existing installer_tmpfs is fine,
# no need to unmount or remount
installer_tmpfs=
installer_tmpfs_opts=
fi
else
installer_say "Creating tmpfs for installer"
installer_tmpfs=$(mktemp -d -t installer-tmpfs-XXXXXX)
installer_tmpfs_opts=
mount -t tmpfs -o size=1024m tmpfs $installer_tmpfs
export TMPDIR=$installer_tmpfs
fi
# Unpack our distribution
if test "${installer_unpack_only}"; then
installer_list=
else
installer_list=$initrd_archive
fi
installer_unzip() {
local zip tmp dummy
zip=$1; shift
installer_say "Extracting from $zip: $@ ..."
tmp=$(mktemp -d -t "unzip-XXXXXX")
if test "$SFX_PAD"; then
# ha ha, busybox cannot exclude multiple files
unzip -o $zip "$@" -x $SFX_PAD -d $tmp
elif test "$SFX_UNZIP"; then
unzip -o $zip "$@" -x $installer_script -d $tmp
else
dd if=$zip bs=$SFX_BLOCKSIZE skip=$SFX_BLOCKS \
| unzip -o - "$@" -x $installer_script -d $tmp
fi
rm -f $tmp/$installer_script
if test "$SFX_PAD"; then
rm -f $tmp/$SFX_PAD
fi
set dummy $tmp/*
if test -e "$2"; then
shift
while test $# -gt 0; do
mv "$1" .
shift
done
else
installer_say "Extracting from $zip: no files extracted"
fi
return 0
}
installer_say "Unpacking ONL installer files..."
installer_unzip $installer_zip $installer_list
# Developer debugging
if has_boot_env onl_installer_unpack_only; then installer_unpack_only=1; fi
if test "${installer_unpack_only}"; then
installer_say "Unpack only requested."
exit 1
fi
rootdir=$(mktemp -d -t "initrd-XXXXXX")
installer_say "Extracting initrd to $rootdir"
if test "$initrd_offset"; then
tmprd=$(mktemp -t initrd-XXXXXX)
dd if="$initrd_archive" of="$tmprd" bs="$initrd_offset" skip=1
dd if=/dev/null of="$tmprd" bs="$initrd_size" seek=1
initrd=$tmprd
else
initrd="${installer_dir}/$initrd_archive"
fi
gzip -dc "$initrd" | ( cd "$rootdir" && cpio -imd )
# get common installer functions
. "${rootdir}/lib/vendor-config/onl/install/lib.sh"
installer_mkchroot "${rootdir}"
# make the installer available to the chroot
mkdir -p "${rootdir}/mnt/installer"
mount -o ro,bind "${installer_dir}" "${rootdir}/mnt/installer"
blkid_find_onie() {
local dev label
dev=$1; shift
label=$1; shift
rest="$@"
installer_say "Examining $dev --> $label"
if test "$label" = "ONIE-BOOT"; then
installer_say "Found ONIE-BOOT at $dev"
ONIE_BOOT_DEVICE="$dev"
return 2
fi
# not found, skip
return 0
}
# make sure onie-boot is mounted
if test -d /mnt/onie-boot; then
if grep -q " /mnt/onie-boot " /proc/mounts; then
:
else
ONIE_BOOT_DEVICE=
visit_blkid blkid_find_onie
if test -b "$ONIE_BOOT_DEVICE"; then
installer_say "Mounting ONIE-BOOT ($ONIE_BOOT_DEVICE) as /mnt/onie-boot"
mount -o defaults,rw $ONIE_BOOT_DEVICE /mnt/onie-boot
else
installer_say "*** missing ONIE-BOOT device"
fi
fi
if grep -q " /mnt/onie-boot " /proc/mounts; then
# make the onie boot files available to the chroot
mkdir -p "${rootdir}/mnt/onie-boot"
mount -o ro,bind "/mnt/onie-boot" "${rootdir}/mnt/onie-boot"
fi
fi
# generate config for installer environment
mkdir -p "${rootdir}/etc/onl"
cp /dev/null "${rootdir}/etc/onl/installer.conf"
echo "onl_version=\"$onl_version\"" >> "${rootdir}/etc/onl/installer.conf"
# pass in the platform identifier, otherwise encoded in
# machine-XXX.conf and onie-sysinfo
echo "onie_platform=$onie_platform" >> "${rootdir}/etc/onl/installer.conf"
echo "onie_arch=$onie_arch" >> "${rootdir}/etc/onl/installer.conf"
# Generate the MD5 signature for ourselves for future reference.
installer_md5=$(md5sum "$0" | awk '{print $1}')
echo "installer_md5=\"$installer_md5\"" >> "${rootdir}/etc/onl/installer.conf"
# expose the zip file for later expansion by the initrd
case "$installer_zip" in
"${installer_dir}"/*)
echo "installer_zip=\"${installer_zip##*/}\"" >> "${rootdir}/etc/onl/installer.conf"
;;
*)
zf=$(mktemp "$rootdir/mnt/installer/installer-zip-XXXXXX")
installer_say "Exposing installer archive $installer_zip as $zf"
mount --bind "$installer_zip" $zf
echo "installer_zip=\"${zf##*/}\"" >> "${rootdir}/etc/onl/installer.conf"
;;
esac
# Cache our install URL if available
if test -f "$0.url"; then
installer_url=$(cat "$0.url")
echo "installer_url=\"$installer_url\"" >> "${rootdir}/etc/onl/installer.conf"
fi
echo "installer_dir=/mnt/installer" >> "${rootdir}/etc/onl/installer.conf"
# include access details for the initrd
if test "$initrd_offset"; then
echo "initrd_archive=\"$initrd_archive\"" >> "${rootdir}/etc/onl/installer.conf"
echo "initrd_offset=\"$initrd_offset\"" >> "${rootdir}/etc/onl/installer.conf"
echo "initrd_size=\"$initrd_size\"" >> "${rootdir}/etc/onl/installer.conf"
fi
postinst=$(mktemp -t postinst-XXXXXX)
b=${postinst##*/}
echo "installer_chroot=\"${rootdir}\"" >> "${rootdir}/etc/onl/installer.conf"
echo "installer_postinst=\"/mnt/installer/$b\"" >> "${rootdir}/etc/onl/installer.conf"
# for now, skip the other dot-files in /etc/onl, we do not need them
# to enable initial install
# no special handling for /tmp or /run, since this is all in /tmp
# anyway
installer_say "Launching ONL installer"
installer_shell_dfl="/usr/bin/onl-install --force"
installer_shell=${installer_shell-"$installer_shell_dfl"}
# default, unmount flash filesystems and run the installer script
# Ugh, unmount /mnt filesystems here,
# they are not accessible from within the chroot
installer_force_umount() {
local dev mpt
dev=$1; shift
mpt=$1; shift
case "$mpt" in
/mnt/*|/boot/*)
installer_say "Unmounting $mpt (--force)"
umount "$mpt"
;;
esac
}
if test "$installer_shell" = "$installer_shell_dfl"; then
visit_proc_mounts installer_force_umount
else
installer_say "*** using non-default installer command: $installer_shell"
installer_say "*** watch out for lingering mount-points"
fi
installer_unzip $installer_zip preinstall.sh || :
if test -f preinstall.sh; then
installer_say "Invoking pre-install actions"
chmod +x preinstall.sh
./preinstall.sh $rootdir
fi
# make sure any GPT data is valid and clean
installer_fixup_gpt || :
chroot "${rootdir}" $installer_shell
if test -f "$postinst"; then
installer_say "Invoking post-install actions"
set -x
. "$postinst"
set +x
fi
installer_unzip $installer_zip postinstall.sh || :
if test -f postinstall.sh; then
chmod +x postinstall.sh
./postinstall.sh $rootdir
fi
trap - 0 1
installer_umount
if test "${onie_platform}"; then
installer_reboot $installer_wait
fi
exit
# Local variables:
# mode: sh
# sh-basic-offset: 2
# End:
# Do not add any additional whitespace after this point.