diff options
Diffstat (limited to 'builder/build-initramfs.sh')
-rwxr-xr-x | builder/build-initramfs.sh | 435 |
1 files changed, 44 insertions, 391 deletions
diff --git a/builder/build-initramfs.sh b/builder/build-initramfs.sh index 9cf0b641..01d08059 100755 --- a/builder/build-initramfs.sh +++ b/builder/build-initramfs.sh @@ -3,28 +3,20 @@ # region header # Copyright Torben Sickert (info["~at~"]torben.website) 29.10.2015 # Janosch Dobler (info["~at~"]jandob.com) 29.10.2015 - +# Jonathan Bauer (jonathan.bauer@rz.uni-freiburg.de) 19.09.2019 # License # ------- # This library written by Torben Sickert and Janosch Dobler stand under a # creative commons naming 3.0 unported license. # see http://creativecommons.org/licenses/by/3.0/deed.de -# 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 +## endregion -# 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="centos8" + ## region ensure presence of needed dependencies set -o errexit if [ ! -e "$_repo_dir" ]; then @@ -32,6 +24,7 @@ if [ ! -e "$_repo_dir" ]; then if ! hash git; then echo "Needed dependency \"git\" isn't available." echo "Please install \"git\" or provide the main repository in \"${_repo_dir}\"." + exit 1 fi git clone --branch "$_git_branch" --single-branch --depth 1 \ "$_git_source" "${_repo_dir}" @@ -66,16 +59,7 @@ if [ ! -e "$_repo_dir" ]; then fi set +o errexit ## endregion -# shellcheck source=./dnbd3-rootfs/scripts/rebash/core.sh -source "${_repo_dir}/builder/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' @@ -84,217 +68,12 @@ 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 --h --help Shows this help message. - --v --verbose Tells you what is going on (default: "$verbose"). - --d --debug Gives you any output from all tools which are used - (default: "$debug"). - --p --file-path Target location for initramfs file - (default: "$file_path"). - --c --cleanup Removes all distribution specific compiled files. --f --full-cleanup Removes all retrieved and compiled files (usefull to retrieve latest version of all nested modules). - --t --target Creates an image against given target template filesystem. If not - explicitly specified current system will be used as template system - (default: "$target"). - --i --init Initializes the various repositories and build the required - dependencies but do not build the initramfs. Use this to accelerate - subsequent calls of this script. - --k --kernel-version Creates an image for the given kernel version. Will - require the presence of kernel headers for this version. - (default: "$(uname -r)") - --s --use-systemd-in-initramfs Use Systemd as init process in initramfs - (improved performance but less features) - (default: "$use_systemd_in_initramfs"). - -Additional dracut parameter and normal parameter can be added by delimiting -them via a single dash (-) (default: "$dracut_parameter" with -"--modules" and dynamically determined modules. Additional custom modules are -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 + echo "help" } -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): - ... - ' +parse_command_line() { while true; do case "$1" in -h|--help) @@ -315,7 +94,7 @@ parse_command_line() { shift file_path="$1" if [[ "$file_path" == '' ]]; then - logging.critical \ + echo \ "Error with given option \"$given_argument\": This option needs a path to save initramfs image to." return 1 fi @@ -338,7 +117,7 @@ parse_command_line() { shift target="$1" if [[ "$target" == '' ]]; then - logging.critical \ + echo \ "Error with given option \"$given_argument\": This option needs a path create initramfs from." return 1 fi @@ -353,7 +132,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 @@ -364,7 +143,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 @@ -375,7 +154,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 @@ -396,74 +175,17 @@ 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 \ - "You have to run this script as \"root\" not as \"${USER}\"." - exit 2 - fi + return 0 } ## 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. - - Example: - - `initialize_dracut` - ' # First check what version to get # Autodetect the kmod version present on the system to decide which dracut version to get # * v47 requires kmod >= 23 (Available in Ubuntu 18.04) @@ -476,14 +198,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 @@ -498,94 +220,48 @@ initialize_dracut() { return $? } +# The idea here was to source each module-setup.sh from our +# custom dracut modules and call their clean() function. +# TODO: Does this still work? cleanup() { - # shellcheck disable=SC2016,SC2034 - local __doc__=' - Removes distribution specific generated files. - - Example: - - `cleanup` - ' local plugin_path plugin_path="${_root_dir}/modules.d/dnbd3-rootfs" - # shellcheck disable=SC1090 source "${plugin_path}/module-setup.sh" - # shellcheck disable=SC2034 moddir="$(cd "$plugin_path" &>/dev/null && pwd)" clean return $? } -## endregion -# endregion -# region controller main() { - # shellcheck disable=SC2016,SC2034 - local __doc__=' - Main Entry point for the build initramfs logic. Triggers command line - parsing and calls sub routines depending on given command line arguments. - - Example: - - `main` - ' - exceptions.activate - # 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 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" - [ -n "$qcow_handler" ] && logging.info " * qcow2 handler: $qcow_handler" - # endregion + echo " * kernel headers: $kernel_headers" + [ -n "$qcow_handler" ] && echo " * qcow2 handler: $qcow_handler" + export _QCOW_HANDLER="$qcow_handler" - # region handle '--update' to update all the modules in 'modules.d' if [ "$update" == "yes" ]; then pushd "${_repo_dir}" git pull popd 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 @@ -596,10 +272,10 @@ main() { _dracut_module_target="${_root_dir}/dracut/modules.d/00${_dracut_module}" if [[ ! -L "$_dracut_module_target" || "$(readlink \ "$_dracut_module_target")" != "$_dracut_module_dir" ]]; then - logging.info \ + echo \ "Link ${_dracut_module} plugin into dracut modules folder ($_dracut_module_dir -> $_dracut_module_target)." if ! ln --symbolic --force "$_dracut_module_dir" "$_dracut_module_target"; then - logging.warn \ + echo \ "Linking \"$_dracut_module_dir\" 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 \ @@ -608,70 +284,47 @@ main() { fi fi done - # endregion - # region prepare modules and perform final dracut call _loglevel='' if [ "$verbose" == 'yes' ]; then _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" - _modules+=(i18n terminfo) + _modules+=(i18n terminfo) fi if [ "$use_systemd_in_initramfs" == 'yes' ]; then - _modules+=(systemd systemd-initrd dracut-systemd) + _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 "${_repo_dir}" "${_root_dir}/dracut" --recursive --force elif [[ "$cleanup" == 'yes' ]]; then - logging.info 'Removing distribution specific files.' + echo 'Removing distribution specific files.' cleanup else . "${_repo_dir}/builder/modules.d/dnbd3-rootfs/helper/build.inc" build_initialize_components - if [[ "$initialize" == 'yes' ]]; then - logging.info "Initialized." - exit 0 - fi - 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 + if [[ "$initialize" == 'yes' ]]; then + echo "Initialized." + exit 0 + fi + 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 -# region vim modline -# vim: set tabstop=4 shiftwidth=4 expandtab: -# vim: foldmethod=marker foldmarker=region,endregion: -# endregion +main "$@" |