Alan Pevec
2008-Dec-10 22:40 UTC
[Ovirt-devel] [PATCH node] refactor Node local disk usage
use LVM partitions created by o-c-storage use file bindmounts for persisted configs add BOOTIF=link|eth* support Signed-off-by: Alan Pevec <apevec at redhat.com> --- scripts/ovirt | 22 --- scripts/ovirt-early | 383 ++++++++++++++++------------------------------- scripts/ovirt-functions | 147 ++++++++++++++---- scripts/ovirt-post | 2 +- 4 files changed, 242 insertions(+), 312 deletions(-) mode change 100644 => 100755 scripts/ovirt diff --git a/scripts/ovirt b/scripts/ovirt old mode 100644 new mode 100755 index 81733a5..e2c406b --- a/scripts/ovirt +++ b/scripts/ovirt @@ -11,28 +11,6 @@ . /etc/init.d/ovirt-functions start() { - # retrieve config from local OVIRT partition if available - ovirt=$(mktemp -d) - ovirt_mount $ovirt - # /config on OVIRT partition contains persisted /etc files - cfg=$ovirt/config - if [ -d $cfg/etc ]; then - cp -rv $cfg/etc/* /etc - restorecon -r /etc - fi - # and optional Augeas augtool script - aug=$cfg/config.aug - if [ -f $aug ]; then - tmpaug=$(mktemp) - cp $aug $tmpaug - echo "save" >> $tmpaug - augtool < $tmpaug > /dev/null 2>&1 - if [ $? -eq 0 ]; then - printf "$aug applied." - fi - fi - umount $ovirt && rmdir $ovirt - if is_standalone; then exit 0 fi diff --git a/scripts/ovirt-early b/scripts/ovirt-early index c09a987..bcf55a3 100755 --- a/scripts/ovirt-early +++ b/scripts/ovirt-early @@ -10,8 +10,6 @@ . /etc/init.d/functions . /etc/init.d/ovirt-functions -# size of the oVirt partition in megabytes -OVIRT_SIZE=64 BONDING_MODCONF_FILE=/etc/modprobe.d/bonding AUGTOOL_CONFIG=/var/tmp/augtool-config @@ -80,11 +78,26 @@ configure_from_network() { echo "Default config applied" } -# find_disk $bus $serial $live_disk +# $(get_live_disk) +# livecd boot disk +get_live_disk() { + local live_dev=/dev/live + if [ ! -e $live_dev ]; then + # PXE boot + live_dev=/dev/loop0 + live_disk+ else + live_part=$(readlink -e $live_dev) + live_disk=$(basename $(dirname $(udevinfo --name=$live_part --query=path))) + fi + echo $live_disk +} + +# find_disk $bus $serial find_disk() { local bus=$1 local serial=$2 - local live=$3 + local live=$(get_live_disk) for d in /dev/disk/by-id/{scsi,usb}*; do ID_FS_USAGE eval $(udevinfo --query env --name $d) @@ -104,216 +117,10 @@ find_disk() { return 1 } -# TODO move to ovirt-config-storage -# local_install $local_boot $local_disk $bootparams -# local_boot - 1=install LiveOS and boot loader -# 0=initialize oVirt partition only -# local_disk - local disk to hold the oVirt partition -# =usb|scsi[:serial#] -# bootparams - extra boot parameters like console-# -# oVirt partition is a local primary ext2 partition, labeled OVIRT -# content: -# /config - local oVirt configuration (ktab, local admin password) -# /boot - boot loader, kernel and initramfs -# /LiveOS - oVirt Node compressed livecd image - -local_install() { - local local_boot=$1 - local local_disk=$2 - local bootparams=$3 - local disk - local part - local live_part - local live_disk - local live_dev=/dev/live - if [ ! -e $live_dev ]; then - # PXE boot - live_dev=/dev/loop0 - live_part=$live_dev - live_disk- else - live_part=$(readlink -e $live_dev) - live_disk=${live_disk%[1-9]} - fi - local ovirt_part=$(readlink -e /dev/disk/by-label/$OVIRT_LABEL) - local ovirt_disk=${ovirt_part%[1-9]} - if [ "$ovirt_disk" = "$ovirt_part" ]; then - ovirt_disk- fi - if [ -z "$local_disk" ]; then - if [ -z "$ovirt_disk" ]; then - return 1 - fi - # ovirt_init not specified, use pre-labeled oVirt partition - mode=update - disk=$ovirt_disk - part=$ovirt_part - else - case "$local_disk" in - =) - # empty ovirt_init, use current live image device - mode=update - disk=$live_disk - part=$live_part - ;; - =scsi*) - bus=scsi - serial=${local_disk#=scsi:} - mode=install - ;; - =usb*) - bus=usb - serial=${local_disk#=usb:} - mode=install - ;; - *) - return 1 - ;; - esac - if [ $mode = "install" ]; then - if [ "$serial" = "=$bus" ]; then - serial- fi - disk=$(find_disk $bus $serial $live_disk) - rc=$? - if [ $rc -ne 0 ]; then - echo "local disk '$local_disk' not available" - return 1 - fi - if [ -n "$ovirt_disk" ]; then - if [ "$disk" = "$ovirt_disk" ]; then - # local disk contains oVirt partition, select it for update - # TODO force reinstall option - mode=update - part=$ovirt_part - else - # remove label from oVirt partition, there can be only one - e2label $ovirt_part "" - fi - fi - fi - if [ "$mode" = "install" ]; then - printf "installing $disk..." | tee /dev/console - dd if=/dev/zero bs=4096 count=1 of=$disk \ - && parted -s $disk mklabel msdos \ - && parted -s $disk mkpart primary ext2 0.0 $OVIRT_SIZE \ - && partprobe -s $disk - if [ $? -ne 0 ]; then - echo "$disk partition creation failed"; return 1 - fi - part=${disk}1 - udevsettle - mkfs.ext2 -L $OVIRT_LABEL $part \ - && tune2fs -c0 -i0 $part - if [ $? -ne 0 ]; then - echo "$disk ext2 creation failed"; return 1 - fi - # update by-label link manually, mkfs won't trigger udev - mkdir -p /dev/disk/by-label - ln -sf $part /dev/disk/by-label/$OVIRT_LABEL - fi - fi - - if [ "$mode" = "update" ]; then - printf "updating $disk..." | tee /dev/console - fi - ovirt=$(mktemp -d) - if [ "$part" = "$live_part" ]; then - # ovirt_init w/o local disk specified - # setup /config on live disk, if writeable - # TODO mlabel/e2label (check fs2 type or just blindly try?) - mount -r $part $ovirt && mount -o remount,rw $ovirt \ - && mkdir -p $ovirt/config - umount $ovirt && rmdir $ovirt - return 0 - fi - live=$(mktemp -d) - mount -r $live_dev $live - if [ $? -ne 0 ]; then - echo "source image mount failed" - rmdir $live - return 1 - fi - mount $part $ovirt - if [ $? -ne 0 ]; then - echo "local disk mount failed" - umount $live && rmdir $live - rmdir $ovirt - return 1 - fi - mkdir -p $ovirt/config - # update local config using the one embedded in livecd image - # TODO admin tool for adding /config into livecd image - if [ -d $live/config ]; then - cp -rv $live/config/* $ovirt/config \ - || echo "config copy failed" - fi - - if [ $local_boot = 0 ]; then - # config update only, cleanup and continue booting - umount $ovirt && rmdir $ovirt - umount $live && rmdir $live - else - # install oVirt Node image for local boot - if [ -e "$live/syslinux" ]; then - syslinux=syslinux - elif [ -e "$live/isolinux" ]; then - syslinux=isolinux - else - syslinux- fi - rm -rf $ovirt/boot - rm -rf $ovirt/LiveOS - mkdir -p $ovirt/boot/grub - mkdir -p $ovirt/LiveOS - cp -p $live/LiveOS/squashfs.img $ovirt/LiveOS \ - && cp -p $live/$syslinux/initrd0.img $ovirt/boot \ - && cp -p $live/$syslinux/vmlinuz0 $ovirt/boot - if [ $? -ne 0 ]; then - echo "image copy failed" - umount $ovirt && rmdir $ovirt - umount $live && rmdir $live - return 1 - fi - part_num=$(( ${part#$disk} - 1 )) - cat > $ovirt/boot/grub/grub.conf << EOF -default=0 -timeout=2 -hiddenmenu -title oVirt Node - root (hd0,$part_num) - kernel /boot/vmlinuz0 ro root=LABEL=OVIRT roottypefs=ext2 liveimg $bootparams - initrd /boot/initrd0.img -EOF - grub-install --root-directory=$ovirt $disk >&2 - if [ $? -ne 0 ]; then - echo "boot loader install failed" - umount $ovirt && rmdir $ovirt - umount $live && rmdir $live - return 1 - fi - # remove 1.5 stages we don't need - find $ovirt/boot/grub -name '*_stage1_5' ! -name e2fs_stage1_5 \ - -exec rm {} \; - umount $ovirt && rmdir $ovirt - umount $live && rmdir $live - # FIXME avoid reboot loops - # temp. workaround: sync and wait - sync; sync; sync - printf "oVirt local installation finished, press Enter to reboot." \ - > /dev/console - read key - if [ "$key" = "debug" ]; then - sh > /dev/console 2>&1 - fi - reboot - fi -} start() { # oVirt boot parameters - # BOOTIF=<MAC> (appended by pxelinux) + # BOOTIF=link|eth*|<MAC> (appended by pxelinux) # ovirt_init=usb|scsi[:serial#] # ovirt_vol=BOOT_MB:SWAP_MB:ROOT_MB:CONFIG_MB:LOGGING_MB # ovirt_local_boot @@ -324,11 +131,14 @@ start() { # syslog=server[:port] # TBD logrotate maxsize - # BOOTIF=<MAC> (appended by pxelinux) + # BOOTIF=link|eth*|<MAC> (appended by pxelinux) # network boot interface is assumed to be on management network where # oVirt Server is reachable - # IPAPPEND 2 in pxelinux.cfg appends MAC address of the booting node - # e.g. BOOTIF=01-00-16-3e-12-34-57 + # BOOTIF=<MAC> e.g. BOOTIF=01-00-16-3e-12-34-57 + # PXELINUX option IPAPPEND 2 in pxelinux.cfg appends MAC address + # of the booting node + # BOOTIF=link - take first eth for which ethtool reports link + # BOOTIF=eth* e.g. BOOTIF=eth0 - use given interface bootif # ovirt_init=usb|scsi[:serial#] @@ -337,23 +147,23 @@ start() { # serial# - select exact disk using serial number, as reported by # udev ID_SERIAL # e.g. ovirt_init=usb:Generic_STORAGE_DEVICE_0000145418-0:0 - ovirt_init+ init # ovirt_vol=BOOT_MB:SWAP_MB:ROOT_MB:CONFIG_MB:LOGGING_MB # local partition sizes in GB - ovirt_vol_boot- ovirt_vol_swap- ovirt_vol_root- ovirt_vol_config- ovirt_vol_logging+ vol_boot_size+ vol_swap_size+ vol_root_size+ vol_config_size+ vol_logging_size # ovirt_local_boot # install/update oVirt Node image on the local installation target disk - ovirt_local_boot=0 + local_boot=0 # ovirt_standalone # force oVirt Node standalone mode - ovirt_standalone=0 + standalone=0 # pxelinux format: ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask> # anaconda format: ip=<client-ip> netmask=<netmask> gateway=<gw-ip> @@ -376,25 +186,64 @@ start() { for i in $(cat /proc/cmdline); do case $i in - BOOTIF=??-??-??-??-??-??-??) - i=${i#BOOTIF=??-} - bootif=$(grep -il $(echo $i|sed 's/-/:/g') /sys/class/net/eth*/address|rev|cut -d/ -f2|rev) + BOOTIF=*) + i=${i#BOOTIF=} + case "$i" in + eth*) + bootif=$i + ;; + link) + for eth in $(cd /sys/class/net; echo eth*); do + if ethtool $eth 2>/dev/null|grep -q "Link detected: yes" + then + bootif=$eth + break + fi + done + ;; + ??-??-??-??-??-??-??) + i=${i#??-} + bootif=$(grep -il $(echo $i|sed 's/-/:/g') /sys/class/net/eth*/address|rev|cut -d/ -f2|rev) + ;; + esac ;; ovirt_init*) - ovirt_init=${i#ovirt_init} - if [ -z "$ovirt_init" ]; then - ovirt_init='=' + i=${i#ovirt_init} + if [ -n "$i" ]; then + # resolve to disk device + case "$i" in + =scsi*) + bus=scsi + i=${i#=scsi} + serial=${i#:} + ;; + =usb*) + bus=usb + i=${i#=usb} + serial=${i#:} + ;; + *) + bus+ serial+ ;; + esac + if [ -n "$bus" ]; then + init=$(find_disk $bus $serial) + fi + else + # 'ovirt_init' without value: grab first disk + init=/dev/sda fi ;; ovirt_vol=*) i=${i#ovirt_vol=} - eval $(printf $i|awk -F: '{print "ovirt_vol_boot="$1; ovirt_vol_swap="$2; print "ovirt_vol_root="$3; print "ovirt_vol_config="$4; print "ovirt_vol_logging="$5;}') + eval $(printf $i|awk -F: '{print "vol_boot_size="$1; print "vol_swap_size="$2; print "vol_root_size="$3; print "vol_config_size="$4; print "vol_logging_size="$5;}') ;; ovirt_local_boot*) - ovirt_local_boot=1 + local_boot=1 ;; ovirt_standalone*) - ovirt_standalone=1 + standalone=1 ;; ip=*) i=${i#ip=} @@ -418,41 +267,62 @@ start() { ;; esac done - # save boot parameters as defaults for ovirt-config-* + if [ -z "$ip_netmask" ]; then ip_netmask=$netmask fi if [ -z "$ip_gateway" ]; then ip_gateway=$gateway fi + # save boot parameters as defaults for ovirt-config-* + params="bootif init vol_boot_size vol_swap_size vol_root_size vol_config_size vol_logging_size local_boot standalone ip_address ip_netmask ip_gateway ipv6 syslog_server syslog_port bootparams" + mount_config + if [ -e $OVIRT_DEFAULTS ]; then + # update persisted defaults + tmpaug=$(mktemp) + for p in $params; do + PARAM=$(uc $p) + value=$(ptr $p) + if [ -n "$value" ] ; then + echo "set /files$OVIRT_DEFAULTS/OVIRT_$PARAM '\"$value\"'" \ + >> $tmpaug + fi + done + if [ -s $tmpaug ]; then + echo "save" >> $tmpaug + # augtool on bindmounted files fails, + # so edit file at persistent config root, /config + augtool -r /config < $tmpaug > /dev/null + fi + else + # initial startup, dump all ovirt bootparams + echo > $OVIRT_DEFAULTS + for p in $params; do + PARAM=$(uc $p) + echo "OVIRT_$PARAM='$(ptr $p)'" >> $OVIRT_DEFAULTS + done + ovirt_config_setup $OVIRT_DEFAULTS + fi - cat > $OVIRT_DEFAULTS <<EOF -# configuration defaults from oVirt Node boot parameters -OVIRT_BOOTIF=$bootif -OVIRT_INIT=$ovirt_init -OVIRT_VOL_BOOT_SIZE=$ovirt_vol_boot -OVIRT_VOL_SWAP_SIZE=$ovirt_vol_swap -OVIRT_VOL_ROOT_SIZE=$ovirt_vol_root -OVIRT_VOL_CONFIG_SIZE=$ovirt_vol_config -OVIRT_VOL_LOGGING_SIZE=$ovirt_vol_logging -OVIRT_LOCAL_BOOT=$ovirt_local_boot -OVIRT_STANDALONE=$ovirt_standalone -OVIRT_IP_ADDRESS=$ip_address -OVIRT_IP_NETMASK=$ip_netmask -OVIRT_IP_GATEWAY=$ip_gateway -OVIRT_IPV6=$ipv6 -OVIRT_SYSLOG_SERVER=$syslog_server -OVIRT_SYSLOG_PORT=$syslog_port -EOF - - set -x - local_install "$ovirt_local_boot" "$ovirt_init" "$bootparams" - set +x - if [ $ovirt_standalone = 0 ]; then + if [ $standalone = 0 ]; then configure_from_network $bootif + if [ -n "$init" -a -n "$vol_config_size" ]; then + # local_install for managed mode + ovirt-config-storage AUTO + fi + if [ $local_boot = 1 ]; then + mount_live + ovirt-config-boot "$init" /live "$bootparams" + fi + # persist configuration from network + ovirt_config_setup \ + /etc/sysconfig/network-scripts/ifcfg-* \ + $BONDING_MODCONF_FILE fi +} -# BEGIN - move to ovirt-config-storage +scan_for_swap() { + # swap partition activation # find all of the partitions on the system # get the system pagesize @@ -478,7 +348,6 @@ EOF swapon $device fi done -# END - move to ovirt-config-storage } case "$1" in diff --git a/scripts/ovirt-functions b/scripts/ovirt-functions index c6a8504..c0ebc3a 100644 --- a/scripts/ovirt-functions +++ b/scripts/ovirt-functions @@ -91,43 +91,126 @@ ovirt_setup_libvirtd() { fi } -ovirt_mount() { - if [ -e /dev/disk/by-label/$OVIRT_LABEL ]; then - mount -r /dev/disk/by-label/$OVIRT_LABEL $1 \ - || mount /dev/disk/by-label/$OVIRT_LABEL $1 +md5() { + md5sum $1 2>/dev/null | (read MD5 filename; echo $MD5) +} + +# return uppercase value +uc() { + echo $(echo $1|tr '[[:lower:]]' '[[:upper:]]') +} + +# return indirect value +# non-bashism for ${!var} +ptr() { + local v=$1 + eval "v=\$$v" + echo $v +} + +# mount livecd media +# e.g. CD /dev/sr0, USB /dev/sda1, +# PXE /dev/loop0 (loopback ISO) +mount_live() { + if grep -q " /live " /proc/mounts; then + return 0 + fi + local live_dev=/dev/live + if [ ! -e $live_dev ]; then + # PXE boot + live_dev=/dev/loop0 + fi + mkdir -p /live + mount $live_dev /live +} + +# mount boot partition +# boot loader + kernel + initrd +mount_boot() { + if grep -q " /boot " /proc/mounts; then + return 0 + fi + mkdir -p /boot + mount /dev/disk/by-label/BOOT /boot +} + +# mount liveos partition +# LiveOS/ +mount_liveos() { + if grep -q " /liveos " /proc/mounts; then + return 0 + fi + mkdir -p /liveos + mount /dev/HostVG/Root /liveos +} + +# mount config partition +# /config for persistance +mount_config() { + if grep -q " /config " /proc/mounts; then + return 0 + fi + mkdir -p /config + mount /dev/HostVG/Config /config + if grep -q " /config " /proc/mounts; then + # TODO cp --update /live/config/ /config + # bind mount all persisted configs to rootfs + for f in $(find /config -type f); do + target=${f#/config} + if grep -q " $target " /proc/mounts ; then + # skip if already bind-mounted + true + else + mount -n --bind $f $target + fi + done else - mount -r /dev/live $1 \ - || mount /dev/live $1 + # /config is not available + return 1 fi } -md5() { - md5sum $1 2>/dev/null | (read MD5 filename; echo $MD5) +# unmount config bindmount /etc/config /etc/config2 ... +# +# augeas save fails on bindmounted files: +# https://fedorahosted.org/augeas/ticket/32 +# the same issue with sed -i +# +# After file is replaced, call ovirt_store_config /etc/config /etc/config2 ... +# to bindmount the config file again. +umount_config() { + if grep -q " /config " /proc/mounts; then + for f in "$@"; do + if grep -q " $f " /proc/mounts ; then + umount -n $f + # refresh rootfs copy + cp /config$f $f + fi + done + fi } -# persist configuration to /config on OVIRT partition +# persist configuration to /config # ovirt_store_config /etc/config /etc/config2 ... -ovirt_store_config() { - ovirt=$(mktemp -d) - ovirt_mount $ovirt - cfg=$ovirt/config - rw=0 - printf "store config:" - for f in "$@"; do - # ignore non-/etc paths - if [ $f != ${f#/etc/} ]; then - # check if changed - if [ "$(md5 $f)" != "$(md5 $cfg$f)" ]; then - if [ $rw = 0 ]; then - mount -o remount,rw $ovirt - rw=1 - fi - mkdir -p $cfg$(dirname $f) - cp $f $cfg$f - printf " $f" - fi - fi - done - echo - umount $ovirt && rmdir $ovirt +# copy to /config and bind-mount back +ovirt_config_setup() { + if grep -q " /config " /proc/mounts; then + printf "storing to /config :" + for f in "$@"; do + printf " $f" + # skip if already bind-mounted + if grep -q " $f " /proc/mounts ; then + printf " already persisted\n" + else + mkdir -p /config$(dirname $f) + cp -a $f /config$f \ + && mount -n --bind /config$f $f \ + || printf " failed to persist\n" + fi + done + echo + else + printf "warning: persistent config storage not available\n" + fi } + diff --git a/scripts/ovirt-post b/scripts/ovirt-post index 06506b7..a5bd930 100644 --- a/scripts/ovirt-post +++ b/scripts/ovirt-post @@ -12,7 +12,7 @@ start() { # persist selected configuration files - ovirt_store_config \ + ovirt_config_setup \ /etc/krb5.conf \ /etc/libvirt/krb5.tab \ /etc/ssh/ssh_host*_key* -- 1.6.0.4
Alan Pevec
2008-Dec-11 16:17 UTC
[Ovirt-devel] [PATCH node] refactor Node local disk usage
use LVM partitions created by o-c-storage use file bindmounts for persisted configs use optional /config from livecd image support for old and new udev versions add BOOTIF=link|eth* support Signed-off-by: Alan Pevec <apevec at redhat.com> --- scripts/ovirt | 22 --- scripts/ovirt-early | 388 ++++++++++++++++------------------------------- scripts/ovirt-functions | 171 +++++++++++++++++---- scripts/ovirt-post | 2 +- 4 files changed, 269 insertions(+), 314 deletions(-) mode change 100644 => 100755 scripts/ovirt mode change 100644 => 100755 scripts/ovirt-post diff --git a/scripts/ovirt b/scripts/ovirt old mode 100644 new mode 100755 index 81733a5..e2c406b --- a/scripts/ovirt +++ b/scripts/ovirt @@ -11,28 +11,6 @@ . /etc/init.d/ovirt-functions start() { - # retrieve config from local OVIRT partition if available - ovirt=$(mktemp -d) - ovirt_mount $ovirt - # /config on OVIRT partition contains persisted /etc files - cfg=$ovirt/config - if [ -d $cfg/etc ]; then - cp -rv $cfg/etc/* /etc - restorecon -r /etc - fi - # and optional Augeas augtool script - aug=$cfg/config.aug - if [ -f $aug ]; then - tmpaug=$(mktemp) - cp $aug $tmpaug - echo "save" >> $tmpaug - augtool < $tmpaug > /dev/null 2>&1 - if [ $? -eq 0 ]; then - printf "$aug applied." - fi - fi - umount $ovirt && rmdir $ovirt - if is_standalone; then exit 0 fi diff --git a/scripts/ovirt-early b/scripts/ovirt-early index c09a987..527d806 100755 --- a/scripts/ovirt-early +++ b/scripts/ovirt-early @@ -10,8 +10,6 @@ . /etc/init.d/functions . /etc/init.d/ovirt-functions -# size of the oVirt partition in megabytes -OVIRT_SIZE=64 BONDING_MODCONF_FILE=/etc/modprobe.d/bonding AUGTOOL_CONFIG=/var/tmp/augtool-config @@ -61,6 +59,7 @@ configure_from_network() { else echo "Failed to retrieve configuration bundle" fi + rm $cfgdb fi fi fi @@ -80,14 +79,29 @@ configure_from_network() { echo "Default config applied" } -# find_disk $bus $serial $live_disk +# $(get_live_disk) +# livecd boot disk +get_live_disk() { + local live_dev=/dev/live + if [ ! -e $live_dev ]; then + # PXE boot + live_dev=/dev/loop0 + live_disk+ else + live_part=$(readlink -e $live_dev) + live_disk=$(basename $(dirname $(udev_info $live_part path))) + fi + echo $live_disk +} + +# find_disk $bus $serial find_disk() { local bus=$1 local serial=$2 - local live=$3 + local live=$(get_live_disk) for d in /dev/disk/by-id/{scsi,usb}*; do ID_FS_USAGE- eval $(udevinfo --query env --name $d) + eval $(udev_info $d env) # ID_FS_USAGE is set for partitions if [ -z "$ID_FS_USAGE" -a "$ID_BUS" = "$bus" ]; then if [ -z "$serial" -o "$ID_SERIAL" = "$serial" ]; then @@ -104,216 +118,10 @@ find_disk() { return 1 } -# TODO move to ovirt-config-storage -# local_install $local_boot $local_disk $bootparams -# local_boot - 1=install LiveOS and boot loader -# 0=initialize oVirt partition only -# local_disk - local disk to hold the oVirt partition -# =usb|scsi[:serial#] -# bootparams - extra boot parameters like console-# -# oVirt partition is a local primary ext2 partition, labeled OVIRT -# content: -# /config - local oVirt configuration (ktab, local admin password) -# /boot - boot loader, kernel and initramfs -# /LiveOS - oVirt Node compressed livecd image - -local_install() { - local local_boot=$1 - local local_disk=$2 - local bootparams=$3 - local disk - local part - local live_part - local live_disk - local live_dev=/dev/live - if [ ! -e $live_dev ]; then - # PXE boot - live_dev=/dev/loop0 - live_part=$live_dev - live_disk- else - live_part=$(readlink -e $live_dev) - live_disk=${live_disk%[1-9]} - fi - local ovirt_part=$(readlink -e /dev/disk/by-label/$OVIRT_LABEL) - local ovirt_disk=${ovirt_part%[1-9]} - if [ "$ovirt_disk" = "$ovirt_part" ]; then - ovirt_disk- fi - if [ -z "$local_disk" ]; then - if [ -z "$ovirt_disk" ]; then - return 1 - fi - # ovirt_init not specified, use pre-labeled oVirt partition - mode=update - disk=$ovirt_disk - part=$ovirt_part - else - case "$local_disk" in - =) - # empty ovirt_init, use current live image device - mode=update - disk=$live_disk - part=$live_part - ;; - =scsi*) - bus=scsi - serial=${local_disk#=scsi:} - mode=install - ;; - =usb*) - bus=usb - serial=${local_disk#=usb:} - mode=install - ;; - *) - return 1 - ;; - esac - if [ $mode = "install" ]; then - if [ "$serial" = "=$bus" ]; then - serial- fi - disk=$(find_disk $bus $serial $live_disk) - rc=$? - if [ $rc -ne 0 ]; then - echo "local disk '$local_disk' not available" - return 1 - fi - if [ -n "$ovirt_disk" ]; then - if [ "$disk" = "$ovirt_disk" ]; then - # local disk contains oVirt partition, select it for update - # TODO force reinstall option - mode=update - part=$ovirt_part - else - # remove label from oVirt partition, there can be only one - e2label $ovirt_part "" - fi - fi - fi - if [ "$mode" = "install" ]; then - printf "installing $disk..." | tee /dev/console - dd if=/dev/zero bs=4096 count=1 of=$disk \ - && parted -s $disk mklabel msdos \ - && parted -s $disk mkpart primary ext2 0.0 $OVIRT_SIZE \ - && partprobe -s $disk - if [ $? -ne 0 ]; then - echo "$disk partition creation failed"; return 1 - fi - part=${disk}1 - udevsettle - mkfs.ext2 -L $OVIRT_LABEL $part \ - && tune2fs -c0 -i0 $part - if [ $? -ne 0 ]; then - echo "$disk ext2 creation failed"; return 1 - fi - # update by-label link manually, mkfs won't trigger udev - mkdir -p /dev/disk/by-label - ln -sf $part /dev/disk/by-label/$OVIRT_LABEL - fi - fi - - if [ "$mode" = "update" ]; then - printf "updating $disk..." | tee /dev/console - fi - ovirt=$(mktemp -d) - if [ "$part" = "$live_part" ]; then - # ovirt_init w/o local disk specified - # setup /config on live disk, if writeable - # TODO mlabel/e2label (check fs2 type or just blindly try?) - mount -r $part $ovirt && mount -o remount,rw $ovirt \ - && mkdir -p $ovirt/config - umount $ovirt && rmdir $ovirt - return 0 - fi - live=$(mktemp -d) - mount -r $live_dev $live - if [ $? -ne 0 ]; then - echo "source image mount failed" - rmdir $live - return 1 - fi - mount $part $ovirt - if [ $? -ne 0 ]; then - echo "local disk mount failed" - umount $live && rmdir $live - rmdir $ovirt - return 1 - fi - mkdir -p $ovirt/config - # update local config using the one embedded in livecd image - # TODO admin tool for adding /config into livecd image - if [ -d $live/config ]; then - cp -rv $live/config/* $ovirt/config \ - || echo "config copy failed" - fi - - if [ $local_boot = 0 ]; then - # config update only, cleanup and continue booting - umount $ovirt && rmdir $ovirt - umount $live && rmdir $live - else - # install oVirt Node image for local boot - if [ -e "$live/syslinux" ]; then - syslinux=syslinux - elif [ -e "$live/isolinux" ]; then - syslinux=isolinux - else - syslinux- fi - rm -rf $ovirt/boot - rm -rf $ovirt/LiveOS - mkdir -p $ovirt/boot/grub - mkdir -p $ovirt/LiveOS - cp -p $live/LiveOS/squashfs.img $ovirt/LiveOS \ - && cp -p $live/$syslinux/initrd0.img $ovirt/boot \ - && cp -p $live/$syslinux/vmlinuz0 $ovirt/boot - if [ $? -ne 0 ]; then - echo "image copy failed" - umount $ovirt && rmdir $ovirt - umount $live && rmdir $live - return 1 - fi - part_num=$(( ${part#$disk} - 1 )) - cat > $ovirt/boot/grub/grub.conf << EOF -default=0 -timeout=2 -hiddenmenu -title oVirt Node - root (hd0,$part_num) - kernel /boot/vmlinuz0 ro root=LABEL=OVIRT roottypefs=ext2 liveimg $bootparams - initrd /boot/initrd0.img -EOF - grub-install --root-directory=$ovirt $disk >&2 - if [ $? -ne 0 ]; then - echo "boot loader install failed" - umount $ovirt && rmdir $ovirt - umount $live && rmdir $live - return 1 - fi - # remove 1.5 stages we don't need - find $ovirt/boot/grub -name '*_stage1_5' ! -name e2fs_stage1_5 \ - -exec rm {} \; - umount $ovirt && rmdir $ovirt - umount $live && rmdir $live - # FIXME avoid reboot loops - # temp. workaround: sync and wait - sync; sync; sync - printf "oVirt local installation finished, press Enter to reboot." \ - > /dev/console - read key - if [ "$key" = "debug" ]; then - sh > /dev/console 2>&1 - fi - reboot - fi -} start() { # oVirt boot parameters - # BOOTIF=<MAC> (appended by pxelinux) + # BOOTIF=link|eth*|<MAC> (appended by pxelinux) # ovirt_init=usb|scsi[:serial#] # ovirt_vol=BOOT_MB:SWAP_MB:ROOT_MB:CONFIG_MB:LOGGING_MB # ovirt_local_boot @@ -324,11 +132,14 @@ start() { # syslog=server[:port] # TBD logrotate maxsize - # BOOTIF=<MAC> (appended by pxelinux) + # BOOTIF=link|eth*|<MAC> (appended by pxelinux) # network boot interface is assumed to be on management network where # oVirt Server is reachable - # IPAPPEND 2 in pxelinux.cfg appends MAC address of the booting node - # e.g. BOOTIF=01-00-16-3e-12-34-57 + # BOOTIF=<MAC> e.g. BOOTIF=01-00-16-3e-12-34-57 + # PXELINUX option IPAPPEND 2 in pxelinux.cfg appends MAC address + # of the booting node + # BOOTIF=link - take first eth for which ethtool reports link + # BOOTIF=eth* e.g. BOOTIF=eth0 - use given interface bootif # ovirt_init=usb|scsi[:serial#] @@ -337,23 +148,23 @@ start() { # serial# - select exact disk using serial number, as reported by # udev ID_SERIAL # e.g. ovirt_init=usb:Generic_STORAGE_DEVICE_0000145418-0:0 - ovirt_init+ init # ovirt_vol=BOOT_MB:SWAP_MB:ROOT_MB:CONFIG_MB:LOGGING_MB # local partition sizes in GB - ovirt_vol_boot- ovirt_vol_swap- ovirt_vol_root- ovirt_vol_config- ovirt_vol_logging+ vol_boot_size+ vol_swap_size+ vol_root_size+ vol_config_size+ vol_logging_size # ovirt_local_boot # install/update oVirt Node image on the local installation target disk - ovirt_local_boot=0 + local_boot=0 # ovirt_standalone # force oVirt Node standalone mode - ovirt_standalone=0 + standalone=0 # pxelinux format: ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask> # anaconda format: ip=<client-ip> netmask=<netmask> gateway=<gw-ip> @@ -376,25 +187,65 @@ start() { for i in $(cat /proc/cmdline); do case $i in - BOOTIF=??-??-??-??-??-??-??) - i=${i#BOOTIF=??-} - bootif=$(grep -il $(echo $i|sed 's/-/:/g') /sys/class/net/eth*/address|rev|cut -d/ -f2|rev) + BOOTIF=*) + i=${i#BOOTIF=} + case "$i" in + eth*) + bootif=$i + ;; + link) + for eth in $(cd /sys/class/net; echo eth*); do + if ethtool $eth 2>/dev/null|grep -q "Link detected: yes" + then + bootif=$eth + break + fi + done + ;; + ??-??-??-??-??-??-??) + i=${i#??-} + bootif=$(grep -il $(echo $i|sed 's/-/:/g') /sys/class/net/eth*/address|rev|cut -d/ -f2|rev) + ;; + esac ;; ovirt_init*) - ovirt_init=${i#ovirt_init} - if [ -z "$ovirt_init" ]; then - ovirt_init='=' + i=${i#ovirt_init} + if [ -n "$i" ]; then + # resolve to disk device + case "$i" in + =scsi*) + bus=scsi + i=${i#=scsi} + serial=${i#:} + ;; + =usb*) + bus=usb + i=${i#=usb} + serial=${i#:} + ;; + *) + bus+ serial+ ;; + esac + if [ -n "$bus" ]; then + init=$(find_disk $bus $serial) + fi + else + # 'ovirt_init' without value: grab first disk + init=/dev/sda fi ;; ovirt_vol=*) i=${i#ovirt_vol=} - eval $(printf $i|awk -F: '{print "ovirt_vol_boot="$1; ovirt_vol_swap="$2; print "ovirt_vol_root="$3; print "ovirt_vol_config="$4; print "ovirt_vol_logging="$5;}') + eval $(printf $i|awk -F: '{print "vol_boot_size="$1; print "vol_swap_size="$2; print "vol_root_size="$3; print "vol_config_size="$4; print "vol_logging_size="$5;}') ;; ovirt_local_boot*) - ovirt_local_boot=1 + local_boot=1 ;; ovirt_standalone*) - ovirt_standalone=1 + standalone=1 + bootparams="$bootparams $i" ;; ip=*) i=${i#ip=} @@ -418,41 +269,63 @@ start() { ;; esac done - # save boot parameters as defaults for ovirt-config-* + if [ -z "$ip_netmask" ]; then ip_netmask=$netmask fi if [ -z "$ip_gateway" ]; then ip_gateway=$gateway fi + # save boot parameters as defaults for ovirt-config-* + params="bootif init vol_boot_size vol_swap_size vol_root_size vol_config_size vol_logging_size local_boot standalone ip_address ip_netmask ip_gateway ipv6 syslog_server syslog_port bootparams" + mount_config + if [ -e $OVIRT_DEFAULTS ]; then + # update persisted defaults + tmpaug=$(mktemp) + for p in $params; do + PARAM=$(uc $p) + value=$(ptr $p) + if [ -n "$value" ] ; then + echo "set /files$OVIRT_DEFAULTS/OVIRT_$PARAM '\"$value\"'" \ + >> $tmpaug + fi + done + if [ -s $tmpaug ]; then + echo "save" >> $tmpaug + # augtool on bindmounted files fails, + # so edit file at persistent config root, /config + augtool -r /config < $tmpaug > /dev/null + rm $tmpaug + fi + else + # initial startup, dump all ovirt bootparams + echo > $OVIRT_DEFAULTS + for p in $params; do + PARAM=$(uc $p) + echo "OVIRT_$PARAM='$(ptr $p)'" >> $OVIRT_DEFAULTS + done + ovirt_config_setup $OVIRT_DEFAULTS + fi - cat > $OVIRT_DEFAULTS <<EOF -# configuration defaults from oVirt Node boot parameters -OVIRT_BOOTIF=$bootif -OVIRT_INIT=$ovirt_init -OVIRT_VOL_BOOT_SIZE=$ovirt_vol_boot -OVIRT_VOL_SWAP_SIZE=$ovirt_vol_swap -OVIRT_VOL_ROOT_SIZE=$ovirt_vol_root -OVIRT_VOL_CONFIG_SIZE=$ovirt_vol_config -OVIRT_VOL_LOGGING_SIZE=$ovirt_vol_logging -OVIRT_LOCAL_BOOT=$ovirt_local_boot -OVIRT_STANDALONE=$ovirt_standalone -OVIRT_IP_ADDRESS=$ip_address -OVIRT_IP_NETMASK=$ip_netmask -OVIRT_IP_GATEWAY=$ip_gateway -OVIRT_IPV6=$ipv6 -OVIRT_SYSLOG_SERVER=$syslog_server -OVIRT_SYSLOG_PORT=$syslog_port -EOF - - set -x - local_install "$ovirt_local_boot" "$ovirt_init" "$bootparams" - set +x - if [ $ovirt_standalone = 0 ]; then + if [ $standalone = 0 ]; then configure_from_network $bootif + if [ -n "$init" -a -n "$vol_config_size" ]; then + # local_install for managed mode + ovirt-config-storage AUTO + fi + if [ $local_boot = 1 ]; then + mount_live + ovirt-config-boot "$init" /live "$bootparams" + fi + # persist configuration from network + ovirt_config_setup \ + /etc/sysconfig/network-scripts/ifcfg-* \ + $BONDING_MODCONF_FILE fi +} -# BEGIN - move to ovirt-config-storage +scan_for_swap() { + # swap partition activation # find all of the partitions on the system # get the system pagesize @@ -478,7 +351,6 @@ EOF swapon $device fi done -# END - move to ovirt-config-storage } case "$1" in diff --git a/scripts/ovirt-functions b/scripts/ovirt-functions index c6a8504..79081b5 100644 --- a/scripts/ovirt-functions +++ b/scripts/ovirt-functions @@ -91,43 +91,148 @@ ovirt_setup_libvirtd() { fi } -ovirt_mount() { - if [ -e /dev/disk/by-label/$OVIRT_LABEL ]; then - mount -r /dev/disk/by-label/$OVIRT_LABEL $1 \ - || mount /dev/disk/by-label/$OVIRT_LABEL $1 +md5() { + md5sum $1 2>/dev/null | (read MD5 filename; echo $MD5) +} + +# return uppercase value +uc() { + echo $(echo $1|tr '[[:lower:]]' '[[:upper:]]') +} + +# return indirect value +# non-bashism for ${!var} +ptr() { + local v=$1 + eval "v=\$$v" + echo $v +} + +# mount livecd media +# e.g. CD /dev/sr0, USB /dev/sda1, +# PXE /dev/loop0 (loopback ISO) +mount_live() { + if grep -q " /live " /proc/mounts; then + return 0 + fi + local live_dev=/dev/live + if [ ! -e $live_dev ]; then + # PXE boot + live_dev=/dev/loop0 + fi + mkdir -p /live + mount $live_dev /live +} + +# mount boot partition +# boot loader + kernel + initrd +mount_boot() { + if grep -q " /boot " /proc/mounts; then + return 0 + fi + mkdir -p /boot + mount /dev/disk/by-label/BOOT /boot +} + +# mount liveos partition +# LiveOS/ +mount_liveos() { + if grep -q " /liveos " /proc/mounts; then + return 0 + fi + mkdir -p /liveos + mount /dev/HostVG/Root /liveos +} + +# mount config partition +# /config for persistance +mount_config() { + if grep -q " /config " /proc/mounts; then + return 0 + fi + mkdir -p /config + mount /dev/HostVG/Config /config + if grep -q " /config " /proc/mounts; then + # optional config embedded in the livecd image + if [ -e /live/config ]; then + cp -rv --update /live/config/* /config + fi + # bind mount all persisted configs to rootfs + for f in $(find /config -type f); do + target=${f#/config} + if grep -q " $target " /proc/mounts ; then + # skip if already bind-mounted + true + else + mount -n --bind $f $target + fi + done else - mount -r /dev/live $1 \ - || mount /dev/live $1 + # /config is not available + return 1 fi } -md5() { - md5sum $1 2>/dev/null | (read MD5 filename; echo $MD5) +# unmount config bindmount /etc/config /etc/config2 ... +# +# augeas save fails on bindmounted files: +# https://fedorahosted.org/augeas/ticket/32 +# the same issue with sed -i +# +# After file is replaced, call ovirt_store_config /etc/config /etc/config2 ... +# to bindmount the config file again. +umount_config() { + if grep -q " /config " /proc/mounts; then + for f in "$@"; do + if grep -q " $f " /proc/mounts ; then + umount -n $f + # refresh rootfs copy + cp /config$f $f + fi + done + fi } -# persist configuration to /config on OVIRT partition -# ovirt_store_config /etc/config /etc/config2 ... -ovirt_store_config() { - ovirt=$(mktemp -d) - ovirt_mount $ovirt - cfg=$ovirt/config - rw=0 - printf "store config:" - for f in "$@"; do - # ignore non-/etc paths - if [ $f != ${f#/etc/} ]; then - # check if changed - if [ "$(md5 $f)" != "$(md5 $cfg$f)" ]; then - if [ $rw = 0 ]; then - mount -o remount,rw $ovirt - rw=1 - fi - mkdir -p $cfg$(dirname $f) - cp $f $cfg$f - printf " $f" - fi - fi - done - echo - umount $ovirt && rmdir $ovirt +# persist configuration to /config +# ovirt_config_setup /etc/config /etc/config2 ... +# copy to /config and bind-mount back +ovirt_config_setup() { + if grep -q " /config " /proc/mounts; then + printf "storing to /config :" + for f in "$@"; do + printf " $f" + # skip if already bind-mounted + if grep -q " $f " /proc/mounts ; then + printf " already persisted\n" + else + mkdir -p /config$(dirname $f) + cp -a $f /config$f \ + && mount -n --bind /config$f $f \ + || printf " failed to persist\n" + fi + done + echo + else + printf "warning: persistent config storage not available\n" + fi +} + +# compat function to handle different udev versions +udev_info() { + local name=$1 + local query=$2 + local out + + # old udev command with shortopts + out=$(udevinfo -n $name -q $query) + rc=$? + if [ $rc -ne 0 ]; then + out=$(udevadm info --name=$name --query=$query) + rc=$? + fi + if [ $rc -eq 0 ]; then + echo $out + fi + return $rc } + diff --git a/scripts/ovirt-post b/scripts/ovirt-post old mode 100644 new mode 100755 index 06506b7..a5bd930 --- a/scripts/ovirt-post +++ b/scripts/ovirt-post @@ -12,7 +12,7 @@ start() { # persist selected configuration files - ovirt_store_config \ + ovirt_config_setup \ /etc/krb5.conf \ /etc/libvirt/krb5.tab \ /etc/ssh/ssh_host*_key* -- 1.6.0.4