summaryrefslogblamecommitdiffstats
path: root/build_initramfs.sh
blob: 99a4bb9ade779f173fd523c5781ec534c7891f74 (plain) (tree)














































































                                                                               
                                                                                       





























































































































                                                                             























                                                                             


























                                                                                    




                                                                      









                                            

                                                














                                                                 

                                                          








                                                                




                                              



                                                                              









                                                                         
 



               
















                                                                           
#!/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