#!/usr/bin/env bash # -*- coding: utf-8 -*- # region header # Copyright Torben Sickert (t.sickert["~at~"]gmail.com) 29.10.2015 # Janosch Dobler (TODO) 29.10.2015 # 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 # 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. # - wget - The non-interactive network downloader. # - xz - Compress or decompress .xz and lzma files. # - tar - The GNU version of the tar archiving utility. # - 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. # Optional dependencies # --------------------- # TODO # TODO __NAME__='build_initramfs' # endregion function build_initramfs() { # Provides the main module scope. # region properties local _SCOPE='local' && \ if [[ $(echo "\"$@\"" | grep --extended-regexp \ '(^"| )(-l|--load-environment)("$| )') != '' ]] then local _SCOPE='export' fi # NOTE: Only initialize environment if current scope wasn't set yet. if [ "$_VERBOSE" == '' ]; then "$_SCOPE" _VERBOSE='no' "$_SCOPE" _LOAD_ENVIRONMENT='no' local dependencies=(bash cpio git test shift echo mktemp cat rm sed \ wget xz tar grep) "$_SCOPE" _DEPENDENCIES="${dependencies[*]}" "$_SCOPE" _KERNEL_MODULE_DIRECTORY="builder/dnbd3-qcow2-rootfs/kernel_modules/" "$_SCOPE" _STANDARD_OUTPUT=/dev/null "$_SCOPE" _ERROR_OUTPUT=/dev/null fi # endregion # region functions ## region command line interface function build_initramfs_print_usage_message() { # Prints a description about how to use this program. cat << EOF $__NAME__ This tool provides a generic way to install systemd based remote linux initramfs. EOF } function build_initramfs_print_usage_examples() { # Prints a description about how to use this program by providing # examples. cat << EOF # Start install progress: # >>> ./build_initramfs.sh EOF } function build_initramfs_print_command_line_option_description() { # Prints descriptions about each available command line option. 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"). -l --load-environment Simple load the install arch linux scope without doing anything else. EOF } function build_initramfs_print_help_message() { # Provides a help message for this module. echo -e "\nUsage: $0 [options]\n" archInstallPrintUsageMessage "$@" echo -e '\nExamples:\n' archInstallPrintUsageExamples "$@" echo -e '\nOption descriptions:\n' archInstallPrintCommandLineOptionDescription "$@" echo } function build_initramfs_command_line_interface() { # Provides the command line interface and interactive questions. while true; do case "$1" in -h|--help) shift build_initramfs_print_help_message "$0" exit 0 ;; -v|--verbose) shift _VERBOSE='yes' ;; -d|--debug) shift _STANDARD_OUTPUT=/dev/stdout _ERROR_OUTPUT=/dev/stderr ;; -l|--load-environment) shift _LOAD_ENVIRONMENT='yes' ;; '') shift break ;; *) build_initramfs_log 'critical' \ "Given argument: \"$1\" is not available." '\n' && \ if [[ "$_SCOPE" == 'local' ]]; then build_initramfs_print_help_message "$0" fi return 1 esac done if [[ "$UID" != '0' ]]; then archInstallLog 'critical' \ "You have to run this script as \"root\" not as \"${USER}\"." exit 2 fi return 0 } function build_initramfs_log() { # Handles logging messages. Returns non zero and exit on log level # error to support chaining the message into toolchain. # # Examples: # # >>> build_initramfs_log # info: test # >>> build_initramfs_log debug message # debug: message # >>> build_initramfs_log info message '\n' # # info: message local loggingType='info' && \ local message="$1" && \ if [ "$2" ]; then loggingType="$1" message="$2" fi if [ "$_VERBOSE" == 'yes' ] || [ "$loggingType" == 'error' ] || \ [ "$loggingType" == 'critical' ]; then if [ "$3" ]; then echo -e -n "$3" fi echo -e "${loggingType}: $message" fi if [ "$loggingType" == 'error' ]; then exit 1 fi return 0 } ## endregion ## region tools function build_initramfs_perform_dependency_check() { # This function check if all given dependencies are present. # # Examples: # # >>> archInstallPerformDependencyCheck "mkdir pacstrap mktemp" # ... local dependenciesToCheck="$1" && \ local result=0 && \ local dependency && \ for dependency in ${dependenciesToCheck[*]}; do if ! hash "$dependency" 1>"$_STANDARD_OUTPUT" 2>/dev/null; then archInstallLog 'critical' \ "Needed dependency \"$dependency\" isn't available." && \ result=1 fi done return $result } ## endregion function build_initramfs_initialize_dracut() { # Downloads and compiles dracut. # # Examples: # # >>> build_initramfs_initialize_dracut # ... mkdir dracut 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ build_initramfs_log 'Download and extract dracut.' && \ curl --location \ https://www.kernel.org/pub/linux/utils/boot/dracut/dracut-043.tar.gz | \ tar --extract --gzip --directory dracut --strip-components 1 \ 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ cd dracut 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ # NOTE: On virtualbox shared folder symlinks are not allowed. # make the dracut-install binary (dracut-install resolves dependencies etc.) build_initramfs_log 'Compile dracut.' && \ make install/dracut-install 1>"$_STANDARD_OUTPUT" \ 2>"$_ERROR_OUTPUT" && \ # NOTE: We have to copy the binary to current instead of symlinking # them since this feature isn't supported in shared virtual box # machine folders. If symlinks would be available we could simply # use: # >>> make dracut-install cp install/dracut-install dracut-install 1>"$_STANDARD_OUTPUT" \ 2>"$_ERROR_OUTPUT" && \ cd - 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" build_initramfs_log \ 'Copy dnbd3 qcow2 plugin into dracut modules folder.' && \ cp --recursive builder/dnbd3-qcow2-rootfs/ \ dracut/modules.d/90dndb3-qcow2-rootfs \ 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" return $? } function build_initramfs_compile_nbd() { # Downloads and compiles nbd. # # Examples: # # >>> build_initramfs_compile_nbd # ... # Provides the following file: # ${_KERNEL_MODULE_DIRECTORY}/nbd/nbd.ko cd "${_KERNEL_MODULE_DIRECTORY}/nbd" \ 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ build_initramfs_log 'Compile the nbd kernel module.' && \ make 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ cd - 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ return $? # TODO make clean } function build_initramfs_compile_dnbd3() { # Downloads and compiles dnbd3. # # Examples: # # >>> build_initramfs_compile_dnbd3 # ... # Provides the following file: # ${_KERNEL_MODULE_DIRECTORY}/dnbd3/build/dnbd3.ko cd $_KERNEL_MODULE_DIRECTORY \ 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ git clone git://git.openslx.org/dnbd3.git \ 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ cd dnbd3 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ ./build.sh 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ return $? # TODO rm -rf build } # endregion # region controller if [[ "$0" == *"${__NAME__}.bash" ]]; then build_initramfs_perform_dependency_check "${_DEPENDENCIES[*]}" || \ build_initramfs_log 'error' 'Satisfying main dependencies failed.' build_initramfs_command_line_interface "$@" || return $? build_initramfs_log 'Checking dracut.' if ! [[ -d ./dracut ]]; then build_initramfs_initialize_dracut && \ build_initramfs_compile_nbd && \ build_initramfs_compile_dnbd3 && \ # TODO add dnbd3-qcow2-rootfs to modules.d build_initramfs_log 'Build initramfs.' && \ ./dracut.sh --local --verbose --force 1>"$_STANDARD_OUTPUT" \ 2>"$_ERROR_OUTPUT" fi fi return 0 # endregion } # region footer if [[ "$0" == *"${__NAME__}.bash" || $(echo "$@" | grep --extended-regexp \ '(^| )(-l|--load-environment)($| )') ]]; then "$__NAME__" "$@" fi # endregion # region vim modline # vim: set tabstop=4 shiftwidth=4 expandtab: # vim: foldmethod=marker foldmarker=region,endregion: # endregion