summaryrefslogblamecommitdiffstats
path: root/builder/build-initramfs.sh
blob: 4791ac39a96e4ffe32cfd73fc184363d2f1c2de1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                       
               
 
                                                                  



                                            


                                                                         















                                                                               





















                                                                               
 
                                                
              
                                                                              

                                                               



                                                                                                                                                                  






                                                                          
                                                                                             



                                                                            
            
 
                                                                           
                      
                   

                   
           


                                    
 
                   
                                                        

                            
                         

                                      


                                                                               
           
                  
                                



                                                                         
          
   



                                                                               

                        
   




                                                                   
 
                                                                              
 

                                                             
 


                                                                               
                                                      
 



                                                                             

                                                                               
   










                                                              
                                               









                                                                    
                                             



                                           
                  




                                             

                                                        



                                                                                  

                     








                                                                                       







                                                           

               


                     
                                                                           


                        








                                                    



                                                                         

            
 
 
            
                






                                              
                                                           


                                                                                


                                                                    



                                                                   
                               



                                                                               

                                                                       








                                                      
             
                          








                                                                



                                                                        
         
             
 
            
           
                   
                           
                                                           
                                         
                                                        



                                                                                                                                       
            



                                                  








                                                                      
                                                                  
                                                                             

                                                                                       












                                                                                      


                                                                           


                                                                                 




                                                                 
                               
                                                                          


                                                         
 
                                                           
                                                                                                       


                                                                     
    

                                                                                                                                            







                                                                                                                                                                                                             
  

                                               






                                                                     
                                                                      
  

                                                           





                                                                              


                                                                             
                                                          


                                                                          
                       
  
                     
            
           
                    

                                                     
           
#!/usr/bin/env bash
# -*- coding: utf-8 -*-

# region header

# Copyright Torben Sickert (info["~at~"]torben.website) 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.
# - 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
    echo "The dnbd3 dracut plugin isn't available, loading it."
    if ! hash git 2>/dev/null; then
        echo "Needed dependency \"git\" isn't available. Please install \"git\" or provide the repositories data structure in \"$(dirname "${BASH_SOURCE[0]}")\"."
        result=1
    fi
    build_initramfs__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"
    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"
fi
set +o errexit
## endregion

source "$(dirname "${BASH_SOURCE[0]}")/dnbd3-rootfs/scripts/rebash/core.sh"
core.import exceptions
exceptions.activate
core.import logging
core.import utils
# endregion

logging.set_commands_log_level debug
logging.set_log_level critical

# region properties
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_dependencies=(cpio git test shift mktemp cat rm sed gzip curl \
    tar grep make gcc cmake readlink dirname dmsetup fakeroot fakechroot \
    chroot qemu-nbd)
# endregion
# region functions
## region command line interface
function build_initramfs_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() {
    # 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() {
    # 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").

-d --debug Gives you any output from all tools which are used
    (default: "$build_initramfs_debug").

-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").

-t --target Creates an image against given target template filesystem. If not
    explicitly speicifed current system will be used as template system
    (default).

Additional dracut parameter and normal parameter can be deleimiter via a single
dash (-) (default: "$build_initramfs_dracut_parameter").
EOF
}
function build_initramfs_print_help_message() {
    # Provides a help message for this module.
    logging.plain "\nUsage: $0 [options]\n"
    build_initramfs_print_usage_message "$@"
    logging.plain '\nExamples:\n'
    build_initramfs_print_usage_examples "$@"
    logging.plain -e '\nOption descriptions:\n'
    build_initramfs_print_command_line_option_description "$@"
    logging.plain
}
function build_initramfs_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"
                exit 0
                ;;
            -v|--verbose)
                shift
                build_initramfs_verbose='yes'
                ;;
            -d|--debug)
                shift
                build_initramfs_debug='yes'
                ;;
            -c|--cleanup)
                shift
                build_initramfs_cleanup='yes'
                ;;
            -i|--create-system-image)
                shift
                build_initramfs_create_system_image="$1"
                if [[ "$build_initramfs_create_system_image" == '' ]]; then
                    logging.critical "This options needs a path to save image to."
                    return 1
                fi
                shift
                ;;
            -t|--target)
                shift
                build_initramfs_target="$1"
                if [[ "$build_initramfs_target" == '' ]]; then
                    logging.critical "This options needs a path create initramfs from."
                    return 1
                fi
                shift
                ;;
            -)
                shift
                while [[ "$1" =~ ^.+$ ]]; do
                    build_initramfs_dracut_parameter+=" $1"
                    shift
                done
                shift
                ;;

            '')
                break
                ;;
            *)
                logging.critical "Given argument: \"$1\" is not available."
                return 1
        esac
    done
    if [ "$build_initramfs_verbose" == 'yes' ]; then
        logging.set_commands_log_level debug
        logging.set_log_level info
    fi
    if [ "$build_initramfs_debug" == 'yes' ]; then
        logging.set_commands_log_level debug
        logging.set_log_level debug
    fi

    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
function build_initramfs_initialize_dracut() {
    # Downloads and compiles dracut.
    #
    # Examples:
    #
    # >>> build_initramfs_initialize_dracut
    # ...
    mkdir --parents "$(dirname "${BASH_SOURCE[0]}")/dracut"
    logging.info 'Download and extract dracut.'
    curl --location \
        https://www.kernel.org/pub/linux/utils/boot/dracut/dracut-043.tar.gz | \
        tar --extract --gzip --directory \
        "$(dirname "${BASH_SOURCE[0]}")/dracut" --strip-components 1
    pushd "$(dirname "${BASH_SOURCE[0]}")/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.'
    make install/dracut-install
    # 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 "$(dirname "${BASH_SOURCE[0]}")/dracut/install/dracut-install" \
        "$(dirname "${BASH_SOURCE[0]}")/dracut/dracut-install"
    popd
    return $?
}
function build_initramfs_create_qcow2_system() {
    # Packs current distribution in a qcow2 container.
    #
    # Examples:
    #
    # >>> build_initramfs_create_qcow2_system
    echo TODO
    # dmsetup snapshot ...
    #qemu-img create -f qcow2 "${CONTAINER_PATH}" "${QCOW_SIZE}"
    return $?
}
function build_initramfs_cleanup() {
    # Removes distribution specific generated files.
    #
    # Examples:
    #
    # >>> build_initramfs_cleanup
    source "$(dirname "${BASH_SOURCE[0]}")/dnbd3-rootfs/module-setup.sh"
    moddir="$(dirname "${BASH_SOURCE[0]}")$(dirname "$(readlink \
        --canonicalize "$(dirname \
        "${BASH_SOURCE[0]}")dnbd3-rootfs/module-setup.sh")")"
    clean
    return $?
}
## endregion
# endregion
# region controller
## region dependency checks
utils.dependency_check "${build_initramfs_dependencies[*]}"
# TODO check for existing kernel headers.
# Find lib locations: $(gcc -print-prog-name=cc1plus) -v
if ! ldconfig --print-cache | grep libz.so; then
    logging.critical "You have to install the compression library \"libz\". Otherwise we aren't able to compile dnbd3 for your kernel."
    exit 1
fi
## endregion
if ! build_initramfs_parse_command_line "$@"; then
    build_initramfs_print_help_message "$0"
    exit 1
fi
## 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)"
        # TODO
        #qemu-nbd "$build_initramfs_target" "$build_initramfs__target"
    fi
    if [[ -d "$build_initramfs__target" ]]; then
        build_initramfs__temporary_working_directory="$(fakeroot \
            fakechroot 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' ]]
            then
                build_initramfs__parameter_skip=true
            else
                build_initramfs__parameter_to_forward+=("$build_initramfs__parameter")
            fi
        done
        # TODO check FAKECHROOT_CMD_SUBST
        FAKECHROOT_CMD_SUBST=/usr/bin/ldconfig=/usr/bin/ldconfig fakeroot \
            fakechroot chroot "${build_initramfs__target}" \
            "${build_initramfs__temporary_working_directory}/${BASH_SOURCE[0]}" \
            ${build_initramfs__parameter_to_forward[*]}
        # TODO grap result from /boot/initramfs-test.img
    fi
    exit 0
fi
## endregion
## region handle dependencies which can be resolved automatically
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
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" ]]
then
    logging.info \
        "Link dnbd3 plugin into dracut modules folder ($build_initramfs__dracut_modules_source -> $build_initramfs__dracut_modules_target)."
    if ! ln --symbolic "$build_initramfs__dracut_modules_source" \
    "$build_initramfs__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 you have to recopy it if you recompile things in specified source."
        cp --recursive --force --no-target-directory \
            "$(dirname "${BASH_SOURCE[0]}")/$(basename "$build_initramfs__dracut_modules_source")" \
            "$build_initramfs__dracut_modules_target"
    fi
fi
## endregion
## region prepare and perform final dracut call
build_initramfs__loglevel=''
if [ "$build_initramfs_verbose" == 'yes' ]; then
    build_initramfs__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"
fi
if [[ "$build_initramfs_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
    logging.info 'Removing distribution specific files.'
    build_initramfs_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
    echo "$(dirname "${BASH_SOURCE[0]}")/dracut/dracut.sh"
    "$(dirname "${BASH_SOURCE[0]}")/dracut/dracut.sh" --local \
        $build_initramfs__loglevel --modules "$build_initramfs__modules" \
        ${build_initramfs_dracut_parameter[*]} /boot/initramfs-test.img
    exceptions.activate
fi
exceptions.deactivate
## endregion
# endregion
# region vim modline
# vim: set tabstop=4 shiftwidth=4 expandtab:
# vim: foldmethod=marker foldmarker=region,endregion:
# endregion