From f2adf46ed4edf89ab0e3e278acdca7754a6df406 Mon Sep 17 00:00:00 2001 From: torben Date: Thu, 4 Feb 2016 18:36:42 +0100 Subject: Adding high level (optional) dependency, package, and shared library checker. --- builder/build-initramfs.sh | 325 +++++++++++++++++++++++++-------------------- 1 file changed, 182 insertions(+), 143 deletions(-) (limited to 'builder/build-initramfs.sh') diff --git a/builder/build-initramfs.sh b/builder/build-initramfs.sh index 2cbb210d..550034c8 100755 --- a/builder/build-initramfs.sh +++ b/builder/build-initramfs.sh @@ -23,53 +23,26 @@ # Note that you only get very necessary output until you provide "--verbose" as # commandline options. -# Dependencies -# ------------ - -# - bash (or any bash like shell) -# - cpio - Copies files into or out of a cpio or tar archive. The -# archive can be another file on the disk, a magnetic tape, -# or a pipe. -# - git - The stupid content tracker. -# - test - Check file types and compare values (part of the shell). -# - shift - Shifts the command line arguments (part of the shell). -# - echo - Display a line of text (part of coreutils). -# - mktemp - Create a temporary file or directory (part of coreutils). -# - cat - Concatenate files and print on the standard output (part of -# coreutils). -# - rm - Remove files or directories (part of coreutils). -# - sed - Stream editor for filtering and transforming text. -# - gzip - Compress or expand files. -# - curl - Transfer a URL -# - tar - The GNU version of the tar archiving utility. -# - make - GNU make utility to maintain groups of programs. -# - cmake - The "cmake" executable is the CMake command-line interface. -# - linux-headers - GNU make utility to maintain groups of programs. -# - grep - Searches the named input files (or standard input if no -# files are named, or if a single hyphen-minus (-) is given -# as file name) for lines containing a match to the given -# PATTERN. By default, grep prints the matching lines. - ## region ensure presence of needed dependencies set -o errexit -build_initramfs__needed_location="$(dirname "${BASH_SOURCE[0]}")/dnbd3-rootfs" -if ! [[ -d "$build_initramfs__needed_location" ]]; then +_needed_location="$(dirname "${BASH_SOURCE[0]}")/dnbd3-rootfs" +if ! [[ -d "$_needed_location" ]]; then echo "The dnbd3 dracut plugin isn't available, loading it." if ! utils.dependency_check git; then echo "Needed dependency \"git\" isn't available. Please install \"git\" or provide the repositories data structure in \"$(dirname "${BASH_SOURCE[0]}")\"." fi - build_initramfs__temporary_repository_location="$(mktemp --directory)" + _temporary_repository_location="$(mktemp --directory)" git clone git://git.openslx.org/openslx-ng/systemd-init.git \ - "$build_initramfs__temporary_repository_location" - pushd "$build_initramfs__temporary_repository_location" + "$_temporary_repository_location" + pushd "$_temporary_repository_location" git submodule init git submodule update popd cp --recursive \ - "${build_initramfs__temporary_repository_location}/builder/dnbd3-rootfs" \ - "$build_initramfs__needed_location" - rm --recursive --force "$build_initramfs__temporary_repository_location" + "${_temporary_repository_location}/builder/dnbd3-rootfs" \ + "$_needed_location" + rm --recursive --force "$_temporary_repository_location" fi set +o errexit @@ -89,17 +62,35 @@ logging.set_log_level critical # region properties -build_initramfs_file_path='/boot/initramfs.img' -build_initramfs_dracut_parameter='--force --no-hostonly' -build_initramfs_verbose='no' -build_initramfs_debug='no' -build_initramfs_target='' -build_initramfs_create_system_image='' -build_initramfs_cleanup='no' -build_initramfs_use_systemd_in_initramfs='no' -build_initramfs_dependencies=(cpio git test shift mktemp cat rm sed gzip curl \ - tar grep make gcc cmake readlink dirname dmsetup chroot pkg-config) -build_initramfs_dependencies_pkgconfig=(fuse glib-2.0 pixman-1) +file_path='/boot/initramfs.img' +dracut_parameter='--force --no-hostonly' +verbose='no' +debug='no' +target='' +create_system_image='' +cleanup='no' +use_systemd_in_initramfs='no' +declare -A dependencies=( + [cpio]='pack initramfs' \ + [shift]='parse command line' \ + [mktemp]=create save temporary files and dictionaries \ + [cat]='print messages' \ + [rm]='remove (temporary) files' \ + [sed]='process strings' \ + [readlink]="connect dracut module with dracut's module system" \ + [dirname]='core logic' \ + [dmsetup]='create a (temporary) writable layer during boot' \ + [pkg-config]='determine if alle needed libraries are present' \ + [grep]='retrieve right boot partition during boot') +declare -A optional_dependencies=( + ['git gzip curl tar']='dynamically retrieve and unpack missing application which will be compiled for current or given kernel' \ + ['make gcc cmake']='dynamically compile needed resources against current or given kernel' \ + [chroot]='build against a distribution other than this program runs in') +declare -A shared_library_pattern_dependencies=() +declare -A optional_shared_library_pattern_dependencies=() +declare -A package_dependencies=() +declare -A optional_package_dependencies=( + ['fuse glib-2.0 pixman-1']='support template systems in container (usually used by virtual runtime environments)') # endregion @@ -107,83 +98,83 @@ build_initramfs_dependencies_pkgconfig=(fuse glib-2.0 pixman-1) ## region command line interface -function build_initramfs_print_usage_message() { +function print_usage_message() { # Prints a description about how to use this program. logging.cat << EOF This program provides a generic way to install systemd based remote linux initramfs. EOF } -function build_initramfs_print_usage_examples() { +function print_usage_examples() { # Prints a description about how to use this program by providing examples. logging.cat << EOF Start install progress: >>> ./build_initramfs.sh EOF } -function build_initramfs_print_command_line_option_description() { +function print_command_line_option_description() { # Prints descriptions about each available command line option. logging.cat << EOF -h --help Shows this help message. --v --verbose Tells you what is going on (default: "$build_initramfs_verbose"). +-v --verbose Tells you what is going on (default: "$verbose"). -d --debug Gives you any output from all tools which are used - (default: "$build_initramfs_debug"). + (default: "$debug"). -p --file-path Target location for initramfs file - (default: "$build_initramfs_file_path"). + (default: "$file_path"). -c --cleanup Removes all distribution specific compiled files. -i --create-system-image Creates an image under given path from current system. - (default: "$build_initramfs_create_system_image"). + (default: "$create_system_image"). -t --target Creates an image against given target template filesystem. If not explicitly speicifed current system will be used as template system - (default: "$build_initramfs_target"). + (default: "$target"). -s --use-systemd-in-initramfs Use Systemd as init process in initramfs (improved performance but less features) - (default: "$build_initramfs_use_systemd_in_initramfs"). + (default: "$use_systemd_in_initramfs"). Additional dracut parameter and normal parameter can be added by delimiting -them via a single dash (-) (default: "$build_initramfs_dracut_parameter" with +them via a single dash (-) (default: "$dracut_parameter" with "--modules" and dynamically determined modules. Additional custom modules are concated.). EOF } -function build_initramfs_print_help_message() { +function print_help_message() { # Provides a help message for this module. logging.plain "\nUsage: $0 [options]\n" - build_initramfs_print_usage_message "$@" + print_usage_message "$@" logging.plain '\nExamples:\n' - build_initramfs_print_usage_examples "$@" + print_usage_examples "$@" logging.plain -e '\nOption descriptions:\n' - build_initramfs_print_command_line_option_description "$@" + print_command_line_option_description "$@" logging.plain } -function build_initramfs_parse_command_line() { +function parse_command_line() { # Provides the command line interface and interactive questions. while true; do case "$1" in -h|--help) shift - build_initramfs_print_help_message "$0" + print_help_message "$0" exit 0 ;; -v|--verbose) shift - build_initramfs_verbose='yes' + verbose='yes' ;; -d|--debug) shift - build_initramfs_debug='yes' + debug='yes' ;; -p|--file-path) shift - build_initramfs_file_path="$1" - if [[ "$build_initramfs_file_path" == '' ]]; then + file_path="$1" + if [[ "$file_path" == '' ]]; then logging.critical \ "This options needs a path to save initramfs image to." return 1 @@ -192,16 +183,16 @@ function build_initramfs_parse_command_line() { ;; -c|--cleanup) shift - build_initramfs_cleanup='yes' + cleanup='yes' ;; -s|--use-systemd-in-initramfs) shift - build_initramfs_use_systemd_in_initramfs='yes' + use_systemd_in_initramfs='yes' ;; -i|--create-system-image) shift - build_initramfs_create_system_image="$1" - if [[ "$build_initramfs_create_system_image" == '' ]]; then + create_system_image="$1" + if [[ "$create_system_image" == '' ]]; then logging.critical \ "This options needs a path to save image to." return 1 @@ -210,9 +201,10 @@ function build_initramfs_parse_command_line() { ;; -t|--target) shift - build_initramfs_target="$1" - if [[ "$build_initramfs_target" == '' ]]; then - logging.critical "This options needs a path create initramfs from." + target="$1" + if [[ "$target" == '' ]]; then + logging.critical \ + "This options needs a path create initramfs from." return 1 fi shift @@ -220,7 +212,7 @@ function build_initramfs_parse_command_line() { -) shift while [[ "$1" =~ ^.+$ ]]; do - build_initramfs_dracut_parameter+=" $1" + dracut_parameter+=" $1" shift done shift @@ -234,11 +226,11 @@ function build_initramfs_parse_command_line() { return 1 esac done - if [ "$build_initramfs_verbose" == 'yes' ]; then + if [ "$verbose" == 'yes' ]; then logging.set_commands_log_level debug logging.set_log_level info fi - if [ "$build_initramfs_debug" == 'yes' ]; then + if [ "$debug" == 'yes' ]; then logging.set_commands_log_level debug logging.set_log_level debug fi @@ -255,12 +247,12 @@ function build_initramfs_parse_command_line() { ## region helper -function build_initramfs_initialize_dracut() { +function initialize_dracut() { # Downloads and compiles dracut. # # Examples: # - # >>> build_initramfs_initialize_dracut + # >>> initialize_dracut # ... mkdir --parents "$(dirname "${BASH_SOURCE[0]}")/dracut" logging.info 'Download and extract dracut.' @@ -283,12 +275,12 @@ function build_initramfs_initialize_dracut() { popd return $? } -function build_initramfs_cleanup() { +function cleanup() { # Removes distribution specific generated files. # # Examples: # - # >>> build_initramfs_cleanup + # >>> cleanup local plugin_path="$(dirname "${BASH_SOURCE[0]}")/dnbd3-rootfs/" source "${plugin_path}module-setup.sh" moddir="$(cd "$plugin_path" &>/dev/null && pwd)" @@ -302,10 +294,33 @@ function build_initramfs_cleanup() { # region controller -## region dependency checks +## region core dependency checks + +for dependency_group in "${!dependencies[@]}"; do + _result="$(utils.dependency_check $dependency_group || true)" + if [[ "$_result" != '' ]]; then + while read dependency; do + logging.critical "Missing core dependency \"$dependency\" needed for ${dependencies[$dependency_group]}." + done <<< $_result + fi +done +for dependency_group in "${!shared_library_pattern_dependencies[@]}"; do + _result="$(utils.dependency_check_shared_library $dependency_group || true)" + if [[ "$_result" != '' ]]; then + while read dependency; do + logging.critical "Missing core shared library dependency \"$dependency\" needed for ${shared_library_pattern_dependencies[$dependency_group]}." + done <<< $_result + fi +done +for dependency_group in "${!package_dependencies[@]}"; do + _result="$(utils.dependency_check_pkgconfig $dependency_group || true)" + if [[ "$_result" != '' ]]; then + while read dependency; do + logging.critical "Missing core package dependency \"$dependency\" needed for ${package_dependencies[$dependency_group]}." + done <<< $_result + fi +done -utils.dependency_check ${build_initramfs_dependencies[*]} -utils_dependency_check_pkgconfig ${build_initramfs_dependencies_pkgconfig[*]} # TODO check for existing kernel headers. # Find lib locations: $(gcc -print-prog-name=cc1plus) -v if ! ldconfig --print-cache | grep libz.so; then @@ -315,42 +330,69 @@ fi ## endregion -if ! build_initramfs_parse_command_line "$@"; then - build_initramfs_print_help_message "$0" +if ! parse_command_line "$@"; then + print_help_message "$0" exit 1 fi +## region optional dependency checks + +for dependency_group in "${!optional_dependencies[@]}"; do + _result="$(utils.dependency_check $dependency_group || true)" + if [[ "$_result" != '' ]]; then + while read dependency; do + logging.warn "Missing optional dependency \"$dependency\" needed for ${optional_dependencies[$dependency_group]}." + done <<< $_result + fi +done +for dependency_group in "${!optional_shared_library_pattern_dependencies[@]}"; do + _result="$(utils.dependency_check_shared_library $dependency_group || true)" + if [[ "$_result" != '' ]]; then + while read dependency; do + logging.critical "Missing optional shared library dependency \"$dependency\" needed for ${optional_shared_library_pattern_dependencies[$dependency_group]}." + done <<< $_result + fi +done +for dependency_group in "${!optional_package_dependencies[@]}"; do + _result="$(utils.dependency_check_pkgconfig $dependency_group || true)" + if [[ "$_result" != '' ]]; then + while read dependency; do + logging.critical "Missing optional package dependency \"$dependency\" needed for ${optional_package_dependencies[$dependency_group]}." + done <<< $_result + fi +done + +## endregion + ## region handle delegated operations to specified target -if [[ "$build_initramfs_target" != '' ]]; then - build_initramfs__target="$build_initramfs_target" - if [[ -f "$build_initramfs_target" ]]; then - build_initramfs__target="$(mktemp --directory)" - build_initramfs__xmount_mountpoint_target="$(mktemp --directory)" - xmount --in qemu "$build_initramfs_target" --out raw \ - "$build_initramfs__xmount_mountpoint_target" - build_initramfs__xmount_device_target="$(losetup --find)" - losetup "$build_initramfs__xmount_device_target" loopdev \ - "${build_initramfs__xmount_mountpoint_target}/"*.dd - mount "$build_initramfs__xmount_device_target" \ - "$build_initramfs__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 "$_xmount_device_target" loopdev \ + "${_xmount_mountpoint_target}/"*.dd + mount "$_xmount_device_target" \ + "$_target" fi - if [[ -d "$build_initramfs__target" ]]; then - build_initramfs__temporary_working_directory="$(chroot \ - "$build_initramfs__target" mktemp --directory)" - mount --bind "$(pwd)" \ - "${build_initramfs__target}${build_initramfs__temporary_working_directory}" - build_initramfs__parameter_skip=false - build_initramfs__parameter_to_forward=() - for build_initramfs__parameter; do - if $build_initramfs__parameter_skip; then - build_initramfs__parameter_skip=false - elif [[ "$build_initramfs__parameter" == '-t' ]] || \ - [[ "$build_initramfs__parameter" == '--target' ]] + 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 - build_initramfs__parameter_skip=true + _parameter_skip=true else - build_initramfs__parameter_to_forward+=("$build_initramfs__parameter") + _parameter_to_forward+=("$_parameter") fi done # NOTE: We would have to temporary patch dracut to avoid removing the @@ -366,11 +408,10 @@ if [[ "$build_initramfs_target" != '' ]]; then # To avoid to broke the "fakechroot" environment pipe the ldconfig call # to the native one: # >>> FAKECHROOT_CMD_SUBST=/usr/bin/ldconfig=/usr/bin/ldconfig - change_root "${build_initramfs__target}" \ - "${build_initramfs__temporary_working_directory}/${BASH_SOURCE[0]}" \ - ${build_initramfs__parameter_to_forward[*]} - mv "${build_initramfs__target}/$build_initramfs_file_path" \ - "$build_initramfs_file_path" + change_root "${_target}" \ + "${_temporary_working_directory}/${BASH_SOURCE[0]}" \ + ${_parameter_to_forward[*]} + mv "${_target}/$file_path" "$file_path" fi exit 0 fi @@ -382,24 +423,23 @@ fi logging.info 'Checking dracut.' if ! [[ -f "$(dirname "${BASH_SOURCE[0]}")/dracut/dracut-install" ]]; then logging.info "Dracut isn't available yet loading it." - build_initramfs_initialize_dracut + initialize_dracut fi -build_initramfs__dracut_modules_source='../../dnbd3-rootfs' -build_initramfs__dracut_modules_target="$(dirname "${BASH_SOURCE[0]}")/dracut/modules.d/90dnbd3-rootfs" -if [[ ! -L "$build_initramfs__dracut_modules_target" || "$(readlink \ - "$build_initramfs__dracut_modules_target")" != \ - "$build_initramfs__dracut_modules_source" ]] +_dracut_modules_source='../../dnbd3-rootfs' +_dracut_modules_target="$(dirname "${BASH_SOURCE[0]}")/dracut/modules.d/90dnbd3-rootfs" +if [[ ! -L "$_dracut_modules_target" || "$(readlink \ + "$_dracut_modules_target")" != "$_dracut_modules_source" ]] then logging.info \ - "Link dnbd3 plugin into dracut modules folder ($build_initramfs__dracut_modules_source -> $build_initramfs__dracut_modules_target)." - if ! ln --symbolic --force "$build_initramfs__dracut_modules_source" \ - "$build_initramfs__dracut_modules_target" 2>/dev/null; then + "Link dnbd3 plugin into dracut modules folder ($_dracut_modules_source -> $_dracut_modules_target)." + if ! ln --symbolic --force "$_dracut_modules_source" \ + "$_dracut_modules_target" 2>/dev/null; then logging.warn \ - "Link \"$build_initramfs__dracut_modules_source\" to \"$build_initramfs__dracut_modules_target\" fails. We will copy them. So we have to recopy it every time to ensure that recompiled things take effect." + "Link \"$_dracut_modules_source\" to \"$_dracut_modules_target\" fails. 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 \ - "$(dirname "${BASH_SOURCE[0]}")/$(basename "$build_initramfs__dracut_modules_source")" \ - "$build_initramfs__dracut_modules_target" + "$(dirname "${BASH_SOURCE[0]}")/$(basename "$_dracut_modules_source")" \ + "$_dracut_modules_target" fi fi @@ -407,32 +447,31 @@ fi ## region prepare and perform final dracut call -build_initramfs__loglevel='' -if [ "$build_initramfs_verbose" == 'yes' ]; then - build_initramfs__loglevel='--verbose' +_loglevel='' +if [ "$verbose" == 'yes' ]; then + _loglevel='--verbose' fi -build_initramfs__modules='dnbd3-rootfs' -if [ "$build_initramfs_debug" == 'yes' ]; then - build_initramfs__loglevel="$build_initramfs__loglevel --stdlog 4" - build_initramfs__modules="$build_initramfs__modules i18n terminfo" +_modules='dnbd3-rootfs' +if [ "$debug" == 'yes' ]; then + _loglevel="$_loglevel --stdlog 4" + _modules="$_modules i18n terminfo" fi -if [ "$build_initramfs_use_systemd_in_initramfs" == 'yes' ]; then - build_initramfs__modules="$build_initramfs__modules systemd systemd-initrd dracut-systemd" +if [ "$use_systemd_in_initramfs" == 'yes' ]; then + _modules="$_modules systemd systemd-initrd dracut-systemd" fi -if [[ "$build_initramfs_create_system_image" != '' ]]; then +if [[ "$create_system_image" != '' ]]; then logging.info 'Create system image.' - build_initramfs_create_qcow2_system "$build_initramfs_create_system_image" -elif [[ "$build_initramfs_cleanup" == 'yes' ]]; then + create_qcow2_system "$create_system_image" +elif [[ "$cleanup" == 'yes' ]]; then logging.info 'Removing distribution specific files.' - build_initramfs_cleanup + cleanup 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 "$(dirname "${BASH_SOURCE[0]}")/dracut/dracut.sh" --local \ - $build_initramfs__loglevel --modules "$build_initramfs__modules" \ - ${build_initramfs_dracut_parameter[*]} "$build_initramfs_file_path" + $_loglevel --modules "$_modules" ${dracut_parameter[*]} "$file_path" exceptions.activate fi exceptions.deactivate -- cgit v1.2.3-55-g7522