From d1c74e2dcf75d2a056102d104d5c1d7674174739 Mon Sep 17 00:00:00 2001 From: torben Date: Wed, 5 Sep 2018 14:57:34 +0200 Subject: Adding logic to auto initialize boot partitions. --- .../dnbd-root-filesystem/hooks/fetch-config.sh | 256 ----------------- .../hooks/update-boot-files.sh | 314 +++++++++++++++++++++ modules.d/dnbd-root-filesystem/module-setup.sh | 12 +- 3 files changed, 324 insertions(+), 258 deletions(-) delete mode 100755 modules.d/dnbd-root-filesystem/hooks/fetch-config.sh create mode 100755 modules.d/dnbd-root-filesystem/hooks/update-boot-files.sh diff --git a/modules.d/dnbd-root-filesystem/hooks/fetch-config.sh b/modules.d/dnbd-root-filesystem/hooks/fetch-config.sh deleted file mode 100755 index da94242d..00000000 --- a/modules.d/dnbd-root-filesystem/hooks/fetch-config.sh +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/env bash -# -*- coding: utf-8 -*- -source /usr/lib/configure-logging.sh -bl.module.import bashlink.path -bl.exception.try { - # region determine boot partition - local kernel_file_path="$( - cat /proc/cmdline | \ - sed --regexp-extended 's:^(BOOT_IMAGE=)?([^ ]+).+$:\2:' | \ - sed 's:\\:/:')" - local initramfs_file_path="$( - cat /proc/cmdline | \ - sed --regexp-extended 's:^(.+ )?initrd=([^ ]+).*$:\2:' | \ - sed 's:\\:/:')" - mkdir --parents /mnt - local boot_partition_mounted=false - local device_name - umount /mnt &>/dev/null || \ - true - while read device_name; do - bl.logging.info Check \"/dev/$device_name\" for boot partition. - if mount "/dev/$device_name" /mnt &>/dev/null; then - if [ -f /mnt/slx_boot ]; then - bl.logging.info \ - Detected \"/dev/$device_name\" as boot partition. - local -r boot_prefix=$(cat /mnt/slx_boot) - kernel_file_path="$( - bl.path.convert_to_absolute "$boot_prefix/$kernel_file_path")" - initramfs_file_path="$( - bl.path.convert_to_absolute "$boot_prefix/$initramfs_file_path")" - bl.logging.info \ - Detected kernel file path \"$kernel_file_path\" and \ - initramfs file path \"$initramfs_file_path\". - boot_partition_mounted=true - break - fi - umount /mnt - fi - done <<< "$(lsblk --list --noheadings --output NAME)" - local -i kernel_version=0 - if [ -f /mnt/kernel-version ]; then - kernel_version=$(cat /mnt/kernel-version) - fi - local -i initramfs_version=0 - if [ -f /mnt/initramfs-version ]; then - initramfs_version=$(cat /mnt/initramfs-version) - fi - local -i new_kernel_version=0 - local -i new_initramfs_version=0 - # endregion - local configuration_file_name="$( - getarg slx_configuration_filename= || \ - true - )" - if [ "$configuration_file_name" = '' ]; then - configuration_file_name=config - fi - local slx_server="$(getarg slxsrv= || true)" - local slx_server_base="$(getarg slxbase= || true)" - slx_server="${slx_server%/}" - slx_server_base="${slx_server_base%/}" - if [ "$slx_server" = '' ]; then - bl.logging.warn \ - No slx server host given, no config, kernel or initramfs updates \ - could be done. - else - bl.logging.info Download SLX configuration from: \"$slx_server\". - local config_passed=false - local timeout_in_seconds - for timeout_in_seconds in 1 1 2 3 6; do - local IFS_backup="$IFS" - IFS=',' - local host - for host in $slx_server; do - if \ - ! $config_passed && \ - wget \ - --timeout "$timeout_in_seconds" \ - --output-document /etc/openslx \ - "http://${host#@}/${slx_server_base#/}/${configuration_file_name#/}" - then - config_passed=true - break - fi - done - if $config_passed; then - break - fi - IFS="$IFS_backup" - done - if ! $config_passed; then - bl.logging.warn \ - Downloading openSLX configuration file from any of the given \ - servers \"$slx_server\" at location \ - \"$slx_server_base/$configuration_file_name\" failed. - fi - fi - if [ -f /etc/openslx ]; then - if $boot_partition_mounted; then - bl.logging.info \ - Saving openslx config at boot partition: \ - \"/dev/$device_name\". - cp /etc/openslx /mnt/ - fi - elif $boot_partition_mounted; then - bl.logging.info \ - Restoring openslx config from boot partition: \ - \"/dev/$device_name\". - cp /mnt/openslx /etc/ - fi - if [ -f /etc/openslx ] && ! $boot_partition_mounted; then - source /etc/openslx - # TODO maybe "a create if not exists" logic could make sende here. - if \ - [[ "$SLX_INITIAL_BOOT_PARTITION_IDENTIFIER" != '' ]] && \ - mount "$SLX_INITIAL_BOOT_PARTITION_IDENTIFIER" /mnt \ - &>/dev/null - then - boot_partition_mounted=true - fi - fi - if [ -f /etc/openslx ]; then - if $boot_partition_mounted && ! [ -f /mnt/openslx ]; then - bl.logging.info \ - Saving openslx config at boot partition: \ - \"/dev/$device_name\". - cp /etc/openslx /mnt/ - fi - else - bl.logging.error_exception \ - No needed openSLX configuration file available. - fi - if [[ "$slx_server" != '' ]] && $boot_partition_mounted; then - bl.logging.info Check for kernel and/or initramfs updates. - local kernel_passed=false - local initramfs_passed=false - for timeout_in_seconds in 1 1 2 3 6; do - local IFS_backup="$IFS" - IFS=',' - local host - for host in $slx_server; do - # region update kernel - if \ - ! $kernel_passed && \ - wget \ - --timeout "$timeout_in_seconds" \ - --output-document /tmp/kernel-version \ - "http://${host#@}/${slx_server_base#/}/kernel-version" - then - bl.logging.info \ - Checking for newer kernel \(current version: \ - $kernel_version\). - if [ -f /tmp/kernel-version ]; then - new_kernel_version=$(cat /tmp/kernel-version) - fi - if (( kernel_version < new_kernel_version )); then - if \ - wget \ - --timeout "$timeout_in_seconds" \ - --output-document "/mnt/$kernel_file_path" \ - "http://${host#@}/${slx_server_base#/}/kernel" - then - kernel_passed=true - echo "$new_kernel_version" > /mnt/kernel-version - fi - else - kernel_passed=true - fi - fi - # endregion - # region update initramfs - if \ - ! $initramfs_passed && \ - wget \ - --timeout "$timeout_in_seconds" \ - --output-document /tmp/initramfs-version \ - "http://${host#@}/${slx_server_base#/}/initramfs-version" - then - bl.logging.info \ - Checking for newer initramfs \(current version: \ - $initramfs_version\). - if [ -f /tmp/initramfs-version ]; then - new_initramfs_version=$(cat /tmp/initramfs-version) - fi - if (( initramfs_version < new_initramfs_version )); then - if \ - wget \ - --timeout "$timeout_in_seconds" \ - --output-document "/mnt/$initramfs_file_path" \ - "http://${host#@}/${slx_server_base#/}/initramfs" - then - initramfs_passed=true - echo "$new_initramfs_version" > /mnt/initramfs-version - fi - else - initramfs_passed=true - fi - fi - # endregion - if $kernel_passed && $initramfs_passed; then - break - fi - done - if $kernel_passed && $initramfs_passed; then - break - fi - IFS="$IFS_backup" - done - if ! $kernel_passed; then - bl.logging.warn \ - Checking for newer kernel version failed from any of the given \ - servers \"$slx_server\" at location \ - \"$slx_server_base/kernel\(-version\)\". - fi - if ! $initramfs_passed; then - bl.logging.warn \ - Checking for newer initramfs version failed from any of the given \ - servers \"$slx_server\" at location \ - \"$slx_server_base/initramfs\(-version\)\". - fi - if \ - (( kernel_version < new_kernel_version )) || \ - (( initramfs_version < new_initramfs_version )) - then - if \ - kexec \ - --load "/mnt/$kernel_file_path" \ - --initrd "/mnt/$initramfs_file_path" \ - --reuse-cmdline - then - umount /mnt - kexec -e - else - bl.logging.warn \ - Failed to hot reload newer kernel and/or initramfs. - fi - fi - fi - if $boot_partition_mounted; then - umount /mnt - fi - # NOTE: slxsrv overrides "SLX_DNBD_SERVERS" if prefixed with "@". - if [[ "${slx_server#@}" != "$slx_server" ]]; then - sed \ - --in-place \ - "s/^SLX_DNBD_SERVERS=.*/SLX_DNBD_SERVERS='${slx_server#@}'/" \ - /etc/openslx - fi -} bl.exception.catch { - bl.logging.error "$bl_exception_last_traceback" - emergency_shell "error in ${BASH_SOURCE[0]}" -} -# region vim modline -# vim: set tabstop=4 shiftwidth=4 expandtab: -# vim: foldmethod=marker foldmarker=region,endregion: -# endregion diff --git a/modules.d/dnbd-root-filesystem/hooks/update-boot-files.sh b/modules.d/dnbd-root-filesystem/hooks/update-boot-files.sh new file mode 100755 index 00000000..071bfdcc --- /dev/null +++ b/modules.d/dnbd-root-filesystem/hooks/update-boot-files.sh @@ -0,0 +1,314 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- +source /usr/lib/configure-logging.sh +bl.module.import bashlink.path +bl.exception.try { + # region determine boot partition + local kernel_file_path="$( + cat /proc/cmdline | \ + sed --regexp-extended 's:^(BOOT_IMAGE=)?([^ ]+).+$:\2:' | \ + sed 's:\\:/:')" + if [ "$kernel_file_path" = '' ]; then + kernel_file_path=kernel + fi + local initramfs_file_path="$( + cat /proc/cmdline | \ + sed --regexp-extended 's:^(.+ )?initrd=([^ ]+).*$:\2:' | \ + sed 's:\\:/:')" + if [ "$initramfs_file_path" = '' ]; then + initramfs_file_path=initramfs + fi + mkdir --parents /mnt + local boot_partition_mounted=false + local device_name + umount /mnt &>/dev/null || \ + true + while read device_name; do + bl.logging.info Check \"/dev/$device_name\" for boot partition. + if mount "/dev/$device_name" /mnt &>/dev/null; then + if [ -f /mnt/slx_boot ]; then + bl.logging.info \ + Detected \"/dev/$device_name\" as boot partition. + local -r boot_prefix=$(cat /mnt/slx_boot) + kernel_file_path="$( + bl.path.convert_to_absolute "$boot_prefix/$kernel_file_path")" + initramfs_file_path="$( + bl.path.convert_to_absolute "$boot_prefix/$initramfs_file_path")" + bl.logging.info \ + Detected kernel file path \"$kernel_file_path\" and \ + initramfs file path \"$initramfs_file_path\". + boot_partition_mounted=true + break + fi + umount /mnt + fi + done <<< "$(lsblk --list --noheadings --output NAME)" + local -i kernel_version=0 + if [ -f /mnt/kernel-version ]; then + kernel_version=$(cat /mnt/kernel-version) + fi + local -i initramfs_version=0 + if [ -f /mnt/initramfs-version ]; then + initramfs_version=$(cat /mnt/initramfs-version) + fi + local -i new_kernel_version=0 + local -i new_initramfs_version=0 + # endregion + local configuration_file_name="$( + getarg slx_configuration_filename= || \ + true + )" + if [ "$configuration_file_name" = '' ]; then + configuration_file_name=config + fi + local slx_server="$(getarg slxsrv= || true)" + local slx_server_base="$(getarg slxbase= || true)" + slx_server="${slx_server%/}" + slx_server_base="${slx_server_base%/}" + if [ "$slx_server" = '' ]; then + bl.logging.warn \ + No slx server host given, no config, kernel or initramfs updates \ + could be done. + else + bl.logging.info Download SLX configuration from: \"$slx_server\". + local config_passed=false + local timeout_in_seconds + for timeout_in_seconds in 1 1 2 3 6; do + local IFS_backup="$IFS" + IFS=',' + local host + for host in $slx_server; do + if \ + ! $config_passed && \ + wget \ + --timeout "$timeout_in_seconds" \ + --output-document /etc/openslx \ + "http://${host#@}/${slx_server_base#/}/${configuration_file_name#/}" + then + config_passed=true + break + fi + done + if $config_passed; then + break + fi + IFS="$IFS_backup" + done + if ! $config_passed; then + bl.logging.warn \ + Downloading openSLX configuration file from any of the given \ + servers \"$slx_server\" at location \ + \"$slx_server_base/$configuration_file_name\" failed. + fi + fi + if [ -f /etc/openslx ]; then + if $boot_partition_mounted; then + bl.logging.info \ + Saving openslx config at boot partition: \ + \"/dev/$device_name\". + cp /etc/openslx /mnt/ + fi + elif $boot_partition_mounted; then + bl.logging.info \ + Restoring openslx config from boot partition: \ + \"/dev/$device_name\". + cp /mnt/openslx /etc/ + fi + if [ -f /etc/openslx ] && ! $boot_partition_mounted; then + source /etc/openslx + # TODO iterate through $SLX_INITIAL_BOOT_PARTITION_IDENTIFIER + if \ + [[ "$SLX_INITIAL_BOOT_PARTITION_IDENTIFIER" != '' ]] && \ + mount "$SLX_INITIAL_BOOT_PARTITION_IDENTIFIER" /mnt \ + &>/dev/null + then + if [ -d /mnt/syslinux ]; then + boot_partition_mounted=true + elif $SLX_AUTO_INITIALIZE_BOOT_PARTITION && false; then + mkdir --parents /mnt/syslinux + #bl.logging.info Copy boot menu binaries to bootloader. + #cp /usr/lib/syslinux/boot/*.c32 /mnt/syslinux + bl.logging.info Install bootloader. + extlinux --install /mnt/syslinux + if false; then + bl.logging.info \ + Set the \"legacy_boot\" flag to gpt based boot partition. + sgdisk /dev/sda --attributes=1:set:2 + bl.logging.info Install MBR to gpt partition layout. + dd \ + bs=440 \ + count=1 \ + conv=notrunc \ + if=/usr/lib/syslinux/bios/gptmbr.bin \ + of=/dev/sda \ + seek=TODO + else + if ! fdisk --list /dev/sda | grep '^/dev/sda2 +\*' &>/dev/null; then + bl.logging.info \ + Set the \"boot\" flag to mbr based boot partition. + fdisk /dev/sda << EOF +a +2 +w +EOF + fi + bl.logging.info Install MBR to gpt partition layout. + dd \ + bs=440 \ + count=1 \ + conv=notrunc \ + if=/usr/lib/syslinux/bios/mbr.bin \ + of=/dev/sda + fi + cat << EOF > /mnt/syslinux/syslinux.cfg +PROMPT 1 +TIMEOUT 50 +DEFAULT arch + +LABEL arch + LINUX ../$kernel_file_path + APPEND $(cat /proc/cmdline) + INITRD ../$initramfs_file_path +EOF + boot_partition_mounted=true + fi + elif $SLX_AUTO_INITIALIZE_BOOT_PARTITION; then + bl.logging.info TODO make gdisk! + #boot_partition_mounted=true + fi + fi + if [ -f /etc/openslx ]; then + if $boot_partition_mounted && ! [ -f /mnt/openslx ]; then + bl.logging.info \ + Saving openslx config at boot partition: \ + \"/dev/$device_name\". + cp /etc/openslx /mnt/ + fi + else + bl.logging.error_exception \ + No needed openSLX configuration file available. + fi + if [[ "$slx_server" != '' ]] && $boot_partition_mounted; then + bl.logging.info Check for kernel and/or initramfs updates. + local kernel_passed=false + local initramfs_passed=false + for timeout_in_seconds in 1 1 2 3 6; do + local IFS_backup="$IFS" + IFS=',' + local host + for host in $slx_server; do + # region update kernel + if \ + ! $kernel_passed && \ + wget \ + --timeout "$timeout_in_seconds" \ + --output-document /tmp/kernel-version \ + "http://${host#@}/${slx_server_base#/}/kernel-version" + then + bl.logging.info \ + Checking for newer kernel \(current version: \ + $kernel_version\). + if [ -f /tmp/kernel-version ]; then + new_kernel_version=$(cat /tmp/kernel-version) + fi + if (( kernel_version < new_kernel_version )); then + if \ + wget \ + --timeout "$timeout_in_seconds" \ + --output-document "/mnt/$kernel_file_path" \ + "http://${host#@}/${slx_server_base#/}/kernel" + then + kernel_passed=true + echo "$new_kernel_version" > /mnt/kernel-version + fi + else + kernel_passed=true + fi + fi + # endregion + # region update initramfs + if \ + ! $initramfs_passed && \ + wget \ + --timeout "$timeout_in_seconds" \ + --output-document /tmp/initramfs-version \ + "http://${host#@}/${slx_server_base#/}/initramfs-version" + then + bl.logging.info \ + Checking for newer initramfs \(current version: \ + $initramfs_version\). + if [ -f /tmp/initramfs-version ]; then + new_initramfs_version=$(cat /tmp/initramfs-version) + fi + if (( initramfs_version < new_initramfs_version )); then + if \ + wget \ + --timeout "$timeout_in_seconds" \ + --output-document "/mnt/$initramfs_file_path" \ + "http://${host#@}/${slx_server_base#/}/initramfs" + then + initramfs_passed=true + echo "$new_initramfs_version" > /mnt/initramfs-version + fi + else + initramfs_passed=true + fi + fi + # endregion + if $kernel_passed && $initramfs_passed; then + break + fi + done + if $kernel_passed && $initramfs_passed; then + break + fi + IFS="$IFS_backup" + done + if ! $kernel_passed; then + bl.logging.warn \ + Checking for newer kernel version failed from any of the given \ + servers \"$slx_server\" at location \ + \"$slx_server_base/kernel\(-version\)\". + fi + if ! $initramfs_passed; then + bl.logging.warn \ + Checking for newer initramfs version failed from any of the given \ + servers \"$slx_server\" at location \ + \"$slx_server_base/initramfs\(-version\)\". + fi + if \ + (( kernel_version < new_kernel_version )) || \ + (( initramfs_version < new_initramfs_version )) + then + if \ + kexec \ + --load "/mnt/$kernel_file_path" \ + --initrd "/mnt/$initramfs_file_path" \ + --reuse-cmdline + then + umount /mnt + kexec -e + else + bl.logging.warn \ + Failed to hot reload newer kernel and/or initramfs. + fi + fi + fi + if $boot_partition_mounted; then + umount /mnt + fi + # NOTE: slxsrv overrides "SLX_DNBD_SERVERS" if prefixed with "@". + if [[ "${slx_server#@}" != "$slx_server" ]]; then + sed \ + --in-place \ + "s/^SLX_DNBD_SERVERS=.*/SLX_DNBD_SERVERS='${slx_server#@}'/" \ + /etc/openslx + fi +} bl.exception.catch { + bl.logging.error "$bl_exception_last_traceback" + emergency_shell "error in ${BASH_SOURCE[0]}" +} +# region vim modline +# vim: set tabstop=4 shiftwidth=4 expandtab: +# vim: foldmethod=marker foldmarker=region,endregion: +# endregion diff --git a/modules.d/dnbd-root-filesystem/module-setup.sh b/modules.d/dnbd-root-filesystem/module-setup.sh index f28c8102..388276e6 100755 --- a/modules.d/dnbd-root-filesystem/module-setup.sh +++ b/modules.d/dnbd-root-filesystem/module-setup.sh @@ -231,7 +231,7 @@ install() { inst_hook pre-udev 00 "$moddir/hooks/load-custom-kernel-modules.sh" # Get the openslx config from the servers configured in the kernel command # line (${SLX_SERVER}/${SLX_SERVER_BASE}/config). - inst_hook pre-mount 10 "$moddir/hooks/fetch-config.sh" + inst_hook pre-mount 10 "$moddir/hooks/update-boot-files.sh" # make the final blockdevice for the root system (dnbd -> xmount -> # device-mapper) if dracut_module_included systemd-initrd; then @@ -295,7 +295,15 @@ install() { pgrep pkill killall \ losetup lsblk \ mkfifo mkfs.ext4 \ - kexec + kexec \ + fdisk \ + gdisk \ + syslinux \ + extlinux \ + sgdisk \ + /usr/lib/syslinux/bios/gptmbr.bin \ + /usr/lib/syslinux/bios/mbr.bin + #/usr/lib/syslinux/boot/*.c32 \ } # endregion # region vim modline -- cgit v1.2.3-55-g7522