kiwi-el8/kiwi/boot/functions.sh
Marcus Schäfer e612e4e5cf
Fixup setupMachineID
Cleaning up existing machine id files by deleting them
causes an interactive session to be started by systemd
This is something we don't want. As the consequences
of touching the machine id files seems to be too critical
the method has been turned into a hook caller. This
allows the user to make use of it on their own purpose
and by default doesn't mess with the machine id files
2017-01-26 11:35:13 +01:00

9677 lines
305 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#================
# FILE : functions.sh
#----------------
# PROJECT : openSUSE Build-Service
# COPYRIGHT : (c) 2006 SUSE LINUX Products GmbH, Germany
# :
# AUTHOR : Marcus Schaefer <ms@suse.de>
# :
# BELONGS TO : Operating System images
# :
# DESCRIPTION : This module contains common used functions
# : for the suse linuxrc and preinit boot image
# : files
# :
# :
# STATUS : Development
#----------------
#======================================
# Exports (General)
#--------------------------------------
export BOOTABLE_FLAG="$(echo -ne '\x80')"
export ELOG_FILE=/var/log/boot.kiwi
export TRANSFER_ERRORS_FILE=/tmp/transfer.errors
export UFONT=/usr/share/fbiterm/fonts/b16.pcf.gz
export CONSOLE_FONT=/usr/share/kbd/consolefonts/default8x16.gz
export HYBRID_PERSISTENT_FILENAME="Live OS's persistent storage.fs"
export HYBRID_PERSISTENT_FS=btrfs
export HYBRID_PERSISTENT_ID=83
export HYBRID_PERSISTENT_DIR=/read-write
export UTIMER_INFO=/dev/utimer
export bootLoaderOK=0
export enablePlymouth=1
export IFS_ORIG=$IFS
export MEDIACHECK_OK_TIMER=5
export partitionerWriteStatus=0
#======================================
# lookup
#--------------------------------------
function lookup {
bash -c "PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin type -p $1"
}
#======================================
# Exports (hybrid filesystem options)
#--------------------------------------
# Optimized for 512kB erase block size
export HYBRID_EXT4_OPTS="-b 4096 -O ^has_journal -E stride=128,stripe-width=128"
#======================================
# Exports (console)
#--------------------------------------
test -z "$ELOG_BOOTSHELL" && export ELOG_BOOTSHELL=/dev/tty2
test -z "$ELOG_EXCEPTION" && export ELOG_EXCEPTION=/dev/console
#======================================
# Exports (General)
#--------------------------------------
test -z "$RECOVERY_THEME" && export RECOVERY_THEME=openSUSE
test -z "$arch" && export arch=$(uname -m)
test -z "$haveDASD" && export haveDASD=0
test -z "$haveZFCP" && export haveZFCP=0
test -z "$ELOG_STOPPED" && export ELOG_STOPPED=0
test -z "$PARTITIONER" && export PARTITIONER=parted
test -z "$DEFAULT_VGA" && export DEFAULT_VGA=0x314
test -z "$HAVE_MODULES_ORDER" && export HAVE_MODULES_ORDER=1
test -z "$DIALOG_LANG" && export DIALOG_LANG=ask
test -z "$TERM" && export TERM=linux
test -z "$LANG" && export LANG=en_US.utf8
test -z "$UTIMER" && export UTIMER=0
test -z "$PARTED_HAVE_ALIGN" && export PARTED_HAVE_ALIGN=0
test -z "$PARTED_HAVE_MACHINE"&& export PARTED_HAVE_MACHINE=0
test -z "$DHCPCD_HAVE_PERSIST"&& export DHCPCD_HAVE_PERSIST=1
if lookup parted &>/dev/null;then
if parted -h | grep -q '\-\-align';then
export PARTED_HAVE_ALIGN=1
fi
if parted -h | grep -q '\-\-machine';then
export PARTED_HAVE_MACHINE=1
fi
if [ $PARTED_HAVE_MACHINE -eq 0 ];then
export PARTITIONER=unsupported
fi
fi
if lookup dhcpcd &>/dev/null;then
if dhcpcd -p 2>&1 | grep -q 'Usage';then
export DHCPCD_HAVE_PERSIST=0
fi
fi
#======================================
# Exports (arch specific)
#--------------------------------------
if [[ $arch =~ ppc64 ]];then
test -z "$loader" && export loader=grub2
elif [[ $arch =~ arm ]];then
test -z "$loader" && export loader=grub2
elif [[ $arch =~ s390 ]];then
test -z "$loader" && export loader=zipl
else
test -z "$loader" && export loader=grub2
fi
#======================================
# Exports boot options
#--------------------------------------
failsafe="ide=nodma apm=off noresume edd=off"
failsafe="$failsafe powersaved=off nohz=off"
failsafe="$failsafe highres=off processsor.max+cstate=1"
failsafe="$failsafe nomodeset x11failsafe"
#======================================
# hideSplash
#--------------------------------------
function hideSplash {
# /.../
# Hides the splash screen for to allow interactive
# dialog sessions on this console. Also, the user can
# control a custom behavior using the handleSplash
# hook called at the end of this function
# ----
local IFS=$IFS_ORIG
test -e /proc/splash && echo verbose > /proc/splash
if lookup plymouthd &>/dev/null;then
plymouth hide-splash
# reset tty after plymouth messed with it
consoleInit
fi
runHook handleSplash "$@"
}
#======================================
# Debug
#--------------------------------------
function Debug {
# /.../
# print message if variable DEBUG is set to 1
# -----
local IFS=$IFS_ORIG
if test "$DEBUG" = 1;then
echo "+++++> $1"
fi
}
#======================================
# Echo
#--------------------------------------
function Echo {
# /.../
# print a message to the controling terminal
# ----
local IFS=$IFS_ORIG
if [ $ELOG_STOPPED = 0 ];then
set +x
fi
if [ ! $UTIMER = 0 ] && kill -0 $UTIMER &>/dev/null;then
kill -HUP $UTIMER
local prefix=$(cat $UTIMER_INFO)
else
local prefix="===>"
fi
local option=""
local optn=""
local opte=""
while getopts "bne" option;do
case $option in
b) prefix=" " ;;
n) optn="-n" ;;
e) opte="-e" ;;
*) echo "Invalid argument: $option" ;;
esac
done
shift $(($OPTIND - 1))
if [ $ELOG_STOPPED = 0 ];then
set -x
fi
echo $optn $opte "$prefix $1"
if [ $ELOG_STOPPED = 0 ];then
set +x
fi
OPTIND=1
if [ $ELOG_STOPPED = 0 ];then
set -x
fi
}
#======================================
# WaitKey
#--------------------------------------
function WaitKey {
# /.../
# if DEBUG is set wait for ENTER to continue
# ----
local IFS=$IFS_ORIG
if test "$DEBUG" = 1;then
Echo -n "Press ENTER to continue..."
read
fi
}
#======================================
# importFile
#--------------------------------------
function importFile {
# /.../
# import the config.<MAC> style format. the function
# will export each entry of the file as variable into
# the current shell environment
# ----
local IFS=$IFS_ORIG
local prefix=$1
# create clean input, no empty lines and comments
cat - | grep -v '^$' | grep -v '^[ \t]*#' > /tmp/srcme
# remove start/stop quoting from values
sed -i -e s"#\(^[a-zA-Z0-9_]\+\)=[\"']\(.*\)[\"']#\1=\2#" /tmp/srcme
# remove backslash quotes if any
sed -i -e s"#\\\\\(.\)#\1#g" /tmp/srcme
# quote simple quotation marks
sed -i -e s"#'\+#'\\\\''#g" /tmp/srcme
# add '...' quoting to values
sed -i -e s"#\(^[a-zA-Z0-9_]\+\)=\(.*\)#$prefix\1='\2'#" /tmp/srcme
source /tmp/srcme &>/dev/null
while read line;do
key=$(echo "$line" | cut -d '=' -f1)
eval "export $key" &>/dev/null
done < /tmp/srcme
if [ ! -z "$ERROR_INTERRUPT" ];then
Echo -e "$ERROR_INTERRUPT"
systemException "*** interrupted ****" "shell"
fi
}
#======================================
# unsetFile
#--------------------------------------
function unsetFile {
# /.../
# unset variables specified within the given file.
# the file must be in the config.<MAC> style format
# ----
local IFS="
"
local prefix=$1 #change name of key with a prefix
while read line;do
echo $line | grep -qi "^#" && continue
key=`echo "$line" | cut -d '=' -f1`
if [ -z "$key" ];then
continue
fi
Debug "unset $prefix$key"
eval unset "$prefix$key"
done
}
#======================================
# condenseConfigData
#--------------------------------------
function condenseConfigData {
# /.../
# if multiple same config files (config files with same deployment path)
# are present on the CONF line,
# only last one will be kept (this preserves compatibility)
# ----
local IFS=","
local conf=( $1 )
local cconf
local sep=''
for (( i=0; i<${#conf[@]}; i++ ));do
local configDest=`echo "${conf[$i]}" | cut -d ';' -f 2`
if test ! -z $configDest;then
local copythis=1
for (( j=i+1; j<${#conf[@]}; j++ ));do
local cmpconfigDest=`echo "${conf[$j]}" | cut -d ';' -f 2`
if [ "$cmpconfigDest" = "$configDest" ];then
copythis=0
break
fi
done
[ $copythis -eq '1' ] && cconf="${cconf}${sep}${conf[$i]}"
sep=$IFS
fi
done
echo "$cconf"
}
#======================================
# systemException
#--------------------------------------
function systemException {
# /.../
# print a message to the controling terminal followed
# by an action. Possible actions are reboot, wait, shutdown,
# and opening a shell
# ----
local IFS=$IFS_ORIG
set +x
local what=$2
local nuldev=/dev/null
local ttydev=$ELOG_EXCEPTION
local prefix=/mnt
for dev in $nuldev $prefix/$nuldev; do
if [ -e $dev ];then
nuldev=$dev; break
fi
done
for dev in $ttydev $prefix/$ttydev; do
if [ -e $dev ];then
ttydev=$dev; break
fi
done
hideSplash
if lookup plymouthd &>/dev/null && [ $enablePlymouth -eq 1 ]; then
plymouth quit
fi
if [ $what = "reboot" ];then
if cat /proc/cmdline 2>/dev/null | grep -qi "kiwidebug=1";then
what="shell"
fi
fi
runHook preException "$@"
Echo -e "$1"
case "$what" in
"reboot")
# in order to see all log information in case of a reboot exception
# we print the current log contents to the console. On systems like
# public clouds the console information is stored and provided to
# the user. Thus it makes sense to be verbose here
cat $ELOG_FILE
Echo "rebootException: reboot in 120 sec..."; sleep 120
/sbin/reboot -f -i >$nuldev
;;
"wait")
Echo "waitException: waiting for ever..."
while true;do sleep 100;done
;;
"waitkey")
Echo "waitException: Press any key to continue: "
read
;;
"shell")
if [ ! -z "$DROPBEAR_PID" ] && [ ! -z "$IPADDR" ];then
Echo "You can connect via ssh to this system"
Echo "ssh root@${IPADDR}"
fi
echo reset > /root/.bashrc
sulogin -e -p $ttydev
;;
"user_reboot")
Echo "reboot triggered by user"
Echo "reboot in 30 sec..."; sleep 30
/sbin/reboot -f -i >$nuldev
;;
*)
Echo "unknownException..."
;;
esac
}
#======================================
# copyDevices
#--------------------------------------
function copyDeviceNodes {
local IFS=$IFS_ORIG
local search=$1
local prefix=$2
local dtype
local major
local minor
local perms
if [ -z "$search" ];then
search=/dev
fi
pushd $search >/dev/null
for i in *;do
if [ -e $prefix/$i ];then
continue
fi
if [ -b $i ];then
dtype=b
elif [ -c $i ];then
dtype=c
elif [ -p $i ];then
dtype=p
else
continue
fi
info=`stat $i -c "0%a:0x%t:0x%T"`
major=`echo $info | cut -f2 -d:`
minor=`echo $info | cut -f3 -d:`
perms=`echo $info | cut -f1 -d:`
if [ $dtype = "p" ];then
mknod -m $perms $prefix/$i $dtype
else
mknod -m $perms $prefix/$i $dtype $major $minor
fi
done
popd >/dev/null
}
#======================================
# createInitialDevices
#--------------------------------------
function createInitialDevices {
local IFS=$IFS_ORIG
local prefix=$1
#======================================
# create master dev dir
#--------------------------------------
mkdir -p $prefix
if [ ! -d $prefix ];then
return
fi
#======================================
# mount devtmpfs or tmpfs
#--------------------------------------
if mount -t devtmpfs -o mode=0755,nr_inodes=0 devtmpfs $prefix; then
export have_devtmpfs=true
else
export have_devtmpfs=false
mount -t tmpfs -o mode=0755,nr_inodes=0 udev $prefix
mknod -m 0666 $prefix/tty c 5 0
mknod -m 0600 $prefix/console c 5 1
mknod -m 0666 $prefix/ptmx c 5 2
mknod -m 0666 $prefix/null c 1 3
mknod -m 0600 $prefix/kmsg c 1 11
mknod -m 0660 $prefix/snapshot c 10 231
mknod -m 0666 $prefix/random c 1 8
mknod -m 0644 $prefix/urandom c 1 9
fi
#======================================
# mount shared mem tmpfs
#--------------------------------------
mkdir -m 1777 $prefix/shm
mount -t tmpfs -o mode=1777 tmpfs $prefix/shm
#======================================
# mount udev db tmpfs
#--------------------------------------
mkdir -p -m 0755 /run
mkdir -p -m 0755 /var/run
if [[ ! $kiwi_initrdname =~ SLE.11 ]] && \
[[ ! $kiwi_initrdname =~ "rhel-06" ]]
then
mount -t tmpfs -o mode=0755,nodev,nosuid tmpfs /run
mount --bind /run /var/run
fi
#======================================
# mount devpts tmpfs
#--------------------------------------
mkdir -m 0755 $prefix/pts
mount -t devpts -o mode=0620,gid=5 devpts $prefix/pts
#======================================
# link default descriptors
#--------------------------------------
ln -s /proc/self/fd $prefix/fd
ln -s fd/0 $prefix/stdin
ln -s fd/1 $prefix/stdout
ln -s fd/2 $prefix/stderr
#======================================
# create directories in /run
#--------------------------------------
mkdir -p -m 0755 /run/lock
mkdir -p -m 0755 /run/log
}
#======================================
# mount_rpc_pipefs
#--------------------------------------
function mount_rpc_pipefs {
local IFS=$IFS_ORIG
# See if the file system is there yet
if [ ! -e /var/lib/nfs/rpc_pipefs ];then
return 0
fi
case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs 2>/dev/null` in
*67596969*)
return 0;;
esac
mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs
}
#======================================
# umount_rpc_pipefs
#--------------------------------------
function umount_rpc_pipefs {
local IFS=$IFS_ORIG
# See if the file system is there
case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs 2>/dev/null` in
*67596969*)
umount /var/lib/nfs/rpc_pipefs
esac
}
#======================================
# setupNFSServices
#--------------------------------------
function setupNFSServices {
local IFS=$IFS_ORIG
mount_rpc_pipefs
if [ -x /sbin/rpcbind ];then
startproc /sbin/rpcbind
fi
if [ -x /usr/sbin/rpc.statd ];then
startproc /usr/sbin/rpc.statd --no-notify
fi
if [ -x /usr/sbin/rpc.idmapd ];then
startproc /usr/sbin/rpc.idmapd
fi
}
#======================================
# mountSystemFilesystems
#--------------------------------------
function mountSystemFilesystems {
local IFS=$IFS_ORIG
if [ ! -e /proc/cmdline ];then
mount -t proc proc /proc
fi
if [ ! -e /sys/kernel ];then
mount -t sysfs sysfs /sys
fi
if [ -e /run/initramfs/shutdown ];then
chmod u+x /run/initramfs/shutdown
fi
updateMTAB
}
#======================================
# umountSystemFilesystems
#--------------------------------------
function umountSystemFilesystems {
local IFS=$IFS_ORIG
umount_rpc_pipefs
umount /dev/pts &>/dev/null
umount /sys &>/dev/null
umount /proc &>/dev/null
}
#======================================
# createFramebufferDevices
#--------------------------------------
function createFramebufferDevices {
local IFS=$IFS_ORIG
if [ -f /proc/fb ]; then
while read fbnum fbtype; do
if [ $(($fbnum < 32)) ] ; then
if [ ! -c /dev/fb$fbnum ];then
Echo "Creating framebuffer device: /dev/fb$fbnum"
mknod -m 0660 /dev/fb$fbnum c 29 $fbnum
fi
fi
done < /proc/fb
fi
}
#======================================
# errorLogStop
#--------------------------------------
function errorLogStop {
local IFS=$IFS_ORIG
set +x
export ELOG_STOPPED=1
exec < $ELOG_EXCEPTION &> $ELOG_EXCEPTION
}
#======================================
# errorLogContinue
#--------------------------------------
function errorLogContinue {
local IFS=$IFS_ORIG
exec 2>>$ELOG_FILE
exec < $ELOG_EXCEPTION > $ELOG_EXCEPTION
export ELOG_STOPPED=0
set -x
}
#======================================
# errorLogStart
#--------------------------------------
function errorLogStart {
# /.../
# Log all errors and the debug information to the
# file set in ELOG_FILE.
# ----
local IFS=$IFS_ORIG
local umountProc=0
if [ ! -f $ELOG_FILE ];then
#======================================
# Header for main stage log
#--------------------------------------
echo "KIWI Log:" >> $ELOG_FILE
else
#======================================
# Header for pre-init stage log
#--------------------------------------
startUtimer
echo "KIWI PreInit Log" >> $ELOG_FILE
fi
#======================================
# Contents of .profile environment
#--------------------------------------
if [ -f .profile ];then
echo "KIWI .profile contents:" >> $ELOG_FILE
cat .profile >> $ELOG_FILE
fi
#======================================
# Redirect stderr to ELOG_FILE
#--------------------------------------
exec 2>>$ELOG_FILE
#======================================
# Mount proc for cmdline quiet check
#--------------------------------------
if [ ! -e /proc/cmdline ];then
mount -t proc proc /proc
umountProc=1
fi
if cat /proc/cmdline | grep -qi "quiet";then
#======================================
# Redirect/Clean stdout if quiet is set
#--------------------------------------
if [ -x /usr/bin/setterm ];then
setterm -clear all
setterm -background black
fi
exec >/dev/null
else
#======================================
# Redirect stdout to console
#--------------------------------------
exec < $ELOG_EXCEPTION > $ELOG_EXCEPTION
fi
#======================================
# Clean proc
#--------------------------------------
if [ $umountProc -eq 1 ];then
umount /proc &>/dev/null
fi
#======================================
# Enable shell debugging
#--------------------------------------
set -x
}
#======================================
# udevPending
#--------------------------------------
function udevPending {
local IFS=$IFS_ORIG
local umountProc=0
if [ ! -e /proc/cmdline ];then
mount -t proc proc /proc
umountProc=1
fi
local timeout=30
local udevadmExec=$(lookup udevadm 2>/dev/null)
if [ -x $udevadmExec ];then
$udevadmExec settle --timeout=$timeout
else
# udevsettle exists on old distros and is not
# affected by the move from sbin to usr
/sbin/udevsettle --timeout=$timeout
fi
if [ $umountProc -eq 1 ];then
umount /proc
fi
}
#======================================
# udevTrigger
#--------------------------------------
function udevTrigger {
local IFS=$IFS_ORIG
local udevadmExec=$(lookup udevadm 2>/dev/null)
if [ -x $udevadmExec ];then
$udevadmExec trigger
else
/sbin/udevtrigger
fi
}
#======================================
# udevSystemStart
#--------------------------------------
function udevSystemStart {
# /.../
# start udev daemon
# ----
local IFS=$IFS_ORIG
local udev_bin=/usr/lib/systemd/systemd-udevd
if [ ! -x $udev_bin ];then
udev_bin=/sbin/udevd
fi
if [ ! -x $udev_bin ];then
udev_bin=/lib/udev/udevd
fi
if [ ! -x $udev_bin ];then
udev_bin=/lib/systemd/systemd-udevd
fi
if [ ! -x $udev_bin ];then
systemException \
"Can't find udev daemon" \
"reboot"
fi
$udev_bin --daemon
export UDEVD_PID=$(pidof $udev_bin | tr ' ' ,)
}
#======================================
# udevSystemStop
#--------------------------------------
function udevSystemStop {
# /.../
# stop udev while in pre-init phase.
# ----
local IFS=$IFS_ORIG
local udevadmExec=$(lookup udevadm 2>/dev/null)
local umountProc=0
if [ ! -e "/proc/mounts" ];then
mount -t proc proc /proc
umountProc=1
fi
if [ -x $udevadmExec ];then
# ignore error messages here, because if the process is not
# stopped properly here, it will be killed the hard way a few
# lines down
$udevadmExec control --exit &>/dev/null
fi
if [ -z "$UDEVD_PID" ];then
. /iprocs
fi
local IFS=,
for p in $UDEVD_PID; do
if kill -0 $p &>/dev/null;then
udevPending
kill $p
fi
done
if [ $umountProc -eq 1 ];then
umount /proc
fi
}
#======================================
# udevStart
#--------------------------------------
function udevStart {
# /.../
# start the udev daemon.
# ----
local IFS=$IFS_ORIG
local enableFips=0
#======================================
# Check time according to build day
#--------------------------------------
if [ -f /build_day ];then
importFile < /build_day
current_day="$(LC_ALL=C date -u '+%Y%m%d')"
if [ "$current_day" -lt "$build_day" ] ; then
LC_ALL=C date -us "$build_day"
sleep 3
export SYSTEM_TIME_INCORRECT=$current_day
fi
fi
#======================================
# Check for modules.order
#--------------------------------------
if ! ls /lib/modules/*/modules.order &>/dev/null;then
# /.../
# without modules.order in place we prevent udev from loading
# the storage modules because it does not make a propper
# choice if there are multiple possible modules available.
# Example:
# udev prefers ata_generic over ata_piix but the hwinfo
# order is ata_piix first which also seems to make more
# sense.
# -----
rm -f /etc/udev/rules.d/*-drivers.rules
rm -f /lib/udev/rules.d/*-drivers.rules
HAVE_MODULES_ORDER=0
fi
#======================================
# Start the daemon
#--------------------------------------
# static nodes
createInitialDevices /dev
# load modules required before udev
moduleLoadBeforeUdev
# start the udev daemon
udevSystemStart
echo UDEVD_PID=$UDEVD_PID >> /iprocs
# trigger events for all devices
udevTrigger
# wait for events to finish
udevPending
# init console
consoleInit
# start plymouth if it exists and enabled
for o in $(cat /proc/cmdline) ; do
case "$o" in
plymouth.enable=0*|rd.plymouth=0*)
enablePlymouth=0
;;
fips=1*)
enableFips=1
;;
esac
done
if [ $enablePlymouth -eq 1 ]; then
startPlymouth
fi
if [ $enableFips -eq 1 ];then
startHaveged
fi
}
#======================================
# moduleLoadBeforeUdev
#--------------------------------------
function moduleLoadBeforeUdev {
# /.../
# load modules which have to be loaded before the
# udev daemon is started in this function
# ----
loadAGPModules
}
#======================================
# loadAGPModules
#--------------------------------------
function loadAGPModules {
local IFS=$IFS_ORIG
local krunning=$(uname -r)
for i in /lib/modules/$krunning/kernel/drivers/char/agp/*; do
test -e $i || continue
modprobe $(echo $i | sed "s#.*\\/\\([^\\/]\\+\\).ko#\\1#")
done
}
#======================================
# udevKill
#--------------------------------------
function udevKill {
local IFS=$IFS_ORIG
udevSystemStop
}
#======================================
# activeConsoles
#--------------------------------------
function activeConsoles {
local IFS=$IFS_ORIG
for i in $(cat /sys/class/tty/console/active 2>/dev/null);do
echo $i
done | wc -l
}
#======================================
# consoleInit
#--------------------------------------
function consoleInit {
local IFS=$IFS_ORIG
local udev_console=/lib/udev/console_init
if [ ! -x $udev_console ];then
udev_console=/lib/udev/console-setup-tty
fi
local systemd_console=/usr/lib/systemd/systemd-vconsole-setup
if [ -x $udev_console ];then
$udev_console /dev/console
elif [ -x $systemd_console ];then
$systemd_console
fi
}
#======================================
# startPlymouth
#--------------------------------------
function startPlymouth {
local IFS=$IFS_ORIG
local consoledev
if lookup plymouthd &>/dev/null;then
# first trigger graphics subsystem
udevadm trigger --action=add --attr-match=class=0x030000 &>/dev/null
# next trigger graphics and tty subsystem
udevadm trigger --action=add --subsystem-match=graphics \
--subsystem-match=drm --subsystem-match=tty &>/dev/null
udevadm settle --timeout=30
mkdir --mode 755 /run/plymouth
consoleInit
plymouth-set-default-theme $kiwi_splash_theme &>/dev/null
plymouthd --attach-to-session --pid-file /run/plymouth/pid &>/dev/null
plymouth show-splash &>/dev/null
# reset tty after plymouth messed with it
consoleInit
fi
}
#======================================
# startHaveged
#--------------------------------------
function startHaveged {
if ! lookup haveged &>/dev/null; then
systemException \
"haveged is missing but required for fips" \
"reboot"
fi
if ! haveged; then
systemException \
"Failed to start haveged required for fips" \
"reboot"
fi
}
#======================================
# startDropBear
#--------------------------------------
function startDropBear {
# /.../
# start dropbear ssh server if installed
# ---
local IFS=$IFS_ORIG
local auth_keys="/root/.ssh/authorized_keys"
if [ -z "$kiwidebug" ];then
return
fi
if lookup dropbear &>/dev/null;then
mkdir -p /root/.ssh
fetchFile KIWI/debug_ssh.pub $auth_keys
if [ ! -e $auth_keys ]; then
return
fi
mkdir -p /etc/dropbear
if [ ! -f /etc/dropbear/dropbear_dss_host_key ];then
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
fi
if [ ! -f /etc/dropbear/dropbear_rsa_host_key ];then
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
fi
Echo "Starting dropbear ssh server"
dropbear
export DROPBEAR_PID=$(pidof /usr/sbin/dropbear)
echo DROPBEAR_PID=$DROPBEAR_PID >> /iprocs
fi
}
#======================================
# readVolumeSetup
#--------------------------------------
function readVolumeSetup {
# /.../
# read the volume setup from the profile file and return
# a list with the following values:
#
# volume_name,resize_mode,requested_size,mount_point ...
# ----
local profile=$1
local skip_all_free_volume=$2
local volume
local name
local mode
local size
local mpoint
local result
for i in $(cat $profile | grep -E "kiwi_Volume_");do
volume=$(echo $i | cut -f2 -d= | tr -d \' | tr -d \")
size=$(echo $volume | cut -f2 -d\| | cut -f2 -d:)
if [ $size = "all" ] && [ ! -z "$skip_all_free_volume" ];then
continue
fi
mode=$(echo $volume | cut -f2 -d\| | cut -f1 -d:)
name=$(echo $volume | cut -f1 -d\|)
mpoint=$(echo $volume | cut -f3 -d\|)
if [ -z "$mpoint" ];then
mpoint='noop'
fi
if [ -z "$result" ];then
result="$name,$mode,$size,$mpoint"
else
result="$result $name,$mode,$size,$mpoint"
fi
done
echo $result
}
#======================================
# readVolumeSetupAllFree
#--------------------------------------
function readVolumeSetupAllFree {
# /.../
# read the volume setup for kiwi_allFreeVolume from the profile
# file and return a list with the following values:
#
# volume_name,mount_point
#
# If no kiwi_allFreeVolume was configured only the default
# volume_name which takes the rest space is returned
# ----
local profile=$1
local size
local volume
local name
local mpoint
for i in $(cat $profile | grep -E "kiwi_Volume_");do
volume=$(echo $i | cut -f2 -d= | tr -d \' | tr -d \")
size=$(echo $volume | cut -f2 -d\| | cut -f2 -d:)
if [ $size = "all" ];then
name=$(echo $volume | cut -f1 -d\|)
mpoint=$(echo $volume | cut -f3 -d\|)
echo "$name,$mpoint"
return
fi
done
echo LVRoot,
}
#======================================
# getVolumeName
#--------------------------------------
function getVolumeName {
echo $1 | cut -f1 -d,
}
#======================================
# getVolumeMountPoint
#--------------------------------------
function getVolumeMountPoint {
echo $1 | cut -f4 -d,
}
#======================================
# getVolumeSizeMode
#--------------------------------------
function getVolumeSizeMode {
echo $1 | cut -f2 -d,
}
#======================================
# getVolumeSize
#--------------------------------------
function getVolumeSize {
echo $1 | cut -f3 -d,
}
#======================================
# installBootLoader
#--------------------------------------
function installBootLoader {
# /.../
# generic function to install the boot loader.
# The selection of the bootloader happens according to
# the architecture of the system
# ----
local IFS=$IFS_ORIG
local arch=$(uname -m)
runHook preInstallBootLoader
case $arch-$loader in
i*86-grub2) installBootLoaderGrub2 ;;
s390*-grub2) installBootLoaderGrub2 ;;
x86_64-grub2) installBootLoaderGrub2 ;;
ppc64*-grub2) installBootLoaderGrub2 ;;
s390-zipl) installBootLoaderS390 ;;
s390x-zipl) installBootLoaderS390 ;;
s390x-grub2_s390x_emu) installBootLoaderS390Grub ;;
aarch64-grub2) installBootLoaderGrub2 ;;
*)
systemException \
"*** boot loader install for $arch-$loader not implemented ***" \
"reboot"
esac
#
# Warning message is disabled because sometimes the message
# can't be displayed on the console which leads to a stopped
# system but the user has no clue why
#
#if [ ! $? = 0 ];then
# if lookup dialog &>/dev/null;then
# Dialog \
# --backtitle \"$TEXT_BOOT_SETUP_FAILED\" \
# --msgbox "\"$TEXT_BOOT_SETUP_FAILED_INFO\"" 10 70
# else
# systemException \
# "$TEXT_BOOT_SETUP_FAILED\n\n$TEXT_BOOT_SETUP_FAILED_INFO" \
# "waitkey"
# fi
#fi
case $arch in
i*386|x86_64)
masterBootID=$(printf 0x%04x%04x $RANDOM $RANDOM)
Echo "writing new MBR ID to master boot record: $masterBootID"
echo $masterBootID > /boot/mbrid
masterBootIDHex=$(echo $masterBootID |\
sed 's/^0x\(..\)\(..\)\(..\)\(..\)$/\\x\4\\x\3\\x\2\\x\1/')
echo -e -n $masterBootIDHex | dd of=$imageDiskDevice \
bs=1 count=4 seek=$((0x1b8))
;;
*)
echo "skiped writing MBR ID for $arch"
;;
esac
runHook postInstallBootLoader
}
#======================================
# installBootLoaderRecovery
#--------------------------------------
function installBootLoaderRecovery {
# /.../
# generic function to install the boot loader into
# the recovery partition. The selection of the bootloader
# happens according to the architecture of the system
# ----
local IFS=$IFS_ORIG
local arch=$(uname -m)
case $arch-$loader in
i*86-grub2) installBootLoaderGrub2Recovery ;;
x86_64-grub2) installBootLoaderGrub2Recovery ;;
s390*-grub2) installBootLoaderGrub2Recovery ;;
s390-zipl) installBootLoaderS390Recovery ;;
s390x-zipl) installBootLoaderS390Recovery ;;
*)
systemException \
"*** boot loader setup for $arch-$loader not implemented ***" \
"reboot"
esac
}
#======================================
# installBootLoaderS390Grub
#--------------------------------------
function installBootLoaderS390Grub {
# /.../
# Create/Delete
# - create active_devices.txt
# - delete kiwi initrd/kernel .vmx files
# Run grub2-mkconfig
# - create new boot/grub2/grub.cfg
# Run grub2-install
# - creates a new boot/zipl/config
# - creates zipl initrd which loads grub2/kexec
# - install zipl
# ----
local IFS=$IFS_ORIG
local confTool=grub2-mkconfig
local instTool=grub2-install
local confFile_grub=/boot/grub2/grub.cfg
local active_devs=/boot/zipl/active_devices.txt
local deviceID=$(cat /sys/firmware/ipl/device)
local instTooOptions
if [ "$kiwi_target_removable" = "true" ];then
instTooOptions="--removable"
fi
#======================================
# mount zipl EFI partition
#--------------------------------------
if [ ! -z "$kiwi_EfiPart" ];then
local jdev=$(ddn $imageDiskDevice $kiwi_EfiPart)
local label=$(blkid $jdev -s LABEL -o value)
if [ "$label" = "ZIPL" ];then
mkdir -p /boot/zipl
if ! mount $jdev /boot/zipl;then
Echo "Failed to mount zipl boot partition"
return 1
fi
fi
fi
#======================================
# Create active devices information
#--------------------------------------
echo $deviceID > $active_devs
#======================================
# create grub2 configuration
#--------------------------------------
if ! lookup $confTool &>/dev/null;then
Echo "System image doesn't provide $confTool"
Echo "Can't create bootloader configuration"
return 1
fi
$confTool > $confFile_grub
if [ ! $? = 0 ];then
Echo "Failed to create grub2 boot configuration"
return 1
fi
#======================================
# Run grub2-install
#--------------------------------------
if ! lookup $instTool &>/dev/null;then
Echo "System image doesn't provide $instTool"
Echo "Can't install bootloader"
return 1
fi
if ! $instTool $instTooOptions;then
Echo "Failed to install bootloader"
return 1
fi
#======================================
# Delete kiwi initrd files
#--------------------------------------
rm -f /boot/zipl/*.vmx
#======================================
# umount zipl boot partition
#--------------------------------------
mountpoint -q /boot/zipl && umount /boot/zipl
return 0
}
#======================================
# installBootLoaderS390
#--------------------------------------
function installBootLoaderS390 {
local IFS=$IFS_ORIG
if [ -x /sbin/zipl ];then
Echo "Installing boot loader..."
zipl -c /etc/zipl.conf 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install boot loader"
return 1
fi
else
Echo "Image doesn't have zipl installed"
Echo "Can't install boot loader"
return 1
fi
return 0
}
#======================================
# installBootLoaderGrub2
#--------------------------------------
function installBootLoaderGrub2 {
# /.../
# configure and install grub2 according to the
# contents of /boot/grub2/grub.cfg
# ----
local IFS=$IFS_ORIG
local confTool=grub2-mkconfig
local instTool=grub2-install
local confFile_grub_bios=/boot/grub2/grub.cfg
local confFile_uefi=/boot/efi/EFI/BOOT/grub.cfg
local confFile_grub=$confFile_grub_bios
local bios_grub=/boot/grub2/i386-pc
local product=/etc/products.d/baseproduct
local grub_efi=/boot/efi/EFI/BOOT/grub.efi
local isEFI=0
local instTooOptions
if [ "$kiwi_target_removable" = "true" ];then
instTooOptions="--removable"
fi
#======================================
# check for EFI and mount EFI partition
#--------------------------------------
if [ ! -z "$kiwi_EfiPart" ];then
local jdev=$(ddn $imageDiskDevice $kiwi_EfiPart)
local label=$(blkid $jdev -s LABEL -o value)
if [ "$label" = "EFI" ];then
mkdir -p /boot/efi
if ! mount $jdev /boot/efi;then
Echo "Failed to mount EFI boot partition"
return 1
fi
isEFI=1
fi
fi
if ! lookup $confTool &>/dev/null;then
Echo "Image doesn't have grub2 installed"
Echo "Can't install boot loader"
return 1
fi
#======================================
# create grub2 configuration
#--------------------------------------
$confTool > $confFile_grub
if [ ! $? = 0 ];then
Echo "Failed to create grub2 boot configuration"
return 1
fi
if [ -e $confFile_grub_bios ];then
cp $confFile_grub $confFile_grub_bios
fi
if [ $isEFI -eq 1 ] && [ -e $confFile_uefi ];then
cp $confFile_grub $confFile_uefi
umount /boot/efi
fi
#======================================
# install grub2 in BIOS mode
#--------------------------------------
if [ ! -z "$kiwi_PrepPart" ];then
local prepdev=$(ddn $imageDiskDevice $kiwi_PrepPart)
# install powerpc grub2
$instTool $instTooOptions $prepdev 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install boot loader"
return 1
fi
elif [ $isEFI -eq 0 ];then
# use plain grub2-install in standard bios mode
$instTool $instTooOptions $imageDiskDevice 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install boot loader"
return 1
fi
elif [ ! -z "$kiwi_BiosGrub" ] && [ -d $bios_grub ];then
# force install of bios grub2 in efi legacy mode
$instTool $instTooOptions --force --target i386-pc $imageDiskDevice 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install legacy boot loader"
return 1
fi
else
Echo "No bootloader installation required"
fi
return 0
}
#======================================
# installBootLoaderS390Recovery
#--------------------------------------
function installBootLoaderS390Recovery {
local IFS=$IFS_ORIG
Echo "*** zipl: recovery boot not implemented ***"
return 1
}
#======================================
# installBootLoaderGrub2Recovery
#--------------------------------------
function installBootLoaderGrub2Recovery {
# /.../
# install grub2 into the recovery partition
# By design the recovery partition is always the
# last primary partition of the disk
# ----
local IFS=$IFS_ORIG
local confTool=grub2-mkconfig
local confFile_grub_bios=/boot/grub2/grub.cfg
local confFile_uefi=/boot/efi/EFI/BOOT/grub.cfg
local confFile_grub=$confFile_grub_bios
local bios_grub=/reco-save/boot/grub2/i386-pc
local isEFI=0
#======================================
# check for EFI and mount EFI partition
#--------------------------------------
if [ ! -z "$kiwi_EfiPart" ];then
local jdev=$(ddn $imageDiskDevice $kiwi_EfiPart)
local label=$(blkid $jdev -s LABEL -o value)
if [ "$label" = "EFI" ];then
mkdir -p /boot/efi
if ! mount $jdev /boot/efi;then
Echo "Failed to mount EFI boot partition"
return 1
fi
isEFI=1
fi
fi
#======================================
# check tool status
#--------------------------------------
if ! lookup $confTool &>/dev/null;then
Echo "Image doesn't have grub2 installed"
Echo "Can't install recovery boot loader"
mountpoint -q /boot/efi && umount /boot/efi
return 1
fi
#======================================
# install grub2 into partition
#--------------------------------------
# this allows a bios to directly jump there, e.g with a function key
grub2-bios-setup -f -d $bios_grub $imageRecoveryDevice 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install recovery boot loader"
fi
#======================================
# create custom recovery entry
#--------------------------------------
cat > /etc/grub.d/40_custom << DONE
#!/bin/bash
cat << EOF
menuentry 'Recovery' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
configfile /boot/grub2/grub.cfg
}
EOF
DONE
#======================================
# create grub2 config file
#--------------------------------------
$confTool > $confFile_grub
if [ ! $? = 0 ];then
Echo "Failed to create recovery grub2 boot configuration"
mountpoint -q /boot/efi && umount /boot/efi
return 1
fi
if [ $isEFI -eq 1 ] && [ -e $confFile_uefi ];then
cp $confFile_grub $confFile_uefi
fi
mountpoint -q /boot/efi && umount /boot/efi
return 0
}
#======================================
# updateModuleDependencies
#--------------------------------------
function updateModuleDependencies {
# /.../
# update the kernel module dependencies list
# ---
local IFS=$IFS_ORIG
local depmodExec=$(lookup depmod 2>/dev/null)
if [ ! -x "$depmodExec" ];then
Echo "Could not find depmod executable"
Echo "Skipping module dependency update"
systemIntegrity=unknown
return
fi
if ! $depmodExec -a;then
Echo "Module dependency update failed."
systemIntegrity=unknown
fi
}
#======================================
# setupInitrd
#--------------------------------------
function setupInitrd {
# /.../
# call initrd creation tool to create the distro initrd
# ----
local IFS=$IFS_ORIG
bootLoaderOK=1
local umountProc=0
local umountSys=0
local systemMap=0
local dracutExec=$(lookup dracut 2>/dev/null)
local params
local running
local rlinux
local rinitrd
local kernel_version=$(uname -r)
for i in $(find /boot/ -name "System.map*");do
systemMap=1
done
setupDefaultTheme
if [ $systemMap -eq 1 ];then
#======================================
# Cleanup
#--------------------------------------
rm -f /boot/initrd-*.img
#======================================
# Prepare for tool call
#--------------------------------------
if [ ! -e /proc/mounts ];then
mount -t proc proc /proc
umountProc=1
fi
if [ ! -e /sys/block ];then
mount -t sysfs sysfs /sys
umountSys=1
fi
modprobe dm-mod &>/dev/null
updateModuleDependencies
#======================================
# Call initrd creation tool
#--------------------------------------
if [ -x "$dracutExec" ]; then
params=" --force"
Echo "Creating dracut based initrd"
if ! $dracutExec $params;then
Echo "Can't create initrd with dracut"
systemIntegrity=unknown
bootLoaderOK=0
fi
else
# no tool found
Echo "Coudn't find a tool to create initrd image"
systemIntegrity=unknown
bootLoaderOK=0
fi
#======================================
# Cleanup kiwi firstboot initrd
#--------------------------------------
if [ $bootLoaderOK = "1" ];then
if [ -f /boot/initrd.vmx ];then
rm -f /boot/initrd.vmx
fi
if [ -f /boot/linux.vmx ];then
rm -f /boot/linux.vmx
fi
fi
#======================================
# Cleanup mounts
#--------------------------------------
rmmod dm-mod &>/dev/null
if [ $umountSys -eq 1 ];then
umount /sys
fi
if [ $umountProc -eq 1 ];then
umount /proc
fi
else
Echo "Image doesn't include kernel system map"
Echo "Can't create initrd"
systemIntegrity=unknown
bootLoaderOK=0
fi
}
#======================================
# setupDefaultTheme
#--------------------------------------
function setupDefaultTheme {
local IFS=$IFS_ORIG
if lookup plymouthd &>/dev/null;then
plymouth-set-default-theme $kiwi_splash_theme &>/dev/null
fi
}
#======================================
# setupBootLoader
#--------------------------------------
function setupBootLoader {
# /.../
# generic function to setup the boot loader configuration.
# The selection of the bootloader happens according to
# the architecture of the system
# ----
local IFS=$IFS_ORIG
local arch=`uname -m`
local para=""
while [ $# -gt 0 ];do
# quote simple quotation marks
arg=$(echo $1 | sed -e s"#'#'\\\\''#g")
para="$para '$arg'"
shift
done
runHook preSetupBootLoader
case $arch-$loader in
i*86-grub2) eval setupBootLoaderGrub2 $para ;;
x86_64-grub2) eval setupBootLoaderGrub2 $para ;;
ppc64*-grub2) eval setupBootLoaderGrub2 $para ;;
s390*-grub2) eval setupBootLoaderGrub2 $para ;;
s390x-grub2_s390x_emu) eval setupBootLoaderS390Grub $para ;;
aarch64-grub2) eval setupBootLoaderGrub2 $para ;;
arm*-grub2) eval setupBootLoaderGrub2 $para ;;
*)
systemException \
"*** boot loader setup for $arch-$loader not implemented ***" \
"reboot"
esac
setupBootThemes "/config"
runHook postSetupBootLoader
}
#======================================
# setupBootThemes
#--------------------------------------
function setupBootThemes {
local IFS=$IFS_ORIG
local destprefix=$1
local prefix=$2
if [ -z "$prefix" ];then
prefix=/mnt
fi
#======================================
# Splash theme setup
#--------------------------------------
if [ ! -z "$kiwi_splash_theme" ];then
local theme=$kiwi_splash_theme
#======================================
# gfxboot default setup
#--------------------------------------
local orig_bootsplash=$prefix/etc/sysconfig/bootsplash
local inst_bootsplash=$destprefix/etc/sysconfig/bootsplash
mkdir -p $destprefix/etc/sysconfig
touch $inst_bootsplash
#======================================
# check for bootsplash config in sysimg
#--------------------------------------
if [ -f $orig_bootsplash ];then
cp $orig_bootsplash $inst_bootsplash
fi
#======================================
# change/create bootsplash config
#--------------------------------------
if cat $inst_bootsplash | grep -q -E "^THEME"; then
sed -i "s/^THEME=.*/THEME=\"$theme\"/" $inst_bootsplash
else
echo "THEME=\"$theme\"" >> $inst_bootsplash
fi
#======================================
# plymouth splash
#--------------------------------------
if lookup plymouthd &>/dev/null;then
local orig_plymouthconf=$prefix/etc/plymouth/plymouth.conf
local inst_plymouthconf=$destprefix/etc/plymouth/plymouth.conf
mkdir -p $destprefix/etc/plymouth
touch $inst_plymouthconf
#======================================
# check for plymouth config in sysimg
#--------------------------------------
if [ -f $orig_plymouthconf ];then
cp $orig_plymouthconf $inst_plymouthconf
fi
#======================================
# change/create plymouth config
#--------------------------------------
if cat $inst_plymouthconf | grep -q -E "^Theme"; then
sed -i "s/^Theme=.*/Theme=\"$theme\"/" $inst_plymouthconf
else
echo "[Daemon]" > $inst_plymouthconf
echo "Theme=\"$theme\"" >> $inst_plymouthconf
fi
fi
fi
}
#======================================
# setupBootLoaderRecovery
#--------------------------------------
function setupBootLoaderRecovery {
# /.../
# generic function to setup the boot loader configuration
# for the recovery partition. The selection of the bootloader
# happens according to the architecture of the system
# ----
local IFS=$IFS_ORIG
local arch=$(uname -m)
local para=""
while [ $# -gt 0 ];do
# quote simple quotation marks
arg=$(echo $1 | sed -e s"#'#'\\\\''#g")
para="$para '$arg'"
shift
done
case $arch-$loader in
i*86-grub2) eval setupBootLoaderGrub2Recovery $para ;;
x86_64-grub2) eval setupBootLoaderGrub2Recovery $para ;;
*)
systemException \
"*** boot loader setup for $arch-$loader not implemented ***" \
"reboot"
esac
}
#======================================
# setupBootLoaderGrub2Recovery
#--------------------------------------
function setupBootLoaderGrub2Recovery {
# /.../
# create grub.cfg file for the recovery boot system
# ----
local IFS=$IFS_ORIG
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gfix=$3 # grub title
local kernel=vmlinuz # this is a copy of the kiwi linux.vmx file
local initrd=initrd # this is a copy of the kiwi initrd.vmx file
local conf=$destsPrefix/boot/grub2/grub.cfg
local theme=$RECOVERY_THEME
#======================================
# setup ID device names
#--------------------------------------
local rootByID=$(getDiskID $imageRootDevice)
local diskByID=$(getDiskID $imageDiskDevice)
#======================================
# operate only in recovery mode
#--------------------------------------
if [ -z "$kiwi_oemrecovery" ];then
return
fi
#======================================
# import grub2 modules into recovery
#--------------------------------------
mkdir -p $destsPrefix/boot
cp -a $mountPrefix/boot/grub2 $destsPrefix/boot/
rm -f $destsPrefix/boot/grub2/grub.cfg
rm -f $destsPrefix/boot/grub2/bootpart.cfg
#======================================
# check for kernel options
#--------------------------------------
local cmdline="KIWI_RECOVERY=$recoid"
if [ ! -z "$KIWI_KERNEL_OPTIONS" ];then
cmdline="$cmdline $KIWI_KERNEL_OPTIONS"
fi
if [ ! -z "$KIWI_INITRD_PARAMS" ];then
cmdline="$cmdline $KIWI_INITRD_PARAMS";
fi
if [ ! -z "$rootByID" ];then
cmdline="$cmdline root=$rootByID"
fi
if [ ! -z "$diskByID" ];then
cmdline="$cmdline disk=$diskByID"
fi
if [ -e /dev/xvc0 ];then
cmdline="$cmdline console=xvc console=tty"
elif [ -e /dev/hvc0 ];then
cmdline="$cmdline console=hvc console=tty"
fi
#======================================
# create recovery grub.cfg
#--------------------------------------
cat > $conf << EOF
insmod ext2
insmod gettext
insmod part_msdos
insmod chain
insmod png
insmod vbe
insmod vga
insmod gzio
set default=0
search --no-floppy --fs-uuid --set=root $reco_uuid
set font=/boot/unicode.pf2
if loadfont \$font ;then
set gfxmode=auto
insmod gfxterm
insmod gfxmenu
terminal_input gfxterm
if terminal_output gfxterm; then true; else
terminal gfxterm
fi
fi
if loadfont /boot/grub2/themes/$theme/ascii.pf2;then
loadfont /boot/grub2/themes/$theme/DejaVuSans-Bold14.pf2
loadfont /boot/grub2/themes/$theme/DejaVuSans10.pf2
loadfont /boot/grub2/themes/$theme/DejaVuSans12.pf2
loadfont /boot/grub2/themes/$theme/ascii.pf2
set theme=/boot/grub2/themes/$theme/theme.txt
set bgimg=/boot/grub2/themes/$theme/background.png
background_image -m stretch \$bgimg
fi
if [ \$grub_platform = "efi" ]; then
set linux=linuxefi
set initrd=initrdefi
else
set linux=linux
set initrd=initrd
fi
set timeout=30
EOF
if xenServer $kernel $mountPrefix;then
cat >> $conf << EOF
menuentry 'Recover/Repair System' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
echo Loading Xen...
multiboot /boot/xen.gz dummy
echo Loading $kernel...
set gfxpayload=keep
module /boot/$kernel dummy $cmdline $kiwi_cmdline showopts
echo Loading $initrd...
module /boot/$initrd dummy
}
menuentry 'Restore Factory System' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
echo Loading Xen...
multiboot /boot/xen.gz dummy
echo Loading $kernel...
set gfxpayload=keep
module /boot/$kernel dummy $cmdline $kiwi_cmdline RESTORE=1 showopts
echo Loading $initrd...
module /boot/$initrd dummy
}
EOF
else
cat >> $conf << EOF
menuentry 'Recover/Repair System' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
echo Loading $kernel...
set gfxpayload=keep
\$linux /boot/$kernel $cmdline $kiwi_cmdline showopts
echo Loading $initrd...
\$initrd /boot/$initrd
}
menuentry 'Restore Factory System' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
echo Loading $kernel...
set gfxpayload=keep
\$linux /boot/$kernel $cmdline $kiwi_cmdline RESTORE=1 showopts
echo Loading $initrd...
\$initrd /boot/$initrd
}
EOF
fi
}
#======================================
# setupBootLoaderS390Grub
#--------------------------------------
function setupBootLoaderS390Grub {
# /.../
# create grub2 configuration for s390
# ----
local IFS=$IFS_ORIG
#======================================
# function paramters
#--------------------------------------
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gnum=$3 # grub boot partition ID
local rdev=$4 # grub root partition
local gfix=$5 # grub title postfix
local swap=$6 # optional swap partition
#======================================
# local variables
#--------------------------------------
local kname=$(uname -r)
local loader_type=grub2
local timeout=10
local title
local cmdline
local vesa
local fstype=$(probeFileSystem $rdev)
#======================================
# setup path names
#--------------------------------------
local inst_default_grub=$destsPrefix/etc/default/grub
local inst_default_grubdev=$destsPrefix/etc/default/grub_installdevice
local inst_default_grubmap=$destsPrefix/boot/grub2/device.map
local inst_sysb=$destsPrefix/etc/sysconfig/bootloader
#======================================
# setup ID device names
#--------------------------------------
local rootByID=$(getDiskID $rdev)
local swapByID=$(getDiskID $swap swap)
local diskByID=$(getDiskID $imageDiskDevice)
#======================================
# setup title name
#--------------------------------------
if [ -z "$gfix" ];then
gfix="unknown"
fi
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
if ! echo $gfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
title=$(makeLabel "$gfix")
elif [ -z "$kiwi_oemtitle" ];then
title=$(makeLabel "$kname [ $gfix ]")
else
title=$(makeLabel "$kiwi_oemtitle [ $gfix ]")
fi
#======================================
# check for kernel options
#--------------------------------------
if [ ! -z "$rootByID" ];then
cmdline="$cmdline root=$rootByID"
fi
if [ ! -z "$diskByID" ];then
cmdline="$cmdline disk=$diskByID"
fi
if [ ! -z "$swapByID" ];then
cmdline="$cmdline resume=$swapByID"
fi
if [ ! -z "$kiwi_cmdline" ];then
cmdline="$cmdline $kiwi_cmdline"
fi
if [[ ! $cmdline =~ quiet ]];then
cmdline="$cmdline quiet"
fi
#======================================
# check for boot TIMEOUT
#--------------------------------------
if [ ! -z "$kiwi_boot_timeout" ];then
timeout=$kiwi_boot_timeout
fi
#======================================
# write etc/default/grub
#--------------------------------------
mkdir -p $destsPrefix/etc/default
cat > $inst_default_grub << EOF
GRUB_DISTRIBUTOR=$(printf %q "$title")
GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=$timeout
GRUB_CMDLINE_LINUX="$cmdline"
GRUB_TERMINAL=console
EOF
#======================================
# enable rollback capability
#--------------------------------------
if [ "$fstype" = "btrfs" ];then
echo "SUSE_BTRFS_SNAPSHOT_BOOTING=true" >> $inst_default_grub
fi
#======================================
# write etc/default/grub_installdevice
#--------------------------------------
cat > $inst_default_grubdev << EOF
$diskByID
EOF
#======================================
# write boot/grub2/device.map
#--------------------------------------
mkdir -p $destsPrefix/boot/grub2
cat > $inst_default_grubmap << EOF
(hd0) $diskByID
EOF
#======================================
# write sysconfig/bootloader
#--------------------------------------
mkdir -p $destsPrefix/etc/sysconfig
cat > $inst_sysb << EOF
LOADER_TYPE="$loader_type"
DEFAULT_APPEND="$cmdline"
FAILSAFE_APPEND="$failsafe $cmdline"
EOF
}
#======================================
# setupBootLoaderGrub2
#--------------------------------------
function setupBootLoaderGrub2 {
# /.../
# create/update default grub2 configuration
# ----
local IFS=$IFS_ORIG
#======================================
# function paramters
#--------------------------------------
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gnum=$3 # grub boot partition ID
local rdev=$4 # grub root partition
local gfix=$5 # grub title postfix
local swap=$6 # optional swap partition
#======================================
# local variables
#--------------------------------------
local kname=$(uname -r)
local title
local cmdline
local timeout
local vesa
local loader_type="grub2"
local fstype=$(probeFileSystem $rdev)
#======================================
# vesa hex => resolution table
#--------------------------------------
vesa[0x301]="640x480"
vesa[0x310]="640x480"
vesa[0x311]="640x480"
vesa[0x312]="640x480"
vesa[0x303]="800x600"
vesa[0x313]="800x600"
vesa[0x314]="800x600"
vesa[0x315]="800x600"
vesa[0x305]="1024x768"
vesa[0x316]="1024x768"
vesa[0x317]="1024x768"
vesa[0x318]="1024x768"
vesa[0x307]="1280x1024"
vesa[0x319]="1280x1024"
vesa[0x31a]="1280x1024"
vesa[0x31b]="1280x1024"
#======================================
# setup ID device names
#--------------------------------------
local rootByID=$(getDiskID $rdev)
local swapByID=$(getDiskID $swap swap)
local diskByID=$(getDiskID $imageDiskDevice)
#======================================
# setup path names
#--------------------------------------
local inst_default_grub=$destsPrefix/etc/default/grub
local inst_default_grubdev=$destsPrefix/etc/default/grub_installdevice
local inst_default_grubmap=$destsPrefix/boot/grub2/device.map
local unifont=$mountPrefix/usr/share/grub2/unicode.pf2
#======================================
# setup title name
#--------------------------------------
if [ -z "$gfix" ];then
gfix="unknown"
fi
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
if ! echo $gfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
title=$(makeLabel "$gfix")
elif [ -z "$kiwi_oemtitle" ];then
title=$(makeLabel "$kname [ $gfix ]")
else
title=$(makeLabel "$kiwi_oemtitle [ $gfix ]")
fi
#======================================
# check for kernel options
#--------------------------------------
if [ ! -z "$KIWI_KERNEL_OPTIONS" ];then
cmdline="$cmdline $KIWI_KERNEL_OPTIONS"
fi
if [ ! -z "$KIWI_INITRD_PARAMS" ];then
cmdline="$cmdline $KIWI_INITRD_PARAMS";
fi
if [ ! -z "$rootByID" ];then
cmdline="$cmdline root=$rootByID"
fi
if [ ! -z "$diskByID" ];then
cmdline="$cmdline disk=$diskByID"
fi
if [ ! -z "$swapByID" ];then
cmdline="$cmdline resume=$swapByID"
fi
if [ ! -z "$kiwi_cmdline" ];then
cmdline="$cmdline $kiwi_cmdline"
fi
if [ -e /dev/xvc0 ];then
cmdline="$cmdline console=xvc console=tty"
elif [ -e /dev/hvc0 ];then
cmdline="$cmdline console=hvc console=tty"
fi
if [[ ! $cmdline =~ quiet ]];then
cmdline="$cmdline quiet"
fi
#======================================
# check for boot TIMEOUT
#--------------------------------------
if [ -z "$kiwi_boot_timeout" ];then
timeout=10;
fi
#======================================
# write etc/default/grub
#--------------------------------------
mkdir -p $destsPrefix/etc/default
cat > $inst_default_grub << EOF
GRUB_DISTRIBUTOR=$(printf %q "$title")
GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=$timeout
GRUB_CMDLINE_LINUX="$cmdline"
EOF
#======================================
# set terminal mode
#--------------------------------------
if [ -z "$kiwi_bootloader_console" ];then
kiwi_bootloader_console=gfxterm
fi
echo "GRUB_TERMINAL=$kiwi_bootloader_console" >> $inst_default_grub
if [ "$kiwi_bootloader_console" = "serial" ];then
local serial
serial="serial --speed=38400 --unit=0 --word=8 --parity=no --stop=1"
echo "GRUB_SERIAL_COMMAND=\"$serial\"" >> $inst_default_grub
fi
#======================================
# write etc/default/grub_installdevice
#--------------------------------------
local grub_install_device=$diskByID
if [ ! -z "$kiwi_OfwGrub" ];then
grub_install_device=$(ddn $imageDiskDevice $kiwi_OfwGrub)
fi
cat > $inst_default_grubdev << EOF
$grub_install_device
EOF
#======================================
# write boot/grub2/device.map
#--------------------------------------
mkdir -p $destsPrefix/boot/grub2
cat > $inst_default_grubmap << EOF
(hd0) $diskByID
EOF
#======================================
# Use linuxefi/initrdefi if needed
#--------------------------------------
if [ "$kiwi_firmware" = "uefi" ] || [ "$kiwi_firmware" = "efi" ];then
case $arch in
i?86|x86_64)
echo "GRUB_USE_LINUXEFI=true" >> $inst_default_grub
echo "GRUB_USE_INITRDEFI=true" >> $inst_default_grub
;;
esac
loader_type="grub2-efi"
fi
#======================================
# write vesa vga setup
#--------------------------------------
if [ ! -z "$kiwi_vga" ] && [ ! -z "${vesa[$kiwi_vga]}" ];then
echo "GRUB_GFXMODE=${vesa[$kiwi_vga]}" >> $inst_default_grub
echo "GRUB_GFXPAYLOAD_LINUX=${vesa[$kiwi_vga]}" >> $inst_default_grub
else
echo "GRUB_GFXMODE=${vesa[$DEFAULT_VGA]}" >> $inst_default_grub
echo "GRUB_GFXPAYLOAD_LINUX=keep" >> $inst_default_grub
fi
#======================================
# write bootloader theme setup
#--------------------------------------
if [ ! -z "$kiwi_loader_theme" ];then
local theme=/boot/grub2/themes/$kiwi_loader_theme/theme.txt
local bgpng=/boot/grub2/themes/$kiwi_loader_theme/background.png
echo "GRUB_THEME=\"$theme\"" >> $inst_default_grub
echo "GRUB_BACKGROUND=\"$bgpng\"" >> $inst_default_grub
fi
#======================================
# write bootloader timeout setup
#--------------------------------------
if [ ! -z "$kiwi_boot_timeout" ];then
echo "GRUB_TIMEOUT=\"$kiwi_boot_timeout\"" >> $inst_default_grub
fi
#======================================
# enable rollback capability
#--------------------------------------
if [ "$fstype" = "btrfs" ];then
echo "SUSE_BTRFS_SNAPSHOT_BOOTING=true" >> $inst_default_grub
fi
#======================================
# create sysconfig/bootloader
#--------------------------------------
mkdir -p $destsPrefix/etc/sysconfig
local sysb=$destsPrefix/etc/sysconfig/bootloader
echo "LOADER_TYPE=\"$loader_type\"" > $sysb
echo "LOADER_LOCATION=\"mbr\"" >> $sysb
echo "DEFAULT_APPEND=\"$cmdline\"" >> $sysb
echo "FAILSAFE_APPEND=\"$failsafe $cmdline\"" >> $sysb
}
#======================================
# setupDefaultPXENetwork
#--------------------------------------
function setupDefaultPXENetwork {
# /.../
# create the /sysconfig/network file according to the PXE
# boot interface.
# ----
local IFS=$IFS_ORIG
if [ -z "$PXE_IFACE" ];then
return
fi
local prefix=$1
local niface=$prefix/etc/sysconfig/network/ifcfg-$PXE_IFACE
mkdir -p $prefix/etc/sysconfig/network
cat > $niface < /dev/null
echo "BOOTPROTO='dhcp'" >> $niface
echo "STARTMODE='ifplugd'" >> $niface
echo "USERCONTROL='no'" >> $niface
}
#======================================
# getBtrfsSubVolumes
#--------------------------------------
function getBtrfsSubVolumes {
local IFS=$IFS_ORIG
local prefix=$1
btrfs subvol list $prefix | \
grep -v .snapshots/ | grep -v @$ | cut -f9 -d ' '
}
#======================================
# mountBtrfsSubVolumes
#--------------------------------------
function mountBtrfsSubVolumes {
local IFS=$IFS_ORIG
local mountDevice=$1
local prefix=$2
local syspath
for subvol in $(getBtrfsSubVolumes "$prefix"); do
syspath=$(echo $subvol | tr -d @)
mount $mountDevice $prefix/$syspath -o subvol=$subvol
done
}
#======================================
# setupDefaultFstab
#--------------------------------------
function setupDefaultFstab {
# /.../
# Update or create new /etc/fstab file with default entries
# ----
# systemd handles all of the kernel filesystems at the moment
# If this is going to change add the missing entries here
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
local config_tmp=$1
local nfstab=$config_tmp/etc/fstab
mkdir -p $config_tmp/etc
if [ -e "$prefix/etc/fstab" ];then
cp $prefix/etc/fstab $config_tmp/etc
else
touch $config_tmp/etc/fstab
fi
}
#======================================
# updateRootDeviceFstab
#--------------------------------------
function updateRootDeviceFstab {
# /.../
# add one line to the fstab file for the root device
# if the root filesystem is a remote filesystem. the
# rootfs entry is normally done by the image build
# process
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
local config_tmp=$1
local rdev=$2
local nfstab=$config_tmp/etc/fstab
#======================================
# check for NFSROOT
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
local server=$(echo $rdev | cut -f3 -d" ")
local option=$(echo $rdev | cut -f2 -d" ")
echo "$server / nfs $option 0 0" >> $nfstab
return
fi
#======================================
# check for device by ID
#--------------------------------------
if [ ! -z "$UNIONFS_CONFIG" ]; then
echo "/dev/root / auto defaults 1 1" >> $nfstab
fi
}
#======================================
# updateSwapDeviceFstab
#--------------------------------------
function updateSwapDeviceFstab {
# /.../
# add one line to the fstab file for the swap device
# which is created at boot time
# ----
local IFS=$IFS_ORIG
local prefix=$1
local sdev=$2
local nfstab=$prefix/etc/fstab
local devicepersistency="by-uuid"
if [ ! -z "$kiwi_devicepersistency" ];then
devicepersistency=$kiwi_devicepersistency
fi
if [ $devicepersistency = "by-label" ];then
local device="LABEL=$(blkid $sdev -s LABEL -o value)"
else
local device="UUID=$(blkid $sdev -s UUID -o value)"
fi
echo "$device swap swap defaults 0 0" >> $nfstab
}
#======================================
# updateBootDeviceFstab
#--------------------------------------
function updateBootDeviceFstab {
# /.../
# add temporary bind mounted boot entry to fstab
# This entry is deleted later on in resetBootBind
# The standard boot entry is created by the build
# process
# ----
local IFS=$IFS_ORIG
local config_tmp=$1
local sdev=$2
local nfstab=$config_tmp/etc/fstab
local mount=boot_bind
local prefix=/mnt
local devicepersistency="by-uuid"
if [ ! -z "$kiwi_devicepersistency" ];then
devicepersistency=$kiwi_devicepersistency
fi
local tmp_fstab=$config_tmp/etc/fstab.tmp
local fstype
#======================================
# Store boot_bind entry
#--------------------------------------
if [ -e $prefix/$mount ];then
fstype=$(probeFileSystem $sdev)
if [ "$fstype" = "unknown" ];then
fstype=auto
fi
# delete existing /boot entry if present
grep -v '/boot ' $nfstab > ${nfstab}.new
mv ${nfstab}.new $nfstab
# add boot entry mounted to boot_bind
if [ $devicepersistency = "by-label" ];then
local device="LABEL=$(blkid $sdev -s LABEL -o value)"
else
local device="UUID=$(blkid $sdev -s UUID -o value)"
fi
echo "$device /$mount $fstype defaults 1 2" >> $tmp_fstab
# add bind mount entry from boot_bind to boot
echo "/$mount/boot /boot none bind 0 0" >> $tmp_fstab
# add existing fstab entries
cat $nfstab >> $tmp_fstab
# move result as new fstab
mv $tmp_fstab $nfstab
fi
}
#======================================
# updateOtherDeviceFstab
#--------------------------------------
function updateOtherDeviceFstab {
# /.../
# check the contents of the $PART variable and
# add one line to the fstab file for each partition
# which has a mount point defined. This is only
# relevant for netboot images configured by a
# config.MAC setup
# ----
local IFS=$IFS_ORIG
local prefix=$1
local nfstab=$prefix/etc/fstab
local index=0
local field=0
local count=0
local sdev
local diskByID
local fstype
local devicepersistency="by-uuid"
if [ ! -z "$kiwi_devicepersistency" ];then
devicepersistency=$kiwi_devicepersistency
fi
local IFS=","
if [ -z "$prefix" ];then
prefix=/mnt
fi
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
if \
[ ! -z "$partMount" ] && \
[ ! "$partMount" = "x" ] && \
[ ! "$partMount" = "swap" ] && \
[ ! "$partMount" = "/" ]
then
if [ ! -z "$RAID" ];then
sdev=/dev/md$((count - 1))
else
sdev=$(ddn $DISK $count)
fi
fstype=$(probeFileSystem $sdev)
if [ ! "$fstype" = "luks" ] && [ ! "$fstype" = "unknown" ];then
if [ ! -d $prefix/$partMount ];then
mkdir -p $prefix/$partMount
fi
if [ $devicepersistency = "by-label" ];then
local device="LABEL=$(blkid $sdev -s LABEL -o value)"
else
local device="UUID=$(blkid $sdev -s UUID -o value)"
fi
echo "$device $partMount $fstype defaults 0 0" >> $nfstab
fi
fi
done
}
#======================================
# setupKernelModules
#--------------------------------------
function setupKernelModules {
# /.../
# placeholder for custom kernel module setup
# used by the distribution initrd tool
:
}
#======================================
# probeFileSystem
#--------------------------------------
function probeFileSystem {
# /.../
# probe for the filesystem type. The function uses the
# result from blkid. If blkid could not detect the
# filesystem type the first 128 kB of the given device
# are read and checked for a known signature
# ----
local IFS=$IFS_ORIG
local fstype
fstype=$(blkid $1 -s TYPE -o value)
if [ -z "$fstype" ];then
fstype=unknown
fi
if [ "$fstype" = "crypto_LUKS" ];then
fstype=luks
fi
if [ $fstype = "unknown" ];then
dd if=$1 of=/tmp/filesystem-$$ bs=128k count=1 >/dev/null
if grep -q ^CLIC /tmp/filesystem-$$;then
fstype=clicfs
fi
if grep -q ^hsqs /tmp/filesystem-$$;then
fstype=squashfs
fi
fi
echo $fstype
}
#======================================
# getSystemIntegrity
#--------------------------------------
function getSystemIntegrity {
# /.../
# check the variable SYSTEM_INTEGRITY which contains
# information about the status of all image portions
# per partition. If a number is given as parameter only
# the information from the image assigned to this partition
# is returned
# ----
local IFS=$IFS_ORIG
if [ -z "$SYSTEM_INTEGRITY" ];then
echo "clean"
else
echo $SYSTEM_INTEGRITY | cut -f$1 -d:
fi
}
#======================================
# getSystemMD5Status
#--------------------------------------
function getSystemMD5Status {
# /.../
# return the md5 status of the given image number.
# the function works similar to getSystemIntegrity
# ----
local IFS=$IFS_ORIG
echo $SYSTEM_MD5STATUS | cut -f$1 -d:
}
#======================================
# waitForIdleEventQueue
#--------------------------------------
function waitForIdleEventQueue {
local IFS=$IFS_ORIG
local devs=0
local p_devs=1
local timeout=5
Echo -n "Waiting for devices to settle..."
while true;do
udevPending
devs=$(ls -1 /dev | wc -l)
if [ $devs -eq $p_devs ];then
break
fi
p_devs=$devs
sleep $timeout
echo -n .
done
echo
}
#======================================
# probeUSB
#--------------------------------------
function probeUSB {
local IFS=$IFS_ORIG
local module=""
local stdevs=""
local hwicmd="/usr/sbin/hwinfo"
if [ $HAVE_MODULES_ORDER = 0 ];then
#======================================
# load host controller modules
#--------------------------------------
IFS="%"
for i in \
`$hwicmd --usb | grep "Driver [IA]" |
sed -es"@modprobe\(.*\)\"@\1%@" | tr -d "\n"`
do
if echo $i | grep -q "#0";then
module=`echo $i | cut -f2 -d"\"" | tr -d " "`
module=`echo $module | sed -es"@modprobe@@g"`
IFS=";"
for m in $module;do
if ! echo $stdevs | grep -q $m;then
stdevs="$stdevs $m"
fi
done
fi
done
for i in \
`$hwicmd --usb-ctrl | grep "Driver [IA]" |
sed -es"@modprobe\(.*\)\"@\1%@" | tr -d "\n"`
do
if echo $i | grep -q "#0";then
module=`echo $i | cut -f2 -d"\"" | tr -d " "`
module=`echo $module | sed -es"@modprobe@@g"`
IFS=";"
for m in $module;do
if ! echo $stdevs | grep -q $m;then
stdevs="$stdevs $m"
fi
done
fi
done
IFS=$IFS_ORIG
stdevs=`echo $stdevs`
for module in $stdevs;do
Echo "Probing module: $module"
modprobe $module >/dev/null
done
#======================================
# check load status for host controller
#--------------------------------------
if [ -z "$stdevs" ];then
return
fi
#======================================
# manually load storage/input drivers
#--------------------------------------
for i in usbhid usb-storage;do
modprobe $i &>/dev/null
done
fi
}
#======================================
# probeDevices
#--------------------------------------
function probeDevices {
local IFS=$IFS_ORIG
local skipUSB=$1
udevPending
if [ $HAVE_MODULES_ORDER = 0 ];then
waitForIdleEventQueue
fi
#======================================
# probe USB devices and load modules
#--------------------------------------
if [ -z "$skipUSB" ];then
probeUSB
fi
#======================================
# probe Disk devices and load modules
#--------------------------------------
if [ $HAVE_MODULES_ORDER = 0 ];then
Echo "Including required kernel modules..."
IFS="%"
local module=""
local stdevs=""
local hwicmd="/usr/sbin/hwinfo"
for i in \
`$hwicmd --storage | grep "Driver [IA]" |
sed -es"@modprobe\(.*\)\"@\1%@" | tr -d "\n"`
do
if echo $i | grep -q "#0";then
module=`echo $i | cut -f2 -d"\"" | tr -d " "`
module=`echo $module | sed -es"@modprobe@@g"`
IFS=";"
for m in $module;do
if ! echo $stdevs | grep -q $m;then
stdevs="$stdevs $m"
fi
done
fi
done
IFS=$IFS_ORIG
stdevs=`echo $stdevs`
if [ ! -z "$kiwikernelmodule" ];then
for module in $kiwikernelmodule;do
Echo "Probing module (cmdline): $module"
INITRD_MODULES="$INITRD_MODULES $module"
modprobe $module >/dev/null
done
fi
for module in $stdevs;do
loadok=1
for broken in $kiwibrokenmodule;do
if [ $broken = $module ];then
Echo "Prevent loading module: $module"
loadok=0; break
fi
done
if [ $loadok = 1 ];then
Echo "Probing module: $module"
INITRD_MODULES="$INITRD_MODULES $module"
modprobe $module >/dev/null
fi
done
hwinfo --block &>/dev/null
# /.../
# older systems require ide-disk to be present at any time
# for details on this crappy call see bug: #250241
# ----
modprobe ide-disk &>/dev/null
else
if [ ! -z "$kiwikernelmodule" ];then
for module in $kiwikernelmodule;do
Echo "Probing module (cmdline): $module"
INITRD_MODULES="$INITRD_MODULES $module"
modprobe $module >/dev/null
done
fi
fi
#======================================
# Manual loading of modules
#--------------------------------------
for i in rd brd edd dm-mod xen:vif xen:vbd virtio_blk loop squashfs fuse;do
modprobe $i &>/dev/null
done
udevPending
if [ $HAVE_MODULES_ORDER = 0 ];then
waitForIdleEventQueue
fi
}
#======================================
# USBStickDevice
#--------------------------------------
function USBStickDevice {
local IFS=$IFS_ORIG
stickFound=0
local mode=$1
local prefix=/mnt
#======================================
# search for USB removable devices
#--------------------------------------
for device in /sys/bus/usb/drivers/usb-storage/*;do
if [ ! -L $device ];then
continue
fi
descriptions=$device/host*/target*/*/block*
for description in $descriptions;do
if [ ! -d $description ];then
continue
fi
isremovable=$description/removable
storageID=$(echo $description | cut -f1 -d: | xargs basename)
devicebID=$(basename $description | cut -f2 -d:)
if [ $devicebID = "block" ];then
devicebID=`ls -1 $description`
isremovable=$description/$devicebID/removable
fi
serial="/sys/bus/usb/devices/$storageID/serial"
device="/dev/$devicebID"
if [ ! -b $device ];then
continue;
fi
if [ ! -f $isremovable ];then
continue;
fi
if ! partitionSize $device >/dev/null;then
continue;
fi
if [ ! -f $serial ];then
serial="USB Stick (unknown type)"
else
serial=`cat $serial`
fi
removable=`cat $isremovable`
# /.../
# don't check the removable flag, it could be wrong
# especially for USB hard disks connected via a
# USB caddy, details in bug: 535113
# ----
removable=1
if [ $removable -eq 1 ];then
stickRoot=$device
stickDevice=$(ddn $device 1)
for devnr in 1 2;do
dev=$(ddn $stickRoot $devnr)
if ! kiwiMount "$dev" "$prefix" "-o ro";then
continue
fi
if [ "$mode" = "install" ];then
# /.../
# USB stick search for install media
# created with kiwi
# ----
if \
[ ! -e $prefix/config.isoclient ] && \
[ ! -e $prefix/config.usbclient ]
then
umountSystem
continue
fi
elif [ "$mode" = "kexec" ];then
# /.../
# USB stick search for hotfix media
# with kernel/initrd for later kexec
# ----
if \
[ ! -e $prefix/linux.kexec ] && \
[ ! -e $prefix/initrd.kexec ]
then
umountSystem
continue
fi
else
# /.../
# USB stick search for Linux system tree
# created with kiwi
# ----
if [ ! -e $prefix/etc/ImageVersion ]; then
umountSystem
continue
fi
fi
stickFound=1
umountSystem
break
done
if [ "$stickFound" = 0 ];then
continue
fi
stickSerial=$serial
return
fi
done
done
}
#======================================
# CDMountOption
#--------------------------------------
function CDMountOption {
# /.../
# checks for the ISO 9660 extension and prints the
# mount option required to mount the device in full
# speed mode
# ----
local IFS=$IFS_ORIG
local id=$(blkid -o value -s TYPE $1)
if [ "$id" = "iso9660" ];then
echo "-t iso9660"
fi
if [ "$id" = "udf" ]; then
echo "-t udf"
fi
}
#======================================
# searchImageISODevice
#--------------------------------------
function searchImageISODevice {
# /.../
# search all devices for the MBR ID stored in the
# iso header. This function is called to identify the
# live media and/or install media
# ----
local IFS=$IFS_ORIG
local mbrVID
local mbrIID
local count=0
local isoinfo=/usr/bin/isoinfo
mkdir -p /cdrom
if [ ! -x $isoinfo ]; then
isoinfo=/usr/lib/genisoimage/isoinfo
fi
if [ ! -x $isoinfo ];then
systemException \
"Can't find isoinfo tool in initrd" \
"reboot"
fi
if [ ! -f /boot/mbrid ];then
systemException \
"Can't find MBR id file in initrd" \
"reboot"
fi
mbrIID=$(cat /boot/mbrid)
udevPending
#======================================
# Check for ISO file on storage media
#--------------------------------------
if [ ! -z "$isofrom_device" ] && [ ! -z "$isofrom_system" ];then
Echo "Looking up ISO on $isofrom_device..."
mkdir /isofrom
if [[ $isofrom_device =~ nfs: ]];then
setupNetwork
isofrom_device=$(echo $isofrom_device | cut -c 5-)
mount -t nfs -o nolock $isofrom_device /isofrom
else
waitForStorageDevice $isofrom_device
mount $isofrom_device /isofrom
fi
if [ ! $? = 0 ];then
systemException \
"Failed to mount ISO storage device !" \
"reboot"
fi
biosBootDevice=$(loop_setup /isofrom/$isofrom_system)
if [ ! $? = 0 ];then
systemException \
"Failed to loop setup ISO system !" \
"reboot"
fi
return 0
fi
#======================================
# Search ISO header in device list
#--------------------------------------
Echo -n "Searching for boot device in Application ID..."
while true;do
for i in /dev/*;do
if [ ! -b $i ];then
continue
fi
mbrVID=$(
$isoinfo -d -i $i 2>/dev/null|grep "Application id:"|cut -f2 -d:
)
mbrVID=$(echo $mbrVID)
if [ "$mbrVID" = "$mbrIID" ];then
# /.../
# found ISO header on a device, now check if there is
# also a partition for this device with the same
# information and prefer that device if it exists
# ----
biosBootDevice=$i
for n in 1 2;do
local pdev=$(ddn $i $n)
if [ -e $pdev ];then
mbrVID=$(
$isoinfo -d -i $pdev 2>/dev/null |\
grep "Application id:"|cut -f2 -d:
)
mbrVID=$(echo $mbrVID)
if [ "$mbrVID" = "$mbrIID" ];then
biosBootDevice=$pdev
echo; return 0
fi
fi
done
echo; return 0
fi
done
if [ $count -eq 30 ];then
systemException \
"Failed to find MBR identifier !" \
"reboot"
fi
count=$(($count + 1))
echo -n .
sleep 1
done
}
#======================================
# runMediaCheck
#--------------------------------------
function runMediaCheck {
# /.../
# run checkmedia program on the specified device
# ----
local IFS=$IFS_ORIG
local device_iso=$biosBootDevice
local device_sdx=$(dn $biosBootDevice)
if [ -e "$device_sdx" ];then
device_iso=$device_sdx
fi
if ! checkmedia $device_iso;then
systemException \
"ISO check failed, you have been warned" \
"waitkey"
else
Echo "ISO check passed"
Echo "Press any key to continue (waiting $MEDIACHECK_OK_TIMER sec...)"
read -s -n 1 -t $MEDIACHECK_OK_TIMER
fi
}
#======================================
# setupHybridFeatures
#--------------------------------------
function setupHybridPersistent {
# /.../
# create a write partition for hybrid images if requested
# and store the device name in HYBRID_RW
# ----
local IFS=$IFS_ORIG
if [ ! "$kiwi_hybridpersistent" = "true" ];then
return
fi
local diskDevice=$(dn $biosBootDevice)
#======================================
# create write partition for hybrid
#--------------------------------------
if [ -z "$kiwi_cowdevice" ] && [ -z "$kiwi_cowsystem" ];then
#======================================
# try to create a write partition
#--------------------------------------
createHybridPersistent $diskDevice
else
#======================================
# use given cow device
#--------------------------------------
createCustomHybridPersistent
fi
#======================================
# check hybrid write partition device
#--------------------------------------
if [ ! -e "$HYBRID_RW" ]; then
# /.../
# failed to create read-write partition
# disable persistent writing
# ----
unset HYBRID_RW
unset kiwi_hybridpersistent
export skipSetupBootPartition=1
fi
}
#======================================
# CDUmount
#--------------------------------------
function CDUmount {
# /.../
# umount the CD device
# ----
local IFS=$IFS_ORIG
umount $biosBootDevice
}
#======================================
# CDEject
#--------------------------------------
function CDEject {
local IFS=$IFS_ORIG
eject $biosBootDevice
}
#======================================
# searchOFBootDevice
#--------------------------------------
function searchOFBootDevice {
# /.../
# search for the device with the OF PROM id
# this is required for the ppc boot architecture
# as we don't have a BIOS and a MBR here
# ----
local IFS=$IFS_ORIG
local ofdev=`cat /proc/device-tree/chosen/bootpath|cut -f1 -d:`
local h=/usr/sbin/ofpathname
local ddevs=`$h -l $ofdev`
#======================================
# Store device with PROM id
#--------------------------------------
for curd in $ddevs;do
if [ $curd = "sda" -o $curd = "vda" ];then
export biosBootDevice="/dev/$curd"
return 0
fi
done
export biosBootDevice="Can't find OF boot device"
return 1
}
#======================================
# searchBusIDBootDevice
#--------------------------------------
function searchBusIDBootDevice {
# /.../
# check for a DASD or ZFCP devices
# like they exist on the s390 architecture. If found the
# device is set online and the biosBootDevice variable
# is set to this device for further processing
# ----
local IFS=$IFS_ORIG
local dpath=/dev/disk/by-path
local ipl_type=$(cat /sys/firmware/ipl/ipl_type)
local deviceID=$(cat /sys/firmware/ipl/device)
local dev_type=$(cat /sys/bus/ccw/devices/$deviceID/devtype)
local wwpn
local slun
#======================================
# check for custom device init command
#--------------------------------------
if [ ! -z "$DEVICE_INIT" ];then
if ! eval $DEVICE_INIT;then
export biosBootDevice="Failed to call: $DEVICE_INIT"
return 1
fi
export biosBootDevice=$DISK
return 0
fi
#======================================
# determine device type: dasd or zfcp
#--------------------------------------
if [ -z "$deviceID" ];then
systemException \
"Can't find IPL device" \
"reboot"
fi
if [ "$ipl_type" = "fcp" ];then
# plain FCP device 512b blocksize
haveZFCP=1
elif [ "$ipl_type" = "ccw" ];then
if [[ "$dev_type" =~ "3390" ]];then
# plain DASD device 4k blocksize
haveDASD=1
elif [[ "$dev_type" =~ "9336" ]];then
# emulated DASD device 512b blocksize, handled as FCP device
# but don't configure host and disk as required for plain
# FCP devices
haveZFCP=1
else
systemException \
"Unknown Device type: $dev_type" \
"reboot"
fi
else
systemException \
"Unknown IPL type: $ipl_type" \
"reboot"
fi
#======================================
# check if we can find the device
#--------------------------------------
if [ ! -e /sys/bus/ccw/devices/$deviceID ];then
systemException \
"Can't find disk with ID: $deviceID" \
"reboot"
fi
#======================================
# DASD real in CDL / LDL mode
#--------------------------------------
if [ $haveDASD -eq 1 ];then
dasd_configure $deviceID 1 0
biosBootDevice="$dpath/ccw-$deviceID"
fi
#======================================
# DASD emulated in FBA mode
#--------------------------------------
if [ $haveZFCP -eq 1 ] && [ "$ipl_type" = "ccw" ];then
dasd_configure $deviceID 1 0
biosBootDevice="$dpath/ccw-$deviceID"
fi
#======================================
# ZFCP real in SCSI mode
#--------------------------------------
if [ $haveZFCP -eq 1 ] && [ "$ipl_type" = "fcp" ];then
wwpn=$(cat /sys/firmware/ipl/wwpn)
slun=$(cat /sys/firmware/ipl/lun)
zfcp_host_configure $deviceID 1
zfcp_disk_configure $deviceID $wwpn $slun 1
biosBootDevice="$dpath/ccw-$deviceID-zfcp-$wwpn:$slun"
fi
#======================================
# setup boot device variable
#--------------------------------------
waitForStorageDevice $biosBootDevice
if [ ! -e $biosBootDevice ];then
export biosBootDevice="Failed to set disk $deviceID online"
return 1
fi
export biosBootDevice=$(getDiskDevice $biosBootDevice)
return 0
}
#======================================
# setupBootDeviceIfMultipath
#--------------------------------------
function setupBootDeviceIfMultipath {
local IFS=$IFS_ORIG
local disk
local found_multipath_device=0
if startMultipathd; then
for wwn in $(multipath -l -v1 $biosBootDevice);do
disk=/dev/mapper/$wwn
if [ -e $disk ];then
biosBootDevice=$disk
found_multipath_device=1
break
fi
done
if [ ! $found_multipath_device = 1 ];then
stopMultipathd
fi
fi
}
#======================================
# lookupDiskDevices
#--------------------------------------
function lookupDiskDevices {
# /.../
# use hwinfo to search for disk device nodes
# ----
local IFS=$IFS_ORIG
local h=/usr/sbin/hwinfo
local c="Device File:|BIOS id"
udevPending
diskDevices=$($h --disk | \
grep -E "$c" | sed -e"s@(.*)@@" | cut -f2 -d: | tr -d " ")
}
#======================================
# lookupBiosBootDevice
#--------------------------------------
function lookupBiosBootDevice {
# /.../
# check for devices which have 0x80 bios flag assigned
# ----
local IFS=$IFS_ORIG
local curd
local pred
for curd in $diskDevices;do
if [ $curd = "0x80" ];then
bios=$pred
return
fi
pred=$curd
done
}
#======================================
# searchBIOSBootDevice
#--------------------------------------
function searchBIOSBootDevice {
# /.../
# search for the boot device. The edd 0x80 information
# is used here but not trusted. Trusted is the MBR disk
# disk label which is compared with the kiwi written
# mbrid file in /boot/grub/ of the system image
# If we got a root device set via cmdline this value
# takes precedence over everything else though
# ----
local IFS=$IFS_ORIG
local file=/boot/mbrid
local ifix
local match_count
local matched
local curd
local mbrML
local mbrMB
local mbrI
local try_count=0
#======================================
# Check root variable
#--------------------------------------
if [ ! -z "$root" ];then
if [[ $root =~ "UUID=" ]];then
root=/dev/disk/by-uuid/$(echo $root | cut -f2 -d=)
elif [[ $root =~ "LABEL=" ]];then
root=/dev/disk/by-label/$(echo $root | cut -f2 -d=)
fi
if ! waitForStorageDevice $root;then
Echo "Specified root device $root not found. Found devices:"
hwinfo --disk
systemException \
"root device not found... fatal !" \
"reboot"
fi
export biosBootDevice=$(dn $root)
if [ ! -e /config.partids ];then
echo "kiwi_RootPart=1" > /config.partids
fi
return 0
fi
#======================================
# Read mbrid from initrd
#--------------------------------------
if [ ! -e $file ];then
export biosBootDevice="Failed to find MBR identifier !"
return 1
fi
read mbrI < $file
#======================================
# Lookup until found
#--------------------------------------
while true;do
#======================================
# initialize variables
#--------------------------------------
ifix=0
match_count=0
try_count=$((try_count + 1))
#======================================
# stop after a long time of retry
#--------------------------------------
if [ $try_count -eq 15 ];then
export biosBootDevice="Failed to find boot device !"
return 1
fi
#======================================
# create device list
#--------------------------------------
lookupDiskDevices
lookupBiosBootDevice
#======================================
# Compare ID with MBR entry
#--------------------------------------
for curd in $diskDevices;do
if [ ! -b $curd ];then
continue
fi
mbrML=$(dd if=$curd bs=1 count=4 skip=$((0x1b8)) | \
hexdump -n4 -e '"0x%08x"')
mbrMB=$(echo $mbrML | \
sed 's/^0x\(..\)\(..\)\(..\)\(..\)$/0x\4\3\2\1/')
if [ "$mbrML" = "$mbrI" ] || [ "$mbrMB" = "$mbrI" ];then
ifix=1
matched=$curd
match_count=$(($match_count + 1))
if [ "$mbrML" = "$mbrI" ];then
export masterBootID=$mbrML
fi
if [ "$mbrMB" = "$mbrI" ];then
export masterBootID=$mbrMB
fi
if [ "$curd" = "$bios" ];then
export biosBootDevice=$curd
return 0
fi
fi
done
#======================================
# Multiple matches are bad
#--------------------------------------
if [ $match_count -gt 1 ];then
export biosBootDevice="multiple devices matches same MBR ID: $mbrI"
return 2
fi
#======================================
# Found it...
#--------------------------------------
if [ $ifix -eq 1 ];then
export biosBootDevice=$matched
return 0
fi
export biosBootDevice="No devices matches MBR ID: $mbrI !"
sleep 1
done
}
#======================================
# searchVolumeGroup
#--------------------------------------
function searchVolumeGroup {
# /.../
# search for a volume group named $kiwi_lvmgroup and if it can be
# found activate it while creating appropriate device nodes:
# /dev/$kiwi_lvmgroup/LVRoot
# return zero on success
# ----
local IFS=$IFS_ORIG
local vg_count=0
local vg_found
local fstype
if [ ! "$kiwi_lvm" = "true" ];then
return 1
fi
local rootdevice=$(ddn $imageDiskDevice $kiwi_RootPart)
fstype=$(probeFileSystem $rootdevice)
if [ "$fstype" = "luks" ];then
luksOpen $rootdevice
export haveLuks=yes
fi
for i in $(vgs --noheadings -o vg_name 2>/dev/null);do
vg_found=$(echo $i)
if [ "$vg_found" = "$kiwi_lvmgroup" ];then
vg_count=$((vg_count + 1))
fi
done
if [ $vg_count -gt 1 ];then
Echo "Duplicate VolumeGroup name $kiwi_lvmgroup found !"
Echo "$vg_count versions of this volume group exists"
Echo "The volume group name must be unique"
Echo "Please check your disks and rename/remove the duplicates"
systemException \
"VolumeGroup $kiwi_lvmgroup not unique !" \
"reboot"
fi
Echo "Activating $kiwi_lvmgroup volume group..."
vgchange -a y $kiwi_lvmgroup
}
#======================================
# deactivateVolumeGroup
#--------------------------------------
function deactivateVolumeGroup {
# /.../
# as signals/ioctls from earlier operations may
# not have been processed by the kernel or udev
# we may require a moment before 'vgchange -a n'
# return zero on success
# ----
local IFS=$IFS_ORIG
if [ ! "$kiwi_lvm" = "true" ];then
return 1
fi
udevPending
Echo "Deactivating $kiwi_lvmgroup volume group..."
vgchange -a n $kiwi_lvmgroup
udevPending
}
#======================================
# activateVolumeGroup
#--------------------------------------
function activateVolumeGroup {
# /.../
# activate volume group if LVM is present
# ----
local IFS=$IFS_ORIG
if [ ! "$kiwi_lvm" = "true" ];then
return 1
fi
udevPending
Echo "Activating $kiwi_lvmgroup volume group..."
vgchange -a y $kiwi_lvmgroup
udevPending
}
#======================================
# activateMDRaid
#--------------------------------------
function activateMDRaid {
local IFS=$IFS_ORIG
if [ ! -z "$kiwi_RaidDev" ];then
udevPending
Echo "Activating $kiwi_RaidDev mdraid array..."
mdadm --assemble --scan
waitForStorageDevice $kiwi_RaidDev
fi
}
#======================================
# resizeMDRaid
#--------------------------------------
function resizeMDRaid {
local IFS=$IFS_ORIG
if [ ! -z "$kiwi_RaidDev" ];then
udevPending
Echo "Resizing $kiwi_RaidDev mdraid array..."
mdadm --grow --size=max $kiwi_RaidDev
fi
}
#======================================
# resizeLVMPVs
#--------------------------------------
function resizeLVMPVs {
local IFS=$IFS_ORIG
local extendID=$1
local device=$(ddn $imageDiskDevice $extendID)
if [ ! -z "$kiwi_RaidDev" ];then
device=$kiwi_RaidDev
fi
if [ ! -z "$luksDeviceOpened" ];then
device=$luksDeviceOpened
fi
local unixDevice=$(getDiskDevice $device)
pvresize $unixDevice
}
#======================================
# deactivateMDRaid
#--------------------------------------
function deactivateMDRaid {
local IFS=$IFS_ORIG
if [ ! -z "$kiwi_RaidDev" ] && [ -e $kiwi_RaidDev ];then
udevPending
Echo "Deactivating $kiwi_RaidDev mdraid array..."
mdadm --stop $kiwi_RaidDev
fi
}
#======================================
# zeroMDRaidSuperBlock
#--------------------------------------
function zeroMDRaidSuperBlock {
local IFS=$IFS_ORIG
if [ ! -z "$kiwi_RaidDev" ] && [ -e $kiwi_RaidDev ];then
local diskDevice=$1
for i in /dev/md*;do
test -b $i && mdadm --stop $i &>/dev/null
done
mdadm --zero-superblock $diskDevice &>/dev/null
fi
}
#======================================
# searchSwapSpace
#--------------------------------------
function searchSwapSpace {
# /.../
# search for a type=82 swap partition
# ----
local IFS=$IFS_ORIG
if [ ! -z $kiwinoswapsearch ];then
return
fi
local hwapp=/usr/sbin/hwinfo
local diskdevs=`$hwapp --disk | grep "Device File:" | cut -f2 -d:`
diskdevs=`echo $diskdevs | sed -e "s@(.*)@@"`
for diskdev in $diskdevs;do
for disknr in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15;do
id=$(partitionID $diskdev $disknr)
if [ "$id" = "82" ];then
echo $diskdev$disknr
return
fi
done
done
}
#======================================
# updateMTAB
#--------------------------------------
function updateMTAB {
local IFS=$IFS_ORIG
local prefix=$1
local umount=0
if [ ! -e /proc/mounts ];then
mount -t proc proc /proc
umount=1
fi
if [ -e /proc/self/mounts ];then
pushd $prefix/etc >/dev/null
rm -f mtab && ln -s /proc/self/mounts mtab
popd >/dev/null
fi
if [ $umount -eq 1 ];then
umount /proc
fi
}
#======================================
# getNicNames
#--------------------------------------
function getNicNames {
local IFS=$IFS_ORIG
for nic in $(ip -4 -o link | cut -f2 -d:);do
if [ ! $nic = 'lo' ];then
echo $nic
fi
done
}
#======================================
# getHWAddress
#--------------------------------------
function getHWAddress {
local IFS=$IFS_ORIG
local iface=$1
ip addr show dev $iface |\
grep 'link\/ether ' | cut -f6 -d ' '
}
#======================================
# setupNic
#--------------------------------------
function setupNic {
local IFS=$IFS_ORIG
local iface=$1
local address=$2
local netmask=$3
ip addr flush dev $iface
# ignore netmask if address is already cidr
if [[ $address =~ / ]] ; then
ip addr add $address dev $iface
else
ip addr add $address/$netmask dev $iface
fi
ip link set dev $iface up
}
#======================================
# deleteNic
#--------------------------------------
function deleteNic {
local IFS=$IFS_ORIG
local iface=$1
local address=$2
local netmask=$3
# ignore netmask if address is already cidr
if [[ $address =~ / ]] ; then
ip addr del $address dev $iface
else
ip addr del $address/$netmask dev $iface
fi
}
#======================================
# probeNetworkCard
#--------------------------------------
function probeNetworkCard {
# /.../
# use hwinfo to probe for all network devices. The
# function will check for the driver which is needed
# to support the card and returns the information in
# the networkModule variable
# ----
local IFS="%"
local module=""
local hwicmd="/usr/sbin/hwinfo"
for i in \
`$hwicmd --netcard | grep "Driver [IA]" |
sed -es"@modprobe\(.*\)\"@\1%@" | tr -d "\n"`
do
if echo $i | grep -q "#0";then
module=`echo $i | cut -f2 -d"\"" | tr -d " "`
module=`echo $module | sed -es"@modprobe@@g"`
IFS=";"
for m in $module;do
if ! echo $networkModule | grep -q $m;then
if [ ! -z "$networkModule" ];then
networkModule="$networkModule:$m"
else
networkModule=$m
fi
fi
done
fi
done
networkModule=`echo $networkModule`
}
#======================================
# loadNetworkCard
#--------------------------------------
function loadNetworkCard {
# /.../
# load network module found by probeNetworkCard()
# ----
local IFS=$IFS_ORIG
local loaded=0
probeNetworkCard
IFS=":" ; for i in $networkModule;do
if [ ! -z "$i" ];then
modprobe $i 2>/dev/null
if [ $? = 0 ];then
loaded=1
fi
fi
done
}
#======================================
# loadNetworkCardS390
#--------------------------------------
function loadNetworkCardS390 {
# /.../
# search and include parameters from a parm file
# provided on the specified dasd id
# ----
local IFS=$IFS_ORIG
local host=$1
local skip="/etc/deactivate_s390_network_config_from_dasd"
local hostdev=/dev/disk/by-path/ccw-${host}
local parmfile_name=PARM-S11
if [ ! -z "$kiwi_oemvmcp_parmfile" ];then
parmfile_name=$kiwi_oemvmcp_parmfile
fi
Echo "Trying parm file lookup on DASD id: ${host}"
#======================================
# check if we got stopped
#--------------------------------------
if [ -e $skip ];then
Echo "Processing skipped by $skip"
rm -f $skip
return 1
fi
#======================================
# check for required tools
#--------------------------------------
if [ ! lookup cmsfscat &>/dev/null ];then
Echo "Can't find cmsfscat program required for loading"
return 1
fi
#======================================
# check for required kernel support
#--------------------------------------
# If loading vmcp fails we assume the support for it has been
# compiled into the kernel. If this is not the case we will run
# into an exception on 'vmcp query' which is the intended way
# to handle the error condition
modprobe vmcp &>/dev/null
#======================================
# bring host online
#--------------------------------------
if [ ! -b $hostdev ];then
dasd_configure ${host} 1 0
udevPending
if [ ! -b $hostdev ];then
Echo "Failed to activate DASD id: ${host}"
return 1
fi
fi
#======================================
# load parm file using cmsfscat
#--------------------------------------
Echo "Loading configuration file <UID>.${parmfile_name} from ${host}..."
local parmfile="$(vmcp query userid | cut -d ' ' -f 1).$parmfile_name"
if ! cmsfscat -d $hostdev -a "$parmfile" > /tmp/"$parmfile";then
Echo "Can't create /tmp/${parmfile} on DASD id: ${host}"
return 1
fi
#======================================
# import data into environment
#--------------------------------------
includeKernelParametersLowerCase "/tmp/$parmfile"
#======================================
# unbind host and cleanup
#--------------------------------------
rm -f "/tmp/$parmfile"
dasd_configure ${host} 0 0
return 0
}
#======================================
# dhclientImportInfo
#-------------------------------------
function dhclientImportInfo {
# /.../
# Import and export the information form the
# dhclient.lease file into the enviroment.
# ----
local IFS=$IFS_ORIG
if [ ! -n $1 ]; then
Echo "NULL argument passed to dhclientImportInfo"
return
fi
local lease=/var/lib/dhclient/$1.lease
export IPADDR=$(
cat $lease | grep 'fixed-address'|\
awk '{print $2}' | tr -d ';'
)
export NETMASK=$(
cat $lease | grep 'subnet-mask'|\
awk '{print $3}' | tr -d ';'
)
export GATEWAYS=$(
cat $lease | grep 'routers ' |\
awk '{print $3}' |tr -d ';'
)
export DOMAIN=$(
cat $lease | grep 'domain-name' | grep -v 'domain-name-server' |\
awk '{print $3}'| tr -d ';'
)
export DNSSERVERS=$(
cat $lease | grep 'domain-name-servers'|\
awk '{print $3}'| tr -d ';' | tr ',' ' '
)
export DHCPSIADDR=$(
cat $lease | grep 'dhcp-server-identifier'|\
awk '{print $3}'| tr -d ';' | tr ',' ' '
)
export DNS=$DNSSERVERS
export DHCPCHADDR=$(
ip link show $1 | grep link | awk '{print $2}' | tr a-z A-Z
)
}
#======================================
# setupNetworkWicked
#--------------------------------------
function setupNetworkWicked {
# /.../
# assign DHCP IP address by using the wicked tool
# ----
local IFS=$IFS_ORIG
local nic_config
local dhcp_info
local wicked_request
local wicked_dhcp4=/usr/lib/wicked/bin/wickedd-dhcp4
for try_iface in ${dev_list[*]}; do
# try DHCP_DISCOVER on all interfaces
if setIPLinkUp $try_iface; then
dhcp_info=/var/run/wicked/wicked-${try_iface}.info
$wicked_dhcp4 --debug all \
--test --test-output $dhcp_info $try_iface
if [ $? = 0 ] && [ -s $dhcp_info ];then
DHCPCD_STARTED="$DHCPCD_STARTED $try_iface"
fi
fi
done
if [ -z "$DHCPCD_STARTED" ];then
if [ -e "$root" ];then
Echo "Failed to setup DHCP network interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to setup DHCP network interface !" \
"reboot"
fi
fi
#======================================
# wait for any preferred interface(s)
#--------------------------------------
for repeat_dhcp_on_discovered in 1 2 ;do
for try_iface in ${prefer_iface[*]} ; do
dhcp_info=/var/run/wicked/wicked-${try_iface}.info
if waitForDHCPInterfaceNegotiation $dhcp_info; then
break 2
fi
done
sleep 2
# /.../
# we are behind the wicked dhcp timeout 20s so the only thing
# we can do now is to try again on discovered interfaces
# ----
for try_iface in $DHCPCD_STARTED; do
dhcp_info=/var/run/wicked/wicked-${try_iface}.info
$wicked_dhcp4 --debug all \
--test --test-output $dhcp_info $try_iface
done
sleep 2
done
#============================================
# select interface from discovered devices
#--------------------------------------------
for try_iface in ${prefer_iface[*]} $DHCPCD_STARTED; do
dhcp_info=/var/run/wicked/wicked-${try_iface}.info
if [ -s $dhcp_info ] && grep -q "^IPADDR=" $dhcp_info; then
wicked_request='<request type="lease">'
wicked_request="$wicked_request<lease-time>3600</lease-time>"
wicked_request="$wicked_request</request>"
echo $wicked_request |\
wicked test dhcp4 --request - -- $try_iface > $dhcp_info
if [ $? = 0 ];then
export PXE_IFACE=$try_iface
break
fi
fi
done
#======================================
# fallback to local boot if possible
#--------------------------------------
if [ -z "$PXE_IFACE" ];then
if [ -e "$root" ];then
Echo "Can't get DHCP reply on any interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Can't get DHCP reply on any interface !" \
"reboot"
fi
fi
#======================================
# setup selected interface
#--------------------------------------
dhcp_info=/var/run/wicked/wicked-${PXE_IFACE}.info
if [ -s $dhcp_info ]; then
waitForDHCPInterfaceNegotiation $dhcp_info
importFile < $dhcp_info
IPADDR=$(echo $IPADDR | cut -f1 -d/)
if setupNic $PXE_IFACE $IPADDR $NETMASK; then
if ip route add default dev $PXE_IFACE; then
if [ ! -z "$GATEWAYS" ];then
# Use first entry as primary gateway
local gw=$(echo $GATEWAYS | cut -f1 -d " ")
if ! ip route change default via $gw dev $PXE_IFACE; then
systemException \
"Failed to change default GW on $PXE_IFACE !" \
"reboot"
fi
fi
else
systemException \
"Failed to setup default route on $PXE_IFACE !" \
"reboot"
fi
else
systemException \
"Failed to setup IP address on $PXE_IFACE !" \
"reboot"
fi
fi
}
#======================================
# setupNetworkDHCPCD
#--------------------------------------
function setupNetworkDHCPCD {
# /.../
# assign DHCP IP address by using the dhcpcd tool
# ----
local IFS=$IFS_ORIG
if [ $DHCPCD_HAVE_PERSIST -eq 0 ];then
# /.../
# older version of dhcpd which doesn't have the
# options we want to pass
# ----
unset opts
fi
mkdir -p /var/lib/dhcpcd
for try_iface in ${dev_list[*]}; do
# try DHCP_DISCOVER on all interfaces
dhcpcd $opts -T $try_iface > /var/lib/dhcpcd/dhcpcd-$try_iface.info &
DHCPCD_STARTED="$DHCPCD_STARTED $try_iface"
done
if [ -z "$DHCPCD_STARTED" ];then
if [ -e "$root" ];then
Echo "Failed to setup DHCP network interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to setup DHCP network interface !" \
"reboot"
fi
fi
#======================================
# wait for any preferred interface(s)
#--------------------------------------
for j in 1 2 ;do
for i in 1 2 3 4 5 6 7 8 9 10 11;do
for try_iface in ${prefer_iface[*]} ; do
if [ -s /var/lib/dhcpcd/dhcpcd-$try_iface.info ] &&
grep -q "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$try_iface.info
then
break 3
fi
done
sleep 2
done
# /.../
# we are behind the dhcpcd timeout 20s so the only thing
# we can do now is to try again
# ----
for try_iface in $DHCPCD_STARTED; do
dhcpcd $opts -T $try_iface \
> /var/lib/dhcpcd/dhcpcd-$try_iface.info &
done
sleep 2
done
#======================================
# select interface from preferred list
#--------------------------------------
for try_iface in ${prefer_iface[*]} $DHCPCD_STARTED; do
if [ -s /var/lib/dhcpcd/dhcpcd-$try_iface.info ] &&
grep -q "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$try_iface.info
then
export PXE_IFACE=$try_iface
eval `grep "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$try_iface.info`
rm /var/lib/dhcpcd/dhcpcd-$try_iface.info
# continue with the DHCP protocol on the selected interface
if [ -e /var/run/dhcpcd-$PXE_IFACE.pid ];then
rm -f /var/run/dhcpcd-$PXE_IFACE.pid
fi
if [ $DHCPCD_HAVE_PERSIST -eq 0 ];then
# /.../
# older version of dhcpd which doesn't provide
# an option to request a specific IP address
# ----
dhcpcd $opts $PXE_IFACE 2>&1
else
dhcpcd $opts -r $IPADDR $PXE_IFACE 2>&1
fi
break
fi
done
#======================================
# fallback to local boot if possible
#--------------------------------------
if [ -z "$PXE_IFACE" ];then
if [ -e "$root" ];then
Echo "Can't get DHCP reply on any interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Can't get DHCP reply on any interface !" \
"reboot"
fi
fi
#======================================
# wait for iface to finish negotiation
#--------------------------------------
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20;do
if [ -s /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info ] &&
grep -q "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info
then
break
fi
sleep 2
done
#======================================
# setup selected interface
#--------------------------------------
setupNic lo 127.0.0.1/8 255.0.0.0
if [ -s /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info ] &&
grep -q "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info; then
importFile < /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info
fi
}
#======================================
# setupNetworkDHCLIENT
#--------------------------------------
function setupNetworkDHCLIENT {
# /.../
# assign DHCP IP address by using the dhclient tool
# ----
local IFS=$IFS_ORIG
local dhclient_opts=" -4 -1 -q"
mkdir -p /var/lib/dhclient
mkdir -p /var/run
for try_iface in ${dev_list[*]}; do
# try DHCP_DISCOVER on all interfaces
dhclient $dhclient_opts \
-lf /var/lib/dhclient/${try_iface}.lease \
-pf /var/run/dhclient-${try_iface}.pid ${try_iface}
DHCPCD_STARTED="$DHCPCD_STARTED $try_iface"
done
if [ -z "$DHCPCD_STARTED" ];then
if [ -e "$root" ];then
Echo "Failed to setup DHCP network interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to setup DHCP network interface !" \
"reboot"
fi
fi
#======================================
# wait for any preferred interface(s)
#--------------------------------------
for j in 1 2 ;do
for i in 1 2 3 4 5 6 7 8 9 10 11;do
for try_iface in ${prefer_iface[*]} ; do
if [ -f /var/lib/dhclient/${try_iface}.lease ] &&
grep -q "fixed-address" /var/lib/dhclient/${try_iface}.lease
then
break 3
fi
done
sleep 2
done
# /.../
# we are behind the dhclient timeout 20s so the only thing
# we can do now is to try again
# ----
for try_iface in $DHCPCD_STARTED; do
dhclient $dhclient_opts \
-lf /var/lib/dhclient/${try_iface}.lease \
-pf /var/run/dhclient-${try_iface}.pid ${try_iface}
done
sleep 2
done
#======================================
# select interface from preferred list
#--------------------------------------
for try_iface in ${prefer_iface[*]} $DHCPCD_STARTED; do
if [ -f /var/lib/dhclient/${try_iface}.lease ] &&
grep -q "fixed-address" /var/lib/dhclient/${try_iface}.lease
then
export PXE_IFACE=$try_iface
export IPADDR=$(
cat /var/lib/dhclient/${try_iface}.lease |\
grep 'fixed-address'| awk '{print $2}' | tr -d ';'
)
break
fi
done
#======================================
# setup selected interface
#--------------------------------------
setupNic lo 127.0.0.1/8 255.0.0.0
if [ -f /var/lib/dhclient/$PXE_IFACE.lease ] &&
grep -q "fixed-address" /var/lib/dhclient/$PXE_IFACE.lease; then
dhclientImportInfo "$PXE_IFACE"
fi
}
#======================================
# setupNetwork
#--------------------------------------
function setupNetwork {
# /.../
# probe for the existing network interface names and
# hardware addresses. Match the BOOTIF address from PXE
# to the correct linux interface name. Setup the network
# interface using a dhcp request. On success the dhcp
# info file is imported into the current shell environment
# and the nameserver information is written to
# /etc/resolv.conf
# ----
local IFS=$IFS_ORIG
#======================================
# local variable setup
#--------------------------------------
local MAC=0
local DEV=0
local mac_list=0
local dev_list=0
local index=0
local hwicmd=/usr/sbin/hwinfo
local opts="--noipv4ll -p"
local try_iface
export DHCPCD_STARTED=""
#======================================
# detect iface and HWaddr
#--------------------------------------
for DEV in $(getNicNames);do
MAC=$(getHWAddress $DEV)
mac_list[$index]=$MAC
dev_list[$index]=$DEV
index=$((index + 1))
done
if [ $index = 0 ];then
systemException \
"No network interfaces found" \
"reboot"
fi
#======================================
# preselect first nic as a start
#--------------------------------------
export prefer_iface=${dev_list[0]}
#======================================
# continue to be smarter in nic check
#--------------------------------------
if [ -z "$BOOTIF" ];then
# /.../
# there is no PXE boot interface information. We will use
# the first interface that responds to dhcp
# ----
prefer_iface=${dev_list[*]}
else
# /.../
# evaluate the information from the PXE boot interface
# if we found the MAC in the list the appropriate interface
# name is assigned.
# ----
index=0
BOOTIF=$(echo $BOOTIF | cut -f2- -d - | tr "-" ":")
for i in ${mac_list[*]};do
list_iface=$(echo $i | tr [:upper:] [:lower:])
if [ $list_iface = $BOOTIF ];then
prefer_iface=${dev_list[$index]}
fi
index=$((index + 1))
done
fi
#======================================
# ask for an address
#--------------------------------------
if lookup wicked &>/dev/null; then
setupNetworkWicked
elif lookup dhcpcd &>/dev/null; then
setupNetworkDHCPCD
elif lookup dhclient &>/dev/null; then
setupNetworkDHCLIENT
else
Echo "No supported DHCP client tool found (dhcpcd/dhclient)"
return 1
fi
#======================================
# check if we got an address
#--------------------------------------
if [ -z "$IPADDR" ];then
if [ -e "$root" ];then
Echo "Can't assign IP addr via dhcp info: dhcpcd-$PXE_IFACE.info !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Can't assign IP addr via dhcp info: dhcpcd-$PXE_IFACE.info !" \
"reboot"
fi
fi
if [ -z "$DOMAIN" ] && [ -n "$DNSDOMAIN" ];then
export DOMAIN=$DNSDOMAIN
fi
echo "search $DOMAIN" > /etc/resolv.conf
if [ -z "$DNS" ] && [ -n "$DNSSERVERS" ];then
export DNS=$DNSSERVERS
fi
IFS=", " ; for i in $DNS;do
echo "nameserver $i" >> /etc/resolv.conf
done
export DHCPCHADDR=$(
ip link show dev $PXE_IFACE | grep link | awk '{print $2}' | tr a-z A-Z
)
}
#======================================
# releaseNetwork
#--------------------------------------
function releaseNetwork {
# /.../
# clean network setup and free the lease. If no tool could
# be found to communicate with the dhcp server in order to
# free the lease, the default behavior will just clean the
# network. The method will only be effective if the root
# device of the system is a _non_ network root device
# ----
local IFS=$IFS_ORIG
if [ -z "$NFSROOT" ] && [ -z "$NBDROOT" ] && [ -z "$AOEROOT" ];then
if lookup dhcpcd &>/dev/null; then
#======================================
# unset dhcp info variables
#--------------------------------------
unsetFile < /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info
#======================================
# free the lease and the cache
#--------------------------------------
dhcpcd -k $PXE_IFACE
elif lookup dhclient &>/dev/null; then
#======================================
# unset dhclient info variables
#--------------------------------------
unset IPADDR
unset GATEWAYS
unset DNSSERVERS
unset NETMASK
unset DOMAIN
unset DNSSERVERS
unset DNS
unset DHCPCHADDR
#======================================
# free the lease and the cache
#--------------------------------------
kill -9 $(cat /var/run/dhclient-$PXE_IFACE.pid )
dhclient -r \
-lf /var/lib/dhclient/$PXE_IFACE.lease $PXE_IFACE
else
deleteNic $PXE_IFACE $IPADDR $NETMASK
fi
#======================================
# remove sysconfig state information
#--------------------------------------
rm -rf /dev/.sysconfig/network
#======================================
# unset host information
#--------------------------------------
unset HOSTNAME
fi
}
#======================================
# setupNetworkInterfaceS390
#--------------------------------------
function setupNetworkInterfaceS390 {
# /.../
# bring up the network card according to the parm file
# parameters and create the correspondent udev rules
# needs includeKernelParametersLowerCase to be run
# because parm file parameters are case insensitive
# ----
local IFS=$IFS_ORIG
case "$instnetdev" in
"osa"|"hsi")
local qeth_cmd="/sbin/qeth_configure"
if [ "$layer2" = "1" ];then
qeth_cmd="$qeth_cmd -l"
fi
if [ -n "$portname" ];then
qeth_cmd="$qeth_cmd -p $portname"
fi
if [ -n "$portno" ];then
qeth_cmd="$qeth_cmd -n $portno"
fi
qeth_cmd="$qeth_cmd $readchannel $writechannel"
if [ -n "$datachannel" ];then
qeth_cmd="$qeth_cmd $datachannel"
fi
eval $qeth_cmd 1
;;
"ctc")
/sbin/ctc_configure $readchannel $writechannel 1 $ctcprotocol
;;
"iucv")
/sbin/iucv_configure $iucvpeer 1
;;
*)
if [ -e "$root" ];then
Echo "Unknown s390 network type: $instnetdev"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Unknown s390 network type: $instnetdev" \
"reboot"
fi
;;
esac
if [ ! $? = 0 ];then
if [ -e "$root" ];then
Echo "Failed to bring up the network: $instnetdev"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to bring up the network: $instnetdev" \
"reboot"
fi
fi
udevPending
}
#======================================
# convertCIDRToNetmask
#--------------------------------------
function convertCIDRToNetmask {
# /.../
# convert the CIDR part to a useable netmask
# ----
local IFS=$IFS_ORIG
local cidr=$1
local count=0
for count in `seq 1 4`;do
if [ $((cidr / 8)) -gt 0 ];then
echo -n 255
else
local remainder=$((cidr % 8))
if [ $remainder -gt 0 ];then
echo -n $(( value = 256 - (256 >> remainder)))
else
echo -n 0
fi
fi
cidr=$((cidr - 8))
if [ $count -lt 4 ];then
echo -n .
fi
done
echo
}
#======================================
# setupNetworkStatic
#--------------------------------------
function setupNetworkStatic {
# /.../
# configure static network either bring it up manually
# or save the configuration depending on 'up' parameter
# ----
local IFS=$IFS_ORIG
local up=$1
if [[ $hostip =~ / ]];then
#======================================
# convert CIDR to netmask
#--------------------------------------
netmask=$(convertCIDRToNetmask $(echo $hostip | cut -f2 -d/))
fi
if [ "$up" = "1" ];then
#======================================
# activate network
#--------------------------------------
# Please note: It is assumed the last interface in the list is the
# one which should receive the interface config. While the loopback
# interface is skipped this could still result in an unexpected
# behavior.
local iface=$(
cat /proc/net/dev|grep -v lo:|tail -n1|cut -d':' -f1|sed 's/ //g'
)
if ! setupNic $iface $hostip $netmask;then
if [ -e "$root" ];then
Echo "Failed to set up the network: $iface"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to set up the network: $iface" \
"reboot"
fi
fi
export iface_static=$iface
elif [ ! -z $iface_static ];then
#======================================
# write network setup
#--------------------------------------
local netFile="/etc/sysconfig/network/ifcfg-$iface_static"
echo "BOOTPROTO='static'" > $netFile
echo "STARTMODE='auto'" >> $netFile
echo "IPADDR='$hostip'" >> $netFile
echo "NETMASK='$netmask'" >> $netFile
if [ -n "$broadcast" ];then
echo "BROADCAST='$broadcast'" >> $netFile
fi
if [ -n "$pointopoint" ];then
echo "REMOTE_IPADDR='$pointopoint'" >> $netFile
fi
fi
setupDefaultGateway $up
setupDNS
}
#======================================
# setupDefaultGateway
#--------------------------------------
function setupDefaultGateway {
# /.../
# setup default gateway. either set the route or save
# the configuration depending on 'up' parameter
# ----
local IFS=$IFS_ORIG
local up=$1
if [ "$up" == "1" ];then
#======================================
# activate GW route
#--------------------------------------
ip route add default via $gateway
else
#======================================
# write GW configuration
#--------------------------------------
echo "default $gateway - -" > "/etc/sysconfig/network/routes"
fi
}
#======================================
# setupDNS
#--------------------------------------
function setupDNS {
# /.../
# setup DNS. write data to resolv.conf
# ----
local IFS=$IFS_ORIG
local file="/etc/resolv.conf"
if [ -n "$domain" ];then
export DOMAIN=$domain
local line="search $domain"
if ! grep -q $line $file;then
echo "$line" >> "$file"
fi
fi
if [ -n "$nameserver" ];then
export DNS=$nameserver
IFS=", " ; for i in $nameserver;do
local line="nameserver $i"
if ! grep -q $line $file;then
echo "$line" >> "$file"
fi
done
fi
}
#======================================
# fetchImageMD5
#--------------------------------------
function fetchImageMD5 {
# /.../
# download image.md5 file either from the network
# or from a local cache directory if specified by
# KIWI_LOCAL_CACHE_DIR.
# ----
local IFS=$IFS_ORIG
local imageMD5s="image/$1-$2.md5"
local imageServer=$3
local imageBlkSize=$4
local error=0
[ -z "$imageServer" ] && imageServer=$SERVER
[ -z "$imageBlkSize" ] && imageBlkSize=8192
#======================================
# Check for MD5 in the local cache
#--------------------------------------
if [ -n "$KIWI_LOCAL_CACHE_DIR" ];then
local cached_md5="$KIWI_LOCAL_CACHE_DIR/$imageMD5s"
if [ -f "$cached_md5" ];then
read sum_local blocks blocksize zblocks zblocksize < "$cached_md5"
fi
fi
#======================================
# Download latest MD5 from the network
#--------------------------------------
fetchFile $imageMD5s /etc/image.md5 uncompressed $imageServer
#======================================
# Check results if download failed
#--------------------------------------
if test $loadCode != 0 || ! loadOK "$loadStatus"; then
Echo "Download of $imageMD5s failed: $loadStatus"
if [ -z "$sum_local" ]; then
Echo "Fatal: No cache copy available"
error=1
else
Echo "Using cache copy: $KIWI_LOCAL_CACHE_DIR/$imageMD5s"
cp "$KIWI_LOCAL_CACHE_DIR/$imageMD5s" /etc/image.md5
error=0
fi
fi
#======================================
# Check error state
#--------------------------------------
# failed MD5 download and no cache copy is fatal
if [ $error -eq 1 ];then
systemException \
"Failed to provide image MD5 data" \
"reboot"
fi
#======================================
# Read in provided MD5 data
#--------------------------------------
read sum1 blocks blocksize zblocks zblocksize < /etc/image.md5
}
#======================================
# updateNeeded
#--------------------------------------
function updateNeeded {
# /.../
# check the contents of the IMAGE key and compare the
# image version file as well as the md5 sum of the installed
# and the available image on the tftp server
# ----
#======================================
# Local variables
#--------------------------------------
local IFS=$IFS_ORIG
local count=0
local sum2
local installed
local field
local atversion
local versionFile
local imageName
local imageVersion
local imageServer
local imageBlkSize
local imageZipped
local prefix=/mnt
#======================================
# Global variables
#--------------------------------------
SYSTEM_INTEGRITY=""
SYSTEM_MD5STATUS=""
#======================================
# Check system update status via md5
#--------------------------------------
IFS="," ; for i in $IMAGE;do
field=0
IFS=";" ; for n in $i;do
case $field in
0) field=1 ;;
1) imageName=$n ; field=2 ;;
2) imageVersion=$n; field=3 ;;
3) imageServer=$n ; field=4 ;;
4) imageBlkSize=$n; field=5 ;;
5) imageZipped=$n ;
esac
done
atversion="$imageName-$imageVersion"
versionFile="$prefix/etc/ImageVersion-$atversion"
IFS=" "
if [ -f "$versionFile" ];then
read installed sum2 < $versionFile
fi
fetchImageMD5 \
"$imageName" "$imageVersion" \
"$imageServer" "$imageBlkSize"
if [ ! -z "$sum1" ];then
SYSTEM_MD5STATUS="$SYSTEM_MD5STATUS:$sum1"
else
SYSTEM_MD5STATUS="$SYSTEM_MD5STATUS:none"
fi
if [ ! -z "$1" ];then
continue
fi
if test "$count" = 1;then
if test "$SYSTEM_INTEGRITY" = ":clean";then
Echo "Main OS image update needed"
Echo -b "Forcing download for multi image session"
RELOAD_IMAGE="yes"
fi
fi
count=$(($count + 1))
Echo "Checking update status for image: $imageName"
if test ! -z $RELOAD_IMAGE;then
Echo -b "Update forced via RELOAD_IMAGE..."
Echo -b "Update status: Clean"
SYSTEM_INTEGRITY="$SYSTEM_INTEGRITY:clean"
continue
fi
if test ! -f $versionFile;then
Echo -b "Update forced: /etc/ImageVersion-$atversion not found"
Echo -b "Update status: Clean"
SYSTEM_INTEGRITY="$SYSTEM_INTEGRITY:clean"
RELOAD_IMAGE="yes"
continue
fi
Echo -b "Current: $atversion Installed: $installed"
if test "$atversion" = "$installed";then
if test "$sum1" = "$sum2";then
Echo -b "Update status: Fine"
SYSTEM_INTEGRITY="$SYSTEM_INTEGRITY:fine"
continue
fi
Echo -b "Image Update for image [ $imageName ] needed"
Echo -b "Image version equals but md5 checksum failed"
Echo -b "This means the contents of the new image differ"
RELOAD_IMAGE="yes"
else
Echo -b "Image Update for image [ $imageName ] needed"
Echo -b "Name and/or image version differ"
RELOAD_IMAGE="yes"
fi
Echo -b "Update status: Clean"
SYSTEM_INTEGRITY="$SYSTEM_INTEGRITY:clean"
done
SYSTEM_INTEGRITY=`echo $SYSTEM_INTEGRITY | cut -f2- -d:`
SYSTEM_MD5STATUS=`echo $SYSTEM_MD5STATUS | cut -f2- -d:`
}
#======================================
# cleanSweep
#--------------------------------------
function cleanSweep {
# /.../
# zero out a the given disk device
# ----
local IFS=$IFS_ORIG
local diskDevice=$1
dd if=/dev/zero of=$diskDevice bs=32M >/dev/null
}
#======================================
# fdasdGetPartitionID
#--------------------------------------
function fdasdGetPartitionID {
local IFS=$IFS_ORIG
local device=$1
local partid=$2
local count=1
for i in $(fdasd -s -p $device | grep -E '^[ ]+\/' |\
awk -v OFS=":" '$1=$1' | cut -f7 -d:)
do
if [ $count -eq $partid ];then
if [ $i = "native" ];then
echo 83
elif [ $i = "swap" ];then
echo 82
else
# /.../
# don't know this partition information
# assume it's a linux partition
# ----
echo 83
fi
return
fi
count=$((count + 1))
done
}
#======================================
# partedGetPartitionID
#--------------------------------------
function partedGetPartitionID {
# /.../
# prints the partition ID for the given device and number
# In case of a GPT map to the GUID code from the sgdisk
# utility. If sgdisk is not available map to the kiwi
# fdisk compatible hex id's which uses ee for any kind
# of unknown GPT partition entry
# ----
local IFS=$IFS_ORIG
local parted=$(parted -m -s $1 print | grep -v Warning:)
local diskhd=$(echo $parted | head -n 3 | tail -n 2 | head -n 1)
local plabel=$(echo $diskhd | cut -f6 -d:)
if [ -z "$plabel" ];then
# can't find a partition label for this disk
echo xx
return
fi
if [[ $plabel =~ gpt ]];then
plabel=gpt
fi
if [ ! $plabel = "gpt" ];then
parted -m -s $1 print | grep ^$2: | cut -f2 -d= |\
sed -e 's@[,; ]@@g' | tr -d 0
else
local name=$(parted -m -s $1 print | grep ^$2: | cut -f6 -d:)
if lookup sgdisk &>/dev/null;then
# map to short gdisk code
echo $(sgdisk -p $1 | grep -E "^ $2") | cut -f6 -d ' '
elif [ "$name" = "lxroot" ];then
# map lxroot to MBR type 83 (linux)
echo 83
elif [ "$name" = "lxswap" ];then
# map lxswap to MBR type 82 (linux swap)
echo 82
elif [ "$name" = "lxlvm" ];then
# map lxlvm to MBR type 8e (linux LVM)
echo 8e
elif [ "$name" = "UEFI" ];then
# map UEFI to MBR type 6 (fat 16)
echo 6
elif [ "$name" = "legacy" ];then
# map bios grub legacy partition to MBR type ef (EFI)
echo ef
else
# map anything else to ee (GPT)
echo ee
fi
fi
}
#======================================
# partitionID
#--------------------------------------
function partitionID {
local IFS=$IFS_ORIG
local diskDevice=$1
local diskNumber=$2
if [ $PARTITIONER = "fdasd" ];then
fdasdGetPartitionID $diskDevice $diskNumber
else
partedGetPartitionID $diskDevice $diskNumber
fi
}
#======================================
# partitionSize
#--------------------------------------
function partitionSize {
local IFS=$IFS_ORIG
local diskDevice=$1
local psizeBytes
local psizeKBytes
if [ -z "$diskDevice" ] || [ ! -e "$diskDevice" ];then
echo 0 ; return 1
fi
psizeBytes=$(blockdev --getsize64 $diskDevice)
psizeKBytes=$((psizeBytes / 1024))
echo $psizeKBytes
}
#======================================
# kernelList
#--------------------------------------
function kernelList {
# /.../
# check for all installed kernels whether there are valid
# links to the initrd and kernel files. The function will
# save the valid linknames in the variable KERNEL_LIST
# ----
local IFS=$IFS_ORIG
local prefix=$1
local kcount=1
local kname=""
local kernel=""
local initrd=""
local kpair=""
local krunning=`uname -r`
KERNEL_LIST=""
KERNEL_NAME=""
KERNEL_PAIR=""
#======================================
# search running kernel first
#--------------------------------------
if [ -d $prefix/lib/modules/$krunning ];then
for name in vmlinux vmlinuz image uImage;do
if [ -f $prefix/boot/$name-$krunning ];then
kernel=$name-$krunning
initrd=initrd-$krunning
break
fi
done
if [ ! -z "$kernel" ];then
KERNEL_PAIR=$kernel:$initrd
KERNEL_NAME[$kcount]=$krunning
KERNEL_LIST=$KERNEL_PAIR
kcount=$((kcount+1))
fi
fi
#======================================
# search for other kernels
#--------------------------------------
for i in $prefix/lib/modules/*;do
if [ ! -d $i ];then
continue
fi
unset kernel
unset initrd
kname=$(basename "$i")
if [ "$kname" = $krunning ];then
continue
fi
for name in vmlinux vmlinuz image uImage;do
for k in $prefix/boot/$name-${i##*/}; do
if [ -f $k ];then
kernel=${k##*/}
initrd=initrd-${i##*/}
break 2
fi
done
done
if [ ! -z "$kernel" ];then
kpair=$kernel:$initrd
KERNEL_NAME[$kcount]=$kname
KERNEL_LIST=$KERNEL_LIST,$kpair
kcount=$((kcount+1))
fi
done
#======================================
# what if no kernel was found...
#--------------------------------------
if [ -z "$KERNEL_LIST" ];then
# /.../
# the system image doesn't provide the kernel and initrd but
# if there is a downloaded kernel and initrd from the KIWI_INITRD
# setup. the kernelList function won't find initrds that gets
# downloaded over tftp so make sure the vmlinu[zx]/initrd combo
# gets added as well as the linux.vmx/initrd.vmx combo
# ----
if [ -e $prefix/boot/vmlinuz ];then
KERNEL_LIST="vmlinuz:initrd"
KERNEL_NAME[1]=vmlinuz
fi
if [ -e $prefix/boot/vmlinux ];then
KERNEL_LIST="vmlinux:initrd"
KERNEL_NAME[1]=vmlinux
fi
if [ -e $prefix/boot/linux.vmx ];then
KERNEL_LIST="vmlinux:initrd"
KERNEL_NAME[1]="vmlinux"
fi
fi
KERNEL_LIST=$(echo $KERNEL_LIST | sed -e s@^,@@)
export KERNEL_LIST
export KERNEL_NAME
export KERNEL_PAIR
}
#======================================
# validateSize
#--------------------------------------
function validateSize {
# /.../
# check if the image fits into the requested partition.
# An information about the sizes is printed out
# ----
local IFS=$IFS_ORIG
haveBytes=$(partitionSize $imageDevice)
haveBytes=$((haveBytes * 1024))
haveMByte=$((haveBytes / 1048576))
needBytes=$((blocks * blocksize))
needMByte=$((needBytes / 1048576))
Echo "Have size: $imageDevice -> $haveBytes Bytes [ $haveMByte MB ]"
Echo "Need size: $needBytes Bytes [ $needMByte MB ]"
if test $haveBytes -gt $needBytes;then
return 0
fi
return 1
}
#======================================
# validateBlockSize
#--------------------------------------
function validateBlockSize {
# /.../
# check the block size value. atftp limits to a maximum of
# 65535 blocks, so the block size must be checked according
# to the size of the image. The block size itself is also
# limited to 65464 bytes
# ----
local IFS=$IFS_ORIG
local blkTest
local nBlk
if [ -z "$zblocks" ] && [ -z "$blocks" ];then
# md5 file not yet read in... skip
return
fi
if [ ! -z "$zblocks" ];then
isize=$((zblocks * zblocksize))
else
isize=$((blocks * blocksize))
fi
local IFS=' '
testBlkSizes="32768 61440 65464"
if [ "$imageBlkSize" -gt 0 ]; then
testBlkSizes="$imageBlkSize $testBlkSizes"
fi
for blkTest in $testBlkSizes ; do
nBlk=$((isize / blkTest))
if [ $nBlk -lt 65535 ] ; then
imageBlkSize=$blkTest
return
fi
done
systemException \
"Maximum blocksize for atftp protocol exceeded" \
"reboot"
}
#======================================
# loadOK
#--------------------------------------
function loadOK {
# /.../
# check the output of the atftp command, unfortunately
# there is no useful return code to check so we have to
# check the output of the command
# ----
local IFS=$IFS_ORIG
for i in "File not found" "aborting" "no option named" "unknown host" ; do
if echo "$1" | grep -q "$i" ; then
return 1
fi
done
return 0
}
#======================================
# includeKernelParameters
#--------------------------------------
function includeKernelParameters {
# /.../
# include the parameters from /proc/cmdline into
# the current shell environment
# ----
local IFS=$IFS_ORIG
local file=$1
local translate=$2
if [ -z "$file" ];then
file=/proc/cmdline
fi
local cmdline=$(
awk -F\" '{OFS="\"";for(i=2;i<NF;i+=2)gsub(/ /,"\030",$i);print}' <$file
)
for i in $cmdline;do
if ! echo $i | grep -q "=";then
continue
fi
kernelKey=$(echo $i | cut -f1 -d=)
#======================================
# convert parameters to lowercase if required
#--------------------------------------
if [ "$translate" = "lowercase" ];then
kernelKey=`echo $kernelKey | tr [:upper:] [:lower:]`
fi
kernelVal=$(echo $i | cut -f2- -d=)
kernelVal=$(echo $kernelVal | sed -e 's/\o30/ /g')
eval export $kernelKey=$kernelVal
done
if [ ! -z "$kiwikernelmodule" ];then
kiwikernelmodule=`echo $kiwikernelmodule | tr , " "`
fi
if [ ! -z "$kiwibrokenmodule" ];then
kiwibrokenmodule=`echo $kiwibrokenmodule | tr , " "`
fi
if [ ! -z "$ramdisk_size" ];then
local modfile=/etc/modprobe.d/99-local.conf
if [ ! -f $modfile ];then
modfile=/etc/modprobe.conf.local
fi
if [ -f $modfile ];then
if grep -q rd_size $modfile;then
sed -i -e s"@rd_size=.*@rd_size=$ramdisk_size@" $modfile
else
echo "options brd rd_size=$ramdisk_size" >> $modfile
fi
fi
fi
if [ ! -z "$lang" ];then
# lang set on the commandline, e.g by the boot theme
export DIALOG_LANG=$lang
elif [ ! -z "$kiwi_language" ];then
# lang set from the XML data, first item is the primary language
export DIALOG_LANG=$(echo $kiwi_language | cut -f1 -d,)
fi
}
#======================================
# includeKernelParametersLowerCase
#--------------------------------------
function includeKernelParametersLowerCase {
includeKernelParameters "$1" "lowercase"
}
#======================================
# umountSystem
#--------------------------------------
function umountSystem {
local IFS=$IFS_ORIG
local retval=0
local mountList="/mnt /read-only /read-write"
#======================================
# umount boot device
#--------------------------------------
if [ ! -z "$imageBootDevice" ];then
umount $imageBootDevice 1>&2
fi
#======================================
# umount mounted mountList paths
#--------------------------------------
for mpath in $(cat /proc/mounts | cut -f2 -d " ");do
for umount in $mountList;do
if [ "$mpath" = "$umount" ];then
if ! umount $mpath >/dev/null;then
if ! umount -l $mpath >/dev/null;then
retval=1
fi
fi
fi
done
done
#======================================
# remove mount points
#--------------------------------------
for dir in "/read-only" "/read-write" "/xino";do
test -d $dir && rmdir $dir 1>&2
done
return $retval
}
#======================================
# kiwiMount
#--------------------------------------
function kiwiMount {
local IFS=$IFS_ORIG
local src=$1
local dst=$2
local opt=$3
local lop=$4
local fstype
#======================================
# load not autoloadable fs modules
#--------------------------------------
modprobe squashfs &>/dev/null
#======================================
# decide for a mount method
#--------------------------------------
if [ ! -z "$lop" ];then
src=$(loop_setup $lop)
if [ ! -e $src ]; then
return 1
fi
# /.../
# for iso images the root device name is set via
# config.isoclient. But in case of a filename the
# root device must be loop mounted and the loop
# setup creates the root device which is stored
# in imageDevice for the isoboot code
# ----
imageDevice=$src
fi
#======================================
# probe filesystem
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
fstype=nfs
else
fstype=$(probeFileSystem $src)
fi
if [ "$fstyoe" = "unknown" ];then
fstype="auto"
fi
if ! mount -t $fstype $opt $src $dst >/dev/null;then
return 1
fi
return 0
}
#======================================
# setupReadWrite
#--------------------------------------
function setupReadWrite {
# /.../
# check/create read-write filesystem used for
# overlay data
# ----
local IFS=$IFS_ORIG
local rwDir=/read-write
local rwDevice=$(echo $UNIONFS_CONFIG | cut -d , -f 1)
local fstype=$(blkid $rwDevice -s TYPE -o value)
local hybrid_fs=$HYBRID_PERSISTENT_FS
local create_hybrid="no"
local fs_opts
mkdir -p $rwDir
if [ $hybrid_fs = "ext4" ];then
fs_opts="$HYBRID_EXT4_OPTS"
fi
if [ ! -z "$kiwi_hybridpersistent_filesystem" ];then
hybrid_fs=$kiwi_hybridpersistent_filesystem
fi
if [ $LOCAL_BOOT = "yes" ] || [ ! $systemIntegrity = "clean" ];then
# no further action on a standard boot/reboot or in unclean state
return 0
fi
if [ ! -z "$fstype" ];then
Echo "Checking filesystem for RW data on $rwDevice..."
checkFilesystem $rwDevice &>/dev/null
fi
if [ "$RELOAD_IMAGE" = "yes" ]; then
# create rw fs explicitly activated
create_hybrid="yes"
elif ! mount -o ro $rwDevice $rwDir &>/dev/null; then
# still failing after check, trigger creation of new rw fs
create_hybrid="yes"
fi
mountpoint -q $rwDir && umount $rwDevice
if [ "$create_hybrid" = "yes" ];then
Echo "Creating filesystem for RW data on $rwDevice..."
if ! createFilesystem \
"$rwDevice" "$hybrid_fs" "" "" "hybrid" "false" "$fs_opts"
then
Echo "Failed to create ${hybrid_fs} filesystem"
return 1
fi
fi
return 0
}
#======================================
# mountSystemSeedBtrFS
#--------------------------------------
function mountSystemSeedBtrFS {
local IFS=$IFS_ORIG
local loopf=$1
local rwDevice=`echo $UNIONFS_CONFIG | cut -d , -f 1`
local roDevice=`echo $UNIONFS_CONFIG | cut -d , -f 2`
local prefix=/mnt
#======================================
# check read/only device location
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
roDevice="$imageRootDevice"
fi
#======================================
# check read/write device location
#--------------------------------------
if [ ! -e $rwDevice ];then
rwDevice=/dev/ram1
fi
#======================================
# mount/check btrfs file
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
#======================================
# btrfs exported via NFS
#--------------------------------------
if ! kiwiMount "$roDevice" "$prefix" "" $loopf;then
Echo "Failed to mount NFS filesystem"
return 1
fi
else
#======================================
# mount btrfs container
#--------------------------------------
if [ -z "$loopf" ];then
loopf=$roDevice
fi
if ! mount -o loop,$kiwi_fsmountoptions $loopf $prefix; then
Echo "Failed to mount btrfs filesystem"
return 1
fi
fi
#======================================
# add seed device
#--------------------------------------
if ! btrfs device add $rwDevice $prefix; then
Echo "Failed to attach btrfs seed device"
return 1
fi
if ! mount -o remount,rw $prefix; then
Echo "Failed to remount read-write"
return 1
fi
return 0
}
#======================================
# mountSystemUnionFS
#--------------------------------------
function mountSystemUnionFS {
local IFS=$IFS_ORIG
local loopf=$1
local roDir=/read-only
local rwDir=/read-write
local rwDevice=`echo $UNIONFS_CONFIG | cut -d , -f 1`
local roDevice=`echo $UNIONFS_CONFIG | cut -d , -f 2`
local unionFST=`echo $UNIONFS_CONFIG | cut -d , -f 3`
local prefix=/mnt
local mount_options
#======================================
# load fuse module
#--------------------------------------
modprobe fuse &>/dev/null
#======================================
# create overlay mount points
#--------------------------------------
mkdir -p $roDir
mkdir -p $rwDir
#======================================
# check read/only device location
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
roDevice="$imageRootDevice"
fi
#======================================
# mount read only device
#--------------------------------------
if ! kiwiMount "$roDevice" "$roDir" "" $loopf;then
Echo "Failed to mount read only filesystem"
return 1
fi
#======================================
# check read/write device location
#--------------------------------------
if [ ! -z "$kiwi_ramonly" ];then
rwDevice=tmpfs
fi
if [ "$rwDevice" = "tmpfs" ];then
#======================================
# write into tmpfs
#--------------------------------------
if ! mount -t tmpfs tmpfs $rwDir >/dev/null;then
Echo "Failed to mount tmpfs read/write filesystem"
return 1
fi
else
#======================================
# write to another device
#--------------------------------------
if [ "$roDevice" = "nfs" ];then
rwDevice="-o nolock,rw $nfsRootServer:$rwDevice"
fi
if [ ! "$roDevice" = "nfs" ] && ! setupReadWrite; then
return 1
fi
if [ "$kiwi_hybridpersistent" = "true" ];then
# When using an overlay writing to a block device safety has
# less priority over speed. If this does not match your use
# case please report an issue on the kiwi github
mount_options="-o defaults,async,relatime,nodiratime"
fi
if ! kiwiMount "$rwDevice" "$rwDir" "$mount_options";then
Echo "Failed to mount read/write filesystem"
return 1
fi
fi
#======================================
# overlay mount the locations
#--------------------------------------
if [ "$unionFST" = "overlay" ];then
#======================================
# setup overlayfs mount
#--------------------------------------
# overlayfs in version >= v22 behaves differently
# + renamed from overlayfs to overlay
# + requires a workdir to become mounted
# + requires workdir and upperdir to reside under the same mount
# + requires workdir and upperdir to be in separate subdirs
# try new mode first, if that fails then fallback to old style
mkdir -p $rwDir/work
mkdir -p $rwDir/rw
local opts="rw,lowerdir=$roDir,upperdir=$rwDir/rw,workdir=$rwDir/work"
if ! mount -t overlay -o $opts overlay $prefix;then
# overlayfs in version < v22 fallback/compat mode
# + does not require a workdir
rm -rf $rwDir/work
rm -rf $rwDir/rw
opts="rw,lowerdir=$roDir,upperdir=$rwDir"
if ! mount -t overlayfs -o $opts overlayfs $prefix;then
Echo "Failed to mount root via overlayfs"
return 1
fi
fi
elif [ "$unionFST" = "unionfs" ];then
#======================================
# setup fuse union mount
#--------------------------------------
local opts="cow,max_files=65000,allow_other,use_ino,suid,dev,nonempty"
if ! unionfs -o $opts $rwDir=RW:$roDir=RO $prefix;then
Echo "Failed to mount root via unionfs"
return 1
fi
fi
export haveUnionFS=yes
return 0
}
#======================================
# mountSystemClicFS
#--------------------------------------
function mountSystemClicFS {
local IFS=$IFS_ORIG
local loopf=$1
local roDir=/read-only
local rwDevice=`echo $UNIONFS_CONFIG | cut -d , -f 1`
local roDevice=`echo $UNIONFS_CONFIG | cut -d , -f 2`
local clic_cmd=clicfs
local resetReadWrite=0
local ramOnly=0
local haveBytes
local haveKByte
local haveMByte
local wantCowFS
local size
local prefix=/mnt
#======================================
# load fuse module
#--------------------------------------
modprobe fuse &>/dev/null
#======================================
# create read only mount point
#--------------------------------------
mkdir -p $roDir
#======================================
# check read/only device location
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
roDevice="$imageRootDevice"
fi
#======================================
# check kernel command line for log file
#--------------------------------------
if [ -n "$cliclog" ]; then
clic_cmd="$clic_cmd -l $cliclog"
fi
#======================================
# check read/write device location
#--------------------------------------
if [ ! -z "$kiwi_ramonly" ];then
ramOnly=1
elif [ ! -e $rwDevice ];then
ramOnly=1
elif getDiskDevice $rwDevice | grep -q ram;then
ramOnly=1
fi
if [ $ramOnly = 1 ];then
haveKByte=`cat /proc/meminfo | grep MemFree | cut -f2 -d:| cut -f1 -dk`
haveMByte=$((haveKByte / 1024))
haveMByte=$((haveMByte * 7 / 10))
clic_cmd="$clic_cmd -m $haveMByte"
else
haveBytes=$(blockdev --getsize64 $rwDevice)
haveMByte=$((haveBytes / 1024 / 1024))
wantCowFS=0
if \
[ "$kiwi_hybrid" = "true" ] && \
[ "$kiwi_hybridpersistent" = "true" ]
then
# write into a cow file on a filesystem, for hybrid iso's
wantCowFS=1
fi
if [ $wantCowFS = 1 ];then
# write into a cow file on a filesystem
mkdir -p $HYBRID_PERSISTENT_DIR
if [ $LOCAL_BOOT = "no" ] && [ $systemIntegrity = "clean" ];then
resetReadWrite=1
elif ! mount $rwDevice $HYBRID_PERSISTENT_DIR;then
resetReadWrite=1
elif [ ! -z "$wipecow" ];then
resetReadWrite=1
fi
if [ $resetReadWrite = 1 ];then
if ! setupReadWrite; then
Echo "Failed to setup read-write filesystem"
return 1
fi
if ! mount $rwDevice $HYBRID_PERSISTENT_DIR;then
Echo "Failed to mount read/write filesystem"
return 1
fi
fi
clic_cmd="$clic_cmd -m $haveMByte"
clic_cmd="$clic_cmd -c $HYBRID_PERSISTENT_DIR/.clicfs_COW"
else
# write into a device directly
clic_cmd="$clic_cmd -m $haveMByte -c $rwDevice --ignore-cow-errors"
fi
fi
#======================================
# mount/check clic file
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
#======================================
# clic exported via NFS
#--------------------------------------
if ! kiwiMount "$roDevice" "$roDir" "" $loopf;then
Echo "Failed to mount NFS filesystem"
return 1
fi
if [ ! -e "$roDir/fsdata.ext4" ];then
Echo "Can't find clic fsdata.ext4 in NFS export"
return 1
fi
else
#======================================
# mount clic container
#--------------------------------------
if [ -z "$loopf" ];then
loopf=$roDevice
fi
if ! $clic_cmd $loopf $roDir; then
Echo "Failed to mount clic filesystem"
return 1
fi
fi
#======================================
# mount root over clic
#--------------------------------------
size=$(stat -c %s $roDir/fsdata.ext4)
size=$((size/512))
# we don't want reserved blocks...
tune2fs -m 0 $roDir/fsdata.ext4 >/dev/null
# we don't want automatic filesystem check...
tune2fs -i 0 $roDir/fsdata.ext4 >/dev/null
if [ ! $LOCAL_BOOT = "no" ];then
e2fsck -p $roDir/fsdata.ext4
fi
if [ $LOCAL_BOOT = "no" ] || [ $ramOnly = 1 ];then
resize2fs $roDir/fsdata.ext4 $size"s"
fi
mount -o loop,noatime,nodiratime,errors=remount-ro,barrier=0 \
$roDir/fsdata.ext4 $prefix
if [ ! $? = 0 ];then
Echo "Failed to mount ext4 clic container"
return 1
fi
# Give fuse enough time to settle for I/O in the ext4 container
# Unconditional waiting is never a good idea however I couldn't
# find a good solution to this problem because a lookup on read
# or write could cause an ro remount of the ext4 container
# Thus we just sleep a while before proceeding
sleep 5
export haveClicFS=yes
return 0
}
#======================================
# mountSystemStandard
#--------------------------------------
function mountSystemStandard {
local IFS=$IFS_ORIG
local mountDevice=$1
local variable
local volume
local content
local volpath
local mpoint
local mppath
local prefix=/mnt
local fstype=$(probeFileSystem $mountDevice)
if [ ! $fstype = "unknown" ]; then
kiwiMount "$mountDevice" "$prefix"
else
mount $mountDevice $prefix >/dev/null
fi
if [ "$haveLVM" = "yes" ];then
local volume_name
local mount_device
local mount_point
for i in $(readVolumeSetup "/.profile");do
volume_name=$(getVolumeName $i)
if [ $volume_name = "LVRoot" ]; then
continue
fi
mount_point=$(getVolumeMountPoint $i)
mount_device="/dev/$kiwi_lvmgroup/$volume_name"
mkdir -p $prefix/$mount_point
kiwiMount "$mount_device" "$prefix/$mount_point"
done
elif [ "$fstype" = "btrfs" ];then
if [ "$kiwi_btrfs_root_is_snapshot" = "true" ];then
mountBtrfsSubVolumes $mountDevice $prefix
fi
fi
return $?
}
#======================================
# mountSystem
#--------------------------------------
function mountSystem {
local IFS=$IFS_ORIG
local retval=0
#======================================
# set primary mount device
#--------------------------------------
local mountDevice="$imageRootDevice"
if [ ! -z "$1" ];then
mountDevice="$1"
fi
#======================================
# wait for storage device to appear
#--------------------------------------
if ! echo $mountDevice | grep -qE "loop|vers=";then
waitForStorageDevice $mountDevice
fi
#======================================
# check root tree type
#--------------------------------------
if [ ! -z "$UNIONFS_CONFIG" ];then
local unionFST=`echo $UNIONFS_CONFIG | cut -d , -f 3`
if [ "$unionFST" = "clicfs" ];then
mountSystemClicFS $2
elif [ "$unionFST" = "seed" ];then
mountSystemSeedBtrFS $2
elif [ "$unionFST" = "overlay" ];then
mountSystemUnionFS $2
elif [ "$unionFST" = "unionfs" ];then
mountSystemUnionFS $2
else
systemException \
"Unknown overlay mount method: $unionFST" \
"reboot"
fi
retval=$?
else
mountSystemStandard "$mountDevice"
retval=$?
fi
#======================================
# setup boot partition
#--------------------------------------
if \
[ -z "$skipSetupBootPartition" ] && \
[ "$LOCAL_BOOT" = "no" ] && \
[ ! "$systemIntegrity" = "fine" ] && \
[ $retval = 0 ] && \
[ -z "$RESTORE" ]
then
if [[ $kiwi_initrdname =~ netboot ]];then
setupBootPartitionPXE
else
setupBootPartition
fi
fi
#======================================
# reset mount counter
#--------------------------------------
resetMountCounter
return $retval
}
#======================================
# mountOrCopyLiveCD
#--------------------------------------
function mountOrCopyLiveCD {
local SIZE
if [ ! -z "$TORAM" ]; then
Echo "Copying CD system into tmpfs"
mkdir -p ${LIVECD}R $LIVECD && \
eval mount $cdopt $biosBootDevice ${LIVECD}R
SIZE="$(du -s /${LIVECD}R | gawk '{print int($1*1.1)}')"
mount -t tmpfs -o size=${SIZE}k tmpfs $LIVECD
if ! cp -ar ${LIVECD}R/* $LIVECD; then
systemException \
"Copying CD contents to tmpfs failed" \
"reboot"
fi
umount ${LIVECD}R
rmdir ${LIVECD}R
else
mkdir -p $LIVECD && eval mount $cdopt $biosBootDevice $LIVECD
fi
}
#======================================
# cleanDirectory
#--------------------------------------
function cleanDirectory {
local IFS=$IFS_ORIG
local directory=$1
shift 1
local save=$@
local tmpdir=`mktemp -d`
for saveItem in $save;do
mv $directory/$saveItem $tmpdir >/dev/null
done
rm -rf $directory/*
mv $tmpdir/* $directory
rm -rf $tmpdir
}
#======================================
# searchGroupConfig
#--------------------------------------
function searchGroupConfig {
local IFS=$IFS_ORIG
local localhwaddr=$DHCPCHADDR
local GROUPCONFIG=/etc/config.group
local list_var
local mac_list
#======================================
# Load group file if it exists
#--------------------------------------
Echo "Checking for config file: config.group";
fetchFile KIWI/config.group $GROUPCONFIG
if [ ! -s $GROUPCONFIG ]; then
return
fi
Echo "Found config.group, determining available groups";
importFile < $GROUPCONFIG
Debug "KIWI_GROUP = '$KIWI_GROUP'"
#======================================
# Parse group file
#--------------------------------------
if [ -z "$KIWI_GROUP" ] ; then
systemException \
"No groups defined in $GROUPCONFIG" \
"reboot"
fi
for i in `echo "$KIWI_GROUP" | sed 's/,/ /g' | sed 's/[ \t]+/ /g'`; do
Echo "Lookup MAC address: $localhwaddr in ${i}_KIWI_MAC_LIST"
eval list_var="${i}_KIWI_MAC_LIST"
eval mac_list=\$$list_var
searchGroupHardwareAddress $i "$mac_list"
if [ -s $CONFIG ]; then
break
fi
unset list_var
unset mac_list
done
}
#======================================
# searchGroupHardwareAddress
#--------------------------------------
function searchGroupHardwareAddress {
# /.../
# function to check the existance of the hosts
# hardware address within the defined "mac_list".
# If the hardware address is found, load the config file.
# ----
local IFS=$IFS_ORIG
local localhwaddr=$DHCPCHADDR
local local_group=$1
local mac_list=$2
for j in `echo "$mac_list" | sed 's/,/ /g' | sed 's/[ \t]+/ /g'`; do
if [ "$localhwaddr" = "$j" ] ; then
Echo "MAC address $localhwaddr found in group $local_group"
Echo "Checking for config file: config.$local_group"
fetchFile KIWI/config.$local_group $CONFIG
if [ ! -s $CONFIG ]; then
systemException \
"No configuration found for $j" \
"reboot"
fi
break
fi
done
}
#======================================
# searchAlternativeConfig
#--------------------------------------
function searchAlternativeConfig {
local IFS=$IFS_ORIG
# Check config.IP in Hex (pxelinux style)
localip=$IPADDR
hexip1=`echo $localip | cut -f1 -d'.'`
hexip2=`echo $localip | cut -f2 -d'.'`
hexip3=`echo $localip | cut -f3 -d'.'`
hexip4=`echo $localip | cut -f4 -d'.'`
hexip=`printf "%02X" $hexip1 $hexip2 $hexip3 $hexip4`
STEP=8
while [ $STEP -gt 0 ]; do
hexippart=`echo $hexip | cut -b -$STEP`
Echo "Checking for config file: config.$hexippart"
fetchFile KIWI/config.$hexippart $CONFIG
if test -s $CONFIG;then
break
fi
let STEP=STEP-1
done
# Check config.default if no hex config was found
if test ! -s $CONFIG;then
Echo "Checking for config file: config.default"
fetchFile KIWI/config.default $CONFIG
fi
}
#======================================
# searchHardwareMapConfig
#--------------------------------------
function searchHardwareMapConfig {
local IFS=$IFS_ORIG
local list_var
local mac_list
#======================================
# return if no map was specified
#--------------------------------------
if [ -z "$HARDWARE_MAP" ];then
return
fi
Echo "Found hardware/vendor map configuration variable"
#===========================================
# Evaluate the MAP list, and test for hwaddr
#-------------------------------------------
for i in `echo "$HARDWARE_MAP" | sed 's/,/ /g' | sed 's/[ \t]+/ /g'`; do
Echo "Lookup MAC address: $localhwaddr in ${i}_HARDWARE_MAP"
eval list_var="${i}_HARDWARE_MAP"
eval mac_list=\$$list_var
Debug "${i}_HARDWARE_MAP = '$mac_list'"
searchHardwareMapHardwareAddress $i "$mac_list"
if [ -s $CONFIG ]; then
break
fi
unset list_var
unset mac_list
done
}
#======================================
# searchHardwareMapHardwareAddress
#--------------------------------------
function searchHardwareMapHardwareAddress {
local IFS=$IFS_ORIG
local HARDWARE_CONFIG=/etc/config.hardware
local localhwaddr=$DHCPCHADDR
local hardware_group=$1
local mac_list=$2
Debug "hardware_group = '$hardware_group'"
Debug "mac_list = '$mac_list'"
for j in `echo "$mac_list" | sed 's/,/ /g' | sed 's/[ \t]+/ /g'`; do
if [ "$localhwaddr" = "$j" ] ; then
Echo "MAC address $localhwaddr found in group $hardware_group"
Echo "Checking for config file: hardware_config.$hardware_group"
fetchFile KIWI/hardware_config.$hardware_group $HARDWARE_CONFIG
if [ ! -s $HARDWARE_CONFIG ]; then
systemException \
"No configuration found for $j" \
"reboot"
fi
importFile < $HARDWARE_CONFIG
break
fi
done
}
#======================================
# runHook
#--------------------------------------
function runHook {
local IFS=$IFS_ORIG
#======================================
# Check for execution permission
#--------------------------------------
if [ ! -z "$KIWI_FORBID_HOOKS" ];then
Echo "Hook script execution is forbidden by KIWI_FORBID_HOOKS"
return
fi
#======================================
# Init custom post hook commands
#--------------------------------------
# a) switch post command execution off, can be activated by hook script
export eval KIWI_ALLOW_HOOK_CMD_$1=0
#======================================
# Search and execute hook script
#--------------------------------------
HOOK="/kiwi-hooks/$1.sh"
if [ ! -e $HOOK ];then
HOOK="/lib/kiwi/hooks/$1.sh"
fi
if [ -e $HOOK ]; then
. $HOOK "$@"
fi
#======================================
# Run custom post hook commands
#--------------------------------------
# b) check permisson and state of command list
if [ ! -z "$KIWI_FORBID_HOOK_CMDS" ];then
Echo "Post-Hook command execution is forbidden by KIWI_FORBID_HOOK_CMDS"
return
fi
eval local call_cmd=\$KIWI_ALLOW_HOOK_CMD_$1
if [ "$call_cmd" -eq 1 ]; then
eval local call=\$KIWI_HOOK_CMD_$1
eval $call
fi
}
#======================================
# getNextPartition
#--------------------------------------
function getNextPartition {
local IFS=$IFS_ORIG
part=$1
nextPart=`echo $part | sed -e "s/\(.*\)[0-9]/\1/"`
nextPartNum=`echo $part | sed -e "s/.*\([0-9]\)/\1/"`
nextPartNum=$((nextPartNum + 1))
nextPart="${nextPart}${nextPartNum}"
echo $nextPart
}
#======================================
# startShell
#--------------------------------------
function startShell {
# /.../
# start a debugging shell on ELOG_BOOTSHELL
# ----
local IFS=$IFS_ORIG
if [ ! -z $kiwidebug ];then
if [ ! -e $ELOG_BOOTSHELL ];then
Echo "No terminal $ELOG_BOOTSHELL available for debug shell"
return
fi
Echo "Starting boot shell on $ELOG_BOOTSHELL"
sulogin -e -p $ELOG_BOOTSHELL &
sleep 2
ELOGSHELL_PID=$(fuser $ELOG_BOOTSHELL | tr -d " ")
echo ELOGSHELL_PID=$ELOGSHELL_PID >> /iprocs
fi
}
#======================================
# killShell
#--------------------------------------
function killShell {
# /.../
# kill debugging shell on ELOG_BOOTSHELL
# ----
local IFS=$IFS_ORIG
local umountProc=0
if [ ! -e /proc/mounts ];then
mount -t proc proc /proc
umountProc=1
fi
if [ ! -z "$ELOGSHELL_PID" ];then
Echo "Stopping boot shell"
kill $ELOGSHELL_PID &>/dev/null
fi
if [ $umountProc -eq 1 ];then
umount /proc
fi
}
#======================================
# waitForStorageDevice
#--------------------------------------
function waitForStorageDevice {
# /.../
# function to check access on a storage device which could be
# a whole disk or a partition. The function will wait until
# the size of the storage device could be obtained and is
# greater than zero or the timeout is reached. Default timeout
# is set to 60 seconds, however it can be set to different
# value by setting the DEVICE_TIMEOUT variable on the kernel
# command line.
# ----
local IFS=$IFS_ORIG
local device=$1
local check=0
local limit=30
local storage_size=0
if [[ $DEVICE_TIMEOUT =~ ^[0-9]+$ ]]; then
limit=$(((DEVICE_TIMEOUT + 1)/ 2))
fi
udevPending
while true;do
storage_size=$(partitionSize $device)
if [ $storage_size -gt 0 ]; then
sleep 1; return 0
fi
if [ $check -eq $limit ]; then
return 1
fi
Echo "Waiting for storage device $device to settle..."
check=$((check + 1))
sleep 2
done
}
#======================================
# waitForLinkUp
#--------------------------------------
function waitForLinkUp {
# /.../
# wait for the network link to enter UP state
# ----
local IFS=$IFS_ORIG
local dev=$1
local check=0
local linkstatus
local linkgrep
while true;do
if lookup ifplugstatus &>/dev/null;then
linkstatus=ifplugstatus
linkgrep="link beat detected"
else
linkstatus="ip link ls"
linkgrep="state UP"
fi
$linkstatus $dev | grep -qi "$linkgrep"
if [ $? = 0 ];then
sleep 1; return 0
fi
if [ $check -eq 30 ];then
return 1
fi
Echo "Waiting for link up on ${dev}..."
check=$((check + 1))
sleep 2
done
}
#======================================
# setIPLinkUp
#--------------------------------------
function setIPLinkUp {
local IFS=$IFS_ORIG
local try_iface=$1
if ip link set dev $try_iface up;then
if [ ! $try_iface = "lo" ];then
waitForLinkUp $try_iface
fi
# success
return 0
fi
# error on ip call, failed state
return 1
}
#======================================
# waitForDHCPInterfaceNegotiation
#--------------------------------------
function waitForDHCPInterfaceNegotiation {
local IFS=$IFS_ORIG
local dhcp_info=$1
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20;do
if [ -s $dhcp_info ] &&
grep -q "^IPADDR=" $dhcp_info
then
# success
return 0
fi
sleep 2
done
# timeout reached, failed state
return 1
}
#======================================
# waitForBlockDevice
#--------------------------------------
function waitForBlockDevice {
# /.../
# function to check if the given block device
# exists. If not the function will wait until the
# device appears or the check counter equals 4
# ----
local IFS=$IFS_ORIG
local device=$1
local check=0
udevPending
while true;do
if [ -b $device ] || [ $check -eq 4 ];then
break
fi
Echo "Waiting for block device $device to settle..."
check=$((check + 1))
sleep 2
done
}
#======================================
# atftpProgress
#--------------------------------------
function atftpProgress {
# /.../
# atftp doesn't use a stream based download and sometimes
# seek back and forth which makes it hard to use pipes for
# progress indication. Therefore we watch the trace output
# ----
local IFS=$IFS_ORIG
local imgsize=$1 # image size in MB
local prefix=$2 # line prefix text
local file=$3 # file with progress data
local blocksize=$4 # blocksize use for download
local bytes=0 # log lines multiplied by blocksize
local lines=0 # log lines
local percent=0 # in percent of all
local all=$((imgsize * 1024 * 1024))
local line
local step=0
# number of cycles for approx. 2% steps
local max_step=$(($all / $blocksize / 25))
cat < dev/null > $file.tmp
#======================================
# print progress information
#--------------------------------------
while read line ;do
echo "$line" >> $file.tmp
let step=step+1
if [ $step -lt $max_step ]; then
continue
fi
step=0
# /.../
# the trace logs two lines indicating one download block of
# blocksize bytes. We assume only full blocks. At the end
# it might happen that only a part of blocksize bytes is
# required. The function does not precisely calculate them
# and assumes blocksize bytes. imho that's ok for the progress
# bar. In order to be exact the function would have to sum
# up all bytes from the trace log for each iteration which
# would cause the download to pause because it has to wait
# for the progress bar to get ready
# ----
# the same block can be transferred multiple times
lines=$(grep "^sent ACK" $file.tmp | sort -u | wc -l)
bytes=$((lines * $blocksize))
percent=$(echo "scale=2; $bytes * 100" | bc)
percent=$(echo "scale=0; $percent / $all" | bc)
echo -en "$prefix ( $percent%)\r"
done
grep -v "^\(received \)\|\(sent \)" $file.tmp > $file
rm $file.tmp
echo
}
#======================================
# encodeURL
#--------------------------------------
function encodeURL {
# /.../
# encode special characters in URL's to correctly
# serve as input for fetchFile and putFile
# ----
local IFS=$IFS_ORIG
local STR
local CH
STR="$@"
echo -n "$STR" | while read -n1 CH; do
[[ $CH =~ [-_A-Za-z0-9./] ]] && printf "$CH" || printf "%%%x" \'"$CH"
done
}
#======================================
# fetchFile
#--------------------------------------
function fetchFile {
# /.../
# the generic fetcher which is able to use different protocols
# tftp,ftp, http, https. fetchFile is used in the netboot linuxrc
# and uses curl and atftp to download files from the network
# ----
local IFS=$IFS_ORIG
local path=$1
local dest=$2
local izip=$3
local host=$4
local type=$5
local chunk=$6
local encoded_path
local dump
local call
local call_pid
local unzip
#======================================
# source path is required
#--------------------------------------
if [ -z "$path" ]; then
systemException "No source path specified" "reboot"
fi
#======================================
# destination path is required
#--------------------------------------
if [ -z "$dest" ];then
systemException "No destination path specified" "reboot"
fi
#======================================
# source host is required
#--------------------------------------
if [ ! -z $kiwiserver ];then
host=$kiwiserver
fi
if [ -z "$host" ]; then
systemException "No source server specified" "reboot"
fi
#======================================
# set default chunk size
#--------------------------------------
if [ -z "$chunk" ];then
chunk=4k
fi
#======================================
# set default service type
#--------------------------------------
if [ ! -z $kiwiservertype ]; then
type=$kiwiservertype
fi
if [ -z "$type" ]; then
type="tftp"
fi
#======================================
# set source path + tool if compressed
#--------------------------------------
if [ ! -z "$izip" ] && [[ ! "$izip" =~ ^uncomp ]];then
if [ $izip = "compressed" ] || [ "$izip" = "compressed-gzip" ]; then
unzip="gzip -d"
path=$(echo "$path" | sed -e s@\\.gz@@)
path="$path.gz"
elif [ $izip = "compressed-xz" ];then
unzip="xz -d"
path=$(echo "$path" | sed -e s@\\.xz@@)
path="$path.xz"
else
systemException "Unknown compression mode: $izip" "reboot"
fi
else
unset izip
fi
#======================================
# encode special URL characters
#--------------------------------------
encoded_path=$(encodeURL "$path")
#======================================
# setup progress meta information
#--------------------------------------
dump="dd bs=$chunk of=\"$dest\""
showProgress=0
if \
[ -x /usr/bin/dcounter ] && \
[ -f /etc/image.md5 ] && \
[ -b "$dest" ] && \
[ -z "$disableProgressInfo" ]
then
showProgress=1
hideSplash
read sum1 blocks blocksize zblocks zblocksize < /etc/image.md5
needBytes=$((blocks * blocksize))
needMByte=$((needBytes / 1048576))
if [ ! -z "$zblocks" ];then
needZBytes=$((zblocks * zblocksize))
needZMByte=$((needZBytes / 1048576))
fi
progressBaseName=$(basename "$path")
TEXT_LOAD=$(getText "Loading %1" "$progressBaseName")
TEXT_COMP=$(getText "Uncompressing %1" "$progressBaseName")
dump="dcounter -s $needMByte -l \"$TEXT_LOAD \" 2>/progress | $dump"
fi
#======================================
# build download command
#--------------------------------------
case "$type" in
"local")
if [ ! -z "$izip" ];then
call="$unzip < $host/$path \
2>$TRANSFER_ERRORS_FILE | $dump"
else
call="dd if=$host/$path bs=$chunk |\
$dump"
fi
;;
"http")
if [ ! -z "$izip" ];then
call="curl -f http://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$unzip 2>>$TRANSFER_ERRORS_FILE | $dump"
else
call="curl -f http://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$dump"
fi
;;
"https")
if [ ! -z "$izip" ];then
call="curl -f -k https://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$unzip 2>>$TRANSFER_ERRORS_FILE | $dump"
else
call="curl -f -k https://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$dump"
fi
;;
"ftp")
if [ ! -z "$izip" ];then
call="curl ftp://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$unzip 2>>$TRANSFER_ERRORS_FILE | $dump"
else
call="curl ftp://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$dump"
fi
;;
"tftp")
validateBlockSize
# /.../
# atftp activates multicast by '--option "multicast"'
# and deactivates it again by '--option "disable multicast"'
# ----
if [ -f /etc/image.md5 ] && [ -b "$dest" ];then
# enable multicast for system image and transfer to block device
multicast_atftp="multicast"
else
# disable multicast for any other transfer
multicast_atftp="disable multicast"
fi
havetemp_dir=1
if [ -z "$FETCH_FILE_TEMP_DIR" ];then
# we don't have a tmp dir available for downloading
havetemp_dir=0
elif [ -e "$FETCH_FILE_TEMP_DIR/${path##*/}" ];then
# temporary download data already exists
havetemp_dir=0
else
# prepare use of temp files for compressed download
FETCH_FILE_TEMP_FILE="$FETCH_FILE_TEMP_DIR/${path##*/}"
export FETCH_FILE_TEMP_FILE
fi
if [ ! -z "$izip" ];then
if [ $havetemp_dir -eq 0 ];then
# /.../
# operate without temp files, standard case
# ----
call="busybox tftp \
-b $imageBlkSize -g -r \"$path\" \
-l >($unzip 2>>$TRANSFER_ERRORS_FILE | $dump) \
$host 2>>$TRANSFER_ERRORS_FILE"
else
# /.../
# operate using temp files
# export the path to allow temp file management in a hook
# ----
if [ $showProgress -eq 1 ];then
call="(atftp \
--trace \
--option \"$multicast_atftp\" \
--option \"blksize $imageBlkSize\" \
-g -r \"$path\" -l \"$FETCH_FILE_TEMP_FILE\" \
$host 2>&1 | \
atftpProgress \
$needZMByte \"$TEXT_LOAD\" \
$TRANSFER_ERRORS_FILE $imageBlkSize \
>&2 ; \
$unzip < \"$FETCH_FILE_TEMP_FILE\" | \
dcounter -s $needMByte -l \"$TEXT_COMP \" | \
dd bs=$chunk of=\"$dest\" ) 2>/progress "
else
call="atftp \
--option \"$multicast_atftp\" \
--option \"blksize $imageBlkSize\" \
-g -r \"$path\" -l \"$FETCH_FILE_TEMP_FILE\" $host \
&> $TRANSFER_ERRORS_FILE ; \
$unzip < \"$FETCH_FILE_TEMP_FILE\" | \
dd bs=$chunk of=\"$dest\" "
fi
fi
else
if [ $showProgress -eq 1 ];then
call="atftp \
--trace \
--option \"$multicast_atftp\" \
--option \"blksize $imageBlkSize\" \
-g -r \"$path\" -l \"$dest\" $host 2>&1 | \
atftpProgress \
$needMByte \"$TEXT_LOAD\" \
$TRANSFER_ERRORS_FILE $imageBlkSize \
> /progress"
else
call="atftp \
--option \"$multicast_atftp\" \
--option \"blksize $imageBlkSize\" \
-g -r \"$path\" -l \"$dest\" $host \
&> $TRANSFER_ERRORS_FILE"
fi
fi
;;
*)
systemException "Unknown download type: $type" "reboot"
;;
esac
#======================================
# run the download
#--------------------------------------
if [ $showProgress -eq 1 ];then
test -e /progress || mkfifo /progress
test -e /tmp/load_code && rm -f /tmp/load_code
errorLogStop
(
eval $call \; 'echo ${PIPESTATUS[0]} > /tmp/load_code' &>/dev/null
)&
call_pid=$!
echo "cat /progress | dialog \
--backtitle \"$TEXT_INSTALLTITLE\" \
--progressbox 3 65
" > /tmp/progress.sh
if FBOK;then
fbiterm -m $UFONT -- bash -e /tmp/progress.sh
else
bash -e /tmp/progress.sh
fi
clear
wait $call_pid
loadCode=`cat /tmp/load_code`
if [ -z "$loadCode" ]; then
systemException \
"Failed to get the download process return value" \
"reboot"
fi
else
eval $call \; 'loadCode=${PIPESTATUS[0]}'
fi
if [ $showProgress -eq 1 ];then
errorLogContinue
fi
loadStatus=`cat $TRANSFER_ERRORS_FILE`
return $loadCode
}
#======================================
# fetchFileLocal
#--------------------------------------
function fetchFileLocal {
# /.../
# ----
fetchFile "$1" "$2" "$3" "$KIWI_LOCAL_CACHE_DIR" "local"
}
#======================================
# putFile
#--------------------------------------
function putFile {
# /.../
# the generic putFile function is used to upload boot data on
# a server. Supported protocols are tftp, ftp, http, https
# ----
local IFS=$IFS_ORIG
local path=$1
local dest=$2
local host=$3
local type=$4
local encoded_dest
if test -z "$path"; then
systemException "No path specified" "reboot"
fi
if [ ! -z $kiwiserver ];then
host=$kiwiserver
fi
if test -z "$host"; then
systemException "No server specified" "reboot"
fi
if [ ! -z $kiwiservertype ]; then
type=$kiwiservertype
fi
if test -z "$type"; then
type="tftp"
fi
encoded_dest=$(encodeURL "$dest")
case "$type" in
"local")
cp -f "$path" "$host/$dest" > $TRANSFER_ERRORS_FILE 2>&1
return $?
;;
"http")
curl -f -T "$path" http://$host/$encoded_dest \
> $TRANSFER_ERRORS_FILE 2>&1
return $?
;;
"https")
curl -f -T "$path" https://$host/$encoded_dest \
> $TRANSFER_ERRORS_FILE 2>&1
return $?
;;
"ftp")
curl -T "$path" ftp://$host/$encoded_dest \
> $TRANSFER_ERRORS_FILE 2>&1
return $?
;;
"tftp")
atftp -p -l "$path" -r "$dest" $host >/dev/null 2>&1
return $?
;;
*)
systemException "Unknown download type: $type" "reboot"
;;
esac
}
#======================================
# validateRootTree
#--------------------------------------
function validateRootTree {
# /.../
# after the root of the system image has been mounted we should
# check whether that mount is a valid system tree or not. Therefore
# some sanity checks are made here
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
if [ ! -x $prefix/sbin/init -a ! -L $prefix/sbin/init ];then
systemException "/sbin/init no such file or not executable" "reboot"
fi
}
#======================================
# getDiskID
#--------------------------------------
function getDiskID {
# /.../
# this function is able to turn a given standard device
# name into the udev ID based representation
# ----
local IFS=$IFS_ORIG
local device=$1
local swap=$2
local prefix=by-id
if [ -z "$device" ];then
return
fi
if [ ! -z "$kiwi_lvmgroup" ] && echo $device | grep -q "$kiwi_lvmgroup";then
echo $device
return
fi
if [ -z "$swap" ] && [[ $device =~ ^/dev/md ]];then
echo $device
return
fi
if [ ! -z "$NON_PERSISTENT_DEVICE_NAMES" ]; then
echo $device
return
fi
if [[ $device =~ ^/dev/dm- ]];then
for i in /dev/mapper/*;do
if [ ! -L $i ];then
continue
fi
local dev=$(readlink $i)
dev=/dev/$(basename "$dev")
if [ $dev = $device ];then
echo $i
return
fi
done
fi
if [ ! -z "$kiwi_devicepersistency" ];then
prefix=$kiwi_devicepersistency
fi
for i in /dev/disk/$prefix/*;do
if [ -z "$i" ];then
continue
fi
if echo $i | grep -q edd-;then
continue
fi
local dev=$(readlink $i)
dev=/dev/$(basename "$dev")
if [ $dev = $device ];then
echo $i
return
fi
done
echo $device
}
#======================================
# getDiskDevice
#--------------------------------------
function getDiskDevice {
# /.../
# this function is able to turn the given udev disk
# ID label into the /dev/ device name
# ----
local IFS=$IFS_ORIG
local device=$(readlink $1)
if [ -z "$device" ];then
echo $1
return
fi
device=$(basename $device)
device=/dev/$device
echo $device
}
#======================================
# getDiskModel
#--------------------------------------
function getDiskModels {
# /.../
# this function returns the disk identifier as
# registered in the sysfs layer
# ----
local IFS=$IFS_ORIG
local models=`cat /sys/block/*/device/model 2>/dev/null`
if [ ! -z "$models" ];then
echo $models; return
fi
echo "unknown"
}
#======================================
# setupInittab
#--------------------------------------
function setupInittab {
# /.../
# setup default runlevel according to /proc/cmdline
# information. If textmode is set to 1 we will boot into
# runlevel 3
# ----
local IFS=$IFS_ORIG
local prefix=$1
if cat /proc/cmdline | grep -qi "textmode=1";then
sed -i -e s"@id:.*:initdefault:@id:3:initdefault:@" $prefix/etc/inittab
fi
}
#======================================
# setupConfigFiles
#--------------------------------------
function setupConfigFiles {
# /.../
# all files created below /config inside the initrd are
# now copied into the system image
# ----
local IFS=$IFS_ORIG
local file
local dir
local prefix=/mnt
cd /config
find . -type f | while read file;do
dir=$(dirname $file)
if [ ! -d $prefix/$dir ];then
mkdir -p $prefix/$dir
fi
if ! canWrite $prefix/$dir;then
Echo "Can't write to $dir, read-only filesystem... skipped"
continue
fi
cp $file $prefix/$file
done
cd /
rm -rf /config
}
#======================================
# setupMachineID
#--------------------------------------
function setupMachineID {
# /.../
# This method can be used to handle the machine ID
# in /etc/machine-id and/or /var/lib/dbus/machine-id
# It is actually implemented as a custom hook script
# ----
runHook handleMachineID "$@"
}
#======================================
# activateImage
#--------------------------------------
function activateImage {
# /.../
# move the udev created nodes from the initrd into
# the system root tree call the pre-init phase which
# already runs in the new tree and finaly switch the
# new tree to be the new root (/)
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
#======================================
# setup image name
#--------------------------------------
local name
if [ ! -z "$stickSerial" ];then
name="$stickSerial on -> $stickDevice"
elif [ ! -z "$imageName" ];then
name=$imageName
elif [ ! -z "$imageRootName" ];then
name=$imageRootName
elif [ ! -z "$imageRootDevice" ];then
name=$imageRootDevice
elif [ ! -z "$imageDiskDevice" ];then
name=$imageDiskDevice
else
name="unknown"
fi
#======================================
# move union mount points to system
#--------------------------------------
local roDir=read-only
local rwDir=read-write
local xiDir=xino
if [ -z "$NFSROOT" ];then
if [ -d $roDir ];then
mkdir -p $prefix/$roDir && mount --move /$roDir $prefix/$roDir
fi
if [ -d $rwDir ];then
mkdir -p $prefix/$rwDir && mount --move /$rwDir $prefix/$rwDir
fi
if [ -d $xiDir ];then
mkdir -p $prefix/$xiDir && mount --move /$xiDir $prefix/$xiDir
fi
fi
#======================================
# move live CD mount points to system
#--------------------------------------
local cdDir=/livecd
if [ -d $cdDir ];then
mkdir -p $prefix/$cdDir && mount --move /$cdDir $prefix/$cdDir
rm -r $cdDir && ln -s $prefix/$cdDir $cdDir
if [ -d /cow ];then
mkdir -p $prefix/cow && mount --move /cow $prefix/cow
fi
if [ -d /isofrom ];then
mkdir -p $prefix/isofrom && mount --move /isofrom $prefix/isofrom
fi
fi
#======================================
# move device nodes
#--------------------------------------
Echo "Activating Image: [$name]"
udevPending
mkdir -p $prefix/run
mkdir -p $prefix/dev
mkdir -p $prefix/var/run
mount --move /dev $prefix/dev
if [[ ! $kiwi_initrdname =~ SLE.11 ]];then
mount --move /run $prefix/run
if [ ! -L $prefix/var/run ];then
mount --move /var/run $prefix/var/run
fi
fi
udevKill
#======================================
# run preinit stage
#--------------------------------------
Echo "Preparing preinit phase..."
if ! cp /iprocs $prefix;then
systemException "Failed to copy: iprocs" "reboot"
fi
if ! cp /preinit $prefix;then
systemException "Failed to copy: preinit" "reboot"
fi
if ! cp /include $prefix;then
systemException "Failed to copy: include" "reboot"
fi
local utimer=$(lookup utimer)
if [ -e "$utimer" ];then
cp $utimer $prefix
fi
local killall5=$(lookup killall5)
if [ ! -e $prefix/$killall5 ]; then
touch $prefix/killall5.from-initrd
fi
if touch $(dirname $prefix/$killall5); then
if ! cp -f -a $killall5 $prefix/$killall5; then
systemException "Failed to copy: killall5" "reboot"
fi
fi
local pidof=$(lookup pidof)
if [ ! -e $prefix/$pidof ];then
touch $prefix/pidof.from-initrd
fi
if touch $(dirname $prefix/$pidof); then
if ! cp -f -a $pidof $prefix/$pidof;then
systemException "Failed to copy: pidof" "reboot"
fi
fi
stopMultipathd
}
#======================================
# cleanImage
#--------------------------------------
function cleanImage {
# /.../
# remove preinit code from system image before
# real init is called. this function runs already
# inside the system root directory via chroot
# ----
local IFS=$IFS_ORIG
local bootdir=boot_bind
#======================================
# setup logging in this mode
#--------------------------------------
exec 2>>$ELOG_FILE
set -x
#======================================
# kill second utimer and tail
#--------------------------------------
. /iprocs
test -n "$UTIMER_PID" && kill $UTIMER_PID &>/dev/null
#======================================
# remove preinit code from system image
#--------------------------------------
rm -f /tmp/utimer
rm -f /dev/utimer
rm -f /utimer
rm -f /iprocs
rm -f /preinit
rm -f /include
rm -f /.kconfig
rm -f /.profile
rm -rf /image
if [ -e /pidof.from-initrd ];then
rm -f /pidof.from-initrd
rm -f $(lookup pidof)
fi
if [ -e /killall5.from-initrd ];then
rm -f /killall5.from-initrd
rm -f $(lookup killall5)
fi
#======================================
# return early for special types
#--------------------------------------
if \
[ "$haveClicFS" = "yes" ] || \
[ ! -z "$NFSROOT" ] || \
[ ! -z "$NBDROOT" ] || \
[ ! -z "$AOEROOT" ]
then
return
fi
#======================================
# return early for systemd
#--------------------------------------
if [ $init = "/bin/systemd" ];then
return
fi
#======================================
# umount LVM root parts
#--------------------------------------
local volume_name
local mount_point
for i in $(readVolumeSetup "/.profile");do
volume_name=$(getVolumeName $i)
if [ $volume_name = "LVRoot" ]; then
continue
fi
mount_point=$(getVolumeMountPoint $i)
umount /$mount_point 1>&2
done
#======================================
# umount image boot partition if any
#--------------------------------------
if [ -e /$bootdir ];then
umount /$bootdir 1>&2
fi
umount /boot 1>&2
#======================================
# turn off swap
#--------------------------------------
mount -t proc proc /proc
swapoff -a 1>&2
umount /proc 1>&2
}
#======================================
# bootImage
#--------------------------------------
function bootImage {
# /.../
# call the system image init process and therefore
# boot into the operating system
# ----
local IFS=$IFS_ORIG
local reboot=no
local option=${kernel_cmdline[@]}
local prefix=/mnt
#======================================
# Set active console to default font
#--------------------------------------
setupConsoleFont
#======================================
# check for init kernel option
#--------------------------------------
if [ -z "$init" ];then
if [ -e $prefix/bin/systemd ];then
export init=/bin/systemd
else
export init=/sbin/init
fi
fi
#======================================
# turn runlevel 4 to 5 if found
#--------------------------------------
option=$(echo $@ | sed -e s@4@5@)
echo && Echo "Booting System: $option"
#======================================
# check for reboot request
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ];then
if [ -z "$KIWI_RECOVERY" ];then
if [ ! -z "$kiwi_oemreboot" ] || [ ! -z "$REBOOT_IMAGE" ];then
reboot=yes
fi
if [ ! -z "$kiwi_oemrebootinteractive" ];then
rebootinter=yes
fi
if [ ! -z "$kiwi_oemshutdown" ];then
shutdown=yes
fi
if [ ! -z "$kiwi_oemshutdowninteractive" ];then
shutdowninter=yes
fi
fi
fi
#======================================
# run resetBootBind
#--------------------------------------
if [ -z "$NETBOOT_ONLY" ];then
resetBootBind $prefix
fi
#======================================
# kill initial tail and utimer
#--------------------------------------
. /iprocs
test -n "$UTIMER_PID" && kill $UTIMER_PID &>/dev/null
#======================================
# copy boot log file into system image
#--------------------------------------
mkdir -p $prefix/var/log
rm -f $prefix/boot/mbrid
if [ -e $prefix/dev/shm/initrd.msg ];then
cp -f $prefix/dev/shm/initrd.msg $prefix/var/log/boot.msg
fi
if [ -e $ELOG_FILE ];then
cp -f $ELOG_FILE $prefix/$ELOG_FILE
fi
if [ ! -d $prefix/var/log/ConsoleKit ];then
mkdir -p $prefix/var/log/ConsoleKit
fi
#======================================
# umount proc
#--------------------------------------
umount proc &>/dev/null && \
umount proc &>/dev/null
#======================================
# run preinit and cleanImage
#--------------------------------------
chroot $prefix /bin/bash -c \
"/preinit"
chroot $prefix /bin/bash -c \
". /include ; exec 2>>$ELOG_FILE ; set -x ; cleanImage"
cd $prefix
#======================================
# tell logging the new root fs
#--------------------------------------
exec 2>>$prefix/$ELOG_FILE
set -x
#======================================
# tell plymouth the new root fs
#--------------------------------------
if lookup plymouthd &>/dev/null;then
plymouth update-root-fs --new-root-dir=$prefix
#======================================
# stop if not installed in system image
#--------------------------------------
if [ ! -e $prefix/usr/bin/plymouth ];then
plymouth quit
fi
fi
#======================================
# export root block device
#--------------------------------------
if [ -b "$imageRootDevice" ];then
export ROOTFS_BLKDEV=$imageRootDevice
fi
#======================================
# rootfs is clean, skip check
#--------------------------------------
export ROOTFS_FSCK="0"
#======================================
# stop dropbear ssh server
#--------------------------------------
if [ ! -z "$DROPBEAR_PID" ];then
kill $DROPBEAR_PID
fi
#======================================
# hand over control to init
#--------------------------------------
if [ $reboot = "yes" ];then
Echo "Reboot requested... rebooting after preinit"
exec chroot . /sbin/reboot -f -i
fi
if [ "$rebootinter" = "yes" ];then
Echo "Reboot requested... rebooting after preinit"
if [ "$OEMInstallType" = "CD" ];then
TEXT_DUMP=$TEXT_CDPULL
else
TEXT_DUMP=$TEXT_USBPULL
fi
Dialog \
--backtitle \"$TEXT_INSTALLTITLE\" \
--msgbox "\"$TEXT_DUMP\"" 5 70
clear
Echo "Prepare for reboot"
exec chroot . /sbin/reboot -f -i
fi
if [ "$shutdown" = "yes" ];then
Echo "Shutdown requested... system shutdown after preinit"
exec chroot . /sbin/halt -fihp
fi
if [ "$shutdowninter" = "yes" ];then
Echo "Shutdown requested... system shutdown after preinit"
if [ "$OEMInstallType" = "CD" ];then
TEXT_DUMP=$TEXT_CDPULL_SDOWN
else
TEXT_DUMP=$TEXT_USBPULL_SDOWN
fi
Dialog \
--backtitle \"$TEXT_INSTALLTITLE\" \
--msgbox "\"$TEXT_DUMP\"" 5 70
clear
Echo "Prepare for shutdown"
exec chroot . /sbin/halt -fihp
fi
if lookup switch_root &>/dev/null;then
exec switch_root . $init $option &>/dev/null
else
if lookup pivot_root &>/dev/null;then
pivot_root . run/initramfs &>/dev/null
fi
exec chroot . $init $option
fi
}
#======================================
# setupUnionFS
#--------------------------------------
function setupUnionFS {
# /.../
# export the UNIONFS_CONFIG environment variable
# which contains a three part coma separated list of the
# following style: rwDevice,roDevice,unionType. The
# devices are stores by disk ID if possible
# ----
local IFS=$IFS_ORIG
local rwDevice=$(getDiskID $1)
local roDevice=$(getDiskID $2)
local unionFST=$3
if [[ "$roDevice" =~ aoe|nbd ]]; then
roDevice=$imageRootDevice
fi
if [ -e "$rwDevice" ]; then
luksOpen $rwDevice luksReadWrite
rwDeviceLuks=$luksDeviceOpened
fi
if [ -e "$roDevice" ]; then
luksOpen $roDevice luksReadOnly
roDeviceLuks=$luksDeviceOpened
fi
if [ ! -z "$rwDeviceLuks" ] && [ ! "$rwDeviceLuks" = "$rwDevice" ];then
rwDevice=$rwDeviceLuks
export haveLuks="yes"
fi
if [ ! -z "$roDeviceLuks" ] && [ ! "$roDeviceLuks" = "$roDevice" ];then
roDevice=$roDeviceLuks
export haveLuks="yes"
fi
if [ ! -z "$rwDevice" ] && [ ! -z "$roDevice" ];then
export UNIONFS_CONFIG="$rwDevice,$roDevice,$unionFST"
fi
}
#======================================
# canWrite
#--------------------------------------
function canWrite {
# /.../
# check if we can write to the given location
# returns zero on success.
# ---
local IFS=$IFS_ORIG
local prefix=$1
if [ -z "$prefix" ];then
prefix=/mnt
fi
if [ ! -d $prefix ];then
return 1
fi
if touch $prefix/can-write &>/dev/null;then
rm $prefix/can-write
return 0
fi
return 1
}
#======================================
# xenServer
#--------------------------------------
function xenServer {
# /.../
# check if the given kernel is a xen kernel and if so
# check if a dom0 or a domU setup was requested
# ----
local IFS=$IFS_ORIG
local kname=$1
local mountPrefix=$2
local sysmap="$mountPrefix/boot/System.map-$kname"
local isxen
if [ ! -e $sysmap ]; then
sysmap="$mountPrefix/boot/System.map"
fi
if [ ! -e $sysmap ]; then
Echo "No system map for kernel $kname found"
return 1
fi
isxen=$(grep -c "xen_base" $sysmap)
if [ $isxen -eq 0 ]; then
# not a xen kernel
return 1
fi
if [ -z "$kiwi_xendomain" ];then
# no xen domain set, assume domU
return 1
fi
if [ $kiwi_xendomain = "dom0" ];then
# xen dom0 requested
return 0
fi
return 1
}
#======================================
# makeLabel
#--------------------------------------
function makeLabel {
# /.../
# create boot label and replace all spaces with
# underscores. current bootloaders show the
# underscore sign as as space in the boot menu
# ---
local IFS=$IFS_ORIG
if [ ! $loader = "grub2" ]; then
echo $1 | tr " " "_"
else
echo $1
fi
}
#======================================
# waitForX
#--------------------------------------
function waitForX {
# /.../
# wait for the X-Server with PID $xserver_pid to
# become read for client calls
# ----
local IFS=$IFS_ORIG
local xserver_pid=$1
local testx=/usr/sbin/testX
local err=1
while kill -0 $xserver_pid 2>/dev/null ; do
sleep 1
if test -e /tmp/.X11-unix/X0 && test -x $testx ; then
$testx 16 2>/dev/null
err=$?
# exit code 1 -> XOpenDisplay failed...
if test $err = 1;then
Echo "TestX: XOpenDisplay failed"
return 1
fi
# exit code 2 -> color or dimensions doesn't fit...
if test $err = 2;then
Echo "TestX: color or dimensions doesn't fit"
kill $xserver_pid
return 1
fi
# server is running, detach oom-killer from it
echo -n '-17' > /proc/$xserver_pid/oom_adj
return 0
fi
done
return 1
}
#======================================
# startX
#--------------------------------------
function startX {
# /.../
# start X-Server and wait for it to become ready
# ----
local IFS=$IFS_ORIG
export DISPLAY=:0
local XServer=/usr/bin/Xorg
if [ -x /usr/X11R6/bin/Xorg ];then
XServer=/usr/X11R6/bin/Xorg
fi
$XServer -deferglyphs 16 vt07 &
export XServerPID=$!
if ! waitForX $XServerPID;then
Echo "Failed to start X-Server"
return 1
fi
return 0
}
#======================================
# stoppX
#--------------------------------------
function stoppX {
local IFS=$IFS_ORIG
if [ -z "$XServerPID" ];then
return
fi
if kill -0 $XServerPID 2>/dev/null; then
sleep 1 && kill $XServerPID
while kill -0 $XServerPID 2>/dev/null; do
sleep 1
done
fi
}
#======================================
# luksOpen
#--------------------------------------
function luksOpen {
# /.../
# check given device if it uses the LUKS extension
# if yes open the device and return the new
# /dev/mapper/ device name
# ----
local IFS=$IFS_ORIG
local ldev=$1
local name=$2
local retry=1
local info
if [ -z "$ldev" ];then
ldev=$(ddn $imageDiskDevice $kiwi_RootPart)
fi
#======================================
# check device for luks extension
#--------------------------------------
if ! cryptsetup isLuks $ldev &>/dev/null;then
return
fi
#======================================
# no map name set, build it from device
#--------------------------------------
if [ -z "$name" ];then
name=luks
fi
#======================================
# luks map already exists, return
#--------------------------------------
if [ -e /dev/mapper/$name ];then
export luksDeviceOpened=/dev/mapper/$name
return
fi
#======================================
# ask for passphrase if not cached
#--------------------------------------
while true;do
if [ -z "$luks_pass" ];then
Echo "Try: $retry"
errorLogStop
Dialog \
--insecure --passwordbox "\"$TEXT_LUKS\"" 10 60
luks_pass=$(DialogResult)
errorLogContinue
fi
if echo "$luks_pass" | cryptsetup luksOpen $ldev $name;then
break
fi
unset luks_pass
if [ -n "$luks_open_can_fail" ]; then
unset luksDeviceOpened
return 1
fi
if [ $retry -eq 3 ];then
systemException \
"Max retries reached... reboot" \
"reboot"
fi
retry=$(($retry + 1))
done
#======================================
# wait for the luks map to appear
#--------------------------------------
if ! waitForStorageDevice /dev/mapper/$name &>/dev/null;then
systemException \
"LUKS map /dev/mapper/$name doesn't appear... fatal !" \
"reboot"
fi
#======================================
# store luks device and return
#--------------------------------------
export luksDeviceOpened=/dev/mapper/$name
return 0
}
#======================================
# luksResize
#--------------------------------------
function luksResize {
# /.../
# check if luksDeviceOpened is defined and
# run cryptsetup resize on the mapper name
# ----
local IFS=$IFS_ORIG
if [ ! -z "$luksDeviceOpened" ] && [ -e $luksDeviceOpened ];then
cryptsetup resize $luksDeviceOpened
udevPending
fi
}
#======================================
# luksClose
#--------------------------------------
function luksClose {
# /.../
# close all open LUKS mappings
# ----
local IFS=$IFS_ORIG
local name=$1
#======================================
# close specified name if set
#--------------------------------------
if [ -n "$1" ]; then
name=$(basename $1)
cryptsetup luksClose $name
return
fi
#======================================
# close all luks* map names
#--------------------------------------
for i in /dev/mapper/luks*;do
name=$(basename "$i")
cryptsetup luksClose $name
done
}
#======================================
# importText
#--------------------------------------
function importText {
# /.../
# read in all texts from the catalog
# ----
local IFS=$IFS_ORIG
export TEXT_TIMEOUT=$(
getText "Boot continues in 10 sec...")
export TEXT_OK=$(
getText "OK")
export TEXT_CANCEL=$(
getText "Cancel")
export TEXT_YES=$(
getText "Yes")
export TEXT_NO=$(
getText "No")
export TEXT_EXIT=$(
getText "Exit")
export TEXT_LUKS=$(
getText "Enter LUKS passphrase")
export TEXT_LICENSE=$(
getText "Do you accept the license agreement ?")
export TEXT_RESTORE=$(
getText "Do you want to start the System-Restore ?")
export TEXT_REPAIR=$(
getText "Do you want to start the System-Recovery ?")
export TEXT_RECOVERYTITLE=$(
getText "Restoring base operating system...")
export TEXT_INSTALLTITLE=$(
getText "Installation...")
export TEXT_CDPULL=$(
getText "Please remove the CD/DVD before reboot")
export TEXT_USBPULL=$(
getText "Please unplug the USB stick before reboot")
export TEXT_CDPULL_SDOWN=$(
getText "Please remove the CD/DVD before shutdown")
export TEXT_USBPULL_SDOWN=$(
getText "System will be shutdown. Remove USB stick before power on")
export TEXT_SELECT=$(
getText "Select disk for installation:")
export TEXT_BOOT_SETUP_FAILED=$(
getText "Bootloader installation has failed")
export TEXT_BOOT_SETUP_FAILED_INFO=$(
getText "The system will not be able to reboot. Please make sure to fixup and install the bootloader before next reboot. Check $ELOG_FILE for details")
}
#======================================
# selectLanguage
#--------------------------------------
function selectLanguage {
# /.../
# select language if not yet done. The value is
# used for all dialog windows with i18n support
# ----
local IFS=$IFS_ORIG
local title="\"Select Language\""
local list="en_US \"[ English ]\" on"
local list_orig=$list
local zh_CN=Chinese
local zh_TW=Taiwanese
local ru_RU=Russian
local de_DE=German
local ar_AR=Arabic
local cs_CZ=Czech
local el_GR=Greek
local es_ES=Spanish
local fi_FI=Finnish
local fr_FR=French
local hu_HU=Hungarian
local it_IT=Italian
local ja_JP=Japanese
local ko_KR=Korean
local nl_NL=Dutch
local pl_PL=Polish
local pt_BR=Portuguese
local sv_SE=Swedish
local tr_TR=Turkish
local nb_NO=Norwegian
local da_DK=Danish
local pt_PT=Portuguese
local en_GB=English
local code
local lang
#======================================
# Exports (Texts), default language
#--------------------------------------
importText
#======================================
# Check language environment
#--------------------------------------
if [ ! -z "$kiwi_oemunattended" ] && [ "$DIALOG_LANG" = "ask" ];then
# answer the language question in unatteneded mode
DIALOG_LANG=en_US
fi
if [ "$DIALOG_LANG" = "ask" ];then
for code in $(echo $kiwi_language | tr "," " ");do
if [ $code = "en_US" ];then
continue
fi
eval lang=\$$code
list="$list $code \"[ $lang ]\" off"
done
if [ "$list" = "$list_orig" ];then
DIALOG_LANG=en_US
else
Dialog \
--timeout 10 --no-cancel \
--backtitle \"$TEXT_TIMEOUT\" \
--radiolist \"$title\" 20 40 10 $list
DIALOG_LANG=$(DialogResult)
fi
fi
export LANG=$DIALOG_LANG.utf8
#======================================
# Exports (Texts), selected language
#--------------------------------------
importText
}
#======================================
# getText
#--------------------------------------
function getText {
# /.../
# return translated text
# ----
local IFS=$IFS_ORIG
local text=$(gettext kiwi "$1")
if [ ! -z "$2" ];then
text=$(echo $text | sed -e s"@%1@$2@")
fi
if [ ! -z "$3" ];then
text=$(echo $text | sed -e s"@%2@$3@")
fi
echo "$text"
}
#======================================
# displayEULA
#--------------------------------------
function displayEULA {
# /.../
# display in a dialog window the text part of the
# selected language file(s). The files are searched
# by the names in kiwi_showlicense
# ----
local IFS=$IFS_ORIG
local code=$(echo $DIALOG_LANG | cut -f1 -d_)
if [ -z "$kiwi_showlicense" ];then
Echo "No license name(s) configured"
return
fi
for name in $kiwi_showlicense;do
#======================================
# select license file by name
#--------------------------------------
code=/$name.$code.txt
if [ ! -f $code ];then
code=/$name.txt
fi
if [ ! -f $code ];then
code=/etc/YaST2/licenses/base/$name.$code.txt
fi
if [ ! -f $code ];then
code=/etc/YaST2/licenses/base/$name.txt
fi
if [ ! -f $code ];then
code=/etc/YaST2/licenses/base/$name
fi
if [ ! -f $code ];then
Echo "License with basename $name not found... skipped"
continue
fi
#======================================
# show license until accepted
#--------------------------------------
while true;do
Dialog --textbox $code 20 70 \
--and-widget --extra-button \
--extra-label "$TEXT_NO" \
--ok-label "$TEXT_YES" \
--cancel-label "$TEXT_CANCEL" \
--yesno "\"$TEXT_LICENSE\"" \
5 45
case $? in
0 ) break
;;
1 ) continue
;;
* ) systemException \
"License not accepted... reboot" \
"reboot"
;;
esac
done
done
}
#======================================
# ddn
#--------------------------------------
function ddn {
# /.../
# print disk device name (node name) according to the
# linux device node specs: If the last character of the
# device is a letter, attach the partition number. If the
# last character is a number, attach a 'p' and then the
# partition number. Exceptions:
# a) If the device name starts with /dev/disk
# the /dev/disk/<name>[-_]partN schema is used exclusively
# b) If the device name starts with /dev/ram
# the /dev/mapper/<name>pN schema is used exclusively
# c) If the device name starts with /dev/mapper
# the /dev/mapper/<name>_partN schema is checked optionally
# if it does not exist the default device node specs applies
# ----
local IFS=$IFS_ORIG
if echo $1 | grep -q "^\/dev\/disk\/" ; then
if [ -e $1"_part"$2 ]; then
echo $1"_part"$2
return
fi
echo $1"-part"$2
return
elif echo $1 | grep -q "^\/dev\/mapper\/" ; then
if [ -e $1"_part"$2 ]; then
echo $1"_part"$2
return
fi
elif echo $1 | grep -q "^\/dev\/ram";then
name=$(echo $1 | tr -d /dev)
echo /dev/mapper/${name}p$2
return
fi
local lastc=$(echo $1 | sed -e 's@\(^.*\)\(.$\)@\2@')
if echo $lastc | grep -qP "^\d+$";then
echo $1"p"$2
return
fi
echo $1$2
}
#======================================
# dn
#--------------------------------------
function dn {
# /.../
# print disk name (device name) according to the
# linux device node specs: If the device matches "p"
# followed by a number remove pX else remove
# the last number. Exceptions:
# loop devices
# ----
local IFS=$IFS_ORIG
local part=$(getDiskDevice $1)
if [[ $part =~ dev/loop[0-9] ]];then
echo $part
return
fi
if [[ $part =~ mapper/loop ]];then
part=$(echo $part | sed -e s@/mapper@@)
fi
local part_new=$(echo $part | sed -e 's@\(^.*\)\(p[0-9].*$\)@\1@')
if [ $part = $part_new ];then
part_new=$(echo $part | sed -e 's@\(^.*\)\([0-9].*$\)@\1@')
fi
echo $part_new
}
#======================================
# nd
#--------------------------------------
function nd {
# /.../
# print the number of the disk device according to the
# device node name.
# ----
local IFS=$IFS_ORIG
local part=$(getDiskDevice $1)
local part_new=$(echo $part | sed -e 's@\(^.*\)p\([0-9].*$\)@\2@')
if [ $part = $part_new ];then
part_new=$(echo $part | sed -e 's@\(^.*\)\([0-9].*$\)@\2@')
fi
echo $part_new
}
#======================================
# Dialog
#--------------------------------------
function Dialog {
# /.../
# run dialog in a bash inside an fbiterm or directly
# on the running terminal. Make the terminal the controlling
# tty first. The output of the dialog call and its exit code
# is stored in files
# ----
local IFS=$IFS_ORIG
local dialog_call=/tmp/dialog_call
local dialog_result=/tmp/dialog_result
local dialog_code=/tmp/dialog_code
hideSplash
cat > $dialog_call <<- EOF
dialog \
--ok-label "$TEXT_OK" \
--cancel-label "$TEXT_CANCEL" \
--yes-label "$TEXT_YES" \
--no-label "$TEXT_NO" \
--exit-label "$TEXT_EXIT" \
$@ 2>$dialog_result
echo -n \$? >$dialog_code
EOF
if FBOK;then
setsid -c -w fbiterm -m $UFONT -- bash -i $dialog_call
else
setsid -c -w bash -i $dialog_call
fi
local code=$(cat $dialog_code)
return $code
}
#======================================
# DialogResult
#--------------------------------------
function DialogResult {
local dialog_result=/tmp/dialog_result
test -e "$dialog_result" && cat $dialog_result && rm $dialog_result
}
#======================================
# DialogExitCode
#--------------------------------------
function DialogExitCode {
local dialog_code=/tmp/dialog_code
test -e "$dialog_code" && cat $dialog_code
}
#======================================
# createCustomHybridPersistent
#--------------------------------------
function createCustomHybridPersistent {
# /.../
# import the write space for the hybrid according to
# the information given by kiwi_cowdevice and kiwi_cowsystem
# ----
local IFS=$IFS_ORIG
#======================================
# check for custom cow location
#--------------------------------------
if [ -z "$kiwi_cowdevice" ];then
return
fi
if [ -z "$kiwi_cowsystem" ];then
return
fi
Echo "Using custom cow file: $kiwi_cowdevice:$kiwi_cowsystem"
#======================================
# got custom cow location
#--------------------------------------
waitForStorageDevice $kiwi_cowdevice
#======================================
# mount cow device
#--------------------------------------
mkdir /cow
if ! mount $kiwi_cowdevice /cow;then
systemException \
"Failed to mount cow device !" \
"reboot"
fi
#======================================
# does the cow file exist
#--------------------------------------
if [ ! -f /cow/$kiwi_cowsystem ];then
Echo "Can't find cow file on write partition... deactivated"
unset kiwi_hybridpersistent
umount /cow
rmdir /cow
return
fi
#======================================
# loop setup cow space
#--------------------------------------
kiwi_cowdevice=$(loop_setup /cow/$kiwi_cowsystem)
if [ ! -e $kiwi_cowdevice ];then
systemException \
"Failed to loop setup cow file !" \
"reboot"
fi
#======================================
# export read-write device name
#--------------------------------------
export skipSetupBootPartition=1
export HYBRID_RW=$kiwi_cowdevice
}
#======================================
# createHybridPersistent
#--------------------------------------
function createHybridPersistent {
# /.../
# create a new partition to handle the copy-on-write actions
# by the clicfs live mount. A new partition with a filesystem
# inside labeled as 'hybrid' is created for this purpose
# ----
local IFS=$IFS_ORIG
local device=$1
local input=/part.input
local pID
rm -f $input
#======================================
# check for custom cow location
#--------------------------------------
if [ ! -z "$kiwi_cowdevice" ] || [ ! -z "$kiwi_cowsystem" ];then
return
fi
#======================================
# check persistent write partition
#--------------------------------------
local hybrid_fs=$HYBRID_PERSISTENT_FS
if [ ! -z "$kiwi_hybridpersistent_filesystem" ];then
hybrid_fs=$kiwi_hybridpersistent_filesystem
fi
for pID in 4 3 2 1;do
local partd=$(ddn $device $pID)
local label=$(blkid $partd -s LABEL -o value)
if [ "$label" = "hybrid" ];then
Echo "Existing persistent hybrid partition found"
if [ "$hybrid_fs" = "fat" ] || [ "$hybrid_fs" = "exfat" ];then
if ! setupHybridCowDevice;then
Echo "Failed to setup hybrid cow device"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
else
export HYBRID_RW=$partd
fi
export skipSetupBootPartition=1
return
fi
done
#======================================
# create persistent write partition
#--------------------------------------
Echo "Creating hybrid persistent partition for COW data"
export imageDiskDevice=$device
if [ ! -e "$imageDiskDevice" ];then
Echo "Disk device $device does not exist, most likely not a disk"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
# Check if device is writable
# Please note, this checks if the device is a read only device.
# It does not check if the media given to the device is a read
# only media. Example: hybrid live iso on readonly CD booted
# from a CD/DVD RW device. An additional media check might be
# required in the future
local ro_device_class=/sys/class/block/$(basename $device)/ro
if [ -e $ro_device_class ] && [ $(cat $ro_device_class) = 1 ];then
Echo "Device $device is marked readonly"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
# Find partition ID we could use to create a new write partition
for pID in 1 2 3 4;do
local partd=$(ddn $device $pID)
if [ ! -e "$partd" ];then
Echo "Creating write partition at ID: $pID"
break
fi
done
if [ "$kiwi_firmware" = "bios" ];then
# we support creation of partitions which are not in ascending order
# in bios mode. The partition table created via isohybrid starts at
# the second partition to allow the creation of the write partition
# as first partition. Reason for this is to support Windows systems
# with a fat partition as write space which has to be the first
# partition otherwise Windows can't cope with it.
#
# Such a write partition can be created using fdisk, however for
# EFI capable hybrid ISO images the GPT table is used which fdisk
# can't handle.
#
# Therefore we use fdisk for bios firmware images and parted for
# efi|uefi firmware images.
#
# This also means we don't support fat
# based persistent write partitions to be created as first partition
# on efi|uefi ISO hybrid images
echo -e "n\np\n$pID\n\n\nw\nq" | fdisk $imageDiskDevice
partitionerWriteStatus=$?
blockdev --rereadpt $imageDiskDevice
else
createPartitionerInput \
n p:lxrw $pID . . t $pID $HYBRID_PERSISTENT_ID
callPartitioner $input
fi
#======================================
# check partition device node
#--------------------------------------
if [ $partitionerWriteStatus != 0 ];then
Echo "Partition creation failed for device $device"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
if ! waitForStorageDevice $(ddn $device $pID);then
Echo "Partition $pID on $device doesn't appear... fatal !"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
#======================================
# create filesystem on write partition
#--------------------------------------
local hybrid_device=$(ddn $device $pID)
local fs_opts
if [ "$hybrid_fs" = "ext4" ];then
fs_opts="$HYBRID_EXT4_OPTS"
fi
if ! createFilesystem \
$hybrid_device "$hybrid_fs" "" "" "hybrid" "false" "$fs_opts"
then
Echo "Failed to create hybrid persistent filesystem"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
#======================================
# export read-write device name
#--------------------------------------
if [ "$hybrid_fs" = "fat" ] || [ "$hybrid_fs" = "exfat" ];then
# The fat filesystem is not really suitable to be used as rootfs
# for linux. Therefore we create a btrfs based file which we store
# on the fat filesystem and loop setup it. The size of the file
# is set to half the size of the fat device
if ! setupHybridCowDevice $hybrid_device;then
Echo "Failed to setup hybrid cow device"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
else
export HYBRID_RW=$(ddn $device $pID)
fi
#======================================
# skip boot partition setup on overlay
#--------------------------------------
export skipSetupBootPartition=1
}
#======================================
# setupHybridCowDevice
#--------------------------------------
function setupHybridCowDevice {
local IFS=$IFS_ORIG
local hybrid_device=$1
mkdir -p /cow
for i in 1 2 3;do
if [ "$hybrid_fs" = "exfat" ]; then
mount $hybrid_device /cow ||\
mount.exfat $hybrid_device /cow && break || sleep 2
else
mount -L hybrid /cow && break || sleep 2
fi
done
if ! mountpoint -q /cow; then
Echo "Failed to mount hybrid persistent filesystem !"
return 1
fi
local hybrid_cow_filename="/cow/${HYBRID_PERSISTENT_FILENAME}"
if [ ! -z "$kiwi_hybridpersistent_cow_filename" ];then
hybrid_cow_filename="/cow/${kiwi_hybridpersistent_cow_filename}"
fi
if [ ! -e "$hybrid_cow_filename" ];then
# default cow filesize is half of partition's capacity
local cowsize="$(($(blockdev --getsize64 $hybrid_device) / 2))"
# but not for FAT due to the 4G file size limit
if [ "$hybrid_fs" = "fat" ] && [ "$cowsize" -gt 4294967295 ];then
cowsize=4294967295
fi
if [ ! -z "$kiwi_hybridpersistent_filesize" ];then
cowsize=$kiwi_hybridpersistent_filesize
fi
qemu-img create "$hybrid_cow_filename" "$cowsize"
if ! createFilesystem \
"$hybrid_cow_filename" "ext4" "" "" "" "false" "$HYBRID_EXT4_OPTS"
then
Echo "Failed to create hybrid persistent cow filesystem"
return 1
fi
fi
export HYBRID_RW=$(loop_setup "$hybrid_cow_filename")
if [ ! -e "$HYBRID_RW" ];then
Echo "Failed to loop setup hybrid cow file !"
return 1
fi
return 0
}
#======================================
# callPartitioner
#--------------------------------------
function callPartitioner {
local IFS=$IFS_ORIG
local input=$1
if [ $PARTITIONER = "fdasd" ];then
Echo "Partition the disk according to real geometry [ fdasd ]"
echo "w" >> $input
echo "q" >> $input
fdasd $imageDiskDevice < $input 1>&2
export partitionerWriteStatus=$?
if test $partitionerWriteStatus != 0; then
systemException "Failed to create partition table" "reboot"
fi
udevPending
blockdev --rereadpt $imageDiskDevice
else
# /.../
# nothing to do for parted here as we write
# imediately with parted and don't create a
# command input file as for fdasd but we re-read
# the disk so that the new table will be used
# ----
udevPending
blockdev --rereadpt $imageDiskDevice
fi
}
#======================================
# createPartitionerInput
#--------------------------------------
function createPartitionerInput {
local IFS=$IFS_ORIG
if isDASDDevice; then
PARTITIONER=fdasd
fi
if [ $PARTITIONER = "fdasd" ];then
createFDasdInput $@
else
Echo "Partition the disk according to real geometry [ parted ]"
partedInit $imageDiskDevice
partedSectorInit $imageDiskDevice
createPartedInput $imageDiskDevice $@
fi
}
#======================================
# createFDasdInput
#--------------------------------------
function createFDasdInput {
local IFS=$IFS_ORIG
local input=/part.input
local ignore_once=0
local ignore=0
normalizeRepartInput $*
for cmd in ${pcmds[*]};do
if [ $ignore = 1 ] && echo $cmd | grep -qE '[dntwq]';then
ignore=0
elif [ $ignore = 1 ];then
continue
fi
if [ $ignore_once = "1" ];then
ignore_once=0
continue
fi
if [ $cmd = "a" ];then
ignore=1
continue
fi
if [[ $cmd =~ ^p: ]];then
ignore_once=1
continue
fi
if [ $cmd = "83" ] || [ $cmd = "8e" ];then
cmd=1
fi
if [ $cmd = "82" ];then
cmd=2
fi
if [ $cmd = "." ];then
echo >> $input
continue
fi
echo $cmd >> $input
done
}
#======================================
# partedInit
#--------------------------------------
function partedInit {
# /.../
# initialize current partition table output
# as well as the number of cylinders and the
# cyliner size in kB for this disk
# ----
local IFS=$IFS_ORIG
local devname=$1
local device=$(getDiskDevice $devname)
IFS=""
local parted=$(parted -m -s $device unit cyl print | grep -v Warning:)
local header=$(echo $parted | head -n 3 | tail -n 1)
local ccount=$(echo $parted | grep ^$device | cut -f 2 -d: | tr -d cyl)
local cksize=$(echo $header | cut -f4 -d: | cut -f1 -dk)
local diskhd=$(echo $parted | head -n 3 | tail -n 2 | head -n 1)
local plabel=$(echo $diskhd | cut -f6 -d:)
if [[ $plabel =~ gpt ]];then
plabel=gpt
fi
export partedTableType=$plabel
export partedOutput=$parted
export partedCylCount=$ccount
export partedCylKSize=$cksize
}
#======================================
# partedWrite
#--------------------------------------
function partedWrite {
# /.../
# call parted with current command queue.
# This will immediately change the partition table
# ----
local IFS=$IFS_ORIG
local device=$1
local cmds=$2
local opts
if [ $PARTED_HAVE_ALIGN -eq 1 ];then
opts="-a cyl"
fi
parted $opts -m -s $device unit cyl $cmds
export partitionerWriteStatus=$?
if [ $partitionerWriteStatus != 0 ];then
if [ ! -z "$kiwi_hybridpersistent" ];then
# /.../
# in case of a iso hybrid table don't stop with a fatal reboot
# exception on error. In this case we want to proceed with the
# boot process but deactivate the persistent write feature
# ----
return 1
fi
systemException "Failed to create partition table" "reboot"
fi
partedInit $device
}
#======================================
# partedSectorInit
#--------------------------------------
function partedSectorInit {
# /.../
# return aligned start/end sectors of current table.
# ----
local IFS=$IFS_ORIG
local disk=$1
local s_start
local s_stopp
unset startSectors
unset endSectors
local align=$((kiwi_align / kiwi_sectorsize))
for i in $(
parted -m -s $disk unit s print |\
grep -E ^[1-9]+:| cut -f2-3 -d: | tr -d s
);do
s_start=$(echo $i | cut -f1 -d:)
s_stopp=$(echo $i | cut -f2 -d:)
if [ -z "$startSectors" ];then
startSectors=${s_start}s
else
startSectors=${startSectors}:${s_start}s
fi
if [ -z "$endSectors" ];then
endSectors=$((s_stopp/align*align+align))s
else
endSectors=$endSectors:$((s_stopp/align*align+align))s
fi
done
# /.../
# in case of an empty disk we use the default start sector
# ----
if [ -z "$startSectors" ];then
startSectors=${kiwi_startsector}s
fi
}
#======================================
# partedEndCylinder
#--------------------------------------
function partedEndCylinder {
# /.../
# return end cylinder of given partition, next
# partition must start at return value plus 1
# ----
local IFS=$IFS_ORIG
local part=$(($1 + 3))
IFS=""
local header=$(echo $partedOutput | head -n $part | tail -n 1)
local ccount=$(echo $header | cut -f3 -d: | tr -d cyl)
echo $ccount
}
#======================================
# partedMBToCylinder
#--------------------------------------
function partedMBToCylinder {
# /.../
# convert size given in MB to cylinder count
# ----
local IFS=$IFS_ORIG
local sizeBytes=$(($1 * 1048576))
# bc truncates to zero decimal places, which results in a partition that
# is slightly smaller than the requested size. Add one cylinder to compensate.
local cylreq=$(echo "scale=0; $sizeBytes / ($partedCylKSize * 1000) + 1" | bc)
echo $cylreq
}
#======================================
# createPartedInput
#--------------------------------------
function createPartedInput {
# /.../
# evaluate partition instructions and turn them
# into a parted command line queue. As soon as the
# geometry data would be changed according to the
# last partedInit() call the command queue is processed
# and the partedInit() will be called afterwards
# ----
local IFS=$IFS_ORIG
local disk=$1
shift
local index=0
local partid
local partnm
local pstart
local pstopp
local value
local cmdq
#======================================
# normalize commands
#--------------------------------------
normalizeRepartInput $*
for cmd in ${pcmds[*]};do
case $cmd in
#======================================
# delete partition
#--------------------------------------
"d")
partid=${pcmds[$index + 1]}
partid=$(($partid / 1))
cmdq="$cmdq rm $partid"
partedWrite "$disk" "$cmdq"
cmdq=""
;;
#======================================
# create new partition
#--------------------------------------
"n")
partnm=${pcmds[$index + 1]}
partid=${pcmds[$index + 2]}
partid=$(($partid / 1))
pstart=${pcmds[$index + 3]}
if [ ! "$partedTableType" = "gpt" ];then
partnm=primary
else
partnm=$(echo $partnm | cut -f2 -d:)
fi
if [ "$pstart" = "1" ];then
pstart=$(echo $startSectors | cut -f $partid -d:)
fi
if [ $pstart = "." ];then
# start is next sector according to previous partition
pstart=$(($partid - 1))
if [ $pstart -gt 0 ];then
pstart=$(echo $endSectors | cut -f $pstart -d:)
else
pstart=$(echo $startSectors | cut -f $partid -d:)
fi
fi
pstopp=${pcmds[$index + 4]}
if [ $pstopp = "." ];then
# use rest of the disk for partition end
pstopp=$partedCylCount
elif echo $pstopp | grep -qi M;then
# calculate stopp cylinder from size
pstopp=$(($partid - 1))
if [ $pstopp -gt 0 ];then
pstopp=$(partedEndCylinder $pstopp)
fi
value=$(echo ${pcmds[$index + 4]} | cut -f1 -dM | tr -d +)
value=$(partedMBToCylinder $value)
pstopp=$((1 + $pstopp + $value))
if [ $pstopp -gt $partedCylCount ];then
# given size is out of bounds, reduce to end of disk
pstopp=$partedCylCount
fi
fi
cmdq="$cmdq mkpart $partnm $pstart $pstopp"
partedWrite "$disk" "$cmdq"
partedSectorInit $imageDiskDevice
cmdq=""
;;
#======================================
# change partition ID
#--------------------------------------
"t")
ptypex=${pcmds[$index + 2]}
partid=${pcmds[$index + 1]}
flagok=1
if [ "$ptypex" = "82" ];then
if [[ $kiwi_initrdname =~ boot-suse ]];then
# /.../
# suse parted is not able to set swap flag. I consider
# this as a bug in the suse parted tool. In order to
# proceed here kiwi uses suse parted 'type' command
# extension.
#
cmdq="$cmdq set $partid type 0x$ptypex"
elif [[ $kiwi_initrdname =~ boot-rhel ]];then
# /.../
# parted on RHEL is not able to set swap flag. I don't
# have a good solution for this thus we skip the flag
# setup in this case
#
flagok=0
else
cmdq="$cmdq set $partid swap on"
fi
elif [ "$ptypex" = "fd" ];then
cmdq="$cmdq set $partid raid on"
elif [ "$ptypex" = "8e" ];then
cmdq="$cmdq set $partid lvm on"
elif [ "$ptypex" = "83" ];then
# default partition type set by parted is linux(83)
flagok=0
else
# be careful, this is a suse parted extension
cmdq="$cmdq set $partid type 0x$ptypex"
fi
if [ ! "$partedTableType" = "gpt" ] && [ $flagok = 1 ];then
partedWrite "$disk" "$cmdq"
fi
cmdq=""
;;
esac
index=$(($index + 1))
done
}
#======================================
# normalizeRepartInput
#--------------------------------------
function normalizeRepartInput {
local IFS=$IFS_ORIG
local pcmds_fix
local index=0
local index_fix=0
local partid
local cmd
#======================================
# create list of commands
#--------------------------------------
unset pcmds
for cmd in $*;do
pcmds[$index]=$cmd
index=$(($index + 1))
done
index=0
#======================================
# fix list of commands
#--------------------------------------
while [ ! -z "${pcmds[$index]}" ];do
cmd=${pcmds[$index]}
pcmds_fix[$index_fix]=$cmd
case $cmd in
"d")
partid=${pcmds[$index + 1]}
if ! echo $partid | grep -q -E "^[0-9]+$";then
# make sure there is a ID set for the deletion
index_fix=$(($index_fix + 1))
pcmds_fix[$index_fix]=1
fi
;;
"n")
partid=${pcmds[$index + 2]}
if [ ! "$PARTITIONER" = "fdasd" ];then
if ! echo $partid | grep -q -E "^[0-9]+$";then
# make sure there is a ID set for the creation
index_fix=$(($index_fix + 1))
pcmds_fix[$index_fix]=${pcmds[$index + 1]}
index_fix=$(($index_fix + 1))
pcmds_fix[$index_fix]=4
index=$(($index + 1))
fi
fi
;;
"t")
partid=${pcmds[$index + 1]}
if ! echo $partid | grep -q -E "^[0-9]+$";then
# make sure there is a ID set for the type
index_fix=$(($index_fix + 1))
pcmds_fix[$index_fix]=1
fi
;;
esac
index=$(($index + 1))
index_fix=$(($index_fix + 1))
done
#======================================
# use fixed list and print log info
#--------------------------------------
unset pcmds
pcmds=(${pcmds_fix[*]})
unset pcmds_fix
echo "Normalized Repartition input: ${pcmds[*]}" 1>&2
}
#======================================
# reloadKernel
#--------------------------------------
function reloadKernel {
# /.../
# reload the given kernel and initrd. This function
# checks USB stick devices for a kernel and initrd
# and shows them in a dialog window. The selected kernel
# and initrd is loaded via kexec.
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
#======================================
# check proc/cmdline
#--------------------------------------
ldconfig
mountSystemFilesystems &>/dev/null
if ! cat /proc/cmdline | grep -qi "hotfix=1";then
umountSystemFilesystems
return
fi
#======================================
# check for kexec
#--------------------------------------
if [ ! -x /sbin/kexec ];then
systemException "Can't find kexec" "reboot"
fi
#======================================
# start udev
#--------------------------------------
touch /etc/modules.conf
touch /lib/modules/*/modules.dep
udevStart
errorLogStart
probeDevices
#======================================
# search hotfix stick
#--------------------------------------
USBStickDevice kexec
if [ $stickFound = 0 ];then
systemException "No hotfix USB stick found" "reboot"
fi
#======================================
# mount stick
#--------------------------------------
if ! mount -o ro $stickDevice $prefix;then
systemException "Failed to mount hotfix stick" "reboot"
fi
#======================================
# load kernel
#--------------------------------------
kexec -l $prefix/linux.kexec --initrd=$prefix/initrd.kexec \
--append="$(cat /proc/cmdline | sed -e s"@hotfix=1@@")"
if [ ! $? = 0 ];then
systemException "Failed to load hotfix kernel" "reboot"
fi
#======================================
# go for gold
#--------------------------------------
exec kexec -e
}
#======================================
# checkFilesystem
#--------------------------------------
function checkFilesystem {
local device=$1
local fstype=$(probeFileSystem $device)
case $fstype in
ext2|ext3|ext4)
e2fsck -p -f $device
;;
btrfs)
btrfsck $device
;;
xfs)
xfs_repair -n $device
;;
*)
# don't know how to check this filesystem
Echo "Don't know how to check ${fstype}... skip it"
;;
esac
}
#======================================
# resizeFilesystem
#--------------------------------------
function resizeFilesystem {
local IFS=$IFS_ORIG
local deviceResize=$1
local callme=$2
local ramdisk=0
local resize_fs
local check
local mpoint=/fs-resize
udevPending
local fstype=$(probeFileSystem $deviceResize)
mkdir -p $mpoint
if echo $deviceResize | grep -qi "/dev/ram";then
ramdisk=1
fi
case $fstype in
ext2|ext3|ext4)
resize_fs="resize2fs -f -p $deviceResize"
if [ $ramdisk -eq 1 ];then
resize_fs="resize2fs -f $deviceResize"
fi
;;
btrfs)
resize_fs="mount $deviceResize $mpoint &&"
if lookup btrfs &>/dev/null;then
resize_fs="$resize_fs btrfs filesystem resize max $mpoint"
resize_fs="$resize_fs;umount $mpoint"
else
resize_fs="$resize_fs btrfsctl -r max $mpoint;umount $mpoint"
fi
;;
xfs)
resize_fs="mount $deviceResize $mpoint &&"
resize_fs="$resize_fs xfs_growfs $mpoint;umount $mpoint"
;;
*)
# don't know how to resize this filesystem
Echo "Don't know how to resize ${fstype}... skip it"
return
;;
esac
if [ -z "$callme" ];then
if [ $ramdisk -eq 0 ]; then
Echo "Checking $fstype filesystem on ${deviceResize}..."
checkFilesystem $deviceResize
fi
Echo "Resizing $fstype filesystem on ${deviceResize}..."
eval $resize_fs
if [ ! $? = 0 ];then
systemException \
"Failed to resize/check filesystem" \
"reboot"
fi
else
echo $resize_fs
fi
}
#======================================
# resetMountCounter
#--------------------------------------
function resetMountCounter {
local IFS=$IFS_ORIG
local fstype
local command
for device in \
$imageRootDevice $imageBootDevice \
$imageRecoveryDevice
do
if [ ! -e $device ];then
continue
fi
fstype=$(probeFileSystem $device)
case $fstype in
ext2|ext3|ext4)
command="tune2fs -c -1 -i 0"
;;
*)
# nothing to do here...
continue
;;
esac
eval $command $device 1>&2
done
}
#======================================
# createFilesystem
#--------------------------------------
function createFilesystem {
local IFS=$IFS_ORIG
local deviceCreate=$1
local filesystem=$2
local blocks=$3
local uuid=$4
local label=$5
local exception_handling=$6
local opts=$7
if [ -z "$exception_handling" ];then
exception_handling="true"
else
exception_handling="false"
fi
if [[ "$filesystem" =~ ext ]];then
opts="$opts -F"
if [ ! -z "$uuid" ];then
opts="$opts -U $uuid"
fi
if [ ! -z "$label" ];then
opts="$opts -L $label"
fi
elif [ "$filesystem" = "btrfs" ];then
opts="$opts -f"
if [ ! -z "$uuid" ];then
opts="$opts -U $uuid"
fi
if [ ! -z "$label" ];then
opts="$opts -L $label"
fi
if [ ! -z "$blocks" ];then
local bytes=$((blocks * 4096))
opts="$opts -b $bytes"
fi
elif [ "$filesystem" = "fat" ];then
if [ ! -z "$label" ];then
opts="$opts -n $label"
fi
elif [ "$filesystem" = "xfs" ];then
if [ ! -z "$label" ];then
opts="$opts -L $label"
fi
elif [ "$filesystem" = "ntfs" ];then
if [ ! -z "$label" ];then
opts="$opts -L $label"
fi
elif [ "$filesystem" = "exfat" ];then
if [ ! -z "$label" ];then
opts="$opts -n $label"
fi
fi
if [ "$filesystem" = "ext2" ];then
mkfs.ext2 $opts "$deviceCreate" $blocks 1>&2
elif [ "$filesystem" = "ext3" ];then
mkfs.ext3 $opts "$deviceCreate" $blocks 1>&2
elif [ "$filesystem" = "ext4" ];then
mkfs.ext4 $opts "$deviceCreate" $blocks 1>&2
elif [ "$filesystem" = "btrfs" ];then
# delete potentially existing btrfs on the device because even
# with the force option enabled mkfs.btrfs refuses to create a
# filesystem if the existing metadata contains the same UUID
dd if=/dev/zero of="$deviceCreate" bs=1M count=1 conv=notrunc
mkfs.btrfs $opts "$deviceCreate"
elif [ "$filesystem" = "xfs" ];then
mkfs.xfs $opts -f "$deviceCreate"
if [ ! -z "$uuid" ];then
xfs_admin -U $uuid "$deviceCreate"
fi
elif [ "$filesystem" = "fat" ];then
mkfs.fat $opts "$deviceCreate" $blocks 1>&2
elif [ "$filesystem" = "ntfs" ];then
mkfs.ntfs $opts "$deviceCreate" $blocks 1>&2
elif [ "$filesystem" = "exfat" ];then
mkfs.exfat $opts "$deviceCreate" 1>&2
else
# use ext3 by default
mkfs.ext3 $opts "$deviceCreate" $blocks 1>&2
fi
if [ $exception_handling = "false" ];then
return $?
fi
if [ ! $? = 0 ];then
systemException \
"Failed to create filesystem" \
"reboot"
fi
}
#======================================
# restoreBtrfsSubVolumes
#--------------------------------------
function restoreBtrfsSubVolumes {
local IFS=$IFS_ORIG
local root=$1
local top=@
btrfs subvolume create $root/@ || return
if [ "$kiwi_btrfs_root_is_snapshot" = "true" ];then
btrfs subvolume create $root/.snapshots
btrfs subvolume create $root/.snapshots/1
btrfs subvolume snapshot $root/@ $root/.snapshots/1/snapshot
top=.snapshots/1/snapshot
fi
local rootid=$(btrfs subvolume list $root | grep $top | cut -f2 -d ' ')
btrfs subvolume set-default $rootid $root || return
local mount_point
local volume_toplevel
for i in $(readVolumeSetup "/.profile");do
mount_point=$(getVolumeMountPoint $i)
volume_toplevel="$root/@/$(dirname $mount_point)"
if [ ! -d $volume_toplevel ];then
mkdir -p $volume_toplevel
fi
btrfs subvolume create $root/@/$mount_point || return
done
umount $root && mount $imageRootDevice $root
if [ "$kiwi_btrfs_root_is_snapshot" = "true" ];then
mountBtrfsSubVolumes $imageRootDevice $root
fi
}
#======================================
# restoreLVMMetadata
#--------------------------------------
function restoreLVMPhysicalVolumes {
# /.../
# restore the pysical volumes by the given restore file
# created from vgcfgbackup. It's important to create them
# with the same uuid's compared to the restore file
# ----
local IFS=$IFS_ORIG
local restorefile=$1
cat $restorefile | grep -A2 -E 'pv[0-9] {' | while read line;do
if [ -z "$uuid" ];then
uuid=$(echo $line | grep 'id =' |\
cut -f2 -d= | tr -d \")
fi
if [ -z "$pdev" ];then
pdev=$(echo $line|grep 'device =' |\
cut -f2 -d\" | cut -f1 -d\")
fi
if [ ! -z "$pdev" ];then
pvcreate -u $uuid $pdev
unset uuid
unset pdev
fi
done
}
#======================================
# pxeCheckServer
#--------------------------------------
function pxeCheckServer {
# /.../
# check the kernel commandline parameter kiwiserver.
# If it exists its contents will be used as
# server address stored in the SERVER variabe
# ----
local IFS=$IFS_ORIG
if [ ! -z $kiwiserver ];then
Echo "Found server in kernel cmdline"
SERVER=$kiwiserver
fi
if [ ! -z $kiwiservertype ]; then
Echo "Found server type in kernel cmdline"
SERVERTYPE=$kiwiservertype
else
SERVERTYPE=tftp
fi
}
#======================================
# pxeSetupDownloadServer
#--------------------------------------
function pxeSetupDownloadServer {
# /.../
# the pxe image system requires a server which stores
# the image files. This function setup the SERVER variable
# pointing to that server using the following heuristic:
# ----
# 1) check for $kiwiserver from cmdline
# 2) try tftp.$DOMAIN whereas $DOMAIN is from dhcpcd-info
# 3) try address of DHCP server if no servertype or tftp is used
# 4) fail if no location was found
# ----
local IFS=$IFS_ORIG
pxeCheckServer
if [ -z "$SERVER" ];then
if [ ! -z "$ip" ];then
Echo "Found PXE download server IP in kernel cmdline"
SERVER=$(echo $ip | awk -F ':' '{ print $2 }')
else
Echo "No PXE download server configured, trying: tftp.$DOMAIN"
SERVER=tftp.$DOMAIN
fi
fi
Echo "Checking connectivity of PXE download server: $SERVER"
if ! ping -c 1 -w 30 $SERVER >/dev/null 2>&1;then
Echo "PXE download server: $SERVER not found"
if [ -z "$SERVERTYPE" ] || [ "$SERVERTYPE" = "tftp" ]; then
if [ ! -z "$DHCPSIADDR" ];then
Echo "Using: $DHCPSIADDR from DHCP info"
SERVER=$DHCPSIADDR
elif [ ! -z "$DHCPSID" ];then
Echo "Using: $DHCPSID from DHCP info"
SERVER=$DHCPSID
elif [ ! -z "$SERVERID" ];then
Echo "Using: $SERVERID from DHCP info"
SERVER=$SERVERID
else
systemException \
"Can't find responding PXE download server... fatal !" \
"reboot"
fi
fi
fi
}
#======================================
# pxeSetupSystemAliasName
#--------------------------------------
function pxeSetupSystemAliasName {
# /.../
# Ask for an alias name if NAME from config.<MAC>
# contains a number. If the number is -1 the system will
# ask for ever for this name otherwhise the number sets
# a timeout how long to wait for input of this data
# ----
local IFS=$IFS_ORIG
if test $NAME -ne 0;then
if test $NAME -eq -1;then
Echo -n "Enter Alias Name for this system: " && \
read SYSALIAS
else
Echo -n "Enter Alias Name [timeout in $NAME sec]: " && \
read -t $NAME SYSALIAS
fi
fi
}
#======================================
# pxeSetupSystemHWInfoFile
#--------------------------------------
function pxeSetupSystemHWInfoFile {
# /.../
# calls hwinfo and stores the information into a file
# suffixed by the hardware address of the network card
# NOTE: it's required to have the dhcp info file sourced
# before this function is called
# ----
local IFS=$IFS_ORIG
hwinfo --all --log=hwinfo.$DHCPCHADDR >/dev/null
}
#======================================
# pxeSetupSystemHWTypeFile
#--------------------------------------
function pxeSetupSystemHWTypeFile {
# /.../
# collects information about the alias name the
# architecture and more and stores that into a
# file suffixed by the hardware address of the
# network card.
# ----
local IFS=$IFS_ORIG
echo "NCNAME=$SYSALIAS" >> hwtype.$DHCPCHADDR
echo "CRNAME=$SYSALIAS" >> hwtype.$DHCPCHADDR
echo "IPADDR=$IPADDR" >> hwtype.$DHCPCHADDR
echo "ARCHITECTURE=$ARCH" >> hwtype.$DHCPCHADDR
}
#======================================
# pxeSizeToMB
#--------------------------------------
function pxeSizeToMB {
local IFS=$IFS_ORIG
local size=$1
if [ "$size" = "x" ];then
echo . ; return
fi
local lastc=$(echo $size | sed -e 's@\(^.*\)\(.$\)@\2@')
local value=$(echo $size | sed -e 's@\(^.*\)\(.$\)@\1@')
if [ "$lastc" = "m" ] || [ "$lastc" = "M" ];then
size=$value
elif [ "$lastc" = "g" ] || [ "$lastc" = "G" ];then
size=$(($value * 1024))
fi
echo +"$size"M
}
#======================================
# pxePartitionInput
#--------------------------------------
function pxePartitionInput {
local IFS=$IFS_ORIG
if [ $PARTITIONER = "fdasd" ];then
pxePartitionInputFDASD
else
pxePartitionInputGeneric
fi
}
#======================================
# pxeRaidPartitionInput
#--------------------------------------
function pxeRaidPartitionInput {
local IFS=$IFS_ORIG
if [ $PARTITIONER = "fdasd" ];then
pxeRaidPartitionInputFDASD
else
pxeRaidPartitionInputGeneric
fi
}
#======================================
# pxePartitionInputFDASD
#--------------------------------------
function pxePartitionInputFDASD {
local IFS=$IFS_ORIG
local field=0
local count=0
local IFS=","
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
partSize=$(pxeSizeToMB $partSize)
if [ "$partID" = '82' ] || [ "$partID" = 'S' ];then
partID=2
elif [ "$partID" = '83' ] || [ "$partID" = 'L' ];then
partID=1
elif [ "$partID" = '8e' ] || [ "$partID" = 'V' ];then
partID=4
else
partID=1
fi
echo -n "n . $partSize "
if [ $partID = "2" ] || [ $partID = "4" ];then
echo -n "t $count $partID "
fi
done
echo "w"
}
#======================================
# pxeRaidPartitionInputFDASD
#--------------------------------------
function pxeRaidPartitionInputFDASD {
pxePartitionInputFDASD
}
#======================================
# pxePartitionInputGeneric
#--------------------------------------
function pxePartitionInputGeneric {
local IFS=","
local field=0
local count=0
local pname
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
partSize=$(pxeSizeToMB $partSize)
pname=lxrw
if [ $partID = "S" ] || [ $partID = "82" ];then
partID=82
pname=lxswap
fi
if [ $partID = "L" ] || [ $partID = "83" ];then
partID=83
if [ "$partMount" = "/boot" ];then
pname=lxboot
else
pname=lxroot
fi
fi
if [ $partID = "V" ] || [ $partID = "8e" ];then
partID=8e
pname=lxlvm
fi
if [ $partID = "fd" ] || [ ! -z "$RAID" ];then
partID=fd
pname=lxroot
fi
if [ $count -eq 1 ];then
echo -n "n p:$pname $count 1 $partSize "
if [ $partID = "82" ] || \
[ $partID = "8e" ] || \
[ $partID = "41" ] || \
[ $partID = "fd" ]
then
echo -n "t $count $partID "
fi
else
echo -n "n p:$pname $count . $partSize "
if [ $partID = "82" ] || \
[ $partID = "8e" ] || \
[ $partID = "41" ] || \
[ $partID = "fd" ]
then
echo -n "t $count $partID "
fi
fi
done
echo "w q"
}
#======================================
# pxeRaidPartitionInputGeneric
#--------------------------------------
function pxeRaidPartitionInputGeneric {
pxePartitionInputGeneric
}
#======================================
# pxeRaidCreate
#--------------------------------------
function pxeRaidCreate {
local IFS=","
local count=0
local mdcount=0
local raidFirst
local raidSecond
local conf=/mdadm.conf
echo -n > $conf
for i in $PART;do
count=$((count + 1))
raidFirst=$(ddn $raidDiskFirst $count)
raidSecond=$(ddn $raidDiskSecond $count)
if ! waitForStorageDevice $raidFirst;then
return
fi
if ! waitForStorageDevice $raidSecond;then
return
fi
mdadm --zero-superblock $raidFirst
mdadm --zero-superblock $raidSecond
mdadm --create --metadata=0.9 --run /dev/md$mdcount \
--level=$raidLevel --raid-disks=2 $raidFirst $raidSecond
if [ ! $? = 0 ];then
systemException \
"Failed to create raid array... fatal !" \
"reboot"
fi
mdadm -Db /dev/md$mdcount >> $conf
mdcount=$((mdcount + 1))
done
}
#======================================
# pxeRaidAssemble
#--------------------------------------
function pxeRaidAssemble {
local IFS=";"
local count=0
local mdcount=0
local field=0
local devices
local raidFirst
local raidSecond
local conf=/mdadm.conf
echo -n > $conf
for n in $RAID;do
case $field in
0) raidLevel=$n ; field=1 ;;
1) raidDiskFirst=$n ; field=2 ;;
2) raidDiskSecond=$n; field=3
esac
done
IFS=","
for i in $PART;do
count=$((count + 1))
raidFirst=$(ddn $raidDiskFirst $count)
raidSecond=$(ddn $raidDiskSecond $count)
if ! waitForStorageDevice $raidFirst;then
echo "Warning: device $raidFirst did not appear"
else
devices=$raidFirst
fi
if ! waitForStorageDevice $raidSecond;then
echo "Warning: device $raidSecond did not appear"
else
devices="$devices $raidSecond"
fi
IFS=$IFS_ORIG
mdadm --assemble --run /dev/md$mdcount $devices
if ! waitForStorageDevice /dev/md$mdcount; then
# start any array that has been partially assembled
mdadm -IRs
if ! waitForStorageDevice /dev/md$mdcount; then
systemException \
"Failed to assemble raid array, too many devices missing" \
"reboot"
fi
fi
mdadm -Db /dev/md$mdcount >> $conf
mdcount=$((mdcount + 1))
done
}
#======================================
# pxeRaidZeroSuperBlock
#--------------------------------------
function pxeRaidZeroSuperBlock {
# /.../
# if we switch from a raid setup back to a non-raid
# setup and use the same partition table setup as before
# it might happen that the raid superblock survives.
# This function removes all raid super blocks from
# all partitions in the PART setup. If the partition
# layout is different compared to the former raid layout
# the superblock is not valid anymore
# ----
local IFS=","
local count=1
local device
for i in $PART;do
device=$(ddn $imageDiskDevice $count)
if ! waitForStorageDevice $device;then
continue
fi
mdadm --zero-superblock $device
count=$((count + 1))
done
}
#======================================
# pxeRaidStop
#--------------------------------------
function pxeRaidStop {
local IFS=","
local count=0
for i in $PART;do
mdadm --stop /dev/md$count
count=$((count + 1))
done
}
#======================================
# pxeSwapDevice
#--------------------------------------
function pxeSwapDevice {
local IFS=","
local field=0
local count=0
local device
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
if test $partID = "82" -o $partID = "S";then
device=$(ddn $DISK $count)
waitForStorageDevice $device
echo $device
return
fi
done
}
#======================================
# pxeRaidSwapDevice
#--------------------------------------
function pxeRaidSwapDevice {
local IFS=","
local field=0
local count=0
local mdcount=0
local device
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
if test $partID = "82" -o $partID = "S";then
device=/dev/md$mdcount
waitForStorageDevice $device
echo $device
return
fi
mdcount=$((mdcount + 1))
done
}
#======================================
# pxeRaidPartCheck
#--------------------------------------
function pxeRaidPartCheck {
local IFS=";"
local count=0
local field=0
local n
local raidLevel
local raidDiskFirst
local raidDiskSecond
local device
local partSize
local partID
local partMount
local IdFirst
local IdSecond
local raidFirst
local raidSecond
local size
local maxDiffPlus=10240 # max 10MB bigger
local maxDiffMinus=10240 # max 10MB smaller
for n in $RAID;do
case $field in
0) raidLevel=$n ; field=1 ;;
1) raidDiskFirst=$n ; field=2 ;;
2) raidDiskSecond=$n; field=3
esac
done
IFS=","
for i in $PART;do
count=$((count + 1))
field=0
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
IdFirst="$(partitionID $raidDiskFirst $count)"
IdSecond="$(partitionID $raidDiskSecond $count)"
raidFirst=$(ddn $raidDiskFirst $count)
raidSecond=$(ddn $raidDiskSecond $count)
if [ "$IdFirst" != "fd" ] || ! waitForStorageDevice $raidFirst;then
raidFirst=
fi
if [ "$IdSecond" != "fd" ] || ! waitForStorageDevice $raidSecond;then
raidSecond=
fi
# /.../
# RAID should be able to work in degraded mode when
# one of the disks is missing
# ----
if [ -z "$raidFirst" -a -z "$raidSecond" ]; then
return 1
fi
if [ "$partSize" == "x" ] ; then
# partition use all available space
continue
fi
for device in $raidFirst $raidSecond ; do
size=$(partitionSize $device)
if [ "$(( partSize * 1024 - size ))" -gt "$maxDiffMinus" -o \
"$(( size - partSize * 1024 ))" -gt "$maxDiffPlus" ]
then
return 1
fi
done
done
return 0
}
#======================================
# pxePartitionSetupCheck
#--------------------------------------
function pxePartitionSetupCheck {
# /.../
# validation check for the PART line. So far this
# function counts the given partition sizes and
# checks if it's possible to setup those partitions
# with respect to the available disk size
# ----
local IFS=","
local field=0
local count=0
local reqsizeMB=0
if [ -z "$DISK" ];then
# no disk device available, might be a ram only
# or diskless client
return
fi
local haveKBytes=$(partitionSize $DISK)
local haveMBytes=$((haveKBytes / 1024))
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n; field=1 ;;
esac
done
if [ "$partSize" == "x" ] ; then
# partition requests all available space
# use a fake value of 10 MB as minimum
reqsizeMB=$((reqsizeMB + 10))
else
# some size was requested, use value as MB size
reqsizeMB=$((reqsizeMB + partSize))
fi
done
if [ $reqsizeMB -gt $haveMBytes ];then
systemException \
"Requested partition sizes exceeds disk size" \
"reboot"
fi
}
#======================================
# pxePartCheck
#--------------------------------------
function pxePartCheck {
# /.../
# check the current partition table according to the
# current setup of the PART line. Thus this function
# checks if a new partition table setup compared to
# the existing one was requested. Additionally the check
# is clever enough to find out if the new partition
# table setup would destroy data on the existing one
# or if it only increases the partitions so that no
# data loss is expected.
# ----
local IFS=$IFS_ORIG
local count=0
local field=0
local n
local partSize
local partID
local partMount
local device
local size
local maxDiffPlus=10240 # max 10MB bigger
local maxDiffMinus=10240 # max 10MB smaller
IFS=","
for i in $PART;do
count=$((count + 1))
field=0
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
device=$(ddn $DISK $count)
if [ "$(partitionID $DISK $count)" != "$partID" ]; then
return 1
fi
if ! waitForStorageDevice $device;then
return 1
fi
if [ "$partSize" == "x" ] ; then
# partition use all available space
continue
fi
size=$(partitionSize $device)
if [ "$(( partSize * 1024 - size ))" -gt "$maxDiffMinus" -o \
"$(( size - partSize * 1024 ))" -gt "$maxDiffPlus" ]
then
return 1
fi
done
return 0
}
#======================================
# pxeBootDevice
#--------------------------------------
function pxeBootDevice {
local IFS=","
local field=0
local count=0
local device
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
if [ $partMount = "/boot" ];then
device=$(ddn $DISK $count)
waitForStorageDevice $device
echo $device
return
fi
done
}
#======================================
# startUtimer
#--------------------------------------
function startUtimer {
local IFS=$IFS_ORIG
local utimer=$(lookup utimer)
if [ -x $utimer ];then
if [ ! -e /tmp/utimer ];then
ln -s $UTIMER_INFO /tmp/utimer
fi
$utimer
export UTIMER=$(cat /var/run/utimer.pid)
if [ -f /iprocs ];then
cat /iprocs | grep -v UTIMER_PID > /iprocs
fi
echo UTIMER_PID=$UTIMER >> /iprocs
fi
}
#======================================
# setupBootPartitionPXE
#--------------------------------------
function setupBootPartitionPXE {
#======================================
# Variable setup
#--------------------------------------
local IFS=$IFS_ORIG
local fstype
local mpoint=boot_bind
unset NETBOOT_ONLY
local prefix=/mnt
#======================================
# Don't operate with unknown root part
#--------------------------------------
if [ -z "$imageRootDevice" ];then
# /.../
# this case should only be reached when the netboot
# code checks if the image needs an update. The update
# check happens as early as possible and at that time
# the root device variable is not set, so we use this
# as the trigger to return
#
return
fi
if [ ! -e "$imageRootDevice" ];then
# /.../
# the device does not exist case happens if NFSROOT is used.
# In this situation the variable holds the nfs root path
# and options and not a local device. For this setup we
# also don't need a boot partition because the client will
# always boot from the network, so we use this as return
# trigger too
# ----
export NETBOOT_ONLY=yes
return
fi
#======================================
# Check for boot partition in PART
#--------------------------------------
local bootdev=$(pxeBootDevice)
if [ -e "$bootdev" ];then
export imageBootDevice=$bootdev
fi
#======================================
# Initial bootid setup
#--------------------------------------
if [ ! -z "$imageBootDevice" ];then
# bootid is boot partition
export bootid=$(nd $imageBootDevice)
else
# bootid is root partition
export bootid=$(nd $imageRootDevice)
export imageBootDevice=$imageRootDevice
fi
if [ ! -z "$RAID" ] && [ ! -z "$bootid" ];then
# raid md devices start with 0 but partition id's start with 1
export bootid=$((bootid + 1))
fi
#======================================
# Probe boot/root filesystem
#--------------------------------------
fstype=$(probeFileSystem $imageRootDevice)
#======================================
# return if no extra boot partition
#--------------------------------------
if [ $imageBootDevice = $imageRootDevice ];then
if [ $fstype = "unknown" ] || [ "$haveLuks" = "yes" ];then
# /.../
# there is no extra boot device and the root device has an
# unsupported boot filesystem or layer, mark as netboot only
# ----
export NETBOOT_ONLY=yes
fi
# no boot partition setup required
return
fi
#======================================
# Check boot partition filesystem
#--------------------------------------
local fstype_boot=$(probeFileSystem $imageBootDevice)
if [ $fstype_boot = "unknown" ];then
# /.../
# there is a boot device with an unknown filesystem
# create boot filesystem
# ----
createFilesystem $imageBootDevice $fstype
fi
#======================================
# export bootpart relevant variables
#--------------------------------------
export bootPartitionFSType=$fstype
export kiwi_BootPart=$bootid
#======================================
# copy boot data from image to bootpart
#--------------------------------------
mkdir -p /$mpoint
mount $imageBootDevice /$mpoint
cp -a $prefix/boot /$mpoint
if [ -e /boot.tgz ];then
tar -xf /boot.tgz -C /$mpoint
fi
umount /$mpoint
rmdir /$mpoint
#======================================
# bind mount boot partition
#--------------------------------------
# the resetBootBind() function will resolve this to a
# standard /boot mount when the bootloader will be
# installed in preinit.
# ---
rm -rf $prefix/boot
mkdir $prefix/boot
mkdir $prefix/$mpoint
mount $imageBootDevice $prefix/$mpoint
mount --bind \
$prefix/$mpoint/boot $prefix/boot
}
#======================================
# setupBootPartition
#--------------------------------------
function setupBootPartition {
#======================================
# Variable setup
#--------------------------------------
local IFS=$IFS_ORIG
local label=undef
local mpoint=boot_bind
local fstype
local BID=1
local prefix=/mnt
#======================================
# Check for partition IDs meta data
#--------------------------------------
if [ ! -z "$kiwi_BootPart" ];then
BID=$kiwi_BootPart
fi
#======================================
# Check for boot partition
#--------------------------------------
if [ -z "$imageDiskDevice" ];then
# no disk device like for live ISO based on clicfs
return
fi
label=$(blkid $(ddn $imageDiskDevice $BID) -s LABEL -o value)
if [ "$label" = "BOOT" ];then
export imageBootDevice=$(ddn $imageDiskDevice $BID)
fi
#======================================
# Probe boot partition filesystem
#--------------------------------------
fstype=$(probeFileSystem $(ddn $imageDiskDevice $BID))
export bootPartitionFSType=$fstype
#======================================
# Export bootid if not yet done
#--------------------------------------
if [ -z "$bootid" ];then
export bootid=$BID
fi
#======================================
# Return if no boot setup required
#--------------------------------------
if [ ! "$label" = "BOOT" ] || [ ! -e "$imageBootDevice" ];then
return
fi
#======================================
# copy boot data from image to bootpart
#--------------------------------------
mkdir -p /$mpoint
mount $imageBootDevice /$mpoint
cp -a $prefix/boot /$mpoint
if [ -e /boot.tgz ];then
tar -xf /boot.tgz -C /$mpoint
fi
umount /$mpoint
rmdir /$mpoint
#======================================
# bind mount boot partition
#--------------------------------------
# the resetBootBind() function will resolve this to a
# standard /boot mount when the bootloader will be
# installed in preinit.
# ---
rm -rf $prefix/boot
mkdir $prefix/boot
mkdir $prefix/$mpoint
mount $imageBootDevice $prefix/$mpoint
mount --bind \
$prefix/$mpoint/boot $prefix/boot
}
#======================================
# isVirtioDevice
#--------------------------------------
function isVirtioDevice {
local IFS=$IFS_ORIG
if [ $haveDASD -eq 0 ] && [ $haveZFCP -eq 0 ];then
return 0
fi
return 1
}
#======================================
# isDASDDevice
#--------------------------------------
function isDASDDevice {
local IFS=$IFS_ORIG
if [ $haveDASD -eq 1 ];then
return 0
fi
return 1
}
#======================================
# isZFCPDevice
#--------------------------------------
function isZFCPDevice {
local IFS=$IFS_ORIG
if [ $haveZFCP -eq 1 ];then
return 0
fi
return 1
}
#======================================
# runPreinitServices
#--------------------------------------
function runPreinitServices {
# /.../
# run the .sh scripts in /etc/init.d/kiwi while
# inside the preinit stage of the kiwi boot process
# ----
local IFS=$IFS_ORIG
local service=/etc/init.d/kiwi/$1
if [ ! -d $service ];then
Echo "kiwi service $service not found... skipped"
return
fi
for script in $service/*.sh;do
test -e $script && bash -x $script
done
}
#======================================
# setupTTY
#--------------------------------------
function setupTTY {
# /.../
# create tty device nodes in case we don't have devtmpfs
# ----
local IFS=$IFS_ORIG
local tty_driver
local major
local minor
local tty
if $have_devtmpfs;then
return
fi
if [ "$console" ]; then
tty_driver="${tty_driver:+$tty_driver }${console%%,*}"
fi
for o in $tty_driver; do
case "$o" in
ttyS*) test -e /dev/$o || mknod -m 0660 /dev/$o c 4 64 ;;
tty*) test -e /dev/$o || mknod -m 0660 /dev/$o c 4 1 ;;
esac
done
tty_driver=$(showconsole -n 2>/dev/null)
if test -n "$tty_driver" ; then
major=${tty_driver%% *}
minor=${tty_driver##* }
if test $major -eq 4 -a $minor -lt 64 ; then
tty=/dev/tty$minor
test -e $tty || mknod -m 0660 $tty c 4 $minor
fi
if test $major -eq 4 -a $minor -ge 64 ; then
tty=/dev/ttyS$((64-$minor))
test -e $tty || mknod -m 0660 $tty c 4 $minor
fi
fi
}
#======================================
# setupConsoleFont
#--------------------------------------
function setupConsoleFont {
setfont $CONSOLE_FONT
}
#======================================
# setupConsole
#--------------------------------------
function setupConsole {
# /.../
# placeholder method for custom console setup
# ----
:
}
#======================================
# cleanPartitionTable
#--------------------------------------
function cleanPartitionTable {
# /.../
# remove partition table and create a new msdos
# table label if parted is in use
# ----
local IFS=$IFS_ORIG
dd if=/dev/zero of=$imageDiskDevice bs=512 count=1 >/dev/null
if [ $PARTITIONER = "parted" ];then
parted -s $imageDiskDevice mklabel msdos
fi
}
#======================================
# partitionTableType
#--------------------------------------
function partitionTableType {
# /.../
# get partition table type
# ----
local device=$(getDiskDevice $imageDiskDevice)
if ! parted -m -s $device unit s print > /tmp/table;then
systemException \
"Failed to retrieve current partition table" \
"reboot"
fi
cat /tmp/table | grep ^$device: | cut -f6 -d:
}
#======================================
# preparePartitionTable
#--------------------------------------
function preparePartitionTable {
# /.../
# update partition table to allow resizing partitions
# for a new disk geometry
# ----
local IFS=$IFS_ORIG
#======================================
# check for hybrid iso
#--------------------------------------
if [ "$kiwi_hybridpersistent" = "true" ];then
# /.../
# The partition table written into an iso doesn't
# like the resync, so we return early here
# ----
return
fi
#======================================
# get table type
#--------------------------------------
local plabel=$(partitionTableType)
#======================================
# prepare table
#--------------------------------------
if [[ "$plabel" =~ gpt ]];then
#======================================
# relocate backup GPT to new disk end
#--------------------------------------
relocateGPTAtEndOfDisk
fi
return 0
}
#======================================
# finalizePartitionTable
#--------------------------------------
function finalizePartitionTable {
# /.../
# finalize partition table with flags which might get
# lost during repartition steps
# ----
local IFS=$IFS_ORIG
#======================================
# get table type
#--------------------------------------
local plabel=$(partitionTableType)
#======================================
# activate boot partition
#--------------------------------------
if [[ $arch =~ i.86|x86_64 ]] && [ $plabel = "msdos" ];then
activateBootPartition
fi
#======================================
# finalize table
#--------------------------------------
if [[ "$plabel" =~ gpt ]];then
#======================================
# check if GPT needs to be hybrid
#--------------------------------------
if [ "$kiwi_gpt_hybrid_mbr" = "true" ];then
createHybridGPT
fi
fi
return 0
}
#======================================
# resetBootBind
#--------------------------------------
function resetBootBind {
# /.../
# remove the bind mount boot setup and replace with a
# symbolic link to make the suse kernel update process
# to work correctly
# ----
local IFS=$IFS_ORIG
local bprefix=$1
local bootdir=$bprefix/boot_bind
if [ ! -e /proc/mounts ];then
mount -t proc proc /proc
fi
#======================================
# find bind boot dir
#--------------------------------------
if [ ! -e "/$bootdir" ];then
return
fi
#======================================
# reset bind mount to standard boot dir
#--------------------------------------
shopt -s dotglob
umount $bprefix/boot
mv /$bootdir/boot /$bootdir/tmp
mv /$bootdir/tmp/* /$bootdir
rm -rf /$bootdir/tmp
umount /$bootdir
rmdir /$bootdir
shopt -u dotglob
#======================================
# update fstab entry
#--------------------------------------
grep -v ^/boot_bind $bprefix/etc/fstab > $bprefix/etc/fstab.new
mv $bprefix/etc/fstab.new $bprefix/etc/fstab
sed -i -e s@/boot_bind@/boot@ $bprefix/etc/fstab
#======================================
# mount boot again
#--------------------------------------
chroot $bprefix mount $imageBootDevice /boot
}
#======================================
# setupKernelLinks
#--------------------------------------
function setupKernelLinks {
# /.../
# check kernel names and links to kernel and initrd
# according to the different boot-up situations
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
#======================================
# mount boot partition if required
#--------------------------------------
local mountCalled=no
if [ -e "$imageBootDevice" ] && blkid $imageBootDevice;then
if kiwiMount $imageBootDevice "$prefix";then
mountCalled=yes
fi
fi
#======================================
# Change to boot directory
#--------------------------------------
pushd $prefix/boot >/dev/null
#======================================
# setup if overlay filesystem is used
#--------------------------------------
if [ "$kiwi_oemkboot" = "true" ] || \
[ "$PXE_KIWI_INITRD" = "yes" ] || \
[ ! -z "$kiwi_ROPart" ]
then
# /.../
# we are using a special root setup based on an overlay
# filesystem. In this case we can't use the SuSE Linux
# initrd but must stick to the kiwi boot system.
# ----
IFS="," ; for i in $KERNEL_LIST;do
if test -z "$i";then
continue
fi
kernel=`echo $i | cut -f1 -d:`
initrd=`echo $i | cut -f2 -d:`
break
done
IFS=$IFS_ORIG
if [ "$PXE_KIWI_INITRD" = "yes" ];then
if [ ! -f initrd.kiwi ] && [ ! -f linux.kiwi ];then
Echo "WARNING: can't find kiwi initrd/linux !"
Echo -b "local boot will not work, maybe you forgot"
Echo -b "to add KIWI_INITRD and KIWI_KERNEL in config.<MAC> ?"
else
rm -f $initrd && ln -s initrd.kiwi $initrd
rm -f $kernel && ln -s linux.kiwi $kernel
fi
else
rm -f $initrd && ln -s initrd.vmx $initrd
rm -f $kernel && ln -s linux.vmx $kernel
fi
fi
#======================================
# make sure boot => . link exists
#--------------------------------------
if [ ! "$bootPartitionFSType" = "vfat" ] && [ ! -e boot ];then
ln -s . boot
fi
#======================================
# umount boot partition if required
#--------------------------------------
popd >/dev/null
if [ "$mountCalled" = "yes" ];then
umount $prefix
fi
}
#======================================
# activateBootPartition
#--------------------------------------
function activateBootPartition {
local IFS=$IFS_ORIG
local device=$imageBootDevice
if [ ! -e $device ];then
device=$imageRootDevice
fi
if [ ! -e $device ];then
echo "Can't find boot partition, activation skipped"
return
fi
local bootID=$(nd $device)
local diskID=$(dn $device)
parted $diskID set $bootID boot on
}
#======================================
# relocateGPTAtEndOfDisk
#--------------------------------------
function relocateGPTAtEndOfDisk {
local IFS=$IFS_ORIG
local input=/part.input
if ! lookup gdisk &>/dev/null;then
Echo "Warning, gdisk tool not found"
Echo "This could break the resize of the image"
fi
rm -f $input
for cmd in x e w y; do
echo $cmd >> $input
done
gdisk $imageDiskDevice < $input 1>&2
if [ ! $? = 0 ]; then
Echo "Failed to write backup GPT at end of disk !"
Echo "This could break the resize of the image"
fi
}
#======================================
# createHybridGPT
#--------------------------------------
function createHybridGPT {
local IFS=$IFS_ORIG
local partition_count=$(
sgdisk -p $imageDiskDevice | grep -E '^\s+[0-9]+' | wc -l
)
if [ $partition_count -gt 3 ]; then
# The max number of partitions to embed is 3
# see man sgdisk for details
partition_count=3
fi
if ! sgdisk -h $(seq -s : 1 $partition_count) $imageDiskDevice; then
Echo "Failed to create hybrid GPT/MBR !"
fi
}
#======================================
# FBOK
#--------------------------------------
function FBOK {
local IFS=$IFS_ORIG
if [ ! -e /dev/fb0 ];then
# no framebuffer device found
return 1
fi
if ! lookup fbiterm &>/dev/null;then
# no framebuffer terminal program found
return 1
fi
if lookup isconsole &>/dev/null;then
if ! isconsole;then
# inappropriate ioctl (not a linux console)
return 1
fi
elif ! fbiterm echo &>/dev/null;then
# fbiterm can't be called with echo test cmd
return 1
fi
return 0
}
#======================================
# backupDiskLayout
#--------------------------------------
function backupDiskLayout {
local IFS=$IFS_ORIG
local devname=$1
local device=$(getDiskDevice $devname)
IFS=""
local parted=$(parted -m -s $device unit cyl print | grep -v Warning:)
local pcount=$(echo $parted | tail -n 1 | cut -f1 -d:)
local diskhd=$(echo $parted | head -n 3 | tail -n 2 | head -n 1)
local plabel=$(echo $diskhd | cut -f6 -d:)
IFS=$IFS_ORIG
if [[ $plabel =~ gpt ]];then
backupGPT $device $pcount
else
backupMBR $device
fi
}
#======================================
# backupMBR
#--------------------------------------
function backupMBR {
local IFS=$IFS_ORIG
local device=$1
dd if=$device bs=1 count=512
}
#======================================
# backupGPT
#--------------------------------------
function backupGPT {
local IFS=$IFS_ORIG
local device=$1
local pcount=$2
dd if=$device bs=1 count=$(((128 * pcount) + 1024))
}
#======================================
# loop_setup
#--------------------------------------
function loop_setup {
local IFS=$IFS_ORIG
local target="$@"
local logical_sector_size
if [ ! -z "$kiwi_target_blocksize" ];then
logical_sector_size="-L $kiwi_target_blocksize"
fi
local loop=$(losetup $logical_sector_size -f --show "$target")
if [ ! -e "$loop" ];then
return 1
fi
echo $loop
}
#======================================
# loop_delete
#--------------------------------------
function loop_delete {
local IFS=$IFS_ORIG
local target="$@"
losetup -d "$target"
}
#======================================
# startMultipathd
#--------------------------------------
function startMultipathd {
local multipath_config=/etc/multipath.conf
local wwid_timeout=3
#======================================
# check already running
#--------------------------------------
if pidof multipathd &>/dev/null; then
Echo "startMultipathd: daemon already running"
return 0
fi
#======================================
# check the tools
#--------------------------------------
for tool in multipathd multipath;do
if ! lookup $tool &>/dev/null;then
Echo "startMultipathd: $tool not found"
return 1
fi
done
#======================================
# lookup multipath configuration
#--------------------------------------
if [ ! -f $multipath_config ];then
Echo "startMultipathd: no multipath configuration found"
return 1
fi
#======================================
# load multipath dm modules
#--------------------------------------
if ! modprobe dm-multipath;then
Echo "startMultipathd: can't load dm-multipath"
return 1
fi
#======================================
# start multipath daemon
#--------------------------------------
mkdir -p /etc/multipath
if ! multipathd;then
Echo "startMultipathd: failed to start multipathd"
return 1
fi
#======================================
# wait for devices to settle
#--------------------------------------
udevPending
#======================================
# sleep for a while
#--------------------------------------
# make sure /etc/multipath/wwids are written
if [ ! -z "$kiwi_wwid_wait_timeout" ];then
wwid_timeout=$kiwi_wwid_wait_timeout
fi
sleep $wwid_timeout
export MULTIPATHD_PID=$(pidof multipathd | tr ' ' ,)
return 0
}
#======================================
# stopMultipathd
#--------------------------------------
function stopMultipathd {
# /.../
# stop multipathd started by us
# ----
local IFS=$IFS_ORIG
if [ -z "$MULTIPATHD_PID" ];then
return
fi
local IFS=,
for p in $MULTIPATHD_PID; do
if kill -0 $p &>/dev/null;then
kill $p
fi
done
}
#======================================
# loadSELinuxPolicy
#--------------------------------------
function loadSELinuxPolicy {
# /.../
# load selinux policy and enforce selinux
# ----
local IFS=$IFS_ORIG
if ! lookup load_policy &>/dev/null;then
Echo "load_policy not found"
fi
if ! lookup restorecon &>/dev/null;then
Echo "restorecon not found"
fi
load_policy -i
echo 0 > /sys/fs/selinux/enforce
restorecon -F -R /dev
}
#======================================
# initialize
#--------------------------------------
function initialize {
local IFS=$IFS_ORIG
#======================================
# Exports boot image .profile
#--------------------------------------
if [ -f /.profile ];then
importFile < /.profile
if [ ! -z "$kiwi_bootloader" ];then
export loader=$kiwi_bootloader
fi
fi
#======================================
# Check partitioner capabilities
#--------------------------------------
if echo $kiwi_initrdname | grep -qE '(oem|net)boot';then
if [ $PARTITIONER = "unsupported" ];then
systemException \
"Installed parted version is too old" \
"reboot"
fi
fi
#======================================
# Check for hotfix kernel
#--------------------------------------
reloadKernel
#======================================
# Prevent blank screen
#--------------------------------------
if [ -x /usr/bin/setterm ];then
setterm -powersave off -blank 0
fi
#======================================
# Start boot timer (first stage)
#--------------------------------------
startUtimer
}
# vim: set noexpandtab: