blob: f910e579c6d5ac3f02d2941664000586fccd4648 (
plain) (
tree)
|
|
#!/usr/bin/env bash
# -*- coding: utf-8 -*-
# region header
# Copyright Torben Sickert (info["~at~"]torben.website) 29.10.2015
# Janosch Dobler (info["~at~"]jandob.com) 29.10.2015
# Jonathan Bauer (jonathan.bauer@rz.uni-freiburg.de) 19.09.2019
# Thiago Abdo (tjabdo@inf.ufpr.br) 06.11.2019
# 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
## endregion
# Afaik the idea here was to have the root dir where build-initramfs.sh
# is called from and the repo dir where the systemd-init.git is cloned to:
# <root_dir>
# |- build-initramfs.sh
# |- dracut
# |- systemd-init
declare -rg _root_dir="$(readlink -f $(dirname ${BASH_SOURCE[0]}))"
# TODO clean these up
file_path='/boot/initramfs.img'
dracut_parameter=(--force --no-hostonly)
verbose='no'
debug='no'
target=''
cleanup='no'
full_cleanup='no'
use_systemd_in_initramfs='no'
declare -rg _bootstrap_modules="bootstrap.conf"
bootstrap() {
if [ ! -f "$_bootstrap_modules" ]; then
echo "Missing modules definition file: $_bootstrap_modules"
print_help_message 1
exit 1
fi
. "$_bootstrap_modules"
if [[ ! -v core_dracut[@] ]] || [[ ! -v core_repo[@] ]]; then
echo "Missing core modules for dracut & systemd-init"
exit 1
fi
declare -rg _repo_dir="$(readlink -f ${core_repo[path]})"
declare -rg _dracut_dir="$(readlink -f ${core_dracut[path]})"
echo "Modules file: $_bootstrap_modules"
echo "Core modules: ${!core_*}"
echo "Modules: ${!module_*}"
echo ""
for module in "${!core_@}" "${!module_@}"; do
declare -n _ref="$module"
if [ -n "$(ls -A "${_ref[path]}" 2> /dev/null)" ]; then
echo "'${_ref[path]}' not empty, skipping..."
continue
fi
echo "######################### $module #########################"
echo "Handler: ${_ref[handler]}"
echo " URL: ${_ref[url]}"
echo " Branch: ${_ref[branch]}"
echo " Commit: ${_ref[commit]}"
echo " Path: ${_ref[path]}"
handler_${_ref[handler]} \
"${_ref[path]}" \
"${_ref[url]}" \
"${_ref[branch]}" \
"${_ref[commit]}"
# apply patches if any are required
shopt -s nullglob
pushd "${_ref[path]}"
for patch in "${_repo_dir}/patches/${_ref[path]##*/}/"*.patch; do
patch -p1 < "$patch"
done
popd
done
}
handler_git() {
local path="$1"
local url="$2"
local branch="$3"
local commit="$4"
mkdir -p "$path"
local gitargs=( \
"--depth" "1" \
"--single-branch" \
)
if [ -n "$branch" ]; then
gitargs+=("--branch" "$branch")
fi
if ! git clone "${gitargs[@]}" "$url" "$path"; then
echo "Error cloning '$url' to '$path'."
exit 1
fi
[ -z "$commit" ] && return 0
# make sure given commit in in the fetched history
local revision="$branch"
if [ -n "$commit" ]; then
revision="$commit"
fi
# manual "shallow clone" since not all server allow it...
pushd "$path"
local i=50
while ! git rev-parse --quiet --verify $revision^{commit}; do
git fetch --depth=$(( i+=50 ))
done
git reset --hard "$revision"
popd
}
handler_http() {
local path="$1"
local url="$2"
mkdir --parents "$path"
curl \
--location \
--max-redirs 5 \
--max-time 7 \
--connect-timeout 2 \
--retry 3 \
--retry-max-time 12 \
"$url" \
| tar \
--extract \
--gzip \
--directory "$path" \
--strip-components 1
}
print_help_message() {
echo "TODO"
}
parse_command_line() {
while true; do
case "$1" in
-h|--help)
shift
print_help_message "$0"
exit 0
;;
-v|--verbose)
shift
verbose='yes'
;;
-d|--debug)
shift
debug='yes'
;;
-p|--file-path)
local given_argument="$1"
shift
file_path="$1"
if [[ "$file_path" == '' ]]; then
echo \
"Error with given option \"$given_argument\":" \
"This option needs a path to save initramfs image to."
return 1
fi
shift
;;
-c|--cleanup)
shift
cleanup='yes'
;;
-f|--full-cleanup)
shift
full_cleanup='yes'
;;
-s|--use-systemd-in-initramfs)
shift
use_systemd_in_initramfs='yes'
;;
-t|--target)
local given_argument="$1"
shift
target="$1"
if [[ "$target" == '' ]]; then
echo \
"Error with given option \"$given_argument\":" \
"This option needs a path create initramfs from."
return 1
fi
shift
;;
-i|--init)
shift
initialize='yes'
;;
-k|--kernel-version)
local given_argument="$1"
shift
kernel_version="$1"
if [ -z "$kernel_version" ]; then
echo \
"Error with given option \"$given_argument\":" \
"This option needs a kernel version to build the initramfs for."
return 1
fi
shift
;;
-H|--kernel-headers)
local given_argument="$1"
shift
kernel_headers="$1"
if [ -z "$kernel_headers" ]; then
echo \
"Error with given option \"$given_argument\":" \
"This option needs the path to the kernel headers."
return 1
fi
shift
;;
-q|--qcow-handler)
local given_argument="$1"
shift
qcow_handler="$1"
if [ -z "$qcow_handler" ]; then
echo \
"Error with given option \"$given_argument\":" \
"This options needs to be either 'xmount' or 'kernel'."
return 1
fi
shift
;;
-u|--update)
shift
update='yes'
;;
-)
shift
while [[ "$1" =~ ^.+$ ]]; do
dracut_parameter+=("$1")
shift
done
;;
'')
break
;;
*)
echo \
"Error with given option \"$1\": This argument is not available."
return 1
esac
done
return 0
}
## endregion
## region helper
initialize_dracut() {
pushd "${_dracut_dir}"
# NOTE: On virtualbox shared folder symlinks are not allowed.
# NOTE: make the dracut-install binary (dracut-install resolves
# dependencies etc.)
echo 'Compiling dracut.'
./configure
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
popd
cp "${_dracut_dir}/install/dracut-install" \
"${_dracut_dir}/dracut-install"
return $?
}
# The idea here was to source each module-setup.sh from our
# custom dracut modules and call their clean() function.
# TODO: Does this still work?
cleanup() {
local plugin_path
plugin_path="${_repo_dir}/modules.d/dnbd3-rootfs"
source "${plugin_path}/module-setup.sh"
moddir="$(cd "$plugin_path" &>/dev/null && pwd)"
clean
return $?
}
main() {
if ! parse_command_line "$@"; then
print_help_message "$0"
exit 1
fi
# prepare remote modules and set core variables.
bootstrap
if [ "$full_cleanup" = "yes" ]; then
echo 'Removing all modules.'
rm "${_repo_dir}" "${_dracut_dir}" --recursive --force
exit $?
fi
if [ "$cleanup" = "yes" ]; then
echo 'Removing distribution specific files.'
cleanup
exit $?
fi
# Default to the running kernel's version if none were specified
echo "Building for:"
if [ -z "$kernel_version" ]; then
kernel_version="$(uname -r)"
fi
echo " * kernel version: $kernel_version"
# similar for kernel headers needed to compile dnbd3 against.
if [ -z "$kernel_headers" ]; then
kernel_headers="/lib/modules/${kernel_version}/build"
fi
if [ ! -f "${kernel_headers}/Makefile" ]; then
echo 'Missing kernel headers for given kernel!'
exit 1
fi
echo " * kernel headers: $kernel_headers"
[ -n "$qcow_handler" ] && echo " * qcow2 handler: $qcow_handler"
export _QCOW_HANDLER="$qcow_handler"
if [ "$update" = "yes" ]; then
pushd "${_repo_dir}"
git pull
popd
fi
echo 'Checking dracut...'
if [ ! -f "${_dracut_dir}/dracut-install" ]; then
echo "Dracut isn't available yet loading it."
initialize_dracut
fi
for _dracut_module_dir in "${_repo_dir}/modules.d/"*; do
[ -d "${_dracut_module_dir}" ] || continue
_dracut_module="$(basename $_dracut_module_dir)"
# TODO allow module-specific priority
_dracut_module_target="${_dracut_dir}/modules.d/00${_dracut_module}"
if [[ ! -L "$_dracut_module_target" || "$(readlink \
"$_dracut_module_target")" != "$_dracut_module_dir" ]]; then
echo \
"Link ${_dracut_module} plugin into dracut modules folder" \
"($_dracut_module_dir -> $_dracut_module_target)."
if ! ln --symbolic --force \
"$_dracut_module_dir" "$_dracut_module_target"; then
echo \
"Linking \"$_dracut_module_dir\" to \"$_dracut_module_target\" failed." \
"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 \
"$_dracut_module_dir" \
"$_dracut_module_target"
fi
fi
done
# default dracut modules
_modules=(dnbd3-rootfs conf-tgz)
echo "Default modules: ${_modules[@]}"
if [ "$verbose" = "yes" ]; then
dracut_parameters+=("--verbose")
fi
if [ "$debug" = "yes" ]; then
dracut_parameters+=("--stdlog" "4")
_modules+=(i18n terminfo)
fi
if [ "$use_systemd_in_initramfs" = "yes" ]; then
_modules+=(systemd systemd-initrd dracut-systemd)
fi
# Initialize and exit if we are only preparing the build environment
. "${_repo_dir}/modules.d/dnbd3-rootfs/helper/build.inc"
build_initialize_components
if [ "$initialize" = "yes" ]; then
echo "Initialization succeeded."
exit 0
fi
echo 'Building initramfs...'
"${_dracut_dir}/dracut.sh" --local \
$_loglevel --modules "${_modules[*]}" --conf /etc/dracut.conf \
--confdir /etc/dracut.conf.d "${dracut_parameter[@]}" \
--kver "${kernel_version}" "$file_path"
_return_code=$?
if [ "$_return_code" != 0 ]; then
echo 'Building initramfs failed.'
exit 1
fi
# NOTE: dracut generate the initramfs with 0600 permissions
chmod 0644 "${file_path}"
}
main "$@"
|