summaryrefslogblamecommitdiffstats
path: root/builder/build-initramfs.sh
blob: bb8fe1c9ad4ac14274660c2ec604c431bcfa24dc (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
core.import change_root

# endregion

logging.set_commands_log_level debug
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)

##TODO dependencies to check
#xmount: fuse
#qemu-xmount: glib-2.0 pixman-1
#dracut: pkg-config

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

-p --file-path Target location for initramfs file
    (default: "$build_initramfs_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").

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

-s --use-systemd-in-initramfs Use Systemd as init process in initramfs
    (improved performance but less features)
    (default: "$build_initramfs_use_systemd_in_initramfs").

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'
                ;;
            -p|--file-path)
                shift
                build_initramfs_file_path="$1"
                if [[ "$build_initramfs_file_path" == '' ]]; then
                    logging.critical \
                        "This options needs a path to save initramfs image to."
                    return 1
                fi
                shift
                ;;
            -c|--cleanup)
                shift
                build_initramfs_cleanup='yes'
                ;;
            -s|--use-systemd-in-initramfs)
                shift
                build_initramfs_use_systemd_in_initramfs='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
    local plugin_path="$(dirname "${BASH_SOURCE[0]}")/dnbd3-rootfs/"
    source "${plugin_path}module-setup.sh"
    moddir="$(cd "$plugin_path" &>/dev/null && pwd)"
    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="$(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
        # NOTE: We would have to temporary patch dracut to avoid removing the
        # environment variables "LD_LIBRARY_PATH" and "LD_PRELOAD" to get
        # "fakechroot" working with dracut. So we should remove this variables
        # before running the patched dracut version to follow the initial
        # intention. You should first do:
        # >>> unset LD_LIBRARY_PATH
        # >>> unset LD_PRELOAD
        # and patch "dracut.sh" temporary to comment out:
        # >>> unset LD_LIBRARY_PATH
        # >>> unset LD_PRELOAD
        # 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"
    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 --force "$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 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"
    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_use_systemd_in_initramfs" == 'yes' ]; then
    build_initramfs__modules="$build_initramfs__modules systemd systemd-initrd dracut-systemd"
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
    "$(dirname "${BASH_SOURCE[0]}")/dracut/dracut.sh" --local \
        $build_initramfs__loglevel --modules "$build_initramfs__modules" \
        ${build_initramfs_dracut_parameter[*]} "$build_initramfs_file_path"
    exceptions.activate
fi
exceptions.deactivate

## endregion

# endregion

# region vim modline

# vim: set tabstop=4 shiftwidth=4 expandtab:
# vim: foldmethod=marker foldmarker=region,endregion:

# endregion