mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2026-01-10 17:21:46 +00:00
603 lines
14 KiB
Bash
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.
|