diff options
Diffstat (limited to 'builder/build-initramfs.sh')
-rwxr-xr-x | builder/build-initramfs.sh | 388 |
1 files changed, 32 insertions, 356 deletions
diff --git a/builder/build-initramfs.sh b/builder/build-initramfs.sh index 51ae5ddf..d9017e74 100755 --- a/builder/build-initramfs.sh +++ b/builder/build-initramfs.sh @@ -13,18 +13,11 @@ # This tool provides a generic way to install systemd based remote linux # initramfs. -# Examples -# -------- - -# Start install progress command (Assuming internet is available): -# >>> ./build-initramfs.sh - -# Note that you only get very necessary output until you provide "--verbose" as -# commandline options. declare -rg _root_dir="$(readlink -f $(dirname ${BASH_SOURCE[0]}))" declare -rg _repo_dir="${_root_dir}/systemd-init.git" declare -rg _git_source="git://git.openslx.org/openslx-ng/systemd-init.git" declare -rg _git_branch="master" + ## region ensure presence of needed dependencies set -o errexit if [ ! -e "$_repo_dir" ]; then @@ -67,16 +60,7 @@ if [ ! -e "$_repo_dir" ]; then fi set +o errexit ## endregion -# shellcheck source=./dnbd3-rootfs/scripts/rebash/core.sh -source "${_root_dir}/modules.d/dnbd3-rootfs/scripts/rebash/core.sh" -core.import exceptions -core.import logging -core.import utils -core.import change_root -# endregion -# region properties -# shellcheck disable=SC2034 -build_initramfs__doc_test_setup__='exceptions.activate' + file_path='/boot/initramfs.img' dracut_parameter=(--force --no-hostonly) verbose='no' @@ -85,72 +69,9 @@ target='' cleanup='no' full_cleanup='no' use_systemd_in_initramfs='no' -# shellcheck disable=SC2034 -declare -A core_dependencies=( - [cat]='print messages' \ - [cpio]='pack initramfs' \ - ['dhclient arping']='support network connection in resulting initramfs' \ - [dirname]='core logic' \ - [dmsetup]='create a (temporary) writable layer during boot' \ - [grep]='retrieve right boot partition during boot' \ - [mktemp]='create save temporary files and dictionaries' \ - [pkg-config]='retrieve information of installed development packages' \ - [tee]='read from standard input and write to standard output and files' \ - [readlink]="connect dracut module with dracut's module system" \ - [rm]='remove (temporary) files' \ - [shift]='parse command line' \ - [sed]='process strings' \ - ['cmake gcc make']='dynamically compile needed resources against current or given kernel') -# shellcheck disable=SC2034 -declare -A optional_dependencies=( - [chroot]='build against a distribution other than this program runs in' \ - ['curl git gzip tar']='dynamically retrieve and unpack missing application which will be compiled for current or given kernel' \ - ['mkfs.ext4 fsck']='support for persistent binary diffs in image files') -# shellcheck disable=SC2034 -declare -A core_shared_library_pattern_dependencies=( - [libz]='compile dnbd3 for given or current kernel') -# shellcheck disable=SC2034 -declare -A optional_shared_library_pattern_dependencies=() -# shellcheck disable=SC2034 -declare -A core_package_dependencies=() -# shellcheck disable=SC2034 -declare -A optional_package_dependencies=( - ['fuse glib-2.0 pixman-1']='support template systems in container (usually used by virtual runtime environments)') -# endregion -# region functions -## region command line interface -print_usage_message() { - # shellcheck disable=SC2016,SC2034 - local __doc__=' - Prints a description about how to use this program. - >>> print_usage_message &>/dev/null - ' - logging.cat << EOF -This program provides a generic way to install systemd based remote linux -initramfs. -EOF -} -print_usage_examples() { - # shellcheck disable=SC2016,SC2034 - local __doc__=' - Prints a description about how to use this program by providing examples. - - >>> print_usage_examples &>/dev/null - ' - logging.cat << EOF -Start install progress: ->>> ./build_initramfs.sh -EOF -} print_command_line_option_description() { - # shellcheck disable=SC2016,SC2034 - local __doc__=' - Prints descriptions about each available command line option. - - >>> print_command_line_option_description &>/dev/null - ' - logging.cat << EOF + cat << EOF -h --help Shows this help message. -v --verbose Tells you what is going on (default: "$verbose"). @@ -187,115 +108,7 @@ them via a single dash (-) (default: "$dracut_parameter" with concatenated.). EOF } -print_help_message() { - # shellcheck disable=SC2016,SC2034 - local __doc__=' - Provides a help message for this module. - - >>> print_help_message &>/dev/null - ' - logging.plain "\nUsage: $0 [options]\n" - print_usage_message "$@" - logging.plain '\nExamples:\n' - print_usage_examples "$@" - logging.plain -e '\nOption descriptions:\n' - print_command_line_option_description "$@" - logging.plain -} parse_command_line() { - # shellcheck disable=SC2016,SC2034 - local __doc__=' - Provides the command line interface and interactive questions. - - >>> parse_command_line -h &>/dev/null - - >>> echo "$verbose" - no - >>> logging.get_level - critical - >>> parse_command_line -v - >>> echo "$verbose" - >>> logging.get_level - yes - info - - >>> echo "$debug" - no - >>> parse_command_line --debug - >>> echo "$debug" - >>> logging.get_level - yes - debug - - >>> parse_command_line -p - +doc_test_capture_stderr - +doc_test_contains - +doc_test_ellipsis - Error with given option "-p": - Traceback (most recent call first): - ... - - >>> echo "$file_path" - /boot/initramfs.img - >>> parse_command_line -p /tmp/test.img - >>> echo "$file_path" - /tmp/test.img - - >>> echo "$cleanup" - no - >>> parse_command_line --cleanup - >>> echo "$cleanup" - yes - - >>> echo "$full_cleanup" - no - >>> parse_command_line --full-cleanup - >>> echo "$full_cleanup" - yes - - >>> echo "$full_cleanup" - no - >>> parse_command_line --full-cleanup - >>> echo "$full_cleanup" - yes - - >>> echo "$use_systemd_in_initramfs" - no - >>> parse_command_line -s - >>> echo "$use_systemd_in_initramfs" - yes - - >>> parse_command_line -t; echo $? - +doc_test_capture_stderr - +doc_test_contains - +doc_test_ellipsis - Error with given option "-t": - Traceback (most recent call first): - ... - - >>> [[ "$target" = "" ]] - >>> parse_command_line -t /tmp/ - >>> echo "$target" - /tmp/ - - >>> echo "${dracut_parameter[@]}" - --force --no-hostonly - >>> parse_command_line - --test - >>> echo "${dracut_parameter[@]}" - --force --no-hostonly --test - - >>> parse_command_line - --install "vim htop" - >>> echo "${dracut_parameter[3]}" - vim htop - - >>> parse_command_line --no-available-option; echo $? - +doc_test_capture_stderr - +doc_test_contains - +doc_test_ellipsis - Error with given option "--no-available-option": - Traceback (most recent call first): - ... - ' while true; do case "$1" in -h|--help) @@ -354,7 +167,7 @@ parse_command_line() { shift kernel_version="$1" if [ -z "$kernel_version" ]; then - logging.critical \ + echo \ "Error with given option \"$given_argument\": This option needs a kernel version to build the initramfs for." return 1 fi @@ -365,7 +178,7 @@ parse_command_line() { shift kernel_headers="$1" if [ -z "$kernel_headers" ]; then - logging.critical \ + echo \ "Error with given option \"$given_argument\": This option needs the path to the kernel headers." return 1 fi @@ -376,7 +189,7 @@ parse_command_line() { shift qcow_handler="$1" if [ -z "$qcow_handler" ]; then - logging.critical \ + echo \ "Error with given option \"$given_argument\": This options needs to be either 'xmount' or 'kernel'." return 1 fi @@ -397,18 +210,12 @@ parse_command_line() { break ;; *) - logging.critical \ + echo \ "Error with given option \"$1\": This argument is not available." return 1 esac done - if [ "$verbose" == 'yes' ]; then - logging.set_level info - fi - if [ "$debug" == 'yes' ]; then - logging.set_level debug - fi - # NOTE: Remove the following line if this sanity check should be performed. + return 0 if [[ "$UID" != '0' ]]; then logging.critical \ @@ -419,45 +226,7 @@ parse_command_line() { } ## endregion ## region helper -dependency_check() { - # shellcheck disable=SC2016,SC2034 - local __doc__=' - Check for given dependencies with given dependency checker and log - corresponding messages. - - Example: - - `dependency_check core dependencies utils_dependency_check program` - ' - local result=0 - - # shellcheck disable=SC2016,SC1004 - eval 'for dependency_group in "${!'"$1"'_'"$2"'[@]}"; do - # NOTE: If "dependency_check_result" would be marked as local it is - # empty later. - dependency_check_result="$($3 $dependency_group)" || \ - local return_code=$? - if [[ $return_code == 1 ]]; then - echo "$dependency_check_result" - return $return_code - elif [[ $return_code == 2 ]]; then - while read dependency; do - eval "local reason=\${${1}_${2}[\"\$dependency_group\"]}" - local message="Missing $1 $4 dependency \"$dependency\" needed to $reason." - if [[ $1 == core ]]; then - logging.critical "$message" - else - logging.warn "$message" - fi - done <<< $dependency_check_result - result=2 - fi - return_code=0 - done' - return $result -} initialize_dracut() { - # shellcheck disable=SC2016,SC2034 local __doc__=' Downloads and compiles dracut. @@ -477,14 +246,14 @@ initialize_dracut() { dracut_resource_url="https://www.kernel.org/pub/linux/utils/boot/dracut/dracut-$dracut_version.tar.gz" if [[ ! -f "${_root_dir}/dracut/install/dracut-install" ]]; then mkdir --parents "${_root_dir}/dracut" - logging.info "Download and extract dracut version $dracut_version" + echo "Download and extract dracut version $dracut_version" curl --location "$dracut_resource_url" | tar --extract --gzip \ --directory "${_root_dir}/dracut" --strip-components 1 pushd "${_root_dir}/dracut" # NOTE: On virtualbox shared folder symlinks are not allowed. # NOTE: make the dracut-install binary (dracut-install resolves # dependencies etc.) - logging.info 'Compiling dracut.' + echo 'Compiling dracut.' ./configure make install/dracut-install # NOTE: We have to copy the binary to current instead of symlinking @@ -499,6 +268,7 @@ initialize_dracut() { return $? } +# TODO does this even works? cleanup() { # shellcheck disable=SC2016,SC2034 local __doc__=' @@ -530,111 +300,30 @@ main() { `main` ' - exceptions.activate # region sanity check kernel version and qcow handler # if no kernel was specified as dracut argument, use the running kernel's version - logging.info "Building for:" + echo "Building for:" if [ -z "$kernel_version" ]; then kernel_version="$(uname -r)" fi - logging.info " * kernel version: $kernel_version" + echo " * kernel version: $kernel_version" # similar for kernel headers needed to compile dnbd3 against. if [ -z "$kernel_headers" ]; then kernel_headers="/lib/modules/${kernel_version}/build" fi if [ ! -f "${kernel_headers}/Makefile" ]; then - logging.critical 'Missing core dependency "linux-headers" for version to compile against given or current kernel.' + echo 'Missing core dependency "linux-headers" for version to compile against given or current kernel.' fi - logging.info " * kernel headers: $kernel_headers" + echo " * kernel headers: $kernel_headers" [ -n "$qcow_handler" ] && logging.info " * qcow2 handler: $qcow_handler" export _QCOW_HANDLER="$qcow_handler" # endregion - # region dependency checks and command line parsing - result=0 - dependency_check core dependencies utils_dependency_check program || \ - result=$? - dependency_check core shared_library_pattern_dependencies \ - utils_dependency_check_shared_library 'shared library' || result=$? - dependency_check core package_dependencies utils_dependency_check_pkgconfig \ - package || result=$? - [[ $result == 0 ]] || exit $result - - logging.set_commands_level debug - logging.set_level critical if ! parse_command_line "$@"; then print_help_message "$0" exit 1 fi - dependency_check optional dependencies utils_dependency_check program || \ - result=$? - dependency_check optional shared_library_pattern_dependencies \ - utils_dependency_check_shared_library 'shared library' || result=$? - dependency_check optional package_dependencies \ - utils_dependency_check_pkgconfig package || result=$? - [[ $result == 1 ]] && exit $result - # endregion - # region handle delegated operations to specified target - if [[ "$target" != '' ]]; then - _target="$target" - if [[ -f "$target" ]]; then - _target="$(mktemp --directory)" - _xmount_mountpoint_target="$(mktemp --directory)" - xmount --in qemu "$target" --out raw "$_xmount_mountpoint_target" - _xmount_device_target="$(losetup --find)" - losetup --partscan "$_xmount_device_target" \ - "${_xmount_mountpoint_target}/"*.dd - # TODO Use partscan - mount "$_xmount_device_target" "$_target" - fi - if [[ -d "$_target" ]]; then - _temporary_working_directory="$(chroot "$_target" mktemp --directory)" - mount --bind "$(pwd)" "${_target}${_temporary_working_directory}" - _parameter_skip=false - _parameter_to_forward=() - for _parameter; do - if $_parameter_skip; then - _parameter_skip=false - elif [[ "$_parameter" == '-t' ]] || \ - [[ "$_parameter" == '--target' ]]; then - _parameter_skip=true - else - _parameter_to_forward+=("$_parameter") - fi - done - # NOTE: We would have to temporary patch dracut to avoid removing the - # environment variables "LD_LIBRARY_PATH" and "LD_PRELOAD" to get - # "fakechroot" working with dracut. So we should remove this variables - # before running the patched dracut version to follow the initial - # intention. You should first do: - # >>> unset LD_LIBRARY_PATH - # >>> unset LD_PRELOAD - # and patch "dracut.sh" temporary to comment out: - # >>> unset LD_LIBRARY_PATH - # >>> unset LD_PRELOAD - # To avoid to broke the "fakechroot" environment pipe the ldconfig call - # to the native one: - # >>> FAKECHROOT_CMD_SUBST=/usr/bin/ldconfig=/usr/bin/ldconfig - # shellcheck disable=SC2086 - change_root "${_target}" \ - "${_temporary_working_directory}/${BASH_SOURCE[0]}" \ - ${_parameter_to_forward[*]} - mv "${_target}/$file_path" "$file_path" - # Do cleanup procedures. - umount "${_target}${_temporary_working_directory}" - rm --recursive --force "${_target}${_temporary_working_directory}" - if [[ -f "$target" ]]; then - umount "$_target" - losetup --detach "$_xmount_device_target" - umount "$_xmount_mountpoint_target" - rm --recursive --force "$_target" "$_xmount_mountpoint_target" - fi - fi - exit 0 - fi - # endregion - # region handle '--update' to update all the modules in 'modules.d' if [ "$update" == "yes" ]; then pushd "${_repo_dir}" git pull @@ -642,9 +331,9 @@ main() { fi # endregion # region handle dependencies which can be resolved automatically - logging.info 'Checking dracut.' + echo 'Checking dracut...' if [[ ! -f "${_root_dir}/dracut/dracut-install" ]]; then - logging.info "Dracut isn't available yet loading it." + echo "Dracut isn't available yet loading it." initialize_dracut fi @@ -653,16 +342,16 @@ main() { _dracut_module="$(basename $_dracut_module)" # shouldn't we use absolute paths here? _dracut_module_relative_path="../../modules.d/${_dracut_module}" - # TODO change to *not* always use '90' ... + # TODO introduce module priority _dracut_module_target="${_root_dir}/dracut/modules.d/00${_dracut_module}" if [[ ! -L "$_dracut_module_target" || "$(readlink \ "$_dracut_module_target")" != "$_dracut_module_relative_path" ]]; then - logging.info \ + echo \ "Link ${_dracut_module} plugin into dracut modules folder ($_dracut_module_relative_path -> $_dracut_module_target)." if ! ln --symbolic --force "$_dracut_module_relative_path" \ "$_dracut_module_target"; then - logging.warn \ - "Linking \"$_dracut_module_relative_path\" to \"$_dracut_module_target\" failed." \ + echo \ + "Linking '$_dracut_module_relative_path' to '$_dracut_module_target' failed." \ " We will copy them. So we have to recopy it every time to ensure that recompiled things take effect." cp --recursive --force --no-target-directory \ "${_root_dir}/modules.d/$_dracut_module" \ @@ -678,59 +367,46 @@ main() { _loglevel='--verbose' fi _modules='dnbd3-rootfs conf-tgz' - logging.info "Default modules: ${_modules}" + echo "Default modules: ${_modules}" if [ "$debug" == 'yes' ]; then _loglevel="$_loglevel --stdlog 4" + # TODO check if we always want this _modules="$_modules i18n terminfo" fi + # TODO does non-systemd initramfs even works nowadays? + # Why you we want to do SysV-init style??? if [ "$use_systemd_in_initramfs" == 'yes' ]; then _modules="$_modules systemd systemd-initrd dracut-systemd" fi # Preprocess done - start build, cleanup or full cleanup if [[ "$full_cleanup" == 'yes' ]]; then - logging.info 'Removing all modules.' + echo 'Removing all modules.' rm "${_root_dir}/modules.d" \ "${_root_dir}/dracut" --recursive --force elif [[ "$cleanup" == 'yes' ]]; then - logging.info 'Removing distribution specific files.' + echo 'Removing distribution specific files.' cleanup elif [[ "$initialize" == 'yes' ]]; then . "${_root_dir}/modules.d/dnbd3-rootfs/helper/build.inc" build_initialize_components else - logging.info 'Build initramfs.' - # NOTE: We deactivate our exception handle since dracut returns "1" if - # it is launched with help parameter ("-h" or "--help"). - exceptions.deactivate - # NOTE: We temporary allow dracut to forward all messages since we - # forward all logging configurations. - _commands_log_level_backup="$(logging.get_commands_level)" - _log_level_backup="$(logging.get_level)" - logging.set_level debug - logging.set_commands_level debug - # shellcheck disable=SC2086 + echo 'Build initramfs.' "${_root_dir}/dracut/dracut.sh" --local \ $_loglevel --modules "$_modules" --conf /etc/dracut.conf \ --confdir /etc/dracut.conf.d "${dracut_parameter[@]}" \ --kver "${kernel_version}" "$file_path" _return_code=$? - logging.set_commands_level "$_commands_log_level_backup" - logging.set_level "$_log_level_backup" - if [[ "$_return_code" != 0 ]]; then - logging.error 'Building initial ram file system failed.' + if [ "$_return_code" != 0 ]; then + echo 'Building initial ram file system failed.' exit 1 fi - exceptions.activate # NOTE: dracut generate the initramfs with 0600 permissions chmod 0644 "${file_path}" fi - # endregion - exceptions.deactivate } # endregion -if core.is_main; then - main "$@" -fi +main "$@" + # region vim modline # vim: set tabstop=4 shiftwidth=4 expandtab: # vim: foldmethod=marker foldmarker=region,endregion: |