diff options
Diffstat (limited to 'modules.d')
78 files changed, 4882 insertions, 0 deletions
diff --git a/modules.d/bootnet-conf/module-setup.sh b/modules.d/bootnet-conf/module-setup.sh new file mode 100755 index 00000000..f1d6697f --- /dev/null +++ b/modules.d/bootnet-conf/module-setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + return 255 +} +depends() { + echo dnbd3-rootfs +} +install() { + inst_hook pre-pivot 50 "$moddir/scripts/gen-bootnet-conf.sh" +} diff --git a/modules.d/bootnet-conf/scripts/gen-bootnet-conf.sh b/modules.d/bootnet-conf/scripts/gen-bootnet-conf.sh new file mode 100755 index 00000000..ec82f143 --- /dev/null +++ b/modules.d/bootnet-conf/scripts/gen-bootnet-conf.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +mac="$(getargs BOOTIF=)" +mac="$(echo $mac | cut -c 4- | tr '-' ':')" +if [ -n "${mac}" ]; then + cat << EOF >> "${NEWROOT}/etc/sysconfig/network-scripts/ifcfg-bootnet" +DEVICE=bootnet +NAME=bootnet +HWADDR=${mac} +BOOTPROTO=dhcp +ONBOOT=yes +NM_CONTROLLED=yes +EOF +else + echo "Could not parse MAC" +fi diff --git a/modules.d/busybox/install-busybox-stage4.sh b/modules.d/busybox/install-busybox-stage4.sh new file mode 100644 index 00000000..ad34b75c --- /dev/null +++ b/modules.d/busybox/install-busybox-stage4.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +if hash busybox; then + # check if the stage4 has a busybox in the same location + # as within the initramfs. If so, we keep it and just hope + # that everything works out. If there is none, we can copy + # our busybox there safely + bb_path="$(type -p busybox)" + if ! [ -x "${NEWROOT}/${bb_path}" ]; then + cp -f "$bb_path" "${NEWROOT}/${bb_path}" + fi + # finally install the applets under /opt/openslx/bin + mkdir -p "${NEWROOT}/opt/openslx/bin" + busybox --install -s "${NEWROOT}/opt/openslx/bin" +fi +true diff --git a/modules.d/busybox/install-busybox.sh b/modules.d/busybox/install-busybox.sh new file mode 100644 index 00000000..6848a735 --- /dev/null +++ b/modules.d/busybox/install-busybox.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if hash busybox; then + busybox --install -s +else + . /lib/dracut-lib.sh + emergency_shell "Failed to initialize busybox, things will go wrong..." +fi +true diff --git a/modules.d/busybox/module-setup.sh b/modules.d/busybox/module-setup.sh new file mode 100644 index 00000000..807022e9 --- /dev/null +++ b/modules.d/busybox/module-setup.sh @@ -0,0 +1,42 @@ +#!/bin/bash +[ -z "$BB_GIT" ] && declare -rg BB_GIT="git://git.busybox.net/busybox" +[ -z "$BB_BRANCH" ] && declare -rg BB_BRANCH="1_25_1" + +build() { + local base_url="https://git.openslx.org/openslx-ng/mltk.git/plain/core/modules/busybox/" + ( + set -e + git clone --depth 1 "$BB_GIT" --branch "$BB_BRANCH" "${moddir}/src" + # apply patches + cd "${moddir}/src" + for _patch in "$base_url"{fbsplash-center,fbsplash-fillbg,rtcwake-compat}.patch ; do + curl "$_patch" | git apply - || derror "Failed to apply: $_patch" + done + + cp "${moddir}/openslx.config" > "${target}/.config" + yes '' | make oldconfig + make -j busybox + cd - &> /dev/null + ) +} +check() { + if [ ! -x "${moddir}/src/busybox" ] && ! build; then + derror "Failed to build busybox." + return 1 + fi + return 255 +} + +depends() { + echo "" +} + +install() { + if [ ! -s "${moddir}/src/busybox" ]; then + derror "Failed to find busybox binary in build directory!" + return 1 + fi + inst "${moddir}/src/busybox" "/bin/busybox" + inst_hook cmdline 00 "${moddir}/install-busybox.sh" + inst_hook pre-pivot 50 "${moddir}/install-busybox-stage4.sh" +} diff --git a/modules.d/busybox/openslx.config b/modules.d/busybox/openslx.config new file mode 100644 index 00000000..177f2fde --- /dev/null +++ b/modules.d/busybox/openslx.config @@ -0,0 +1,1191 @@ +# +# Automatically generated make config: don't edit +# Busybox version: 1.31.0 +# Tue Jul 16 16:43:28 2019 +# +CONFIG_HAVE_DOT_CONFIG=y + +# +# Settings +# +# CONFIG_DESKTOP is not set +# CONFIG_EXTRA_COMPAT is not set +# CONFIG_FEDORA_COMPAT is not set +# CONFIG_INCLUDE_SUSv2 is not set +CONFIG_LONG_OPTS=y +CONFIG_SHOW_USAGE=y +# CONFIG_FEATURE_VERBOSE_USAGE is not set +CONFIG_FEATURE_COMPRESS_USAGE=y +CONFIG_LFS=y +# CONFIG_PAM is not set +CONFIG_FEATURE_DEVPTS=y +CONFIG_FEATURE_UTMP=y +# CONFIG_FEATURE_WTMP is not set +CONFIG_FEATURE_PIDFILE=y +CONFIG_PID_FILE_PATH="/var/run" +CONFIG_BUSYBOX=y +CONFIG_FEATURE_SHOW_SCRIPT=y +CONFIG_FEATURE_INSTALLER=y +CONFIG_INSTALL_NO_USR=y +CONFIG_FEATURE_SUID=y +# CONFIG_FEATURE_SUID_CONFIG is not set +# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set +# CONFIG_FEATURE_PREFER_APPLETS is not set +CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" +# CONFIG_SELINUX is not set +# CONFIG_FEATURE_CLEAN_UP is not set +CONFIG_FEATURE_SYSLOG_INFO=y +CONFIG_FEATURE_SYSLOG=y +CONFIG_PLATFORM_LINUX=y + +# +# Build Options +# +# CONFIG_STATIC is not set +# CONFIG_PIE is not set +# CONFIG_NOMMU is not set +# CONFIG_BUILD_LIBBUSYBOX is not set +# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set +# CONFIG_FEATURE_INDIVIDUAL is not set +# CONFIG_FEATURE_SHARED_BUSYBOX is not set +CONFIG_CROSS_COMPILER_PREFIX="" +CONFIG_SYSROOT="" +CONFIG_EXTRA_CFLAGS="" +CONFIG_EXTRA_LDFLAGS="" +CONFIG_EXTRA_LDLIBS="" +# CONFIG_USE_PORTABLE_CODE is not set +CONFIG_STACK_OPTIMIZATION_386=y + +# +# Installation Options ("make install" behavior) +# +CONFIG_INSTALL_APPLET_SYMLINKS=y +# CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +# CONFIG_INSTALL_APPLET_DONT is not set +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_PREFIX="./_install" + +# +# Debugging Options +# +# CONFIG_DEBUG is not set +# CONFIG_DEBUG_PESSIMIZE is not set +# CONFIG_DEBUG_SANITIZE is not set +# CONFIG_UNIT_TEST is not set +# CONFIG_WERROR is not set +CONFIG_NO_DEBUG_LIB=y +# CONFIG_DMALLOC is not set +# CONFIG_EFENCE is not set + +# +# Library Tuning +# +# CONFIG_FEATURE_USE_BSS_TAIL is not set +CONFIG_FLOAT_DURATION=y +CONFIG_FEATURE_RTMINMAX=y +CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS=y +CONFIG_FEATURE_BUFFERS_USE_MALLOC=y +# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set +# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_PASSWORD_MINLEN=6 +CONFIG_MD5_SMALL=1 +CONFIG_SHA3_SMALL=1 +CONFIG_FEATURE_FAST_TOP=y +# CONFIG_FEATURE_ETC_NETWORKS is not set +# CONFIG_FEATURE_ETC_SERVICES is not set +CONFIG_FEATURE_EDITING=y +CONFIG_FEATURE_EDITING_MAX_LEN=1024 +# CONFIG_FEATURE_EDITING_VI is not set +CONFIG_FEATURE_EDITING_HISTORY=15 +CONFIG_FEATURE_EDITING_SAVEHISTORY=y +# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set +CONFIG_FEATURE_REVERSE_SEARCH=y +CONFIG_FEATURE_TAB_COMPLETION=y +# CONFIG_FEATURE_USERNAME_COMPLETION is not set +CONFIG_FEATURE_EDITING_FANCY_PROMPT=y +CONFIG_FEATURE_EDITING_WINCH=y +# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set +CONFIG_LOCALE_SUPPORT=y +CONFIG_UNICODE_SUPPORT=y +# CONFIG_UNICODE_USING_LOCALE is not set +CONFIG_FEATURE_CHECK_UNICODE_IN_ENV=y +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +# CONFIG_UNICODE_WIDE_WCHARS is not set +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +CONFIG_FEATURE_NON_POSIX_CP=y +CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y +CONFIG_FEATURE_USE_SENDFILE=y +CONFIG_FEATURE_COPYBUF_KB=4 +CONFIG_FEATURE_SKIP_ROOTFS=y +CONFIG_MONOTONIC_SYSCALL=y +CONFIG_IOCTL_HEX2STR_ERROR=y +# CONFIG_FEATURE_HWIB is not set + +# +# Applets +# + +# +# Archival Utilities +# +CONFIG_FEATURE_SEAMLESS_XZ=y +CONFIG_FEATURE_SEAMLESS_LZMA=y +CONFIG_FEATURE_SEAMLESS_BZ2=y +CONFIG_FEATURE_SEAMLESS_GZ=y +CONFIG_FEATURE_SEAMLESS_Z=y +CONFIG_AR=y +# CONFIG_FEATURE_AR_LONG_FILENAMES is not set +CONFIG_FEATURE_AR_CREATE=y +# CONFIG_UNCOMPRESS is not set +CONFIG_GUNZIP=y +CONFIG_ZCAT=y +CONFIG_FEATURE_GUNZIP_LONG_OPTIONS=y +CONFIG_BUNZIP2=y +CONFIG_BZCAT=y +CONFIG_UNLZMA=y +CONFIG_LZCAT=y +CONFIG_LZMA=y +CONFIG_UNXZ=y +CONFIG_XZCAT=y +CONFIG_XZ=y +CONFIG_BZIP2=y +CONFIG_BZIP2_SMALL=8 +CONFIG_FEATURE_BZIP2_DECOMPRESS=y +CONFIG_CPIO=y +# CONFIG_FEATURE_CPIO_O is not set +# CONFIG_FEATURE_CPIO_P is not set +# CONFIG_DPKG is not set +# CONFIG_DPKG_DEB is not set +CONFIG_GZIP=y +# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set +CONFIG_GZIP_FAST=0 +# CONFIG_FEATURE_GZIP_LEVELS is not set +CONFIG_FEATURE_GZIP_DECOMPRESS=y +# CONFIG_LZOP is not set +# CONFIG_UNLZOP is not set +# CONFIG_LZOPCAT is not set +# CONFIG_LZOP_COMPR_HIGH is not set +# CONFIG_RPM is not set +CONFIG_RPM2CPIO=y +CONFIG_TAR=y +CONFIG_FEATURE_TAR_LONG_OPTIONS=y +CONFIG_FEATURE_TAR_CREATE=y +CONFIG_FEATURE_TAR_AUTODETECT=y +CONFIG_FEATURE_TAR_FROM=y +# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y +# CONFIG_FEATURE_TAR_TO_COMMAND is not set +# CONFIG_FEATURE_TAR_UNAME_GNAME is not set +CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y +# CONFIG_FEATURE_TAR_SELINUX is not set +# CONFIG_UNZIP is not set +# CONFIG_FEATURE_UNZIP_CDF is not set +# CONFIG_FEATURE_UNZIP_BZIP2 is not set +# CONFIG_FEATURE_UNZIP_LZMA is not set +# CONFIG_FEATURE_UNZIP_XZ is not set +# CONFIG_FEATURE_LZMA_FAST is not set + +# +# Coreutils +# +CONFIG_BASENAME=y +CONFIG_CAT=y +CONFIG_FEATURE_CATN=y +CONFIG_FEATURE_CATV=y +CONFIG_CHGRP=y +CONFIG_CHMOD=y +CONFIG_CHOWN=y +CONFIG_FEATURE_CHOWN_LONG_OPTIONS +CONFIG_CHROOT=y +# CONFIG_CKSUM is not set +# CONFIG_COMM is not set +CONFIG_CP=y +CONFIG_FEATURE_CP_LONG_OPTIONS=y +# CONFIG_FEATURE_CP_REFLINK is not set +CONFIG_CUT=y +CONFIG_DATE=y +CONFIG_FEATURE_DATE_ISOFMT=y +CONFIG_FEATURE_DATE_NANO=y +CONFIG_FEATURE_DATE_COMPAT=y +CONFIG_DD=y +CONFIG_FEATURE_DD_SIGNAL_HANDLING=y +# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set +# CONFIG_FEATURE_DD_IBS_OBS is not set +CONFIG_FEATURE_DD_STATUS=y +CONFIG_DF=y +# CONFIG_FEATURE_DF_FANCY is not set +CONFIG_DIRNAME=y +# CONFIG_DOS2UNIX is not set +# CONFIG_UNIX2DOS is not set +CONFIG_DU=y +CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y +CONFIG_ECHO=y +CONFIG_FEATURE_FANCY_ECHO=y +CONFIG_ENV=y +# CONFIG_EXPAND is not set +# CONFIG_UNEXPAND is not set +CONFIG_EXPR=y +CONFIG_EXPR_MATH_SUPPORT_64=y +CONFIG_FACTOR=y +CONFIG_FALSE=y +# CONFIG_FOLD is not set +CONFIG_HEAD=y +# CONFIG_FEATURE_FANCY_HEAD is not set +# CONFIG_HOSTID is not set +CONFIG_ID=y +CONFIG_GROUPS=y +# CONFIG_INSTALL is not set +# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set +CONFIG_LINK=y +CONFIG_LN=y +# CONFIG_LOGNAME is not set +CONFIG_LS=y +CONFIG_FEATURE_LS_FILETYPES=y +CONFIG_FEATURE_LS_FOLLOWLINKS=y +CONFIG_FEATURE_LS_RECURSIVE=y +CONFIG_FEATURE_LS_WIDTH=y +CONFIG_FEATURE_LS_SORTFILES=y +CONFIG_FEATURE_LS_TIMESTAMPS=y +CONFIG_FEATURE_LS_USERNAME=y +CONFIG_FEATURE_LS_COLOR=y +# CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set +CONFIG_MD5SUM=y +# CONFIG_SHA1SUM is not set +CONFIG_SHA256SUM=y +# CONFIG_SHA512SUM is not set +# CONFIG_SHA3SUM is not set + +# +# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum +# +CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y +CONFIG_MKDIR=y +CONFIG_MKFIFO=y +CONFIG_MKNOD=y +CONFIG_MKTEMP=y +CONFIG_MV=y +CONFIG_NICE=y +CONFIG_NL=y +# CONFIG_NOHUP is not set +CONFIG_NPROC=y +# CONFIG_OD is not set +CONFIG_PASTE=y +# CONFIG_PRINTENV is not set +CONFIG_PRINTF=y +CONFIG_PWD=y +CONFIG_READLINK=y +CONFIG_FEATURE_READLINK_FOLLOW=y +CONFIG_REALPATH=y +CONFIG_RM=y +CONFIG_RMDIR=y +# CONFIG_SEQ is not set +CONFIG_SHRED=y +CONFIG_SHUF=y +CONFIG_SLEEP=y +# CONFIG_FEATURE_FANCY_SLEEP is not set +CONFIG_SORT=y +CONFIG_FEATURE_SORT_BIG=y +# CONFIG_FEATURE_SORT_OPTIMIZE_MEMORY is not set +# CONFIG_SPLIT is not set +# CONFIG_FEATURE_SPLIT_FANCY is not set +CONFIG_STAT=y +CONFIG_FEATURE_STAT_FORMAT=y +CONFIG_FEATURE_STAT_FILESYSTEM=y +# CONFIG_STTY is not set +# CONFIG_SUM is not set +CONFIG_SYNC=y +CONFIG_FEATURE_SYNC_FANCY=y +# CONFIG_FSYNC is not set +# CONFIG_TAC is not set +CONFIG_TAIL=y +CONFIG_FEATURE_FANCY_TAIL=y +CONFIG_TEE=y +# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set +CONFIG_TEST=y +CONFIG_TEST1=y +CONFIG_TEST2=y +# CONFIG_FEATURE_TEST_64 is not set +CONFIG_TIMEOUT=y +CONFIG_TOUCH=y +CONFIG_FEATURE_TOUCH_NODEREF=y +CONFIG_FEATURE_TOUCH_SUSV3=y +CONFIG_TR=y +# CONFIG_FEATURE_TR_CLASSES is not set +# CONFIG_FEATURE_TR_EQUIV is not set +CONFIG_TRUE=y +CONFIG_TRUNCATE=y +# CONFIG_TTY is not set +CONFIG_UNAME=y +CONFIG_UNAME_OSNAME="GNU/Linux" +CONFIG_BB_ARCH=y +CONFIG_UNIQ=y +CONFIG_UNLINK=y +CONFIG_USLEEP=y +# CONFIG_UUDECODE is not set +CONFIG_BASE64=y +# CONFIG_UUENCODE is not set +CONFIG_WC=y +# CONFIG_FEATURE_WC_LARGE is not set +CONFIG_WHOAMI=y +CONFIG_WHO=y +CONFIG_W=y +# CONFIG_USERS is not set +# CONFIG_YES is not set + +# +# Common options +# +CONFIG_FEATURE_VERBOSE=y + +# +# Common options for cp and mv +# +CONFIG_FEATURE_PRESERVE_HARDLINKS=y + +# +# Common options for df, du, ls +# +CONFIG_FEATURE_HUMAN_READABLE=y + +# +# Console Utilities +# +CONFIG_CHVT=y +CONFIG_CLEAR=y +CONFIG_DEALLOCVT=y +CONFIG_DUMPKMAP=y +CONFIG_FGCONSOLE=y +# CONFIG_KBD_MODE is not set +CONFIG_LOADFONT=y +CONFIG_SETFONT=y +CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y +CONFIG_DEFAULT_SETFONT_DIR="" + +# +# Common options for loadfont and setfont +# +CONFIG_FEATURE_LOADFONT_PSF2=y +CONFIG_FEATURE_LOADFONT_RAW=y +CONFIG_LOADKMAP=y +CONFIG_OPENVT=y +CONFIG_RESET=y +CONFIG_RESIZE=y +CONFIG_FEATURE_RESIZE_PRINT=y +CONFIG_SETCONSOLE=y +CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y +CONFIG_SETKEYCODES=y +CONFIG_SETLOGCONS=y +# CONFIG_SHOWKEY is not set + +# +# Debian Utilities +# +# CONFIG_PIPE_PROGRESS is not set +# CONFIG_RUN_PARTS is not set +# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set +# CONFIG_FEATURE_RUN_PARTS_FANCY is not set +# CONFIG_START_STOP_DAEMON is not set +# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set +CONFIG_WHICH=y + +# +# klibc-utils +# +# CONFIG_MINIPS is not set +CONFIG_NUKE=y +CONFIG_RESUME=y +CONFIG_RUN_INIT=y + +# +# Editors +# +CONFIG_AWK=y +# CONFIG_FEATURE_AWK_LIBM is not set +CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y +# CONFIG_CMP is not set +CONFIG_DIFF=y +CONFIG_FEATURE_DIFF_LONG_OPTIONS=y +CONFIG_FEATURE_DIFF_DIR=y +# CONFIG_ED is not set +# CONFIG_PATCH is not set +CONFIG_SED=y +CONFIG_VI=y +CONFIG_FEATURE_VI_MAX_LEN=1024 +CONFIG_FEATURE_VI_8BIT=y +CONFIG_FEATURE_VI_COLON=y +CONFIG_FEATURE_VI_YANKMARK=y +CONFIG_FEATURE_VI_SEARCH=y +CONFIG_FEATURE_VI_REGEX_SEARCH=y +CONFIG_FEATURE_VI_USE_SIGNALS=y +CONFIG_FEATURE_VI_DOT_CMD=y +CONFIG_FEATURE_VI_READONLY=y +CONFIG_FEATURE_VI_SETOPTS=y +CONFIG_FEATURE_VI_SET=y +CONFIG_FEATURE_VI_WIN_RESIZE=y +CONFIG_FEATURE_VI_ASK_TERMINAL=y +CONFIG_FEATURE_VI_UNDO=y +CONFIG_FEATURE_VI_UNDO_QUEUE=y +CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256 +# CONFIG_FEATURE_ALLOW_EXEC is not set + +# +# Finding Utilities +# +CONFIG_FIND=y +CONFIG_FEATURE_FIND_PRINT0=y +CONFIG_FEATURE_FIND_MTIME=y +CONFIG_FEATURE_FIND_MMIN=y +CONFIG_FEATURE_FIND_PERM=y +CONFIG_FEATURE_FIND_TYPE=y +CONFIG_FEATURE_FIND_EXECUTABLE=y +CONFIG_FEATURE_FIND_XDEV=y +CONFIG_FEATURE_FIND_MAXDEPTH=y +CONFIG_FEATURE_FIND_NEWER=y +CONFIG_FEATURE_FIND_INUM=y +CONFIG_FEATURE_FIND_EXEC=y +CONFIG_FEATURE_FIND_EXEC_PLUS=y +CONFIG_FEATURE_FIND_USER=y +CONFIG_FEATURE_FIND_GROUP=y +CONFIG_FEATURE_FIND_NOT=y +CONFIG_FEATURE_FIND_DEPTH=y +CONFIG_FEATURE_FIND_PAREN=y +CONFIG_FEATURE_FIND_SIZE=y +CONFIG_FEATURE_FIND_PRUNE=y +CONFIG_FEATURE_FIND_QUIT=y +CONFIG_FEATURE_FIND_DELETE=y +CONFIG_FEATURE_FIND_PATH=y +CONFIG_FEATURE_FIND_REGEX=y +# CONFIG_FEATURE_FIND_CONTEXT is not set +# CONFIG_FEATURE_FIND_LINKS is not set +CONFIG_GREP=y +CONFIG_EGREP=y +CONFIG_FGREP=y +CONFIG_FEATURE_GREP_CONTEXT=y +CONFIG_XARGS=y +# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set +# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set +# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set +# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set +CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR=y +CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL=y +CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE=y + +# +# Init Utilities +# +# CONFIG_BOOTCHARTD is not set +# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +CONFIG_HALT=y +CONFIG_POWEROFF=y +CONFIG_REBOOT=y +CONFIG_FEATURE_WAIT_FOR_INIT=y +CONFIG_FEATURE_CALL_TELINIT=y +CONFIG_TELINIT_PATH="/sbin/telinit" +# CONFIG_INIT is not set +CONFIG_LINUXRC=y +# CONFIG_FEATURE_USE_INITTAB is not set +# CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_FEATURE_KILL_DELAY=0 +# CONFIG_FEATURE_INIT_SCTTY is not set +# CONFIG_FEATURE_INIT_SYSLOG is not set +CONFIG_FEATURE_INIT_QUIET=y +# CONFIG_FEATURE_INIT_COREDUMPS is not set +CONFIG_INIT_TERMINAL_TYPE="" +CONFIG_FEATURE_INIT_MODIFY_CMDLINE=y + +# +# Login/Password Management Utilities +# +CONFIG_FEATURE_SHADOWPASSWDS=y +# CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_USE_BB_SHADOW is not set +CONFIG_USE_BB_CRYPT=y +CONFIG_USE_BB_CRYPT_SHA=y +CONFIG_ADDGROUP=y +CONFIG_FEATURE_ADDUSER_TO_GROUP=y +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set +CONFIG_ADDUSER=y +# CONFIG_FEATURE_CHECK_NAMES is not set +CONFIG_LAST_ID=60000 +CONFIG_FIRST_SYSTEM_ID=100 +CONFIG_LAST_SYSTEM_ID=999 +# CONFIG_CHPASSWD is not set +CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="des" +# CONFIG_CRYPTPW is not set +CONFIG_MKPASSWD=y +# CONFIG_DELUSER is not set +# CONFIG_DELGROUP is not set +# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set +CONFIG_GETTY=y +# CONFIG_LOGIN is not set +# CONFIG_LOGIN_SESSION_AS_CHILD is not set +# CONFIG_LOGIN_SCRIPTS is not set +# CONFIG_FEATURE_NOLOGIN is not set +# CONFIG_FEATURE_SECURETTY is not set +CONFIG_PASSWD=y +CONFIG_FEATURE_PASSWD_WEAK_CHECK=y +CONFIG_SU=y +CONFIG_FEATURE_SU_SYSLOG=y +CONFIG_FEATURE_SU_CHECKS_SHELLS=y +# CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set +# CONFIG_SULOGIN is not set +# CONFIG_VLOCK is not set + +# +# Linux Ext2 FS Progs +# +# CONFIG_CHATTR is not set +# CONFIG_FSCK is not set +# CONFIG_LSATTR is not set +# CONFIG_TUNE2FS is not set + +# +# Linux Module Utilities +# +# CONFIG_MODPROBE_SMALL is not set +# CONFIG_DEPMOD is not set +CONFIG_INSMOD=y +CONFIG_LSMOD=y +# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +CONFIG_MODINFO=y +CONFIG_MODPROBE=y +CONFIG_FEATURE_MODPROBE_BLACKLIST=y +CONFIG_RMMOD=y + +# +# Options common to multiple modutils +# +CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS=y +# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set +# CONFIG_FEATURE_2_4_MODULES is not set +# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set +CONFIG_FEATURE_CHECK_TAINTED_MODULE=y +# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set +CONFIG_FEATURE_MODUTILS_ALIAS=y +CONFIG_FEATURE_MODUTILS_SYMBOLS=y +CONFIG_DEFAULT_MODULES_DIR="/lib/modules" +CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" + +# +# Linux System Utilities +# +# CONFIG_ACPID is not set +# CONFIG_FEATURE_ACPID_COMPAT is not set +CONFIG_BLKDISCARD=y +CONFIG_BLKID=y +# CONFIG_FEATURE_BLKID_TYPE is not set +CONFIG_BLOCKDEV=y +# CONFIG_CAL is not set +# CONFIG_CHRT is not set +CONFIG_DMESG=y +CONFIG_FEATURE_DMESG_PRETTY=y +CONFIG_EJECT=y +CONFIG_FEATURE_EJECT_SCSI=y +CONFIG_FALLOCATE=y +CONFIG_FATATTR=y +CONFIG_FBSET=y +CONFIG_FEATURE_FBSET_FANCY=y +# CONFIG_FEATURE_FBSET_READMODE is not set +# CONFIG_FDFORMAT is not set +CONFIG_FDISK=y +# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set +CONFIG_FEATURE_FDISK_WRITABLE=y +# CONFIG_FEATURE_AIX_LABEL is not set +# CONFIG_FEATURE_SGI_LABEL is not set +# CONFIG_FEATURE_SUN_LABEL is not set +# CONFIG_FEATURE_OSF_LABEL is not set +CONFIG_FEATURE_GPT_LABEL=y +# CONFIG_FEATURE_FDISK_ADVANCED is not set +# CONFIG_FINDFS is not set +CONFIG_FLOCK=y +# CONFIG_FDFLUSH is not set +# CONFIG_FREERAMDISK is not set +# CONFIG_FSCK_MINIX is not set +CONFIG_FSFREEZE=y +# CONFIG_FSTRIM is not set +# CONFIG_GETOPT is not set +# CONFIG_FEATURE_GETOPT_LONG is not set +# CONFIG_HEXDUMP is not set +# CONFIG_FEATURE_HEXDUMP_REVERSE is not set +# CONFIG_HD is not set +CONFIG_XXD=y +CONFIG_HWCLOCK=y +CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS=y +# CONFIG_IONICE is not set +# CONFIG_IPCRM is not set +# CONFIG_IPCS is not set +# CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_FANCY is not set +# CONFIG_LOSETUP is not set +CONFIG_LSPCI=y +CONFIG_LSUSB=y +# CONFIG_MDEV is not set +# CONFIG_FEATURE_MDEV_CONF is not set +# CONFIG_FEATURE_MDEV_RENAME is not set +# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set +# CONFIG_FEATURE_MDEV_EXEC is not set +# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set +# CONFIG_FEATURE_MDEV_DAEMON is not set +# CONFIG_MESG is not set +# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set +CONFIG_MKE2FS=y +CONFIG_MKFS_EXT2=y +# CONFIG_MKFS_MINIX is not set +# CONFIG_FEATURE_MINIX2 is not set +# CONFIG_MKFS_REISER is not set +CONFIG_MKDOSFS=y +CONFIG_MKFS_VFAT=y +CONFIG_MKSWAP=y +# CONFIG_FEATURE_MKSWAP_UUID is not set +CONFIG_MORE=y +CONFIG_MOUNT=y +# CONFIG_FEATURE_MOUNT_FAKE is not set +# CONFIG_FEATURE_MOUNT_VERBOSE is not set +CONFIG_FEATURE_MOUNT_HELPERS=y +# CONFIG_FEATURE_MOUNT_LABEL is not set +CONFIG_FEATURE_MOUNT_NFS=y +CONFIG_FEATURE_MOUNT_CIFS=y +CONFIG_FEATURE_MOUNT_FLAGS=y +CONFIG_FEATURE_MOUNT_FSTAB=y +CONFIG_FEATURE_MOUNT_OTHERTAB=y +# CONFIG_MOUNTPOINT is not set +CONFIG_NOLOGIN=y +CONFIG_NOLOGIN_DEPENDENCIES=y +CONFIG_NSENTER=y +# CONFIG_PIVOT_ROOT is not set +CONFIG_RDATE=y +# CONFIG_RDEV is not set +# CONFIG_READPROFILE is not set +# CONFIG_RENICE is not set +# CONFIG_REV is not set +CONFIG_RTCWAKE=y +# CONFIG_SCRIPT is not set +# CONFIG_SCRIPTREPLAY is not set +# CONFIG_SETARCH is not set +CONFIG_LINUX32=y +CONFIG_LINUX64=y +CONFIG_SETPRIV=y +CONFIG_FEATURE_SETPRIV_DUMP=y +CONFIG_FEATURE_SETPRIV_CAPABILITIES=y +CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES=y +CONFIG_SETSID=y +CONFIG_SWAPON=y +CONFIG_FEATURE_SWAPON_DISCARD=y +CONFIG_FEATURE_SWAPON_PRI=y +CONFIG_SWAPOFF=y +CONFIG_FEATURE_SWAPONOFF_LABEL=y +CONFIG_SWITCH_ROOT=y +# CONFIG_TASKSET is not set +# CONFIG_FEATURE_TASKSET_FANCY is not set +CONFIG_UEVENT=y +CONFIG_UMOUNT=y +# CONFIG_FEATURE_UMOUNT_ALL is not set +CONFIG_UNSHARE=y +# CONFIG_WALL is not set + +# +# Common options for mount/umount +# +CONFIG_FEATURE_MOUNT_LOOP=y +CONFIG_FEATURE_MOUNT_LOOP_CREATE=y +# CONFIG_FEATURE_MTAB_SUPPORT is not set +CONFIG_VOLUMEID=y + +# +# Filesystem/Volume identification +# +CONFIG_FEATURE_VOLUMEID_BCACHE=y +CONFIG_FEATURE_VOLUMEID_BTRFS=y +CONFIG_FEATURE_VOLUMEID_CRAMFS=y +CONFIG_FEATURE_VOLUMEID_EXFAT=y +CONFIG_FEATURE_VOLUMEID_EXT=y +CONFIG_FEATURE_VOLUMEID_F2FS=y +CONFIG_FEATURE_VOLUMEID_FAT=y +CONFIG_FEATURE_VOLUMEID_HFS=y +CONFIG_FEATURE_VOLUMEID_ISO9660=y +CONFIG_FEATURE_VOLUMEID_JFS=y +# CONFIG_FEATURE_VOLUMEID_LFS is not set +CONFIG_FEATURE_VOLUMEID_LINUXRAID=y +CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y +CONFIG_FEATURE_VOLUMEID_LUKS=y +CONFIG_FEATURE_VOLUMEID_MINIX=y +CONFIG_FEATURE_VOLUMEID_NILFS=y +CONFIG_FEATURE_VOLUMEID_NTFS=y +CONFIG_FEATURE_VOLUMEID_OCFS2=y +CONFIG_FEATURE_VOLUMEID_REISERFS=y +CONFIG_FEATURE_VOLUMEID_ROMFS=y +# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set +CONFIG_FEATURE_VOLUMEID_SYSV=y +CONFIG_FEATURE_VOLUMEID_UBIFS=y +CONFIG_FEATURE_VOLUMEID_UDF=y +CONFIG_FEATURE_VOLUMEID_XFS=y + +# +# Miscellaneous Utilities +# +# CONFIG_ADJTIMEX is not set +# CONFIG_BBCONFIG is not set +# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set +CONFIG_BC=y +# CONFIG_DC is not set +CONFIG_FEATURE_DC_BIG=y +# CONFIG_FEATURE_DC_LIBM is not set +CONFIG_FEATURE_BC_INTERACTIVE=y +CONFIG_FEATURE_BC_LONG_OPTIONS=y +# CONFIG_BEEP is not set +CONFIG_FEATURE_BEEP_FREQ=0 +CONFIG_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_CHAT is not set +# CONFIG_FEATURE_CHAT_NOFAIL is not set +# CONFIG_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_FEATURE_CHAT_CLR_ABORT is not set +# CONFIG_CONSPY is not set +# CONFIG_CROND is not set +# CONFIG_FEATURE_CROND_D is not set +# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +# CONFIG_FEATURE_CROND_SPECIAL_TIMES is not set +CONFIG_FEATURE_CROND_DIR="" +# CONFIG_CRONTAB is not set +# CONFIG_DEVFSD is not set +# CONFIG_DEVFSD_MODLOAD is not set +# CONFIG_DEVFSD_FG_NP is not set +# CONFIG_DEVFSD_VERBOSE is not set +# CONFIG_FEATURE_DEVFS is not set +# CONFIG_DEVMEM is not set +CONFIG_FBSPLASH=y +# CONFIG_FLASHCP is not set +# CONFIG_FLASH_ERASEALL is not set +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +CONFIG_HDPARM=y +CONFIG_FEATURE_HDPARM_GET_IDENTITY=y +CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF=y +CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF=y +CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET=y +CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF=y +CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA=y +CONFIG_HEXEDIT=y +CONFIG_I2CGET=y +CONFIG_I2CSET=y +CONFIG_I2CDUMP=y +CONFIG_I2CDETECT=y +CONFIG_I2CTRANSFER=y +CONFIG_INOTIFYD=y +# CONFIG_LESS is not set +CONFIG_FEATURE_LESS_MAXLINES=0 +# CONFIG_FEATURE_LESS_BRACKETS is not set +# CONFIG_FEATURE_LESS_FLAGS is not set +# CONFIG_FEATURE_LESS_TRUNCATE is not set +# CONFIG_FEATURE_LESS_MARKS is not set +# CONFIG_FEATURE_LESS_REGEXP is not set +# CONFIG_FEATURE_LESS_WINCH is not set +# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set +# CONFIG_FEATURE_LESS_DASHCMD is not set +# CONFIG_FEATURE_LESS_LINENUMS is not set +# CONFIG_FEATURE_LESS_RAW is not set +# CONFIG_FEATURE_LESS_ENV is not set +CONFIG_LSSCSI=y +# CONFIG_MAKEDEVS is not set +# CONFIG_FEATURE_MAKEDEVS_LEAF is not set +# CONFIG_FEATURE_MAKEDEVS_TABLE is not set +# CONFIG_MAN is not set +# CONFIG_MICROCOM is not set +# CONFIG_MT is not set +# CONFIG_NANDWRITE is not set +# CONFIG_NANDDUMP is not set +CONFIG_PARTPROBE=y +# CONFIG_RAIDAUTORUN is not set +CONFIG_READAHEAD=y +# CONFIG_RFKILL is not set +# CONFIG_RUNLEVEL is not set +# CONFIG_RX is not set +CONFIG_SETFATTR=y +CONFIG_SETSERIAL=y +CONFIG_STRINGS=y +CONFIG_TIME=y +CONFIG_TS=y +CONFIG_TTYSIZE=y +CONFIG_UBIRENAME=y +# CONFIG_UBIATTACH is not set +# CONFIG_UBIDETACH is not set +CONFIG_UBIMKVOL=y +CONFIG_UBIRMVOL=y +CONFIG_UBIRSVOL=y +CONFIG_UBIUPDATEVOL=y +# CONFIG_VOLNAME is not set +CONFIG_WATCHDOG=y + +# +# Networking Utilities +# +CONFIG_FEATURE_IPV6=y +# CONFIG_FEATURE_UNIX_LOCAL is not set +# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set +# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set +# CONFIG_FEATURE_TLS_SHA1 is not set +CONFIG_ARP=y +CONFIG_ARPING=y +CONFIG_BRCTL=y +CONFIG_FEATURE_BRCTL_FANCY=y +CONFIG_FEATURE_BRCTL_SHOW=y +# CONFIG_DNSD is not set +# CONFIG_ETHER_WAKE is not set +# CONFIG_FTPD is not set +# CONFIG_FEATURE_FTPD_WRITE is not set +# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set +# CONFIG_FEATURE_FTPD_AUTHENTICATION is not set +CONFIG_FTPGET=y +CONFIG_FTPPUT=y +# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set +CONFIG_HOSTNAME=y +CONFIG_DNSDOMAINNAME=y +# CONFIG_HTTPD is not set +# CONFIG_FEATURE_HTTPD_RANGES is not set +# CONFIG_FEATURE_HTTPD_SETUID is not set +# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set +# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set +# CONFIG_FEATURE_HTTPD_CGI is not set +# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set +# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set +# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set +# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_FEATURE_HTTPD_PROXY is not set +# CONFIG_FEATURE_HTTPD_GZIP is not set +# CONFIG_IFCONFIG is not set +# CONFIG_FEATURE_IFCONFIG_STATUS is not set +# CONFIG_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +# CONFIG_FEATURE_IFCONFIG_HW is not set +# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set +# CONFIG_IFENSLAVE is not set +# CONFIG_IFPLUGD is not set +CONFIG_IFUP=y +CONFIG_IFDOWN=y +CONFIG_IFUPDOWN_IFSTATE_PATH="" +# CONFIG_FEATURE_IFUPDOWN_IP is not set +# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set +# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set +# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set +# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set +# CONFIG_INETD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +# CONFIG_FEATURE_INETD_RPC is not set +CONFIG_IP=y +# CONFIG_IPADDR is not set +# CONFIG_IPLINK is not set +# CONFIG_IPROUTE is not set +# CONFIG_IPTUNNEL is not set +# CONFIG_IPRULE is not set +CONFIG_IPNEIGH=y +CONFIG_FEATURE_IP_ADDRESS=y +CONFIG_FEATURE_IP_LINK=y +CONFIG_FEATURE_IP_ROUTE=y +CONFIG_FEATURE_IP_ROUTE_DIR="/etc/iproute2" +CONFIG_FEATURE_IP_TUNNEL=y +# CONFIG_FEATURE_IP_RULE is not set +CONFIG_FEATURE_IP_NEIGH=y +# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set +CONFIG_IPCALC=y +CONFIG_FEATURE_IPCALC_LONG_OPTIONS=y +CONFIG_FEATURE_IPCALC_FANCY=y +# CONFIG_FAKEIDENTD is not set +# CONFIG_NAMEIF is not set +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set +CONFIG_NBDCLIENT=y +CONFIG_NC=y +# CONFIG_NETCAT is not set +# CONFIG_NC_SERVER is not set +# CONFIG_NC_EXTRA is not set +# CONFIG_NC_110_COMPAT is not set +CONFIG_NETSTAT=y +CONFIG_FEATURE_NETSTAT_WIDE=y +CONFIG_FEATURE_NETSTAT_PRG=y +CONFIG_NSLOOKUP=y +CONFIG_FEATURE_NSLOOKUP_BIG=y +CONFIG_FEATURE_NSLOOKUP_LONG_OPTIONS=y +# CONFIG_NTPD is not set +# CONFIG_FEATURE_NTPD_SERVER is not set +# CONFIG_FEATURE_NTPD_CONF is not set +# CONFIG_FEATURE_NTP_AUTH is not set +CONFIG_PING=y +CONFIG_PING6=y +CONFIG_FEATURE_FANCY_PING=y +# CONFIG_PSCAN is not set +CONFIG_ROUTE=y +# CONFIG_SLATTACH is not set +CONFIG_SSL_CLIENT=y +CONFIG_TC=y +CONFIG_FEATURE_TC_INGRESS=y +CONFIG_TCPSVD=y +# CONFIG_UDPSVD is not set +CONFIG_TELNET=y +CONFIG_FEATURE_TELNET_TTYPE=y +CONFIG_FEATURE_TELNET_AUTOLOGIN=y +CONFIG_FEATURE_TELNET_WIDTH=y +# CONFIG_TELNETD is not set +# CONFIG_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set +CONFIG_TFTP=y +# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +CONFIG_FEATURE_TFTP_HPA_COMPAT=y +# CONFIG_TFTPD is not set +CONFIG_FEATURE_TFTP_GET=y +# CONFIG_FEATURE_TFTP_PUT is not set +# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set +# CONFIG_TFTP_DEBUG is not set +CONFIG_TLS=y +# CONFIG_TRACEROUTE is not set +# CONFIG_TRACEROUTE6 is not set +# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set +# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set +CONFIG_TUNCTL=y +CONFIG_FEATURE_TUNCTL_UG=y +CONFIG_VCONFIG=y +CONFIG_WGET=y +CONFIG_FEATURE_WGET_LONG_OPTIONS=y +CONFIG_FEATURE_WGET_STATUSBAR=y +CONFIG_FEATURE_WGET_AUTHENTICATION=y +CONFIG_FEATURE_WGET_TIMEOUT=y +CONFIG_FEATURE_WGET_HTTPS=y +CONFIG_FEATURE_WGET_OPENSSL=y +CONFIG_WHOIS=y +CONFIG_ZCIP=y +CONFIG_UDHCPD=y +# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set +CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY=y +CONFIG_DHCPD_LEASES_FILE="/var/lib/misc/udhcpd.leases" +CONFIG_DUMPLEASES=y +CONFIG_DHCPRELAY=y +CONFIG_UDHCPC=y +CONFIG_FEATURE_UDHCPC_ARPING=y +CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y +CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" +# CONFIG_UDHCPC6 is not set +# CONFIG_FEATURE_UDHCPC6_RFC3646 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4704 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4833 is not set +# CONFIG_FEATURE_UDHCPC6_RFC5970 is not set + +# +# Common options for DHCP applets +# +# CONFIG_FEATURE_UDHCP_PORT is not set +CONFIG_UDHCP_DEBUG=0 +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 +CONFIG_FEATURE_UDHCP_RFC3397=y +CONFIG_FEATURE_UDHCP_8021Q=y +CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" + +# +# Print Utilities +# +CONFIG_LPD=y +CONFIG_LPR=y +CONFIG_LPQ=y + +# +# Mail Utilities +# +# CONFIG_MAKEMIME is not set +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_SENDMAIL is not set +CONFIG_FEATURE_MIME_CHARSET="" + +# +# Process Utilities +# +CONFIG_FREE=y +CONFIG_FUSER=y +CONFIG_IOSTAT=y +CONFIG_KILL=y +CONFIG_KILLALL=y +# CONFIG_KILLALL5 is not set +CONFIG_LSOF=y +CONFIG_MPSTAT=y +CONFIG_NMETER=y +# CONFIG_PGREP is not set +# CONFIG_PKILL is not set +CONFIG_PIDOF=y +# CONFIG_FEATURE_PIDOF_SINGLE is not set +# CONFIG_FEATURE_PIDOF_OMIT is not set +CONFIG_PMAP=y +CONFIG_POWERTOP=y +CONFIG_FEATURE_POWERTOP_INTERACTIVE=y +CONFIG_PS=y +CONFIG_FEATURE_PS_WIDE=y +CONFIG_FEATURE_PS_LONG=y +# CONFIG_FEATURE_PS_TIME is not set +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set +# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set +CONFIG_PSTREE=y +CONFIG_PWDX=y +CONFIG_SMEMCAP=y +CONFIG_BB_SYSCTL=y +CONFIG_TOP=y +CONFIG_FEATURE_TOP_INTERACTIVE=y +CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y +CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y +CONFIG_FEATURE_TOP_SMP_CPU=y +CONFIG_FEATURE_TOP_DECIMALS=y +CONFIG_FEATURE_TOP_SMP_PROCESS=y +CONFIG_FEATURE_TOPMEM=y +CONFIG_UPTIME=y +# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set +# CONFIG_WATCH is not set +# CONFIG_FEATURE_SHOW_THREADS is not set + +# +# Runit Utilities +# +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +CONFIG_SVC=y +CONFIG_SVOK=y +# CONFIG_SVLOGD is not set +# CONFIG_CHCON is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RUNCON is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SESTATUS is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_RESTORECON is not set +# CONFIG_SETSEBOOL is not set + +# +# Shells +# +CONFIG_SH_IS_ASH=y +# CONFIG_SH_IS_HUSH is not set +# CONFIG_SH_IS_NONE is not set +# CONFIG_BASH_IS_ASH is not set +# CONFIG_BASH_IS_HUSH is not set +CONFIG_BASH_IS_NONE=y +CONFIG_ASH=y +CONFIG_ASH_OPTIMIZE_FOR_SIZE=y +CONFIG_ASH_INTERNAL_GLOB=y +CONFIG_ASH_BASH_COMPAT=y +# CONFIG_ASH_BASH_SOURCE_CURDIR is not set +CONFIG_ASH_BASH_NOT_FOUND_HOOK=y +CONFIG_ASH_JOB_CONTROL=y +CONFIG_ASH_ALIAS=y +CONFIG_ASH_RANDOM_SUPPORT=y +CONFIG_ASH_EXPAND_PRMT=y +# CONFIG_ASH_IDLE_TIMEOUT is not set +# CONFIG_ASH_MAIL is not set +CONFIG_ASH_ECHO=y +CONFIG_ASH_PRINTF=y +CONFIG_ASH_TEST=y +CONFIG_ASH_HELP=y +CONFIG_ASH_GETOPTS=y +CONFIG_ASH_CMDCMD=y +CONFIG_CTTYHACK=y +# CONFIG_HUSH is not set +# CONFIG_HUSH_BASH_COMPAT is not set +# CONFIG_HUSH_BRACE_EXPANSION is not set +# CONFIG_HUSH_LINENO_VAR is not set +# CONFIG_HUSH_BASH_SOURCE_CURDIR is not set +# CONFIG_HUSH_INTERACTIVE is not set +# CONFIG_HUSH_SAVEHISTORY is not set +# CONFIG_HUSH_JOB is not set +# CONFIG_HUSH_TICK is not set +# CONFIG_HUSH_IF is not set +# CONFIG_HUSH_LOOPS is not set +# CONFIG_HUSH_CASE is not set +# CONFIG_HUSH_FUNCTIONS is not set +# CONFIG_HUSH_LOCAL is not set +# CONFIG_HUSH_RANDOM_SUPPORT is not set +# CONFIG_HUSH_MODE_X is not set +# CONFIG_HUSH_ECHO is not set +# CONFIG_HUSH_PRINTF is not set +# CONFIG_HUSH_TEST is not set +# CONFIG_HUSH_HELP is not set +# CONFIG_HUSH_EXPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_READONLY is not set +# CONFIG_HUSH_KILL is not set +# CONFIG_HUSH_WAIT is not set +# CONFIG_HUSH_COMMAND is not set +# CONFIG_HUSH_TRAP is not set +# CONFIG_HUSH_TYPE is not set +# CONFIG_HUSH_TIMES is not set +# CONFIG_HUSH_READ is not set +# CONFIG_HUSH_SET is not set +# CONFIG_HUSH_UNSET is not set +# CONFIG_HUSH_ULIMIT is not set +# CONFIG_HUSH_UMASK is not set +# CONFIG_HUSH_GETOPTS is not set +# CONFIG_HUSH_MEMLEAK is not set + +# +# Options common to all shells +# +CONFIG_FEATURE_SH_MATH=y +CONFIG_FEATURE_SH_MATH_64=y +CONFIG_FEATURE_SH_MATH_BASE=y +CONFIG_FEATURE_SH_EXTRA_QUIET=y +# CONFIG_FEATURE_SH_STANDALONE is not set +# CONFIG_FEATURE_SH_NOFORK is not set +CONFIG_FEATURE_SH_READ_FRAC=y +CONFIG_FEATURE_SH_HISTFILESIZE=y +CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS=y + +# +# System Logging Utilities +# +CONFIG_KLOGD=y + +# +# klogd should not be used together with syslog to kernel printk buffer +# +CONFIG_FEATURE_KLOGD_KLOGCTL=y +CONFIG_LOGGER=y +CONFIG_LOGREAD=y +CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y +CONFIG_SYSLOGD=y +# CONFIG_FEATURE_ROTATE_LOGFILE is not set +CONFIG_FEATURE_REMOTE_LOG=y +# CONFIG_FEATURE_SYSLOGD_DUP is not set +CONFIG_FEATURE_SYSLOGD_CFG=y +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256 +CONFIG_FEATURE_IPC_SYSLOG=y +CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16 +CONFIG_FEATURE_KMSG_SYSLOG=y diff --git a/modules.d/conf-tgz/hooks/fetch-config-tgz.sh b/modules.d/conf-tgz/hooks/fetch-config-tgz.sh new file mode 100755 index 00000000..1c8ace61 --- /dev/null +++ b/modules.d/conf-tgz/hooks/fetch-config-tgz.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- + +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + + + slx_server="$(getarg slxsrv=)" + slx_server_base="$(getarg slxbase=)" + + if [ -z "$SLX_NO_CONFIG_TGZ" ]; then + # build config.tgz url + conftgz_url="http://${slx_server#@}/${slx_server_base}/config.tgz" + + # check if system's uuid was set + if [ -s "/run/system-uuid" ]; then + uuid="$(cat /run/system-uuid)" + if [ -n "$uuid" ]; then + conftgz_url="${conftgz_url}?uuid=${uuid}" + fi + fi + info "Download config.tgz from '$conftgz_url'..." + slx-tools download_retry -s "${conftgz_url}" > "/etc/config.tgz" + + if [[ ! -s "/etc/config.tgz" ]]; then + warn \ + "Downloading 'config.tgz' from '${slx_server}' failed with: $return_code" + # TODO handle error + fi + fi diff --git a/modules.d/conf-tgz/hooks/unpack-config-tgz.sh b/modules.d/conf-tgz/hooks/unpack-config-tgz.sh new file mode 100755 index 00000000..a0da0cd3 --- /dev/null +++ b/modules.d/conf-tgz/hooks/unpack-config-tgz.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- + +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +# tarcopy <source_dir> <target_dir> +tarcopy() { + [ -d "$1" -a -d "$2" ] || return 1 + cd "$1" + local filelist="$(mktemp)" + find . \! -type d > "$filelist" + tar -c -p -T "$filelist" | tar -xp -C "$2" + rm -f -- "$filelist" + cd - &>/dev/null +} + +# this module unpacks the config.tgz +temporary_extract_directory="$(mktemp -d)" + if [[ -e "/etc/config.tgz" ]]; then + tar --extract --preserve-permissions \ + --file="/etc/config.tgz" \ + --directory="$temporary_extract_directory" + fi + warn "Failed to extract '/etc/config.tgz' to '$temporary_extract_directory'." + warn "$exceptions_last_traceback" +# extracted to temporary directory, now check for SLX_LOCAL_CONFIGURATION + +source "/etc/openslx" +if [[ -n "$SLX_LOCAL_CONFIGURATION" ]]; then + if [[ ! -d "${temporary_extract_directory}/openslx-configs/${SLX_LOCAL_CONFIGURATION}" ]]; then + warn "SLX_LOCAL_CONFIGURATION is set but no corresponding folder found in '/etc/config.tgz'. Ignoring..." + else + tarcopy "${temporary_extract_directory}/openslx-configs/${SLX_LOCAL_CONFIGURATION}" "${temporary_extract_directory}" + fi +fi + # purge openslx-configs/ + rm -rf "${temporary_extract_directory}/openslx-configs" + tarcopy "${temporary_extract_directory}" "$NEWROOT" + + + # TODO error handling diff --git a/modules.d/conf-tgz/module-setup.sh b/modules.d/conf-tgz/module-setup.sh new file mode 100755 index 00000000..a07539cb --- /dev/null +++ b/modules.d/conf-tgz/module-setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +check() { + return 255 +} +depends() { + echo dnbd3-rootfs slx-tools +} +install() { + inst_hook pre-mount 20 "$moddir/hooks/fetch-config-tgz.sh" + inst_hook pre-pivot 20 "$moddir/hooks/unpack-config-tgz.sh" + # TODO check if busybox is enough + inst_multiple tar mktemp gzip +} diff --git a/modules.d/dnbd3-rootfs/binaries/dnbd3 b/modules.d/dnbd3-rootfs/binaries/dnbd3 new file mode 160000 +Subproject a6ddfe1212a2df72cacb0f44cc872b1bd0363c3 diff --git a/modules.d/dnbd3-rootfs/binaries/kernel-qcow2-linux b/modules.d/dnbd3-rootfs/binaries/kernel-qcow2-linux new file mode 160000 +Subproject 0761b3e9e03ed63b4adfd8b4a82f334352729a4 diff --git a/modules.d/dnbd3-rootfs/binaries/kernel-qcow2-util-linux b/modules.d/dnbd3-rootfs/binaries/kernel-qcow2-util-linux new file mode 160000 +Subproject 0692b963aa3cb846d8abab5ef5247c4dbb3fec9 diff --git a/modules.d/dnbd3-rootfs/binaries/qemu-xmount b/modules.d/dnbd3-rootfs/binaries/qemu-xmount new file mode 160000 +Subproject 4873cd023da8511ed9792a318d1456c94904612 diff --git a/modules.d/dnbd3-rootfs/binaries/systemd-preserve-process-marker/Makefile b/modules.d/dnbd3-rootfs/binaries/systemd-preserve-process-marker/Makefile new file mode 100644 index 00000000..406ec50f --- /dev/null +++ b/modules.d/dnbd3-rootfs/binaries/systemd-preserve-process-marker/Makefile @@ -0,0 +1,12 @@ +CC=gcc +OPTS=-c -Wall +SOURCES=$(wildcard *.c) +OBJECTS=$(SOURCES:.c=.o) +BINS=$(SOURCES:.c=) + +all: $(BINS) + +$(BINS): $(OBJECTS) + +clean: + rm -f $(BINS) $(OBJECTS) diff --git a/modules.d/dnbd3-rootfs/binaries/systemd-preserve-process-marker/systemd-preserve-process-marker.c b/modules.d/dnbd3-rootfs/binaries/systemd-preserve-process-marker/systemd-preserve-process-marker.c new file mode 100644 index 00000000..8f0fc108 --- /dev/null +++ b/modules.d/dnbd3-rootfs/binaries/systemd-preserve-process-marker/systemd-preserve-process-marker.c @@ -0,0 +1,33 @@ +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +void print_array(int argc, char *argv[]) { + // Helper function to print given array with given length. + int i = 0; + int j = 0; + for (i = 0; i < argc; i ++) { + j = 0; + while(argv[i][j] != '\0') + printf("%c", argv[i][j++]); + printf(" "); + } + printf("\n"); +} +int main(int argc, char *argv[]) { + int count; + // Last item acts as null pointer. + char **copy = calloc(sizeof(char *), argc); + // Slice first given command line argument. + for (count = 0; count < argc - 1; count++) + copy[count] = strdup(argv[count + 1]); + // Adding systemd indicator to preserve wrapped process during changing + // root filesystem. We mark wrapper and child process. + argv[0][0] = '@'; + copy[0][0] = '@'; + if (-1 == execvp(argv[1], copy)) { + perror("Executing child process failed."); + return -1; + } +} diff --git a/modules.d/dnbd3-rootfs/binaries/xmount b/modules.d/dnbd3-rootfs/binaries/xmount new file mode 160000 +Subproject 015137556fce1e21273f198ae0b9158157f74f7 diff --git a/modules.d/dnbd3-rootfs/configuration/bash b/modules.d/dnbd3-rootfs/configuration/bash new file mode 100755 index 00000000..adefda40 --- /dev/null +++ b/modules.d/dnbd3-rootfs/configuration/bash @@ -0,0 +1,3 @@ +alias poweroff='poweroff --force' +alias halt='poweroff' +alias reboot='reboot --force' diff --git a/modules.d/dnbd3-rootfs/helper/build.inc b/modules.d/dnbd3-rootfs/helper/build.inc new file mode 100644 index 00000000..b3f9561c --- /dev/null +++ b/modules.d/dnbd3-rootfs/helper/build.inc @@ -0,0 +1,291 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- + +declare -rg _mainmoddir="$(dirname "${BASH_SOURCE[0]}")/.." 2> /dev/null + +declare -rg _supported_qcow_handlers=("xmount" "kernel") +build_initialize_components() { + local qcow_handler="$_QCOW_HANDLER" + IFS='|' _pattern="^(${_supported_qcow_handlers[*]})$" export _pattern + if [[ ! "$qcow_handler" =~ $_pattern ]] ; then + echo "Unknown qcow handler '$qcow_handler' - will built all known." + echo "Supported handlers: ${_supported_qcow_handlers[*]}" + fi + _deps_base_dir="${_mainmoddir}/binaries" + # We might want to move the "binaries" repos from the dnbd3-rootfs module to main repo one day... + # TODO check for its existence using modinfo -k <kernel_version> + if [[ ! -f "${_deps_base_dir}/dnbd3/build/dnbd3.ko" ]] || \ + [[ ! -f "${_deps_base_dir}/dnbd3/build/dnbd3-client" ]]; then + echo "Could not find dnbd3, building it..." + if ! CMAKE_FLAGS="-DKERNEL_DIR=${kernel_headers}" \ + build_compile_dnbd3 "${_deps_base_dir}/dnbd3/"; then + echo "Failed to build dnbd3." + return 1 + fi + fi + # take care of the qcow handler + if [ -z "$qcow_handler" ] || [ "$qcow_handler" = "xmount" ]; then + if [[ ! -f "${_deps_base_dir}/xmount/trunk/build/src/xmount" ]]; then + echo "Could not find xmount binary, building it..." + if ! build_compile_xmount "${_deps_base_dir}/xmount/"; then + echo "Failed to build xmount binary." + return 1 + fi + fi + if [[ ! -f "${_deps_base_dir}/qemu-xmount/libxmount_input_qemu.so" ]]; then + echo "Could not find xmount qemu library, building it..." + if ! build_compile_qemu_xmount "${_deps_base_dir}/qemu-xmount/"; then + echo "Failed to build xmount qemu library." + return 1 + fi + fi + fi + if [ -z "$qcow_handler" ] || [ "$qcow_handler" = "kernel" ]; then + if [ ! -f "${_deps_base_dir}/kernel-qcow2-linux/drivers/block/loop/loop.ko" ] \ + || [ ! -f "${_deps_base_dir}/kernel-qcow2-linux/drivers/block/loop/loop_file_fmt_qcow.ko" ] \ + || [ ! -f "${_deps_base_dir}/kernel-qcow2-linux/drivers/block/loop/loop_file_fmt_raw.ko" ]; then + echo "Could not find loop kernel modules, building them..." + if ! build_compile_kernel_qcow "${_deps_base_dir}/kernel-qcow2-linux"; then + echo "Failed to build qcow loop kernel modules." + return 1 + fi + fi + if [ ! -f "${_deps_base_dir}/kernel-qcow2-util-linux/losetup" ]; then + echo "Could not find losetup with qcow2 support, building it..." + if ! build_compile_losetup_qcow "${_deps_base_dir}/kernel-qcow2-util-linux"; then + echo "Failed to build losetup with qcow support." + return 1 + fi + fi + fi + + # always compile this helper since it does not cost much to do so + if [[ ! -f "${_deps_base_dir}/systemd-preserve-process-marker/systemd-preserve-process-marker" ]]; then + echo "Could not find systemd-preserve-process-marker binary, building it ..." + if ! build_compile_systemd_preserve_process_marker \ + "${_deps_base_dir}/systemd-preserve-process-marker/"; then + echo "Failed to build systemd-preserve-process-marker" + return 1 + fi + fi + echo "Compilation of dnbd3-rootfs dependencies succeeded." + return 0 +} + +clean_components() { + local __doc__=' + Removes all compiled kernel specific files. + NOTE: This method is triggered manually and not supported by dracut itself. + + Example: + + `clean` + ' + local _submoddir="${_mainmoddir}/binaries" + build_clean_xmount "${_submoddir}/xmount/" + build_clean_qemu_xmount "${_submoddir}/qemu-xmount/" + build_clean_dnbd3 "${_submoddir}/dnbd3/" + build_clean_losetup_qcow "${_submoddir}/kernel-qcow2-util-linux" + build_clean_dnbd3 "${_submoddir}/dnbd3/" + build_clean_systemd_preserve_process_marker \ + "${_submoddir}/systemd-preserve-process-marker/" + return 0 +} +# endregion + +build_compile_qemu_xmount() { + local __doc__=' + Compiles qemu libxmount. + NOTE: expects xmount installation under + $1/../xmount/trunk/build/release_build/ + + Provides the following file: + "$1/libxmount_input_qemu.so" + + Example: + + `build_compile_qemu_xmount /qemu_source /xmount/installation` + ' + pushd "$1" + local xmount_installation="../xmount/trunk/build/release_build/usr" + [ ! -z "$2" ] && xmount_installation="$2" + ./configure --enable-xmount-input --python="$(which python2)" \ + --extra-cflags="-std=gnu99" \ + --disable-werror \ + --extra-cflags="-fPIC" \ + --extra-cflags="-I${xmount_installation}/include" \ + --extra-cflags="-I${xmount_installation}/include/xmount" \ + --disable-fdt --target-list="" + make -j libxmount_input_qemu.so + local ret=$? + popd + return $ret +} +build_clean_qemu_xmount() { + local __doc__='Clean the build of `build_compile_qemu_xmount`.' + pushd "$1" + make clean + local ret=$? + popd + return $ret +} +build_compile_xmount() { + local __doc__=' + Compiles xmount. + + Provides the xmount installation under: + "$1/trunk/build/release_build/" + + Example: + + `build_compile_xmount /xmount_source /xmount_source/build /usr` + ' + pushd "$1" + + local destination_directory="./release_build" + [ ! -z "$2" ] && destination_directory="$2" + local install_prefix="/usr" + [ ! -z "$3" ] && install_prefix="$3" + + mkdir --parents trunk/build + cd trunk/build || return 1 + cmake -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$install_prefix" .. + make -j + make install DESTDIR="$destination_directory" + local ret=$? + popd + return $ret +} +build_clean_xmount() { + local __doc__='Clean the build of `build_compile_xmount`.' + rm --recursive --force "$1/trunk/build" +} +build_compile_dnbd3() { + local __doc__=' + Compiles dnbd3 kernel module and client. + + Provides the following file: + "$1/build/dnbd3.ko" + "$1/build/dnbd3-client" + + Examples: + + `build_compile_dnbd3 path/to/dnbd3/source/` + + Passing the kernel version to cmake: + `CMAKE_FLAGS="-DKERNEL_VERSION=4.14.6-openslx+" \ + build_compile_dnbd3 path/to/dnbd3/source/` + ' + pushd "$1" + # NOTE: The generic way would be: "./build.sh" but this tries to build + # more than we really need and takes more time. + mkdir --parents build + cd build + # Inject CMAKE_FLAGS as a way to control how cmake is called, + # e.g. to pass the kernel version + cmake ${CMAKE_FLAGS} \ + -DBUILD_FUSE_CLIENT=OFF \ + -DBUILD_KERNEL_MODULE=ON \ + -DBUILD_SERVER=OFF \ + -DBUILD_STRESSTEST=OFF \ + ../ + make -j dnbd3 dnbd3-client + local ret=$? + popd + return $ret +} +build_clean_dnbd3() { + local __doc__='Clean the build of `build_compile_dnbd3`.' + rm --recursive --force "$1/build" + return $? +} +build_compile_kernel_qcow() { + pushd "$1" + # https://lab.ks.uni-freiburg.de/projects/kernel-qcow2/wiki + if [ -z "$kernel_headers" ]; then + echo "Kernel header directory not set, ignoring." + return 1 + fi + mkdir -p "${kernel_headers}/drivers/block/loop" + for _file in \ + include/uapi/linux/loop.h \ + drivers/block/Kconfig \ + drivers/block/loop/loop_main.h \ + drivers/block/loop/loop_file_fmt.h \ + drivers/block/loop/Kconfig; do + cp -f "${_file}" "${kernel_headers}/${_file}" + done + ( + set -o errexit + make -C "$kernel_headers" CONFIG_BLK_DEV_LOOP=m \ + M=$(pwd)/drivers/block/loop loop.ko + make -C "$kernel_headers" CONFIG_BLK_DEV_LOOP_FILE_FMT_RAW=m \ + M=$(pwd)/drivers/block/loop loop_file_fmt_raw.ko + make -C "$kernel_headers" CONFIG_BLK_DEV_LOOP_FILE_FMT_QCOW=m \ + M=$(pwd)/drivers/block/loop loop_file_fmt_qcow.ko + ) + local ret=$? + popd + return $ret +} +build_clean_kernel_qcow() { + if [ -z "$kernel_headers" ]; then + echo "Kernel header directory not set, ignoring." + return 1 + fi + pushd "$kernel_headers" + make -C "$kernel_headers" M=$(pwd)/drivers/block/loop clean + local ret=$? + popd + return $ret +} +build_compile_losetup_qcow() { + pushd "$1" + ( + set -o errexit + ./autogen.sh + ./configure + make -j losetup + gcc -I./libsmartcols/src -O2 -o .libs/losetup sys-utils/losetup-losetup.o .libs/libcommon.a .libs/libsmartcols.a + ) + local ret=$? + popd + return $ret +} +build_clean_losetup_qcow() { + pushd "$1" + make clean + local ret=$? + popd + return $ret +} +build_compile_systemd_preserve_process_marker() { + local __doc__=' + Compiles simple c program. + + Examples: + + `build_compile_systemd_preserve_process_marker path/to/program/folder` + ' + pushd "$1" + make + local ret=$? + popd + return $ret +} +build_clean_systemd_preserve_process_marker() { + local __doc__=' + Clean the build of + `build_compile_systemd_preserve_process_marker`. + ' + pushd "$1" + make clean + local ret=$? + popd + return $ret +} +# region vim modline +# vim: set tabstop=4 shiftwidth=4 expandtab: +# vim: foldmethod=marker foldmarker=region,endregion: +# endregion diff --git a/modules.d/dnbd3-rootfs/hooks/copy-dnbd3-service-into-newroot.sh b/modules.d/dnbd3-rootfs/hooks/copy-dnbd3-service-into-newroot.sh new file mode 100755 index 00000000..ddfe4992 --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/copy-dnbd3-service-into-newroot.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +systemd_system_unit_path="$(dirname \ + "$(systemctl show -p FragmentPath dracut-mount.service | cut -c 14-)")" +new_systemd_system_unit_path="${NEWROOT}/lib/systemd/system" +cp "${systemd_system_unit_path}/dnbd3root.service" \ + "${new_systemd_system_unit_path}/dnbd3root.service" +mkdir --parents "${new_systemd_system_unit_path}/sysinit.target.wants" +ln --symbolic '../dnbd3root.service' \ + "${new_systemd_system_unit_path}/sysinit.target.wants/dnbd3root.service" diff --git a/modules.d/dnbd3-rootfs/hooks/copy-dracut-systemd-files-into-newroot.sh b/modules.d/dnbd3-rootfs/hooks/copy-dracut-systemd-files-into-newroot.sh new file mode 100755 index 00000000..5de1f2e9 --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/copy-dracut-systemd-files-into-newroot.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +# Needed to be able to go back to dracut at system shutdown. +temporary_directory_path="$(mktemp --directory)" +mount --options bind / "$temporary_directory_path" +cp --recursive --no-target-directory "$temporary_directory_path" /run/initramfs +umount "$temporary_directory_path" +rm --dir "$temporary_directory_path" + +# Dracut may not be installed on the new root. Thus copy all services over. +dracut_mount_unit_path="$(systemctl show -p FragmentPath dracut-mount.service \ + | cut -c 14-)" +systemd_system_unit_path="${dracut_mount_unit_path%/*}" +new_systemd_system_unit_path="${NEWROOT}/lib/systemd/system" + +mkdir --parents "$new_systemd_system_unit_path/initrd.target.wants" +for file in \ + dracut-cmdline.service \ + dracut-initqueue.service \ + dracut-mount.service \ + dracut-pre-mount.service \ + dracut-pre-pivot.service \ + dracut-pre-trigger.service \ + dracut-pre-udev.service +do + cp "${systemd_system_unit_path}/${file}" \ + "${new_systemd_system_unit_path}/${file}" + # "ln" returns an error if the link already exists. + source_path="../${file}" + target_path="${new_systemd_system_unit_path}/initrd.target.wants/${file}" + ln --symbolic "$source_path" "$targetPath" &>/dev/null || \ + warn "Failed to link \"$source_path\" to \"$target_path\"." +done diff --git a/modules.d/dnbd3-rootfs/hooks/copy-openslx-configuration-into-newroot.sh b/modules.d/dnbd3-rootfs/hooks/copy-openslx-configuration-into-newroot.sh new file mode 100755 index 00000000..ff01474f --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/copy-openslx-configuration-into-newroot.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh +source "/etc/openslx" + +mkdir --parents "${NEWROOT}/opt/openslx" +cp "/etc/openslx" "${NEWROOT}/opt/openslx/config" + +echo "## Generated by '$0' in stage3" >> "${NEWROOT}/opt/openslx/config" +cat "/run/openslx/network.conf" >> "${NEWROOT}/opt/openslx/config" + +# Set root/demo password for stage4, if set +if [ -n "${SLX_ROOT_PASS}" ]; then + sed -i "s#^root:[^:]*:#root:$SLX_ROOT_PASS:#" $NEWROOT/etc/shadow +fi +if [ -n "${SLX_DEMO_PASS}" ] && grep -q '^demo' $NEWROOT/etc/shadow; then + sed -i "s#^demo:[^:]*:#demo:$SLX_DEMO_PASS:#" $NEWROOT/etc/shadow +fi diff --git a/modules.d/dnbd3-rootfs/hooks/enable-sysrq.sh b/modules.d/dnbd3-rootfs/hooks/enable-sysrq.sh new file mode 100755 index 00000000..323ec45e --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/enable-sysrq.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- + +# Enables magic sysrq kernel supported key combinations. +echo 1 > /proc/sys/kernel/sysrq diff --git a/modules.d/dnbd3-rootfs/hooks/fetch-config.sh b/modules.d/dnbd3-rootfs/hooks/fetch-config.sh new file mode 100755 index 00000000..a11332a7 --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/fetch-config.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- +# region imports +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh +# endregion + +slx_server="$(getarg slxsrv=)" +slx_server_base="$(getarg slxbase=)" + +# build config_url +config_url="http://${slx_server#@}/${slx_server_base}/config" + +# check if system's uuid was set +if [ -s "/run/system-uuid" ]; then + uuid=$(cat "/run/system-uuid") + if [ -n "$uuid" ]; then + config_url="${config_url}?uuid=${uuid}" + fi +fi + +config_path="/etc/openslx.tmp" + +echo "Downloading '$config_url'..." +slx-tools download_retry -s "$config_url" > "$config_path" + +if [ ! -s "$config_path" ] ; then + warn "Downloading OpenSLX configuration file from '$config_url' failed with: $return_code" + emergency_shell "CRITICAL: System unusable." +fi + +if ! ash -n "$config_path"; then + warn "Downloaded OpenSLX configuration failed syntax check!" + emergency_shell "CRITICAL: System unusable." +fi + +# remember kcl server and base +{ + echo "SLX_KCL_SERVERS='$slx_server'" + echo "SLX_BASE_PATH='$slx_server_base'" + echo "# Config fetched from $config_url" + echo "CONFIG_DOWNLOAD_TIME=$(sed -r 's/^([0-9]+)\.([0-9]+).*$/\1\2/' /proc/uptime)" + echo '#_RCONFIG_TAG' +} > /etc/openslx + +# finally copy remote config into it +cat "$config_path" >> /etc/openslx + +# slxsrv overrides SLX_DNBD3_SERVERS if prefixed with @ +[ "${slx_server#@}" != "${slx_server}" ] && sed -i "s/^SLX_DNBD3_SERVERS=.*/SLX_DNBD3_SERVERS='${slx_server#@}'/" "/etc/openslx" +true diff --git a/modules.d/dnbd3-rootfs/hooks/load-custom-kernel-modules.sh b/modules.d/dnbd3-rootfs/hooks/load-custom-kernel-modules.sh new file mode 100755 index 00000000..b3d3eb75 --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/load-custom-kernel-modules.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh +for kmod in dnbd3 \ + "loop max_loop=8" \ + loop_file_fmt_qcow \ + loop_file_fmt_raw; do + if ! modprobe ${kmod}; then + warn "Failed to load kernel module: $kmod" + ! : + fi +done diff --git a/modules.d/dnbd3-rootfs/hooks/mount-root-device.sh b/modules.d/dnbd3-rootfs/hooks/mount-root-device.sh new file mode 100755 index 00000000..6f31bbac --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/mount-root-device.sh @@ -0,0 +1,9 @@ +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +source "/etc/openslx" +mount "$SLX_DNBD3_DEVICE_COW" "$NEWROOT" $SLX_MOUNT_ROOT_OPTIONS +if [ -n "$SLX_GENERATE_FSTAB_SCRIPT" ]; then + eval "$SLX_GENERATE_FSTAB_SCRIPT" +else + echo "" > "$NEWROOT/etc/fstab" +fi diff --git a/modules.d/dnbd3-rootfs/hooks/prepare-root-partition.sh b/modules.d/dnbd3-rootfs/hooks/prepare-root-partition.sh new file mode 100755 index 00000000..aa782184 --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/prepare-root-partition.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +type emergency_shell > /dev/null 2>&1 || source /lib/dracut-lib.sh +source /etc/openslx + +export PATH="/usr/local/bin:$PATH" +export LD_LIBRARY_PATH="/usr/local/lib" + + +# hardcode dnbd device path +declare -rg _dnbd3_dev="/dev/dnbd0" + +# all outputs are redirected to stderr, since this functions should +# only echo the path to the unpacked container to stdout. +container_unpack_xmount() { + local in_device="$1" + local out_path="/mnt/xmount" + mkdir -p "$out_path" + # check tools first + if ! hash xmount systemd-preserve-process-marker; then + warn "Missing xmount deps, will try raw..." 1>&2 + elif ! systemd-preserve-process-marker xmount \ + --in qemu "$in_device" \ + --out raw "$out_path" &>/dev/null; then + warn "xmount call failed, assuming raw image." 1>&2 + else + in_device="${out_path}/${_dnbd3_dev##*/}.dd" + fi + local out_device="$(losetup -f)" + if ! losetup "$out_device" "$in_device" --partscan; then + warn "Failed to attach '$in_device' to '$out_device'." + return 1 + fi + udevadm settle + echo "$out_device" +} + +container_unpack_losetup() { + local in_device="$1" + local out_device="$(losetup -f)" + if ! losetup -r -t QCOW "$out_device" "$in_device" --partscan; then + warn "Failed to attach '$in_device' to '$out_device'." + return + fi + udevadm settle + echo "$out_device" +} +# endregion + +( +IFS=", " +for host in ${SLX_DNBD3_SERVERS} FAIL; do + if [ "$host" = "FAIL" ]; then + emergency_shell "Failed to connect '${SLX_DNBD3_IMAGE}' "\ + "${SLX_DNBD3_RID:+(revision: $SLX_DNBD3_RID)} " + "from one of '$SLX_DNBD3_SERVERS' to '$_dnbd3_dev'." + fi + info "Trying host \"$host\"." + if systemd-preserve-process-marker dnbd3-client \ + --host "$host" \ + --image "${SLX_DNBD3_IMAGE}" \ + --device "$_dnbd3_dev" \ + ${SLX_DNBD3_RID:+--rid "$SLX_DNBD3_RID"}; then + break + fi +done +) +# endregion +# region unpack dnbd3 image +[ -z "$SLX_QCOW_HANDLER" ] && SLX_QCOW_HANDLER="xmount" +if [ "$SLX_QCOW_HANDLER" = "xmount" ]; then + read_only_device="$(container_unpack_xmount "$_dnbd3_dev")" +elif [ "$SLX_QCOW_HANDLER" = "kernel" ]; then + read_only_device="$(container_unpack_losetup "$_dnbd3_dev")" +else + warn "Unsupported QCOW handler: $SLX_QCOW_HANDLER" +fi + +# Fail fast if unpacking dnbd3 image failed. +[ -z "$read_only_device" ] && exit 1 + +# endregion +# region find system partition within dnbd3 image +if [ -z "$SLX_SYSTEM_PARTITION_PREPARATION_SCRIPT" ]; then + if [ -z "$SLX_SYSTEM_PARTITION_IDENTIFIER" ]; then + # if empty use whole device + read_only_partition="$read_only_device" + true + else + read_only_partition="$(slx-tools dev_find_partitions \ + "$read_only_device" "$SLX_SYSTEM_PARTITION_IDENTIFIER")" + fi +else + eval "$SLX_SYSTEM_PARTITION_PREPARATION_SCRIPT" +fi +if [[ ! $? || -z "$read_only_partition" ]]; then + warn "Failed to find unique device with identifier" \ + "\"${SLX_SYSTEM_PARTITION_IDENTIFIER}\"; matched devices:" \ + "\"${read_only_partition}\"" + exit 1 +fi +info "Using read-only partition: $read_only_partition" +# endregion + +# region add rw layer to dnbd3 image +# don't be fooled to think we are done, the next part is crucial +dmsetup-slx-device "$read_only_partition" +# endregion diff --git a/modules.d/dnbd3-rootfs/hooks/set-dracut-environment-variables.sh b/modules.d/dnbd3-rootfs/hooks/set-dracut-environment-variables.sh new file mode 100755 index 00000000..ad80349b --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/set-dracut-environment-variables.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- + +# Set rootok and root as dracut expects them to be set by the module preparing +# the root filesystem. + +# Tell dracut that we parsed the command line and all needed parameters are +# available. +rootok=1 +# Tell dracut where the final root fs will be located. +root=block:/dev/devicemapper/root + +# region vim modline +# vim: set tabstop=4 shiftwidth=4 expandtab: +# vim: foldmethod=marker foldmarker=region,endregion: +# endregion diff --git a/modules.d/dnbd3-rootfs/hooks/shutdown-umount.sh b/modules.d/dnbd3-rootfs/hooks/shutdown-umount.sh new file mode 100644 index 00000000..ab78733c --- /dev/null +++ b/modules.d/dnbd3-rootfs/hooks/shutdown-umount.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +source /etc/openslx + +export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +umount /oldroot +dmsetup --noudevsync remove root +losetup --detach-all +umount /mnt/* +dnbd3-client --device "$SLX_DNBD3_DEVICE" --close diff --git a/modules.d/dnbd3-rootfs/module-setup.sh b/modules.d/dnbd3-rootfs/module-setup.sh new file mode 100755 index 00000000..77543a54 --- /dev/null +++ b/modules.d/dnbd3-rootfs/module-setup.sh @@ -0,0 +1,231 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- + + +_parse_dracut_args() { + local __doc__=' + Set log level via dracut logging options and returns current debug state. + + >>> echo "$_debug" + 1 + >>> _parse_dracut_args; echo $? + 1 + + >>> _parse_dracut_args --stdlog 3; echo $? + + >>> _parse_dracut_args --stdlog 4; echo $? + >>> logging.get_commands_level + >>> logging.get_level + 0 + debug + debug + + >>> logging.get_level + critical + >>> _parse_dracut_args --stdlog 4 --verbose + >>> logging.get_level + debug + + >>> _parse_dracut_args --stdlog 4 --unknown-dracut-option; echo $? + 0 + ' + local verbose=false + local debug=false + while true; do + case "$1" in + --stdlog) + shift + local level="$1" + shift + [[ "$level" -ge 4 ]] && debug=true + ;; + --verbose) + shift + verbose=true + ;; + '') + break + ;; + *) + shift + ;; + esac + local level + $verbose && level=info + $debug && level=debug + #logging.set_level "$level" + #logging.set_commands_level debug + done + $debug + return $? +} +# WTF does this actually do aside from taking space! +_debug=0 +_parse_dracut_args ${dracut_args[*]} || _debug=$? +# endregion + +clean() { +# Sourcing some helper functions + . "$(dirname "${BASH_SOURCE[0]}")/helper/build.inc" + clean_components +} +# region dracut plugin api +check() { +# Sourcing some helper functions + . "$(dirname "${BASH_SOURCE[0]}")/helper/build.inc" + if ! build_initialize_components; then + echo "Failed to initialize components." + return 1 + fi + # NOTE: xmount must be compiled before qemu_xmount + local xmount_is_built=true + if [[ ! -f "$moddir/binaries/xmount/trunk/build/src/xmount" ]] || + [[ ! -f "$moddir/binaries/qemu-xmount/libxmount_input_qemu.so" ]]; then + xmount_is_built=false + fi + # non-critical if failed + $xmount_is_built || warn "Compiling 'xmount'/'libxmount_input_qemu' failed." + + if [[ ! -f "$moddir/binaries/dnbd3/build/dnbd3.ko" ]] || \ + [[ ! -f "$moddir/binaries/dnbd3/build/dnbd3-client" ]]; then + CMAKE_FLAGS="-DKERNEL_VERSION=${kernel}" \ + build_compile_dnbd3 "$moddir/binaries/dnbd3/" + [[ $? != 0 ]] && return 1 + fi + if [[ ! -f "$moddir/binaries/systemd-preserve-process-marker/systemd-preserve-process-marker" ]]; then + build_compile_systemd_preserve_process_marker \ + "$moddir/binaries/systemd-preserve-process-marker/" + [[ $? != 0 ]] && return 1 + fi + # TODO do we still need this ? + # NOTE: This are workarounds for: + # - distributions where "systemd-udevd" doesn't lives in "/usr/lib" but in + # "/lib". + local alternate_systemd_udevd_location='/lib/systemd/systemd-udevd' + if [[ ! -f "${systemdutildir}/systemd-udevd" ]] && \ + [[ -f "$alternate_systemd_udevd_location" ]]; then + mkdir --parents "${initdir}${systemdutildir}" + ln --symbolic --force "$alternate_systemd_udevd_location" \ + "${initdir}${systemdutildir}/systemd-udevd" + fi + # WTF? + # - "/usr/bin/sh" isn't available but "/bin/sh". + if [[ ! -f /usr/bin/sh ]] && [[ -f /bin/sh ]]; then + ln --symbolic --force /bin/sh /usr/bin/sh + fi + return 255 +} +depends() { + echo base bash kernel-modules shutdown slx-dmsetup slx-network +} +installkernel() { + local block_kmod_dir="/lib/modules/${kernel}/kernel/drivers/block" + + # dnbd3 + mkdir -p "${initdir}/${block_kmod_dir}" + inst "${moddir}/binaries/dnbd3/build/dnbd3.ko" "${block_kmod_dir}/dnbd3.ko" + + # kqcow2 kernel + local kqcow_loop_kmod_dir="${moddir}/binaries/kernel-qcow2-linux/drivers/block/loop" + if [ -e "${kqcow_loop_kmod_dir}/loop.ko" ] && \ + [ -e "${kqcow_loop_kmod_dir}/loop_file_fmt_raw.ko" ] && \ + [ -e "${kqcow_loop_kmod_dir}/loop_file_fmt_qcow.ko" ]; then + mkdir -p "${initdir}/${block_kmod_dir}/loop" + for kmod in "${kqcow_loop_kmod_dir}/"*.ko ; do + inst "$kmod" "${block_kmod_dir}/loop/$(basename $kmod)" + done + fi +} +install() { + # region binaries + inst "$moddir/binaries/dnbd3/build/dnbd3-client" /usr/local/bin/dnbd3-client + inst "$moddir/binaries/systemd-preserve-process-marker/systemd-preserve-process-marker" \ + /usr/local/bin/systemd-preserve-process-marker + # xmount + local \ + xmount_installation="$moddir/binaries/xmount/trunk/build/release_build" + if [[ -f "${xmount_installation}/usr/bin/xmount" ]]; then + inst "${xmount_installation}/usr/bin/xmount" /usr/bin/xmount + for file in ${xmount_installation}/usr/lib/xmount/*; do + inst "$file" /usr/lib/xmount/"$(basename "$file")" + done + inst "$moddir/binaries/qemu-xmount/libxmount_input_qemu.so" \ + /usr/lib/xmount/libxmount_input_qemu.so + # HACK fix missing libraries for some xmount input libs + # TODO copy the dependencies using dracut functions... + inst_libdir_file 'libafflib.so*' + inst_libdir_file 'libewf.so*' + fi + # kqcow2 losetup + local losetup_qcow2_dir="$moddir/binaries/kernel-qcow2-util-linux" + if [[ -f "${losetup_qcow2_dir}/.libs/losetup" ]]; then + inst "${losetup_qcow2_dir}/.libs/losetup" /usr/local/bin/losetup + mkdir -p "${initdir}/usr/local/lib" + cp -a "${losetup_qcow2_dir}/.libs/"*.so* "${initdir}/usr/local/lib" + fi + # endregion + # region hooks + inst_hook cmdline 00 "$moddir/hooks/enable-sysrq.sh" + # NOTE: Can be used to support old style ip append syntax and have an + # exclusive interface name - required when using dracut's regular + # 'network' module + dracut_module_included "network" && inst_hook cmdline 10 \ + "$moddir/hooks/prepare-kernel-command-line-parameter.sh" + inst_hook cmdline 90 "$moddir/hooks/set-dracut-environment-variables.sh" + inst_hook pre-udev 00 "$moddir/hooks/load-custom-kernel-modules.sh" + # Get the openslx config from the servers configured in the kernel command + # line (${SLX_SERVER}/${SLX_SERVER_BASE}/config). + inst_hook pre-mount 10 "$moddir/hooks/fetch-config.sh" + # make the final blockdevice for the root system (dnbd3 -> xmount -> + # device-mapper) + if dracut_module_included "systemd-initrd"; then + inst "$moddir/hooks/prepare-root-partition.sh" \ + /usr/local/bin/dnbd3root + inst_simple "${moddir}/services/dnbd3root.service" \ + "${systemdsystemunitdir}/dnbd3root.service" + mkdir --parents \ + "${initdir}/${systemdsystemunitdir}/dracut-mount.service.requires" + ln_r "${systemdsystemunitdir}/dnbd3root.service" \ + "${systemdsystemunitdir}/dracut-mount.service.requires/dnbd3root.service" + mkdir --parents \ + "${initdir}/${systemdsystemunitdir}/initrd.target.requires" + ln_r "${systemdsystemunitdir}/dnbd3root.service" \ + "${systemdsystemunitdir}/initrd.target.requires/dnbd3root.service" + # Copy systemd services to new root (so they don't get killed after + # switch_root) + inst_hook pre-pivot 00 \ + "$moddir/hooks/copy-dnbd3-service-into-newroot.sh" + inst_hook pre-pivot 00 \ + "$moddir/hooks/copy-dracut-systemd-files-into-newroot.sh" + inst_hook pre-shutdown 00 "$moddir/hooks/shutdown-umount.sh" + else + inst_hook pre-mount 10 "$moddir/hooks/prepare-root-partition.sh" + fi + inst_hook mount 10 "$moddir/hooks/mount-root-device.sh" + inst_hook pre-pivot 00 \ + "$moddir/hooks/copy-openslx-configuration-into-newroot.sh" + # endregion + # region scripts + # endregion + # region configuration files + # Use terminal readline settings from the template system. + inst /etc/inputrc /etc/inputrc + # Set some aliases for the initramfs context. + if [[ "$_debug" == 0 ]]; then + inst "$moddir/configuration/bash" '/etc/bash.bashrc' + inst "$moddir/configuration/bash" '/etc/profile.d/aliases' + fi + # endregion + inst_multiple \ + awk \ + basename bash blockdev \ + cat cut curl \ + dd diff dirname dmsetup \ + find \ + grep \ + insmod \ + lsblk \ + mkfifo mktemp mount mountpoint \ + sed sleep sort \ + tee touch tr +} diff --git a/modules.d/dnbd3-rootfs/services/dnbd3root.service b/modules.d/dnbd3-rootfs/services/dnbd3root.service new file mode 100644 index 00000000..df079576 --- /dev/null +++ b/modules.d/dnbd3-rootfs/services/dnbd3root.service @@ -0,0 +1,12 @@ +[Unit] +Description=root fs on dnbd3 (distributed network block device) +After=dracut-pre-mount.service network.target +Before=dracut-mount.service +DefaultDependencies=no +IgnoreOnIsolate=true + +[Service] +Type=oneshot +RemainAfterExit=true +KillMode=none +ExecStart=/usr/local/bin/dnbd3root diff --git a/modules.d/dns/module-setup.sh b/modules.d/dns/module-setup.sh new file mode 100755 index 00000000..3bad6548 --- /dev/null +++ b/modules.d/dns/module-setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + return 255 +} +depends() { + echo base +} +install() { + inst_hook pre-mount 50 "$moddir/scripts/gen-resolv-conf.sh" +} diff --git a/modules.d/dns/scripts/gen-resolv-conf.sh b/modules.d/dns/scripts/gen-resolv-conf.sh new file mode 100755 index 00000000..1601bb12 --- /dev/null +++ b/modules.d/dns/scripts/gen-resolv-conf.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +CONFFILE="/etc/resolv.conf" + +DNS=$(getargs dns=) +HOSTNAME=$(getargs hostname=) + +[ -n "$DNS" ] && echo "nameserver $DNS" >> "$CONFFILE" +[ -n "$HOSTNAME" ] && echo "$HOSTNAME" >> /etc/hostname diff --git a/modules.d/haveged/module-setup.sh b/modules.d/haveged/module-setup.sh new file mode 100644 index 00000000..d3183dbe --- /dev/null +++ b/modules.d/haveged/module-setup.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +check() { + if ! hash haveged 2>/dev/null; then + warn "Could not find haveged in $PATH. Check if its installed." + return 1 + fi + return 0 +} +# called by dracut +install() { + # see where haveged is installed + local haveged_bin="$(command -v haveged)" + if [ -z "$haveged_bin" ]; then + warn "Could not find havaged in $PATH. Check if its installed." + return 1 + fi + # TODO SysVInit support, if that even a thing anymore :) + local haveged_service="$systemdsystemunitdir/haveged.service" + if [ ! -f "$haveged_service" ]; then + # query systemd directly + haveged_service="$(systemctl show -p FragmentPath haveged | cut -c 14-)" + if [ -z "$haveged_service" ]; then + warn "Could not find haveged service in '$systemdsystemunitdir' or by querying systemd." + warn "Check if it is installed properly." + return 1 + fi + fi + inst_multiple -o \ + "$haveged_bin" \ + "$haveged_service" + + # In Ubuntu, the service sources an EnvironmentFile for default options + local haveged_env_file="$(grep -oP '^EnvironmentFile=-?\K.*' $haveged_service)" + if [ -n "$haveged_env_file" ]; then + mkdir -p "$initdir/${haveged_env_file%/*}" 2>/dev/null + cp "$haveged_env_file" "$initdir/$haveged_env_file" + fi + mkdir "$initdir/$systemdsystemunitdir/sysinit.target.wants" 2>/dev/null + ln_r "$systemdsystemunitdir/haveged.service" "$systemdsystemunitdir/sysinit.target.wants/haveged.service" +} diff --git a/modules.d/ib-conf/module-setup.sh b/modules.d/ib-conf/module-setup.sh new file mode 100755 index 00000000..0a80d89e --- /dev/null +++ b/modules.d/ib-conf/module-setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + return 255 +} +depends() { + echo dnbd3-rootfs +} +install() { + inst_hook pre-pivot 50 "$moddir/scripts/gen-ib-conf.sh" +} diff --git a/modules.d/ib-conf/scripts/gen-ib-conf.sh b/modules.d/ib-conf/scripts/gen-ib-conf.sh new file mode 100755 index 00000000..430dc887 --- /dev/null +++ b/modules.d/ib-conf/scripts/gen-ib-conf.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +type emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +. "/run/openslx/network.conf" + +# get the IP from the VLAN device if a VLAN is configured +[ -n "${SLX_VLAN_ID}" ] && SLX_PXE_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}" + +IPSUFFIX=$( + ip -4 -o addr show dev "${SLX_PXE_NETIF}" | \ + awk '{split($4,a,"/");split(a[1],b,".");print b[3]"."b[4]}' +) + +cat << EOF >> "${NEWROOT}/etc/sysconfig/network-scripts/ifcfg-ib0" +DEVICE=ib0 +NAME=ib0 +TYPE=Infiniband +BOOTPROTO=static +IPADDR=10.12.${IPSUFFIX} +BROADCAST=10.12.255.255 +NETWORK=10.12.0.0 +NETMASK=255.255.0.0 +ONBOOT=yes +NM_CONTROLLED=yes +CONNECTED_MODE=yes +MTU=65520 +EOF + diff --git a/modules.d/kexec-reboot/module-setup.sh b/modules.d/kexec-reboot/module-setup.sh new file mode 100755 index 00000000..1cda92a0 --- /dev/null +++ b/modules.d/kexec-reboot/module-setup.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + if ! hash kexec; then + derror "Failed to find kexec, please install it when using this module." + return 1 + fi + return 255 +} +depends() { + echo dnbd3-rootfs slx-tools +} +install() { + inst_simple "$moddir/scripts/kexec-reboot.sh" "/bin/kexec-reboot" + inst_multiple kexec +} diff --git a/modules.d/kexec-reboot/scripts/kexec-reboot.sh b/modules.d/kexec-reboot/scripts/kexec-reboot.sh new file mode 100755 index 00000000..68fa73b9 --- /dev/null +++ b/modules.d/kexec-reboot/scripts/kexec-reboot.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +kexec_load() { + . /lib/dracut-lib.sh + + local SLXSRV="$(getarg slxsrv)" + local SLXBASE="$(getarg slxbase)" + local DIR="$(mktemp -d)" + + if [ -z "$SLXSRV" -o -z "$SLXBASE" -o -z "$DIR" ]; then + echo "Failed to construct download URL..." + return 1 + fi + for FILE in kernel initramfs-stage31; do + if ! slx-tools download_retry "http://${SLXSRV}/${SLXBASE}/${FILE}" > "${DIR}/${FILE}" ; then + echo "Failed to download ${FILE}." + return 1 + fi + done + + if ! kexec --load "${DIR}/kernel" \ + --initrd "${DIR}/initramfs-stage31" \ + --reuse-cmdline "${1:+--append "$@"}"; then + echo "Failed to load kernel/initrd from ${DIR}" + return 1 + fi + return 0 +} + +if ! hash kexec; then + echo "kexec binary not found, aborting..." + exit 1 +fi +if kexec_load $@; then + kexec -e +else + echo "Failed to execute kexec --load" + exit 1 +fi diff --git a/modules.d/slx-addons/module-setup.sh b/modules.d/slx-addons/module-setup.sh new file mode 100755 index 00000000..296b3fe4 --- /dev/null +++ b/modules.d/slx-addons/module-setup.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + return 255 +} +depends() { + echo dnbd3-rootfs +} +install() { + inst_hook pre-pivot 30 "$moddir/scripts/setup-addons.sh" +} diff --git a/modules.d/slx-addons/scripts/setup-addons.sh b/modules.d/slx-addons/scripts/setup-addons.sh new file mode 100644 index 00000000..94c2c444 --- /dev/null +++ b/modules.d/slx-addons/scripts/setup-addons.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash +# +# Stage4 addons setup script +# +############################################################################### +# Support stage4 addons residing under '/opt/openslx/addons'. +# This script will loop over all addons found, in the form of +# directories containing directory structures relative to '/' +# +# Additionally addons are expected to provide: +# * <addon_dir>/addon-required -> script to check whether the +# addon should be installed (exit 0) or not (exit 1). +# +# * <addon_dir>/opt/openslx/etc/<addon_name>.whiteout -> list of files +# that were removed during the addon installation and thus need to be +# removed after the addon was installed. +# +# * <addon_dir>/opt/openslx/etc/<addon_name> ld.so.cache -> ld cache containing +# the newly installed libraries. CAVE: multiple addons -> ld cache combination +# +### CURRENTLY NOT EXECUTED +# * <addon_dir>/addon-init -> script that will be automatically +# be executed after the addon was installed. +# NOTE: question remains if this should be done within stage3 +# or by chroot'ing into the stage4 before executing it. +### CURRENTLY NOT EXECUTED: Since whiteouts could be handled for _all_addons + +type emergency_shell >/dev/null 2>&1 || . /lib/dracut-lib.sh + +# Check if we even have any addons to process +if [ ! -d "$NEWROOT/opt/openslx/addons" ]; then + info "No stage4 addons found." + return 0 +fi + +setup_addons() { + local ADDONS_DIR="$NEWROOT/opt/openslx/addons/" + cd "$ADDONS_DIR" || return 1 + for ADDON in *; do + if ! setup_addon "$ADDON"; then + info "Failed to setup $ADDON" + fi + done +} + +setup_addon() { + [ -z "$1" -o ! -d "$ADDONS_DIR/$1" ] && return 1 + local ADDON="$1" + cd "$ADDONS_DIR/$ADDON" || return 1 + + if ! bash addon-required 2>&1 ; then + info "'$ADDONS_DIR/$ADDON/addon-required' missing or returned non-zero, skipping..." + return 1 + fi + + for entry in $(find * -not -wholename "addon-*" 2>/dev/null); do + if [ -d "$entry" ]; then + [ -d "/$entry" ] || mkdir -p "/${entry}" + continue + fi + local dir=${entry%/*} + [ -d "$NEWROOT/$dir" ] || mkdir -p "$NEWROOT/$dir" + if [ -f "$entry" -a ! -L "$entry" ]; then + if [ ! -e "$NEWROOT/${entry}" ] || ! diff -q "$entry" "$NEWROOT/${entry}"; then + mv -f -- "$entry" "$NEWROOT/${entry}" + fi + else + # either block dev, char dev or a symlink, just overwrite them "blindly" + mv -f -- "$entry" "$NEWROOT/${entry}" + fi + done + + # post merge: remove whiteouts from filesystem + for WHITEOUT in "$NEWROOT/opt/openslx/etc/"*.whiteout; do + [ -e "$WHITEOUT" ] || continue + while read line; do + rm -f "${NEWROOT}/${line}" + done < "$WHITEOUT" + done + + # finally update ld.so.cache expected to be under /opt/openslx/etc/<addon_name>.ld.so.cache + # NOTE: if we have more than one addon in the future, we need to be extra + # careful with prebuilt ld.caches since they need to match *ALL* addons + local ADDON_LD_CACHE="$NEWROOT/opt/openslx/etc/$ADDON.ld.so.cache" + if [ ! -e "$ADDON_LD_CACHE" ] || ! mv -f -- "$ADDON_LD_CACHE" "$NEWROOT/etc/ld.so.cache" ; then + # Using prebuilt ld cache failed, try hard to find a ldconfig... + for LDCONFIG in "$(type -p ldconfig 2>/dev/null)" "${NEWROOT}/sbin/ldconfig.real"; do + if [ -x "$LDCONFIG" ] && "$LDCONFIG" -r "$NEWROOT"; then + return 0 + fi + done + # try with chroot if we have it + local CHROOT_PATH="$(type -p chroot 2>/dev/null)" + if [ -x "$CHROOT_PATH" ] && "$CHROOT_PATH" "$NEWROOT" ldconfig; then + return 0 + fi + # very bad indeed, libraries won't be registered in the cache ... + warn "Failed to find 'ldconfig' to rebuild the addon's missing ld.so.cache..." + return 1 + fi +} + +if ! setup_addons; then + warn "Failed to fully setup some addons! They will likely malfunction..." +fi diff --git a/modules.d/slx-clock/module-setup.sh b/modules.d/slx-clock/module-setup.sh new file mode 100755 index 00000000..0c21b032 --- /dev/null +++ b/modules.d/slx-clock/module-setup.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +check() { + if ! hash ntpdate; then + derror "Missing 'ntpdate'. Please install it." + return 1 + fi + # Tell dracut that this module should only be included if it is required + # explicitly. + return 255 +} +depends() { + echo dnbd3-rootfs busybox +} +install() { + # wait til we have the openslx config for ntp servers + # which happens in pre-mount/10 + inst_multiple ntpdate /etc/services /usr/share/zoneinfo/Europe/Berlin + inst /usr/share/zoneinfo/Europe/Berlin /etc/localtime + inst_hook pre-mount 15 "$moddir/scripts/ntp-sync.sh" +} diff --git a/modules.d/slx-clock/scripts/ntp-sync.sh b/modules.d/slx-clock/scripts/ntp-sync.sh new file mode 100755 index 00000000..887d5b13 --- /dev/null +++ b/modules.d/slx-clock/scripts/ntp-sync.sh @@ -0,0 +1,55 @@ +#!/bin/ash +# Sync time via network + +. /etc/openslx + +ntp_sync() { + # Try to merge with servers from DHCP. Prefer DHCP, skip duplicates + for SERVER in $SLX_NTP_SERVER; do + if ! echo "$SLX_DHCP_NTP" | grep -wq "$SERVER"; then + SLX_DHCP_NTP="$SLX_DHCP_NTP $SERVER" + fi + done + local SUCCESS= + for SERVER in $SLX_DHCP_NTP; do + if ntpdate -u -p 2 "$SERVER"; then + echo "Successfully queried $SERVER for time." + if [ "x$SLX_BIOS_CLOCK" = "xlocal" ]; then + usleep 100000 + hwclock -l -w || echo "... but could not set BIOS clock to localtime" + elif [ "x$SLX_BIOS_CLOCK" = "xutc" ]; then + usleep 100000 + hwclock -u -w || echo "... but could not set BIOS clock to UTC" + fi + SUCCESS=1 + break + fi + echo "Error querying $SERVER for current time." + done + if [ -z "$SUCCESS" ]; then + echo "No NTP server reachable" + # See if we have a timestamp in our server-config - should only be a few seconds off by now + if [ -n "$SLX_NOW" ] && [ "$SLX_NOW" -gt 1234567890 ]; then + TTS="$SLX_NOW" + if [ -n "$CONFIG_DOWNLOAD_TIME" ]; then + NOW_TIME=$(sed -r 's/^([0-9]+)\.([0-9]+).*$/\1\2/' /proc/uptime) + if [ "$CONFIG_DOWNLOAD_TIME" -gt 0 ] && [ "$NOW_TIME" -gt 0 ]; then + TTS=$(( TTS + ( NOW_TIME - CONFIG_DOWNLOAD_TIME ) / 100 )) + fi + fi + echo "Setting time to SLX_NOW ($SLX_NOW, corrected $TTS)" + date -s "@$TTS" + else + echo "No fallback option for timesync available, relying on correct RTC setup" + if [ "x$SLX_BIOS_CLOCK" = "xlocal" ]; then + # Linux defaults to RTC = UTC, so read again in this case + hwclock -l -s + fi + fi + fi +} + +ntp_sync & + +true + diff --git a/modules.d/slx-dmsetup/module-setup.sh b/modules.d/slx-dmsetup/module-setup.sh new file mode 100755 index 00000000..68e9b7b4 --- /dev/null +++ b/modules.d/slx-dmsetup/module-setup.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +check() { + return 255 +} +depends() { + echo "slx-tools" +} +install() { + inst "$moddir/scripts/dmsetup-slx-device" "/usr/local/bin/dmsetup-slx-device" + + inst_hook pre-pivot 10 "$moddir/scripts/generate-fstab-swap.sh" + inst_hook pre-pivot 00 "$moddir/scripts/grow-rootfs.sh" + # deliberatly left ext helpers out for now, since we don't really use it. + inst_multiple blockdev xxd \ + mkfs.ext4 resize2fs \ + xfs_repair xfs_growfs +} +installkernel() { + # install those modules in case the used kernel does not have them builtin + instmods \ + dm-thin-pool dm-snapshot \ + dm-crypt crc32c xts \ + xfs ext4 +} diff --git a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device new file mode 100755 index 00000000..1756865e --- /dev/null +++ b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device @@ -0,0 +1,446 @@ +#!/usr/bin/env bash +# +# Script to back given read-only device using the block device +# specified by SLX_WRITABLE_DEVICE_IDENTIFIER in the SLX config. +# If SLX_WRITABLE_DEVICE_PARTITION_TABLE is sepcified, it will +# further create device mapper devices accordingly. +# +# Example partition config: +# <type> <name> <size> <crypt> +# thin-snapshot root 10G 1 +# thin-volume tmp 20G 0 +# linear data0 5-10G 1 +# linear data1 1-50% 1 +# +# NOTE: Encrypting thin-snapshot will actually encrypt the +# entire pool data device used for the pool. +# TODO: Support external keys + +type -p emergency_shell || . /lib/dracut-lib.sh + +# for debugging purposes +set -x +exec &> /run/openslx/dmsetup.log + +# read-only device to prepare for CoW +[ -z "$1" ] && emergency_shell "Read-only device was not given!" +declare -rg read_only_device="$1" +declare -rg read_only_device_size="$(blockdev --getsz $1)" + +# global array variables storing the configuration of the partitions +declare -ag linear snapshot thin_snapshot thin_volume +parse_config() { + [ -z "$1" ] && return 1 + while IFS= read -r line; do + [ -z "$line" ] && continue + read -r type name range crypt ignore <<< "$line" + type=${type//-/_} # to use the type as variable in eval + if ! [[ "$type" =~ \ + ^(linear|snapshot|thin_snapshot|thin_volume)$ ]]; then + echo "$0: Ignoring invalid type: $line" + continue + fi + if [[ -z "$name" ]]; then + echo "$0: Ignoring nameless entry: $line" + continue + fi + unset unit min max + # ranges can be like: 40G, 40-80G, 10-20% + if ! [[ $range =~ ^([0-9]+-)*([0-9])+[GgMmKkBb%]$ ]]; then + echo "$0: Ignoring invalid range: $line" + continue + fi + # process ranges: convert percentages (of read_only_device!) + # to actual sizes (in sectors!) before saving them + local unit=${range: -1} + local min="$(cut -d'-' -f1 <<< "${range%?}" )" + local max="$(cut -d'-' -f2 <<< "${range%?}" )" + if [ "$min" -gt "$max" ]; then + echo "$0: Ignoring invalid range: $line" + continue + fi + # default for bytes + local -i potency=0 + case "$unit" in + [%]) + if [ "$max" -gt 100 ]; then + echo "Ignoring invalid percentages: $min/$max" + continue + fi + min=$(( $writable_device_size * $min / 100 )) + max=$(( $writable_device_size * $max / 100 )) + ;; + [Kk]) potency=1 ;;& + [Mm]) potency=2 ;;& + [Gg]) potency=3 ;;& + *) + # => 1024 ** potency for G, M, K, etc results in bytes + # => bytes / 512 = sectors + min=$(( $min * ( 1024 ** $potency) / 512 )) + max=$(( $max * ( 1024 ** $potency) / 512 )) + ;; + esac + if ! [[ "$crypt" =~ ^[01]$ ]]; then + echo "$0: Disabling encryption due to invalid crypt argument: $line" + crypt=0 + fi + # finally save it to the global array for this type + eval "${type}"'+=("'${name} ${crypt} ${min} ${max}'")' + done <<< "$1" +} + +# Helper to call 'dmsetup setup' without syncing with udev +# and then actively create the devices with the mknodes command. +# dmsetup_create_noudevsync <name> <table> +dmsetup_create_noudevsync() { + ( + set -o errexit + dmsetup create "$1" --noudevsync --table "$2" + dmsetup mknodes --noudevsync "$1" + ) + local ret=$? + [ $ret -ne 0 ] && dmsetup remove --noudevsync "$1" + return $ret +} + +# encrypt_device <dev_path> <encrypted_name> [<size>] +encrypt_device() { + modprobe dm-crypt || echo "$0: dm-crypt loading failed, maybe builtin?" + [ -b "$1" ] || return 1 + [ -n "$2" ] || return 1 + [ -z "$3" ] && local size="$(blockdev --getsz $1)" + local key="$(head -c32 /dev/random | xxd -p | tr -d '\n')" + if ! dmsetup_create_noudevsync "$2" \ + "0 ${3:-${size}} crypt aes-xts-plain64 $key 0 $1 0 1 allow_discards"; then + echo "$0: Failed to encrypt $1." + return 1 + fi + return 0 +} +# create_snapshot "<name> <persist>" +create_snapshot() { + modprobe dm-snapshot || echo "$0: dm-snapshot loading failed, maybe builtin?" + read -r name persist ignore <<< "$1" + if ! dmsetup_create_noudevsync "$name" \ + "0 $read_only_device_size snapshot $read_only_device $writable_device ${persist:-N} 8"; then + echo "$0: Failed to create snapshot on '$writable_device' for '$read_only_device'." + return 1 + fi + return 0 +} + +# Call this to fallback to a RAMdisk stored under /run/openslx +# This will call terminate the whole script by calling finish_setup, if successful +ramdisk_fallback() { + echo "$0: Falling back to regular dm-snapshot on a RAMdisk." + local file="$(mktemp -u -p /run/openslx dnbd_cow.XXX)" + local size="$SLX_RAMDISK_SIZE_IN_MB" + [ -z "$size" ] && size="$(awk '/MemTotal/ {printf("%d\n", $2 / 2 / 1024 )}' /proc/meminfo)" + dd of="$file" seek="$size" bs=1M count=0 &> /dev/null + writable_device="$(losetup --show --find "$file")" + cow_device_candidate="root" + while [ -b "/dev/mapper/$cow_device_candidate" ]; do + cow_device_candidate="root.$RANDOM" + done + if [ -z "$writable_device" ] || ! create_snapshot "$cow_device_candidate N"; then + emergency_shell "CRITICAL: failed to setup RAMdisk fallback." + exit 1 + fi + finish_setup "$cow_device_candidate" "0" "$size" +} + +# finish_setup <device> <type> [<size>] +# <device> is the device name only, /dev/mapper will be prepended automatically. +# <type> denotes if the created device lies in a RAMdisk (0) or is backed by a disk (1). +# <size> is given in sectors. +finish_setup() { + if [ -z "$1" ] || [ ! -b "/dev/mapper/$1" ]; then + emergency_shell "'/dev/mapper/$1' not a block device. Failed to setup CoW layer." + exit 1 + fi + if ! [[ "$2" =~ ^[0-9]$ ]]; then + emergency_shell "'$2' not a valid type, 0 or 1 expected." + fi + # <size> optional? + ( + echo "# Generated by '$0'." + echo "SLX_DNBD3_DEVICE_COW=/dev/mapper/$1" + ) >> /etc/openslx + save_partition_info "$1" "/" "$2" "$3" + exit 0 +} + +# path to save the achieved setup to +declare -rg partitions_config="/run/openslx/dmsetup.state" +cat <<-EOF > "$partitions_config" +# Generated by '$0'. +# Format: <device_mapper_dev> <mount_point> <options> +# Options can be: +# * type -> CoW layer type: 0 is RAMdisk, 1 is disk, 2 is network +# * size -> in 512 byte sectors +EOF + +# save_partition_info <dm_dev> <mount_point> <type> [<size>] +save_partition_info() { + [ -b "/dev/mapper/$1" ] || return 1 + [ -n "$2" ] || return 1 + [[ "$3" =~ ^[0-9]$ ]] || return 1 + local opts="type=$3" + # plain size given + [[ "$4" =~ ^[0-9]+$ ]] && opts="$opts,physical_size=$4" + # <physical_backing_dev_size>-<virtual_size> + [[ "$4" =~ ^[0-9]+-[0-9]+$ ]] && opts="$opts,shared_physical_size=${4%-*},virtual_size=${4#*-}" + echo "/dev/mapper/$1 $2 ${opts}" >> "$partitions_config" +} + +### +## MAIN +### + +. /etc/openslx +# This is the main variable driving this script +declare -g writable_device= +if [ -n "$SLX_WRITABLE_DEVICE_IDENTIFIER" ]; then + # only first one for now TODO create linear devices of all ID44s + writable_device="$(slx-tools dev_find_partitions "$SLX_WRITABLE_DEVICE_IDENTIFIER" | head -n 1)" +fi +if [ -z "$writable_device" ]; then + echo "$0: Could not find writable device with id '$SLX_WRITABLE_DEVICE_IDENTIFIER'." + ramdisk_fallback +fi + +# NOTE: from here on out, every value related to size is in 512 bytes sectors! +declare -g writable_device_size="$(blockdev --getsz $writable_device)" + +# If SLX_WRITABLE_DEVICE_PARTITION_TABLE is not set, just do +# regular thin-snapshot for the CoW layer, else parse it. +if [ -n "$SLX_WRITABLE_DEVICE_PARTITION_TABLE" ]; then + parse_config "$SLX_WRITABLE_DEVICE_PARTITION_TABLE" +fi +# Default to thin-snapshot, if none were configured +if [ -z "$snapshot" ] && [ -z "$thin_snapshot" ]; then + parse_config "thin-snapshot root 100% 0" +fi + +# Sanity checks for weird configurations +if [ "${#snapshot[@]}" -gt 1 ]; then + echo "Multiple snapshots specified, using first one: ${snapshot[0]}" + snapshot="${snapshot[0]}" +fi +if [ "${#thin_snapshot[@]}" -gt 1 ]; then + echo "Multiple thin-snapshots specified, using first one: ${thin_snapshot[0]}" + thin_snapshot="${thin_snapshot[0]}" +fi +if [ -n "$snapshot" ] && [ -n "$thin_snapshot" ]; then + echo "$0: Both snapshot and thin-snapshot specified, prefering thin-snapshot." + snapshot= +fi + +### +## LINEAR SLICES +### + +# start allocating spaces to the configured devices +declare -g writable_device_allocated=0 +# reserve the space for the snapshot (of either type)... +read -r name crypt min max ignore <<< "${thin_snapshot:-${snapshot}}" + +declare -g scratch_device_size=0 +if (( $min <= $writable_device_size )); then + scratch_device_size=$max + while (( $scratch_device_size >= 0 )) && (( $scratch_device_size > $writable_device_size )); do + (( scratch_device_size -= 2097152 )) # 1G steps => 2097152 sectors + done + (( $scratch_device_size < $min )) && scratch_device_size="$min" +else + # minimum snapshot size is bigger than physical device size + echo "$0: Minimum snapshot size is too big for the scratch partition." + echo "$0: You probably need to use a more conservative value." + echo "$0: Using this client maximum scratch space ($writable_device_size sectors)." + scratch_device_size="$writable_device_size" +fi + +# ... and slice it from the start of the writable device (for performance). +declare -g scratch_device="/dev/mapper/scratch" +if ! dmsetup_create_noudevsync "${scratch_device##*/}" \ + "0 $scratch_device_size linear $writable_device $writable_device_allocated"; then + echo "$0: Failed to create scratch space for the CoW layer." + # TODO do not bail directly, but try to to create the linear devices at least? + ramdisk_fallback +fi +save_partition_info "${scratch_device##*/}" "*" "1" "$scratch_device_size" + +# encrypt the scratch device, if configured +if [ "$crypt" -ne 0 ] && encrypt_device \ + "$scratch_device" "${scratch_device##*/}-crypt" "$scratch_device_size"; then + scratch_device="${scratch_device}-crypt" +fi + +writable_device_allocated="$scratch_device_size" + +# first setup linear slices of the writable device +for i in ${!linear[@]}; do + [ -z "${linear[$i]}" ] && continue + read -r name crypt min max ignore <<< "${linear[$i]}" + free_space=$(( $writable_device_size - $writable_device_allocated )) + if [ "$min" -gt "$free_space" ]; then + echo "$0: Not enough space left for linear devices: ${linear[$i]}" + break + fi + # allocate its max if it fits within the free space, otherwise use the space left. + to_allocate="$max" + [ "$to_allocate" -gt "$free_space" ] && to_allocate="$free_space" + + if ! dmsetup_create_noudevsync "$name" "0 $to_allocate linear $writable_device $writable_device_allocated"; then + echo "$0: Failed to create linear device: ${linear[$i]}" + continue + fi + # TODO sane? + save_partition_info "$name" "*" "1" "$to_allocate" + if [ "$crypt" -ne 0 ] && \ + ! encrypt_device "/dev/mapper/$name" "${name}-crypt" "$to_allocate"; then + echo "$0: Failed to encrypt '$name'." + fi + writable_device_allocated=$(( $to_allocate + $writable_device_allocated )) +done + +# we are done with the physical device, use the scratch space from now on +writable_device="$scratch_device" +writable_device_size="$scratch_device_size" + +### +## THIN-PROVISIONING +### +declare -rg pool_metadata_dev="/dev/mapper/pool-metadata" +declare -rg pool_data_dev="/dev/mapper/pool-data" +declare -rg pool_dev="/dev/mapper/pool" +create_pool() { + # create external snapshot for read-only device + # create remaining thin volumes + modprobe dm-thin-pool || echo "$0: dm-thin-pool load failed, maybe builtin?" + # create temporary metadata device + data_block_size=255 + # calculate number of sectors needed and check boundaries: + metadata_dev_size="$(( 48 * $writable_device_size / $data_block_size / 512 ))" + # Min 2MB -> 4096 sectors, max 16GB -> 33554432 sectors + [ "$metadata_dev_size" -lt 4096 ] && metadata_dev_size="4096" + # TODO handle the exotic case of a too large metadata device to fit within RAM. + [ "$metadata_dev_size" -gt 33554432 ] && metadata_dev_size="33554432" + # TODO handle persistent metadata device on disk + # create RAMdisk in /run for metadata device + metadata_dev="$(mktemp -p /run/openslx .pool-metadata.XXX)" + dd of="$metadata_dev" bs=512 seek="$metadata_dev_size" &> /dev/null + metadata_dev="$(losetup --show --find $metadata_dev)" + if ! dmsetup_create_noudevsync "${pool_metadata_dev##*/}" \ + "0 $metadata_dev_size linear $metadata_dev 0"; then + echo "$0: Failed to create pool metadata device on '$writable_device'." + return 1 + fi + # For persistent metadata device we will need to cut that space off first: + # writable_device_size=$(( $writable_device_size - $metadata_dev_size )) + + if ! dmsetup_create_noudevsync "${pool_data_dev##*/}" \ + "0 $writable_device_size linear $writable_device 0"; then + echo "$0: Failed to create pool data device on '$writable_device'." + return 1 + fi + low_water_mark=32 + if ! dmsetup_create_noudevsync "${pool_dev##*/}" \ + "0 $writable_device_size thin-pool $pool_metadata_dev $pool_data_dev $data_block_size $low_water_mark"; then + echo "$0: Failed to create thin-pool device on '$writable_device'." + return 1 + fi + return 0 +} + +# create_volume "<name> <id> <size> <backing_dev>" +create_volume() { + if [ -z "$pool_dev" -o ! -b "$pool_dev" ]; then + echo "$0: Global pool device not set or present." + return 1 + fi + if [ $# -ne 1 -o -z "$1" ]; then + echo "$0: create_volume requires one non-empty argument." + return 1 + fi + local name id size backing_dev ignore + read -r name id size backing_dev ignore <<< "$1" + + if ! dmsetup message "$pool_dev" 0 "create_thin $id"; then + echo "$0: Failed to create thin volume with id '$id' in pool '$pool_dev'." + echo "$0: It might already exists, trying anyway..." + fi + if ! dmsetup_create_noudevsync "$name" "0 $size thin $pool_dev $id $backing_dev"; then + echo "$0: Failed to create external snapshot named '$name':" + echo " Size: $size" + echo " Backing device: $backing_dev" + echo " Thin volume id: $id" + return 1 + fi + return 0 +} +if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then + if ! create_pool ; then + echo "Failed to create thin pool. Will ignore:" + echo -e "\tThin snapshot: $(declare -p thin_snapshot)" + echo -e "\tThin volumes: $(declare -p thin_volume)" + ramdisk_fallback + fi + # the order in which pool devices are created does not matter + # so start with thin volumes starting with id 2 and end with + # the thin-snapshot with id 1 which needs to call finish_setup. + volume_id=2 + # go over thin-volumes + for i in ${!thin_volume[@]}; do + [ -z "${thin_volume[$i]}" ] && continue + read -r name crypt min max ignore <<< "${thin_volume[$i]}" + # thin-volume can be safely created with max size, + # since they are overprovisioned anyway. + if ! create_volume "$name $(( volume_id++ )) $max"; then + echo "Failed to create thin volume '$name'." + fi + save_partition_info "$name" "*" "1" "${writable_device_size}-${max}" + if [ "$crypt" -ne 0 ] && ! encrypt_device \ + "/dev/mapper/$name" "$name-crypt" "$max"; then + echo "Failed to encrypt thin volume '$name'." + fi + done + + if [ -n "$thin_snapshot" ]; then + # create thin-snapshot, use first one + read -r name crypt min max ignore <<< "$thin_snapshot" + # min/max was used for the pool data device, ignore it here! + # NOTE: the filesystem will most likely malfunction if the size of the + # thin-snapshot is smaller than what it was upon creation. + # As such, the size of the thin-snapshot can only be $writable_device_size + # if it is larger than $read_only_device_size, otherwise we should only + # use $read_only_device_size. While live-shrinking the filesystem might be + # an option, it is not supported throughout all fileystems (xfs can't). + if (( writable_device_size >= read_only_device_size )); then + thin_snapshot_size="$writable_device_size" + else + thin_snapshot_size="$read_only_device_size" + fi + if ! create_volume "$name 1 $thin_snapshot_size $read_only_device"; then + echo "Failed to create external snapshot for '$read_only_device'." + ramdisk_fallback + fi + finish_setup "$name" "1" "$thin_snapshot_size" + fi +fi + +### +## SNAPSHOT (OLD FUNCTIONALITY) +### +if [ -n "$snapshot" ]; then + read -r name crypt min max ignore <<< "$snapshot" + if ! create_snapshot "$name $persist"; then + echo "Failed to create regular snapshot for '$read_only_device' on '$writable_device'." + ramdisk_fallback + fi + finish_setup "$name" "1" "$writable_device_size" +fi + +# ultimate fallback +ramdisk_fallback +exit 1 diff --git a/modules.d/slx-dmsetup/scripts/gen-fstab-persistent b/modules.d/slx-dmsetup/scripts/gen-fstab-persistent new file mode 100644 index 00000000..ed00b5de --- /dev/null +++ b/modules.d/slx-dmsetup/scripts/gen-fstab-persistent @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# +# Hook to generate stage4's fstab entries for persistent partitions +# +# Persistent identifiers (MBR types, GPT partition labels) +# are expected to be specified in the OpenSLX config +# as 'SLX_PERSISTENT_DEVICE_IDENTIFIER' and their filesystem +# as 'SLX_PERSISTENT_DEVICE_FILESYSTEM', e.g ext4 or xfs. +# If not specified, will default to 'auto' but will not +# active systemd's features 'x-systemd.makefs' and 'x-systemd.growfs' + +. /etc/openslx + +type -p emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +# NOTE: systemd makes the mount point path automatically. +# if multiple exists, take the biggest one (first in the list) +if [ -n "$SLX_PERSISTENT_DEVICE_IDENTIFIER" ]; then + declare -a persistent_dev_list + for persistent_dev in \ + $(get_partitions_by_id ${SLX_PERSISTENT_DEVICE_IDENTIFIER//,/ /}); do + [ -z "$persistent_dev" ] && continue + persistent_dev_list+=("$persistent_dev") + done + if [ "${#persistent_dev[@]}" -gt 0 ]; then + if [ "${#persistent_dev[@]}" -gt 1 ]; then + warn "$0: More than one persistent device found." + warn "$0: Will use the biggest one: ${persistent_dev[0]}" + fi + persistent_dev_systemd_name="$( tr '/' '-' <<< ${persistent_dev[0]:1})" + persistent_mount_opts="nofail" + if [ -n "$SLX_PERSISTENT_DEVICE_FILESYSTEM" ]; then + #persistent_mount_opts+=",x-systemd.requires=ensure-fs@${persistent_dev_systemd_name}" + persistent_mount_opts+=",x-systemd.after=ensure-fs@${persistent_dev_systemd_name}" + fi + ( + echo -ne "${persistent_dev[0]}\t" + echo -ne "${SLX_PERSISTENT_DEVICE_MOUNT_POINT:-/opt/openslx/persistent}\t" + echo -ne "${SLX_PERSISTENT_DEVICE_FILESYSTEM:-auto}\t" + echo -ne "${persistent_mount_opts}\t0\t2" + ) >> "$NEWROOT/etc/fstab" + + # drop-in to create filesystem if needed and + #persistent_dev_systemd_name="$( tr '/' '-' <<< ${persistent_dev[0]:1})" + #mkdir -p "$NEWROOT/etc/systemd/system/${persistent_dev_systemd_name}" + #cat <<- EOF > "$NEWROOT" + #EOF + else + warn "$0: No device with ID '$SLX_PERSISTENT_DEVICE_IDENTIFIER' found." + fi +fi +true diff --git a/modules.d/slx-dmsetup/scripts/generate-fstab-persistent.sh b/modules.d/slx-dmsetup/scripts/generate-fstab-persistent.sh new file mode 100644 index 00000000..5c6f2b82 --- /dev/null +++ b/modules.d/slx-dmsetup/scripts/generate-fstab-persistent.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# +# Hook to generate stage4's fstab entries for persistent partitions +# +# Persistent identifiers (MBR types, GPT partition labels) +# are expected to be specified in the OpenSLX config +# as 'SLX_PERSISTENT_DEVICE_IDENTIFIER' and their filesystem +# as 'SLX_PERSISTENT_DEVICE_FILESYSTEM', e.g ext4 or xfs. +# If not specified, will default to 'auto' but will not +# active systemd's features 'x-systemd.makefs' and 'x-systemd.growfs' + +. /etc/openslx + +type -p emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh + +# NOTE: systemd makes the mount point path automatically. +# if multiple exists, take the biggest one (first in the list) +if [ -n "$SLX_PERSISTENT_DEVICE_IDENTIFIER" ]; then + declare -a persistent_dev_list + for persistent_dev in \ + $(get-partitions-by-id ${SLX_PERSISTENT_DEVICE_IDENTIFIER//,/ /}); do + [ -z "$persistent_dev" ] && continue + persistent_dev_list+=("$persistent_dev") + done + if [ "${#persistent_dev[@]}" -gt 0 ]; then + if [ "${#persistent_dev[@]}" -gt 1 ]; then + warn "$0: More than one persistent device found." + warn "$0: Will use the biggest one: ${persistent_dev[0]}" + fi + persistent_dev_systemd_name="$( tr '/' '-' <<< ${persistent_dev[0]:1})" + persistent_mount_opts="nofail" + if [ -n "$SLX_PERSISTENT_DEVICE_FILESYSTEM" ]; then + #persistent_mount_opts+=",x-systemd.requires=ensure-fs@${persistent_dev_systemd_name}" + persistent_mount_opts+=",x-systemd.after=ensure-fs@${persistent_dev_systemd_name}" + fi + ( + echo -ne "${persistent_dev[0]}\t" + echo -ne "${SLX_PERSISTENT_DEVICE_MOUNT_POINT:-/opt/openslx/persistent}\t" + echo -ne "${SLX_PERSISTENT_DEVICE_FILESYSTEM:-auto}\t" + echo -ne "${persistent_mount_opts}\t0\t2" + ) >> "$NEWROOT/etc/fstab" + + # drop-in to create filesystem if needed and + #persistent_dev_systemd_name="$( tr '/' '-' <<< ${persistent_dev[0]:1})" + #mkdir -p "$NEWROOT/etc/systemd/system/${persistent_dev_systemd_name}" + #cat <<- EOF > "$NEWROOT" + #EOF + else + warn "$0: No device with ID '$SLX_PERSISTENT_DEVICE_IDENTIFIER' found." + fi +fi +true diff --git a/modules.d/slx-dmsetup/scripts/generate-fstab-swap.sh b/modules.d/slx-dmsetup/scripts/generate-fstab-swap.sh new file mode 100644 index 00000000..bb37d6cf --- /dev/null +++ b/modules.d/slx-dmsetup/scripts/generate-fstab-swap.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# +# Script to create stage4's fstab entry for swap devices +# +# Will use swap partitions of MBR's type '82' or +# GPT UUID '0657fd6d-a4ab-43c4-84e5-0933c84b4f4f' +# +. /etc/openslx + +for swap_dev in \ + $(slx-tools dev_find_partitions "82" "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f"); do + + [ -z "$swap_dev" ] && continue + + # Generate swap fstab entry for NEWROOT. Use priority 10 to prefer zram + echo -e "$swap_dev\tswap\t\tswap\t\tx-systemd.makefs,pri=10\t0\t0" \ + >> "$NEWROOT/etc/fstab" + + # check if configured not to wipe any existing filesystem + [ "$SLX_WIPE_SWAP_DEVICE" = "yes" ] || continue + + # create a drop-in to wipe the device's filesystem + swap_dev_systemd_escaped="$(tr '/' '-' <<< ${swap_dev:1})" + base_dir="$NEWROOT/etc/systemd/system" + dropin_dir="$base_dir/systemd-mkswap@${swap_dev_systemd_escaped}.service.d" + mkdir -p "$dropin_dir" + cat <<- EOF > "$dropin_dir/wipefs.conf" + [Service] + ExecStartPre=/sbin/wipefs -a %f + EOF +done + +true diff --git a/modules.d/slx-dmsetup/scripts/get-partitions-by-id b/modules.d/slx-dmsetup/scripts/get-partitions-by-id new file mode 100755 index 00000000..2fe5ce7a --- /dev/null +++ b/modules.d/slx-dmsetup/scripts/get-partitions-by-id @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# +# Get all partitions with given ids (list of /dev/sdXX) +# Examples of supported ID types: +# * MBR's type: 44 +# * GPT's UUID: 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f (swap) +# * GPT's Name: OpenSLX-ID44 +# +# First argument can be a block device to limit the search to +# partitions thereof, e.g. for /dev/loop0 to look for /dev/loop0pX +# +# NOTE: for compatibility reasons, MBR's type will also +# be matched against part name 'OpenSLX-ID<id>'. +# The output will be a list of matching devices, +# sorted from largest to smallest. +get_partitions_by_id () { + local ID dev exp target + exp= + # target for the scan, defaults to /dev to check everything + target=/dev + if [ -b "$1" ]; then + target="$1"'*' + shift + fi + # support commas and pipes to separate identifiers + local args=$@ + set -- ${args//[,|]/ } + while [ $# -gt 0 ]; do + ID=$1 + shift + [ -z "$ID" ] && continue + # if single digit, e.g. 7, look for 0x7 and 0x07 + [[ $ID =~ ^[0-9]$ ]] && ID="0?$ID" + if [[ $ID =~ ^[0-9]{2}$ ]]; then + # if double digit look for MBR types and OpenSLX-ID$ID GPT labels + exp="$exp|ID_PART_ENTRY_(NAME=OpenSLX-ID|TYPE=0x)$ID" + elif [[ $ID =~ ^(0x[0-9]{2}|[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})$ ]]; then + # if full MBR type (e.g. 0x44) or UUID look for TYPE + exp="$exp|ID_PART_ENTRY_TYPE=$ID" + else + # something else, look for names of partitions / filesystems + exp="$exp|ID_(PART_ENTRY_NAME|FS_LABEL)=$ID" + fi + done + exp=${exp:1} + #echo "Partition find is '$exp'" >&2 + for dev in $(find $target -type b); do + udevadm info --name="$dev" | grep -iqE "($exp)\$" \ + && echo "$(blockdev --getsize64 "$dev") $dev" + done | sort -n -k1 -r | cut -d' ' -f2 +} + +## MAIN +if [ $# -eq 0 ]; then + echo "$0 needs at least one argument." + exit 1 +fi + +get_partitions_by_id $@ + diff --git a/modules.d/slx-dmsetup/scripts/grow-rootfs.sh b/modules.d/slx-dmsetup/scripts/grow-rootfs.sh new file mode 100644 index 00000000..e2603835 --- /dev/null +++ b/modules.d/slx-dmsetup/scripts/grow-rootfs.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# This tried to call growfs helpers (xfs_growfs, resize2fs, ...) to resize +# the root filesystem mounted on $NEWROOT to the maximum size of the backing +# disk partition (done by dmsetup-slx-device). + +. /etc/openslx + +declare -Ag growfs_helpers growfs_targets growfs_opts +# xfs +growfs_helpers[xfs]="xfs_growfs" +growfs_targets[xfs]="$NEWROOT" +growfs_opts[xfs]="-d" +# ext4 +growfs_helpers[ext4]="resize2fs" +growfs_targets[ext4]="$SLX_DNBD3_DEVICE_COW" +growfs_opts[ext4]="" + +resize_rootfs() { + # First let's check what filesystem it is + local fstype="$(blkid "$SLX_DNBD3_DEVICE_COW" | grep -oE 'TYPE=\S+')" + if [ -z "$fstype" ]; then + echo "Failed to detect filesystem on '$SLX_DNBD3_DEVICE_COW' - ignoring." + return 1 + fi + fstype="${fstype#TYPE=}" + fstype="${fstype//\"/}" + if [ ! "${growfs_helpers[${fstype}]+set}" ]; then + echo "'$fstype' not supported - ignoring." + return 1 + fi + if ! hash "${growfs_helpers[${fstype}]}" &> /dev/null; then + echo "'$fstype' is supported, but cannot find helper binary - ignoring." + return 1 + fi + if ! "${growfs_helpers[${fstype}]}" ${growfs_opts[$fstype]} "${growfs_targets[$fstype]}"; then + echo "Failed to run '${growfs_helpers[${fstype}]}' on '${growfs_targets[$fstype]}'." + return 1 + fi + return 0 +} &> /run/openslx/rootfs-grow.log + +[ -b "$SLX_DNBD3_DEVICE_COW" ] && resize_rootfs +# non-critical, so always fake success +true diff --git a/modules.d/slx-drm/hooks/activate-nvidia-drivers.sh b/modules.d/slx-drm/hooks/activate-nvidia-drivers.sh new file mode 100644 index 00000000..5c9310e8 --- /dev/null +++ b/modules.d/slx-drm/hooks/activate-nvidia-drivers.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +type emergency_shell >/dev/null 2>&1 || . /lib/dracut-lib.sh + +detect_nvidia_cards() { + # hard check on nvidia graphic cards + local cards="$(lspci | grep 'Class 0300: 10de:' | awk '{print $4}')" + if ! [ -d "/drm.cfg.d" ] && [ -n $cards ]; then + warn "Failed to find '/drm.cfg.d' or nvidia cards." + return 1 + fi + for card in $cards; do + local driver="$(awk '$1 = /'"$card"'/ {print $2}' /drm.cfg.d/*)" + [ -z "$driver" ] && continue + driver="${driver//@/}" + driver="${driver//-/\/}" + local driver_dir="/lib/modules/${driver}" + [ -d "$driver_dir" ] || continue + local driver_target="/lib/modules/$(uname -r)/kernel/drivers/gpu/drm/nvidia" + if [ -d "$driver_target" ]; then + warn "'$driver_target' exists, will not overwrite!" + return 1 + fi + # all good, move it over + if ! mv "$driver_dir" "$driver_target" 2>&1; then + warn "Failed to move '$driver_dir' to '$driver_target'." + return 1 + fi + # finally run depmod to make it visible to udev + if ! depmod -a 2>&1 ; then + warn "Failed to run depmod, udev won't see the nvidia modules." + return 1 + fi + # blacklist nouveau + echo 'blacklist nouveau' > "/lib/modprobe.d/disable-nouveau.conf" + info "Initialized nvidia drivers." + return 0 + done +} + +detect_nvidia_cards +: diff --git a/modules.d/slx-drm/hooks/copy-nvidia-drivers.sh b/modules.d/slx-drm/hooks/copy-nvidia-drivers.sh new file mode 100644 index 00000000..323af6d2 --- /dev/null +++ b/modules.d/slx-drm/hooks/copy-nvidia-drivers.sh @@ -0,0 +1,28 @@ +#!/bin/ash +# +# This script checks whether the nvidia kernel module was loaded by udev +# and copies the kernel modules over to stage4 and disables nouveau + +type emergency_shell >/dev/null 2>&1 || . /lib/dracut-lib.sh + +copy_nvidia_modules() { + local nvidia_moddir="/lib/modules/$(uname -r)/kernel/drivers/gpu/drm/nvidia" + if [ -d "${NEWROOT}/${nvidia_moddir}" ]; then + warn "Stage4 contains nvidia driver which would be overwritten - skipping." + return 1 + fi + if ! ( cp -r "$nvidia_moddir" "${NEWROOT}/${nvidia_moddir}" \ + && depmod -a -b "$NEWROOT" ); then + warn "Failed to copy/depmod nvidia modules to stage4." + return 1 + fi + # nouveau driver would needlessly load, prevent that + mkdir -p "${NEWROOT}/etc/modprobe.d" # cause why not + echo "blacklist nouveau" > "${NEWROOT}/etc/modprobe.d/disable-nouveau.conf" + return 0 +} + +if lsmod | grep -q nvidia; then + copy_nvidia_modules +fi +: # fake success diff --git a/modules.d/slx-drm/module-setup.sh b/modules.d/slx-drm/module-setup.sh new file mode 100755 index 00000000..4baa5b2a --- /dev/null +++ b/modules.d/slx-drm/module-setup.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + return 255 +} +depends() { + echo drm +} +installkernel() { + instmods acpi_ipmi +} +install() { + # grab what mltk produced, to externalize this part! + for dir in "/drm.cfg.d" "/lib/modules/nvidia"; do + [ -d "$dir" ] || continue + mkdir -p "${initdir}/${dir%/*}" + cp -ar "$dir" "${initdir}/${dir%/*}" + done + inst_hook pre-udev 10 "${moddir}/hooks/activate-nvidia-drivers.sh" + inst_hook pre-pivot 50 "${moddir}/hooks/copy-nvidia-drivers.sh" +} diff --git a/modules.d/slx-network/TODO b/modules.d/slx-network/TODO new file mode 100644 index 00000000..bd119512 --- /dev/null +++ b/modules.d/slx-network/TODO @@ -0,0 +1 @@ +# autostart dhcp in stage4 diff --git a/modules.d/slx-network/hooks/activate-bootif-dhcp.sh b/modules.d/slx-network/hooks/activate-bootif-dhcp.sh new file mode 100644 index 00000000..f5345c61 --- /dev/null +++ b/modules.d/slx-network/hooks/activate-bootif-dhcp.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# This script configures the udhcpc-based DHCP service for +# within stage4, unless specifically disabled by SLX_STAGE4_DHCP + +. /etc/openslx +[ -n "$SLX_STAGE4_DHCP" ] || exit 0 + +for script in setup-bootif-network udhcpc-trigger; do + if [ -e "${NEWROOT}/opt/openslx/scripts/${script}" ]; then + mv "${NEWROOT}/opt/openslx/scripts/${script}"{,.stage4} + fi + cp -f "/opt/openslx/scripts/${script}.stage4" \ + "${NEWROOT}/opt/openslx/scripts/${script}" +done + +# copy udhcpc@ systemd service, backup existing ones for debugging +mkdir -p "${NEWROOT}/etc/systemd/system" +cp -f "/opt/openslx/services/udhcpc-bootif.service" "${NEWROOT}/etc/systemd/system" + +# it requires /run/network +echo 'd /run/network 0755 root root' > "${NEWROOT}/etc/tmpfiles.d/network.conf" + +# activate it for the bridge or the physical interface if not bridged +systemctl --quiet --root "$NEWROOT" enable "udhcpc-bootif" + diff --git a/modules.d/slx-network/hooks/copy-network-files.sh b/modules.d/slx-network/hooks/copy-network-files.sh new file mode 100644 index 00000000..d1dd48d1 --- /dev/null +++ b/modules.d/slx-network/hooks/copy-network-files.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +type -p warn &> /dev/null || . /lib/dracut-lib.sh + +if [ -n "$NEWROOT" ]; then + # backup network configuration files found in stage4 + for file in /etc/{hostname,hosts,resolv.conf}; do + if [ ! -e "$file" ]; then + warn "Missing '$file' - won't move it to stage4. " + continue + fi + if [ -e "${NEWROOT}/${file}" ] || [ -h "${NEWROOT}/${file}" ]; then + mv "${NEWROOT}/${file}" "${NEWROOT}/${file}.stage4" + fi + cp -af "$file" "${NEWROOT}/etc" + done + # special handling for resolv.conf: + # move it to /opt/openslx to detect we are managing it + mkdir -p "${NEWROOT}/opt/openslx" + mv "${NEWROOT}/etc/resolv.conf" "${NEWROOT}/opt/openslx/resolv.conf" + ln -s "/opt/openslx/resolv.conf" "${NEWROOT}/etc/resolv.conf" + + # HACK: finally make sure we have rdns helper + # This should be done more elegantly one day... + rdns="$(type -p rdns)" + if [ -n "$rdns" ]; then + mkdir -p "${NEWROOT}/opt/openslx/bin" + cp -f "$rdns" "${NEWROOT}/opt/openslx/bin" + fi +fi +true diff --git a/modules.d/slx-network/hooks/parse-ipxe-network-kcl.sh b/modules.d/slx-network/hooks/parse-ipxe-network-kcl.sh new file mode 100644 index 00000000..56abb680 --- /dev/null +++ b/modules.d/slx-network/hooks/parse-ipxe-network-kcl.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# +# TODO VLAN support + +command -v getarg >/dev/null || . /lib/dracut-lib.sh + +# static names for the boot interface and its bridge +declare -rg BOOTIF_NAME="boot0" +declare -rg BRIDGE_NAME="br0" +declare -rg RUNTIME_CONF="/run/openslx/network.conf" +mkdir -p "${RUNTIME_CONF%/*}" +# Get all the ip-related arguments from the KCL +parse_kernel_command_line() { + ## KCL "BOOTIF": MAC address of the interface that DHCP'ed during PXE + declare -g BOOTIF="$(getarg BOOTIF=)" + # Remove the hardware type prefix of BOOTIF if it has 20 chars to get + # the plain MAC address. The hardware type prefix has length 3, e.g. "01-". + if [ -n "${BOOTIF}" ] && [ ${#BOOTIF} -eq 20 ]; then + BOOTIF="${BOOTIF#???}" + BOOTIF="${BOOTIF//-/:}" + fi + readonly BOOTIF + + ## KCL "ip": is expected in following format (syslinux IPAPPEND3): + declare -rg IPCONF="$(getarg ip=)" + # <CLIENT_IP>:<PXE_SERVER_IP>:<GATEWAY_IP>:<NETMASK> + declare -g CLIENT_IP= + declare -g SERVER_IP= + declare -g GATEWAY_IP= + declare -g NETMASK= + read -r CLIENT_IP SERVER_IP GATEWAY_IP NETMASK \ + <<< $( awk -F: '{print $1" "$2" "$3" "$4}' <<< "${IPCONF}" ) + readonly CLIENT_IP SERVER_IP GATEWAY_IP NETMASK + + # Calculate routing prefix from netmask + declare -rg ROUTING_PREFIX="$(ipcalc -s -p "$CLIENT_IP" "$NETMASK")" + + # KCL "hostname" + declare -rg HOSTNAME="$(getarg hostname=)" + [ -n "$HOSTNAME" ] && echo "$HOSTNAME" > /proc/sys/kernel/hostname + + # KCL "dns" + declare -rg DNS="$(getarg dns=)" + + # KCL "domain" + declare -rg DOMAIN="$(getarg domain=)" + + # VLAN tag + declare -rg VLAN="$(getarg vlan=)" + if [ -n "$VLAN" ]; then + modprobe 8021q || warn "VLAN mode detected but failed to load 8021q!" + fi + + # Bridged mode? + grep -wqE 'bridged' /proc/cmdline && declare -rg BRIDGED="y" +} + +save_network_config() { + cat <<-EOF > "${RUNTIME_CONF}" + SLX_PXE_CLIENT_IP='${CLIENT_IP}' + SLX_PXE_SERVER_IP='${SERVER_IP}' + SLX_PXE_GATEWAY='${GATEWAY_IP}' + SLX_PXE_NETMASK='${NETMASK}' + SLX_PXE_MAC='${BOOTIF}' + SLX_PXE_NETIF='${BOOTIF_NAME}' + SLX_PXE_DNS='${DNS}' + SLX_PXE_HOSTNAME='${HOSTNAME}' + SLX_PXE_DOMAIN='${DOMAIN}' + SLX_BRIDGE='${BRIDGED:+${BRIDGE_NAME}}' + SLX_VLAN_ID='${VLAN}' + EOF +} + +# Create udev rule to rename the PXE boot interface to BOOTIF_NAME +create_udev_bootif_name_rule() { + if [ -z "${BOOTIF}" ]; then + echo "No BOOTIF set, was it present in the kernel command line?" + return 1 + fi + # priority 70 < 80-net-name-slot.rules. + echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'${BOOTIF}'", NAME="'${BOOTIF_NAME}'"' > /etc/udev/rules.d/70-pxe-boot-interface.rules +} + +## MAIN ## +# Get IP config from KCL +parse_kernel_command_line + +# Save network config for later use +save_network_config & + +# Create the udev rule to rename the boot interface to the declared BOOTIF_NAME +create_udev_bootif_name_rule & + +/sbin/initqueue --settled /usr/local/bin/setup-bootif-network +/sbin/initqueue --finished [ -e "/.network" ] diff --git a/modules.d/slx-network/module-setup.sh b/modules.d/slx-network/module-setup.sh new file mode 100755 index 00000000..df95bfee --- /dev/null +++ b/modules.d/slx-network/module-setup.sh @@ -0,0 +1,40 @@ +#!/bin/bash +check() { + [[ $mount_needs ]] && return 1 + + if dracut_module_included "network" || dracut_module_included "systemd-networkd" ; then + derror "This module conflicts with 'network' and 'systemd-networkd'!" + return 1 + fi + return 255 +} + +# called by dracut +depends() { + echo "busybox kernel-network-modules" +} + +# called by dracut +install() { + # need initqueue to get a clean network start + dracut_need_initqueue + + # install basic dns libs + _arch=$(uname -m) + inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libnss_dns.so.*" + + # stage3 network scripts + inst "${moddir}/scripts/setup-bootif-network.stage3" "/usr/local/bin/setup-bootif-network" + inst "${moddir}/scripts/udhcpc-trigger.stage3" "/usr/local/bin/udhcpc-trigger" + + # files for stage4, park them in /opt/openslx + gcc -o "${initdir}/usr/local/bin/rdns" "${moddir}/rdns.c" + inst "${moddir}/scripts/setup-bootif-network.stage4" "/opt/openslx/scripts/setup-bootif-network.stage4" + inst "${moddir}/scripts/udhcpc-trigger.stage4" "/opt/openslx/scripts/udhcpc-trigger.stage4" + inst "${moddir}/services/udhcpc-bootif.service" "/opt/openslx/services/udhcpc-bootif.service" + + # hooks + inst_hook cmdline 10 "${moddir}/hooks/parse-ipxe-network-kcl.sh" + inst_hook pre-pivot 50 "${moddir}/hooks/copy-network-files.sh" + inst_hook pre-pivot 60 "${moddir}/hooks/activate-bootif-dhcp.sh" +} diff --git a/modules.d/slx-network/rdns.c b/modules.d/slx-network/rdns.c new file mode 100644 index 00000000..218f7400 --- /dev/null +++ b/modules.d/slx-network/rdns.c @@ -0,0 +1,28 @@ +#include <stdio.h> +#include <errno.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr,"usage: %s <IPADDRESS>\n", argv[0]); + return 1; + } + + struct hostent *he; + struct in_addr ipv4addr; + struct in6_addr ipv6addr; + + inet_pton(AF_INET, argv[1], &ipv4addr); + he = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET); + if (he == NULL) return 2; + if (he->h_name == NULL) return 3; + printf("%s\n", he->h_name); + + return 0; +} + diff --git a/modules.d/slx-network/scripts/setup-bootif-network.stage3 b/modules.d/slx-network/scripts/setup-bootif-network.stage3 new file mode 100755 index 00000000..53ad8de9 --- /dev/null +++ b/modules.d/slx-network/scripts/setup-bootif-network.stage3 @@ -0,0 +1,112 @@ +#!/bin/bash +# +# This script sets up the main network interface we booted from, +# as designated by SLX_PXE_NETIF (parsed from the PXE KCL in the +# cmdline dracut hook). +# It is run inside dracut's initqueue, on settles to detect the +# physical network interface as fast as possible. + +type emergency_shell >/dev/null 2>&1 || . /lib/dracut-lib.sh + +. /run/openslx/network.conf + +# guard to not run until the phsyical interface is not ready yet +if [ ! -e "/sys/class/net/${SLX_PXE_NETIF}/device" ]; then + exit 1 +fi + +wait_for_iface() { + local _iface="$1" + local _timeout="${2:-50}" + while [ "$_timeout" -ne 0 ]; do + [ "$(cat /sys/class/net/${_iface}/operstate)" = "up" ] && break + (( _timeout -- )) + usleep 100000 + done + [ "$_timeout" -ne 0 ] +} + +# For debugging... +{ +set -x + +ip link set dev "$SLX_PXE_NETIF" up +if ! wait_for_iface "$SLX_PXE_NETIF" 300; then + warn "'$SLX_PXE_NETIF' still not up after 30sec ... trying anyway." + # TODO handle case where we waited for 30sec and it is still not up +fi + +# now determine whether we are in bridged/vlan/plain mode +MAIN_NETIF="$SLX_PXE_NETIF" +if [ -n "$SLX_VLAN_ID" ]; then + # create VLAN interface + modprobe 8021q || warn "Loading '8021q' failed - missing module?" + ip link add link "$SLX_PXE_NETIF" name "${SLX_PXE_NETIF}.${SLX_VLAN_ID}" \ + type vlan id "$SLX_VLAN_ID" + ip link set dev "${SLX_PXE_NETIF}.${SLX_VLAN_ID}" up + if wait_for_iface "${SLX_PXE_NETIF}.${SLX_VLAN_ID}"; then + MAIN_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}" + else + warn "Setting up VLAN '$SLX_VLAN_ID' failed, trying plain..." + fi +fi + +if [ -n "$SLX_BRIDGE" ]; then + for try in {1..10} ""; do + ( + set -e + brctl addbr "$SLX_BRIDGE" + brctl stp "$SLX_BRIDGE" 0 + brctl setfd "$SLX_BRIDGE" 0.000000000001 + ip link set addr "$SLX_PXE_MAC" "$SLX_BRIDGE" + brctl addif "$SLX_BRIDGE" "$MAIN_NETIF" + ip link set dev "$SLX_BRIDGE" up + wait_for_iface "$SLX_BRIDGE" + ) + # success? + if [ "$?" -eq 0 ]; then + MAIN_NETIF="$SLX_BRIDGE" + break + fi + + # nope, handle + if [ -z "$try" ]; then + emergency_shell "Failed to setup main network bridge, giving up!" + fi + warn "Failed to setup main network bridge on try $try. Retrying ..." + # delete bridge, inc try and sleep 100ms before trying again + [ -e "/sys/class/net/${SLX_BRIDGE}" ] && brctl delbr "$SLX_BRIDGE" + usleep 100000 + done +fi + +# finally add the IP address on the main NIC +if [ -n "$SLX_PXE_CLIENT_IP" ]; then + ip addr add \ + "${SLX_PXE_CLIENT_IP}/$(ipcalc -s -p "$SLX_PXE_CLIENT_IP" "$SLX_PXE_NETMASK" | sed "s/.*=//")" \ + broadcast "$(ipcalc -s -b "$SLX_PXE_CLIENT_IP" "$SLX_PXE_NETMASK" | sed "s/.*=//")" \ + dev "$MAIN_NETIF" +fi + +if [ "$USE_DHCP_UUID" = "yes" ] && [ -s "/run/system-uuid" ]; then + UUID="$(cat /run/system-uuid)" +fi + +# udhcpc +for i in 1 1 1 fail; do + [ "$i" = "fail" ] && emergency_shell "DHCP failed 3 times... cannot continue." + udhcpc -t 4 -T 3 -f -n -q \ + -i "${MAIN_NETIF}" \ + "${SLX_PXE_CLIENT_IP:+-r $SLX_PXE_CLIENT_IP}" \ + "${UUID:+-x 0x3d:$UUID}" \ + -O ntpsrv -O domain -O wpad -O search -O nisdomain \ + -s "/usr/local/bin/udhcpc-trigger" + # success? + [ "$?" -eq 0 ] && break + # nope, keep trying... + warn "DHCP failed, retrying in 1sec..." + sleep $i +done + +set +x +} &>> "/run/openslx/initramfs-network.log.$$" diff --git a/modules.d/slx-network/scripts/setup-bootif-network.stage4 b/modules.d/slx-network/scripts/setup-bootif-network.stage4 new file mode 100755 index 00000000..61f925d0 --- /dev/null +++ b/modules.d/slx-network/scripts/setup-bootif-network.stage4 @@ -0,0 +1,56 @@ +#!/bin/bash +# +# This script sets up the main network interface we booted from, +# as designated by SLX_PXE_NETIF in /opt/openslx/config +# It will run on either the bridge (SLX_BRIDGE is set) or the +# physical interface directly. + +export PATH=$PATH:/opt/openslx/sbin:/opt/openslx/bin + +. /opt/openslx/config + +if [ -z "$SLX_PXE_NETIF" ]; then + echo "Missing network information of the main boot interface." + exit 1 +fi + +MAIN_NETIF="$SLX_PXE_NETIF" +[ -n "$SLX_VLAN_ID" ] && MAIN_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}" +[ -n "$SLX_BRIDGE" ] && MAIN_NETIF="${SLX_BRIDGE}" +readonly MAIN_NETIF + +# set default options +declare -a udhcpc_opts +udhcpc_opts+=("-t" "8") +udhcpc_opts+=("-O" "domain") +udhcpc_opts+=("-O" "nissrv") +udhcpc_opts+=("-O" "nisdomain") +udhcpc_opts+=("-O" "wpad") +udhcpc_opts+=("-O" "search") +udhcpc_opts+=("-O" "wins") + +# send machine uuid during DHCP if configured +if [ "$SLX_NET_DHCP_UUID" = "yes" ]; then + uid=$(dmidecode -s system-uuid | \ + sed -r 's/^(..)(..)(..)(..)-(..)(..)-(..)(..)-(....)-/00\4\3\2\1\6\5\8\7\9/') + if [ "${#uid}" = 34 ]; then + echo "Using SMBIOS uid for DHCP" + udhcpc_opts+=( "-x" "0x3d:$uid" ) + fi +fi + +mkdir -p /run/udhcpc || echo "Could not create '/run/udhcpc'." + +udhcpc "${udhcpc_opts[@]}" \ + -i "$MAIN_NETIF" \ + -r "${SLX_PXE_CLIENT_IP}" \ + -s /opt/openslx/scripts/udhcpc-trigger \ + -p "/run/udhcpc/udhcpc.${MAIN_NETIF}.pid" +ret=$? + +if [ "${ret}" != 0 ]; then + echo "udhcpc" "Could not run 'udhcpc ${udhcpc_opts[*]}' on ${MAIN_NETIF}." +fi + +exit "${ret}" + diff --git a/modules.d/slx-network/scripts/udhcpc-trigger.stage3 b/modules.d/slx-network/scripts/udhcpc-trigger.stage3 new file mode 100755 index 00000000..d54939a8 --- /dev/null +++ b/modules.d/slx-network/scripts/udhcpc-trigger.stage3 @@ -0,0 +1,140 @@ +#!/bin/bash +# +# This script is triggered by udhcpc in stage3 and handle the +# DHCP information given as parameters + +{ +# for debugging +set -x +NETWORK_CONF="/run/openslx/network.conf" +. "$NETWORK_CONF" + +MAIN_NETIF="$SLX_PXE_NETIF" +[ -n "$SLX_VLAN_ID" ] && MAIN_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}" +[ -n "$SLX_BRIDGE" ] && MAIN_NETIF="$SLX_BRIDGE" +readonly MAIN_NETIF + +if [ "x$1" != "xbound" -a "x$1" != "xrenew" ] \ + || [ "x$interface" != "x${MAIN_NETIF}" ] \ + || [ -z "$ip" ]; then + exit 0 +fi + +## +## CORE NETWORK CONFIGURATION +## +## > IP, subnet, route + +# If we already got an IP from KCL, see if it differs, and remove first if so +# We just try to prevent everything from breaking if the DHCP server doesn't +# objey the renew request by the client and hands out a new address +if [ -n "$SLX_PXE_CLIENT_IP" ]; then + #...some address is already configured... + if [ "x${SLX_PXE_CLIENT_IP}" != "x${ip}" ]; then + #...it's a different one, reconfigure... + echo "..reconfiguring ${SLX_PXE_CLIENT_IP} to ${ip}.." + # remove default route and let it be added again below, as it might get lost when changing the primary address on the interface + ip route del default 2>/dev/null + ip addr del "$SLX_PXE_CLIENT_IP" dev "${interface}" 2>/dev/null + ip addr add "${ip}/$(ipcalc -s -p "${ip}" "${subnet}" | sed s/.*=//)" dev "${interface}" + fi +else + #...no address configured yet, just add... + echo "..adding ${ip}.." + ip addr add "${ip}/$(ipcalc -s -p "${ip}" "${subnet}" | sed s/.*=//)" dev "${interface}" +fi +echo "SLX_DHCP_CLIENT_IP='$ip'" >> "$NETWORK_CONF" + +# Same procedure for default gateway +if [ -n "${router}" ]; then + if [ -s "$SLX_PXE_GATEWAY" ]; then + if [ "x${SLX_PXE_GATEWAY}" != "x${router}" ]; then + echo "..reconfiguring default gw from ${SLX_PXE_GATEWAY} to ${router}.." + ip route replace default via "$router" + fi + else + ip route add default via "$router" + fi + echo "SLX_DHCP_GATEWAY='$router'" >> "$NETWORK_CONF" +fi + +## +## ADDITIONAL NETWORK CONFIGURATION +## +## > DNS, domain, hostname + +rm -f -- "/etc/resolv.conf" + +# DNS/domain? +if [ -n "$dns" ]; then + echo "..got DNS.." + echo "# From DHCP in stage 3.1" >> "$NETWORK_CONF" + echo "SLX_DNS='$dns'" >> "$NETWORK_CONF" +fi +for srv in $dns; do + echo "nameserver $srv" >> "/etc/resolv.conf" +done +if [ -z "$domain" ]; then + # try to get domain via reverse lookup if empty + echo "..trying to get domain via DNS, as DHCP didn't supply one.." + fqdn=$(timeout -t 3 nslookup "$ip" | grep -E "^Address +[0-9]+: +$ip " | head -n 1 | awk '{print $4}') + domain="${fqdn#*.}" +fi +# Add domain to list of search domains if not in there yet +if [ -n "$domain" ] && [ -n "$search" ]; then + FOUND=no + for sd in $search; do + [ "x$sd" = "x$domain" ] && FOUND=yes + done + [ "$FOUND" = "no" ] && search="$domain $search" +elif [ -n "$domain" ]; then + search="$domain" +fi +# Write out +if [ -n "$domain" ]; then + echo "domain $domain" >> "/etc/resolv.conf" + echo "SLX_NET_DOMAIN='$domain'" >> "/run/openslx/network.conf" +fi +if [ -n "$search" ]; then + echo "search $search" >> "/etc/resolv.conf" + echo "SLX_NET_SEARCH='$search'" >> "/run/openslx/network.conf" +fi + +if [ -n "$ntpsrv" ]; then + echo "SLX_DHCP_NTP='$ntpsrv'" >> "/run/openslx/network.conf" +fi + +# Hostname +# Ignore hostname/fqdn it if hostname was forced per KCL. +if [ -n "$SLX_PXE_HOSTNAME" ]; then + echo "Hostname set via KCL, ignoring DHCP hostname: '$hostname'" + hostname="$SLX_PXE_HOSTNAME" +else + if [ -z "$hostname" ]; then + # as with domain, if there's no hostname, try to get via DNS + echo "..trying to get hostname via DNS, as DHCP didn't supply one.." + [ -z "$fqdn" ] && fqdn=$(timeout -t 3 nslookup "$ip" | grep -E "^Address +[0-9]+: +$ip " | head -n 1 | awk '{print $4}') + hostname="${fqdn%%.*}" + elif [ -n "$domain" ]; then + fqdn="${hostname}.${domain%% *}" # in case domain is a list + fi +fi + +if [ -z "$hostname" ]; then + # no fallback hostname from DNS, use IP address + hostname="${ip//./-}" +fi + +if [ -n "$hostname" ]; then + [ -z "$fqdn" ] && fqdn="$hostname" + echo "..setting hostname $hostname (fqdn: $fqdn).." + echo "$hostname" > "/proc/sys/kernel/hostname" + echo "$hostname" > "/etc/hostname" + echo "127.0.0.1 localhost" > "/etc/hosts" + echo "127.0.1.1 $fqdn $hostname" >> "/etc/hosts" + echo "SLX_HOSTNAME='$hostname'" >> "/run/openslx/network.conf" +fi + +touch /.network +set +x +} &>> "/run/openslx/initramfs-udhcpc.log.$$" diff --git a/modules.d/slx-network/scripts/udhcpc-trigger.stage4 b/modules.d/slx-network/scripts/udhcpc-trigger.stage4 new file mode 100755 index 00000000..b4dfeafa --- /dev/null +++ b/modules.d/slx-network/scripts/udhcpc-trigger.stage4 @@ -0,0 +1,208 @@ +#!/bin/bash +# +# This script is triggered by udhcpc and handle the DHCP information +# given to this script as parameters. + +export PATH=$PATH:/opt/openslx/sbin:/opt/openslx/bin + +. /opt/openslx/config + +if [ -z "$SLX_PXE_NETIF" ]; then + echo "Missing PXE network interface information." + exit 1 +fi + +MAIN_NETIF="$SLX_PXE_NETIF" +[ -n "$SLX_VLAN_ID" ] && MAIN_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}" +[ -n "$SLX_BRIDGE" ] && MAIN_NETIF="$SLX_BRIDGE" +readonly MAIN_NETIF + +RESOLV_CONF="/opt/openslx/resolv.conf" +THIS_RESOLV="/run/network/${MAIN_NETIF}.resolv" + +rebuild_resolv_conf () { + # Don't do anything if the active resolv.conf is not ours + # Also this will not run resolvconf update.d... No idea if we should still do so... + [ -L "/etc/resolv.conf" ] || return 0 + [ "x$(readlink "/etc/resolv.conf")" == "x${RESOLV_CONF}" ] || return 0 + # Maybe make this smarter some time, if anyone is using clients that are on multiple networks at once etc... + # This is a little braindead but should work most of the time + sort -u /run/network/*.resolv > "$RESOLV_CONF" 2> /dev/null + + # add support for resolv.conf update scripts // see man(8) resolvconf + for s in /etc/resolvconf/update.d/*.sh; do + [ -f "$s" ] && [ -x "$s" ] && "$s" + done +} + +escape_search() { + echo "$@" | sed -e 's/[]\/()$*.^|[]/\\&/g' +} + +escape_replace() { + echo "$@" | sed -e 's/[\/&]/\\&/g' +} + +check_env() { + if [ -z "$ip" ] || [ -z "$subnet" ] || [ -z "$interface" ]; then + echo "$1 event with missing data" >&2 + echo "ip = '$ip'" >&2 + echo "subnet = '$subnet'" >&2 + echo "interface = '$interface'" >&2 + exit 1 + fi + # only run for the boot network interface + # TODO VLAN support + if [ "$interface" != "$MAIN_NETIF" ]; then + echo "Ignoring '$interface'..." + exit 1 + fi +} + +case "$1" in + bound|renew) + check_env "$1" + # Set address on interface + ip addr add "$ip/$(ipcalc -s -p "$ip" "$subnet" | sed s/.*=//)" dev "$interface" + # Set default route, if given + if [ -n "$router" ]; then + ip route replace default via "$router" + fi + + # get domain, hostname and thus fqdn from DNS + dns_fqdn=$(busybox timeout -t 3 rdns "$ip") + dns_short="${dns_fqdn%%.*}" + # check if it is fqdn + if [ "$dns_fqdn" == "$dns_short" ]; then + unset dns_fqdn dns_short + fi + + # Update resolver configuration file + conf_file="$(mktemp)" + # Own domain suffix + if [ -n "$domain" ]; then + : + elif [ -n "$dns_fqdn" ]; then + domain="${dns_fqdn#*.}" + + elif [ -n "$SLX_NET_DOMAIN" ]; then + domain="$SLX_NET_DOMAIN" + fi + if [ -n "$domain" ]; then + echo "domain ${domain%% *}" >> "${conf_file}" + fi + # Add domain to list of search domains if not in there yet + if [ -n "$domain" ] && [ -n "$search" ]; then + FOUND=no + for sd in $search; do + [ "x$sd" = "x$domain" ] && FOUND=yes + done + [ "$FOUND" = "no" ] && search="$domain $search" + elif [ -n "$domain" ]; then + search="$domain" + fi + # Search domains + if [ -n "$search" ]; then + echo "search $search" >> "${conf_file}" + elif [ -n "$SLX_NET_SEARCH" ]; then + echo "search $SLX_NET_SEARCH" >> "${conf_file}" + elif [ -n "$SLX_NET_DOMAIN" ]; then + echo "search $SLX_NET_DOMAIN" >> "${conf_file}" + fi + for i in $dns; do + echo "$0: Adding DNS $i" + echo "nameserver $i" >> "${conf_file}" + done + + if [ -x "/sbin/resolvconf" ] && [ -L "/etc/resolv.conf" ] && [ -d "/etc/resolvconf/update.d" ]; then + # Automatic handling :-) + resolvconf --create-runtime-directories + resolvconf --enable-updates + < "$conf_file" resolvconf -a "${interface}.udhcpc" + rm -- "$conf_file" + else + # Manual handling required :-( + mv -f "$conf_file" "$THIS_RESOLV" + rebuild_resolv_conf + fi + + # TODO: check if we really want/need to overwrite the PXE_IP, + # it might be better/clearer to change the SLX_DHCP_CLIENT_IP... + sed -i "s/^\(SLX_PXE_CLIENT_IP=\).*$/\1'$ip'/" /opt/openslx/config + # Write DOMAIN and SEARCH to /opt/openslx/config if empty + if [ -z "$SLX_NET_DOMAIN" ] && [ -n "$domain" ]; then + sed -i "/^SLX_NET_DOMAIN=/d" /opt/openslx/config + echo "SLX_NET_DOMAIN='$domain'" >> /opt/openslx/config + fi + if [ -z "$SLX_NET_SEARCH" ] && [ -n "$search" ]; then + sed -i "/^SLX_NET_SEARCH=/d" /opt/openslx/config + echo "SLX_NET_SEARCH='$search'" >> /opt/openslx/config + fi + # Same for WINS servers + if [ -z "$SLX_NET_WINS" ] && [ -n "$wins" ]; then + sed -i "/^SLX_NET_WINS=/d" /opt/openslx/config + echo "SLX_NET_WINS='$wins'" >> /opt/openslx/config + fi + + # TODO find a better way to trigger additional code, hook dir? + # Update /etc/issue for proper spacing + [ -x "/opt/openslx/scripts/openslx-create_issue" ] && /opt/openslx/scripts/openslx-create_issue + + # Remove any stray addresses; we expect the primary interface to only have one + # address supplied via DHCP. We do this after adding the new one, obviously. + rem_list=$( ip -o addr show "$interface" | awk '{ for (i=1;i<NF;++i) if ($i == "inet") print $(i+1) }' | grep -v "^${ip}/" ) + if [ -n "$rem_list" ]; then + echo "PRIMARY: Removing $rem_list since we just got assigned $ip" + echo 1 > "/proc/sys/net/ipv4/conf/$interface/promote_secondaries" + for addr in $rem_list; do + ip addr del "$addr" dev "$interface" + sed -i "/^$(escape_search "${addr%/*}")(\s|$)/d" /etc/hosts + done + fi + + # Write to openslx-config + echo "# Config written by openslx-dhcp-script (2)" >> /opt/openslx/config + sed -i "/^SLX_DNS=/d" /opt/openslx/config + echo "SLX_DNS='$dns'" >> /opt/openslx/config + ;; + + deconfig) + check_env "$1" + if [ "$interface" = "$primary" ]; then + echo "Ignoring deconfig for primary interface" + else + echo 1 > "/proc/sys/net/ipv4/conf/$interface/promote_secondaries" + clientip=${ip%%:*} + ip addr del "$clientip/$(ipcalc -s -p "$clientip" "$subnet" | sed s/.*=//)" dev "$interface" + sed -i "/^$(escape_search "$ip")(\s|$)/d" /etc/hosts + fi + + if [ -x /sbin/resolvconf ] && [ -L /etc/resolv.conf ] && [ -d /etc/resolvconf/update.d ]; then + # Automatic handling :-) + resolvconf -d "${interface}.udhcpc" + else + # Manual handling required :-( + rm -f -- "$THIS_RESOLV" + rebuild_resolv_conf + fi + ;; + + leasefail) + echo "$0: Lease failed: $message" >&2 + + ;; + + nak) + echo "$0: Received a NAK: $message" >&2 + + ;; + + *) + echo "$0: Unknown udhcpc command: $1" >&2 + exit 1 + + ;; +esac + +exit 0 + diff --git a/modules.d/slx-network/services/udhcpc-bootif.service b/modules.d/slx-network/services/udhcpc-bootif.service new file mode 100644 index 00000000..21a5de3c --- /dev/null +++ b/modules.d/slx-network/services/udhcpc-bootif.service @@ -0,0 +1,12 @@ +[Unit] +Description=DHCP Client for the main boot interface +Before=network.target +Requires=systemd-tmpfiles-setup.service +After=systemd-tmpfiles-setup.service + +[Service] +Type=forking +ExecStart=/opt/openslx/scripts/setup-bootif-network + +[Install] +WantedBy=network.target diff --git a/modules.d/slx-runmode/module-setup.sh b/modules.d/slx-runmode/module-setup.sh new file mode 100755 index 00000000..7705ad06 --- /dev/null +++ b/modules.d/slx-runmode/module-setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + return 255 +} +depends() { + echo dnbd3-rootfs +} +install() { + # unpacking config.tgz should be pre-pivot 10, let's do this afterwards + inst_hook pre-pivot 50 "$moddir/scripts/runmode.sh" +} diff --git a/modules.d/slx-runmode/scripts/runmode.sh b/modules.d/slx-runmode/scripts/runmode.sh new file mode 100644 index 00000000..a563486f --- /dev/null +++ b/modules.d/slx-runmode/scripts/runmode.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# +# SLX_SYSTEMD_TARGET overrides the default.target to boot +# the stage4 into - required for the so-called 'run mode'. + +. /etc/openslx + +if [ -n "$SLX_SYSTEMD_TARGET" ]; then + SLX_SYSTEMD_TARGET="${SLX_SYSTEMD_TARGET%.target}.target" + ln -sf "$SLX_SYSTEMD_TARGET" "$NEWROOT/etc/systemd/system/default.target" +fi + +true diff --git a/modules.d/slx-splash/data/splash.ppm.gz b/modules.d/slx-splash/data/splash.ppm.gz Binary files differnew file mode 100644 index 00000000..d30d44e2 --- /dev/null +++ b/modules.d/slx-splash/data/splash.ppm.gz diff --git a/modules.d/slx-splash/module-setup.sh b/modules.d/slx-splash/module-setup.sh new file mode 100755 index 00000000..05542269 --- /dev/null +++ b/modules.d/slx-splash/module-setup.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + return 255 +} +depends() { + echo slx-drm +} +install() { + cp "$moddir/data/splash.ppm.gz" "$initdir/etc/splash.ppm.gz" + inst_hook pre-trigger 10 "$moddir/scripts/slx-splash.sh" + inst_hook pre-pivot 20 "$moddir/scripts/restore-cursor.sh" +} diff --git a/modules.d/slx-splash/scripts/restore-cursor.sh b/modules.d/slx-splash/scripts/restore-cursor.sh new file mode 100644 index 00000000..4ba9880d --- /dev/null +++ b/modules.d/slx-splash/scripts/restore-cursor.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# +# The console cursor is disabled when starting the splash screen. +# This will add a drop-in to getty@.service to ensure the cursor +# is restored when starting gettys. + +mkdir -p "$NEWROOT/etc/systemd/system/getty@.service.d/" +cat <<- EOF > "$NEWROOT/etc/systemd/system/getty@.service.d/restore-cursor.conf" + [Service] + ExecStartPre=-/usr/bin/env bash -c "echo -en '\033c' > /dev/%I" +EOF diff --git a/modules.d/slx-splash/scripts/slx-splash.sh b/modules.d/slx-splash/scripts/slx-splash.sh new file mode 100644 index 00000000..7381997b --- /dev/null +++ b/modules.d/slx-splash/scripts/slx-splash.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +show_splash() { + if [ -e "/etc/splash.ppm.gz" ]; then + systemd-preserve-process-marker /bin/busybox fbsplash -x -b -s "/etc/splash.ppm.gz" & + elif [ -e "/etc/splash.ppm" ]; then + systemd-preserve-process-marker /bin/busybox fbsplash -x -b -s "/etc/splash.ppm" & + else + echo "Splash screen requested, but not found in initramfs..." + fi +} + +init_drm() { + # taken from dracut's plymouth module + # first trigger graphics subsystem + udevadm trigger --action=add --attr-match=class=0x030000 >/dev/null 2>&1 + # first trigger graphics and tty subsystem + udevadm trigger --action=add \ + --subsystem-match=graphics \ + --subsystem-match=drm \ + --subsystem-match=tty \ + --subsystem-match=acpi \ + >/dev/null 2>&1 + + udevadm settle --timeout=180 2>&1 +} + +if grep -wqE 'splash' /proc/cmdline; then + # first init graphics + init_drm + # disable non-critical kernel messages + echo "1 1 0 1" > /proc/sys/kernel/printk + # disable systemd's status message on console + # See: https://www.freedesktop.org/software/systemd/man/systemd.html#Signals + kill -55 1 + # clear console + busybox clear + # disable cursor + echo -e "\033[?25l" > /dev/console + # finally: + show_splash +fi + +true diff --git a/modules.d/slx-tools/module-setup.sh b/modules.d/slx-tools/module-setup.sh new file mode 100644 index 00000000..faf2a04f --- /dev/null +++ b/modules.d/slx-tools/module-setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +build() { + # clone if not cloned yet + if [ ! -d "${moddir}/src" ]; then + git clone --depth 1 "git://git.openslx.org/openslx-ng/slx-tools" "${moddir}/src" + fi + cd "${moddir}/src" + bash make.sh /usr/share/slx-tools + cd - &>/dev/null +} +check() { + if [ ! -s "${moddir}/src/slx-tools" ] && ! build; then + derror "Failed to build slx-tools" + return 1 + fi + return 255 +} + +depends() { + echo "busybox" +} + +install() { + inst "${moddir}/src/slx-tools" "/usr/bin/slx-tools" + mkdir -p "${initdir}/usr/share/slx-tools" + cp -r "${moddir}/src/modules" "${initdir}/usr/share/slx-tools" +} diff --git a/modules.d/slx-tpm/module-setup.sh b/modules.d/slx-tpm/module-setup.sh new file mode 100755 index 00000000..f9a239e0 --- /dev/null +++ b/modules.d/slx-tpm/module-setup.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +declare -rg openssl_tpm2_engine_url="https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl_tpm2_engine.git/snapshot" +declare -rg openssl_tpm2_engine_target="openssl_tpm2_engine-1.2.1" +declare -rg ibm_tss_target="ibmtss1234.tar.gz" +declare -rg ibm_tss_url="https://sourceforge.net/projects/ibmtpm20tss/files/$ibm_tss_target/download" +# TODO download in "$moddir/src" +check() { + if ! hash help2man 2>&1 /dev/null; then + echo "Missing help2man, please install it..." + return 1 + fi + mkdir -p "$moddir/build" + if [ ! -d "$moddir/build/${openssl_tpm2_engine_target}" ]; then + compile_openssl_tpm2_engine || return 1 + fi + return 255 +} +depends() { + : +} +compile_ibm_tss() { + ( + set -o errexit + wget -O "$ibm_tss_target" "$ibm_tss_url" + local build_dir="$moddir/build/${ibm_tss_target%%.*}" + mkdir -p "$build_dir" + tar xvf "$ibm_tss_target" -C "$build_dir" + cd "$build_dir/utils" + make + ) + local ret=$? + if [ $ret -ne 0 ]; then + echo "Failed to compile IBM TSS" + rm -rf "$moddir/build/${ibm_tss_target%%.*}" + fi + return $ret +} +compile_openssl_tpm2_engine() { + if [ -d "$moddir/build/${ibm_tss_target%%.*}" ]; then + compile_ibm_tss || return 1 + fi + install_ibm_tss "/" + ( + set -o errexit + wget -O "$openssl_tpm2_engine_target.tar.gz" "$openssl_tpm2_engine_url/$openssl_tpm2_engine_target.tar.gz" + tar xvf "$openssl_tpm2_engine_target.tar.gz" -C "$moddir/build" + cd "$moddir/build/$openssl_tpm2_engine_target" + bash bootstrap.sh + CFLAGS="-I$moddir/build/${ibm_tss_target%%.*}/utils -Wno-pointer-sign" ./configure + # cause help2man suck... + sed -i '/^HELP2MAN/ s/$/ --no-discard-stderr/' Makefile + make + ) +} +install_ibm_tss() { + if [ "$#" -ne 1 ]; then + echo "Failed: Needs one arg." + return 1 + fi + if [ ! -d "$moddir/build/${ibm_tss_target%%.*}" ]; then + compile_ibm_tss || return 1 + fi + cd "$moddir/build/${ibm_tss_target%%.*}/utils" + mkdir -p "$1/usr/local/bin" + # this is hacky, TODO better with /etc/ld.cache.conf.d ? + cp -a *.so* "$1/usr/lib" + mkdir -p "$1/usr/local/bin" + find . -perm /a+x -type f -exec cp {} "$1/usr/local/bin/" \; + # only needed to compile some tpm binary (not needed in initramfs) +# tar cvf - tss2 | tar xvf - -C "$1/usr/local/include" + cd - +} +install_openssl_tpm2_engine() { + if [ ! -d "$moddir/build/${openssl_tpm2_engine_target}" ]; then + echo "no build of openssl tpm2 engine" + return 1 + fi + cd "$moddir/build/${openssl_tpm2_engine_target}" + make DESTDIR="$initdir" install + mkdir -p "$initdir/usr/lib/x86_64-linux-gnu/" + cp -r /usr/lib/x86_64-linux-gnu/engines-1.1 "$initdir/usr/lib/x86_64-linux-gnu/" + ln -s "libtpm2.so" "$initdir/usr/lib/x86_64-linux-gnu/engines-1.1/tpm2.so" +} +install() { + install_openssl_tpm2_engine + install_ibm_tss "$initdir" + inst_multiple openssl + return 0 +} +installkernel() { + instmods =drivers/char/tpm +} diff --git a/modules.d/slx-uuid/bad-uuid-defaults.conf b/modules.d/slx-uuid/bad-uuid-defaults.conf new file mode 100644 index 00000000..aaf59a7d --- /dev/null +++ b/modules.d/slx-uuid/bad-uuid-defaults.conf @@ -0,0 +1,8 @@ +00000000-0000-0000-0000-000000000000 +03000200-0400-0500-0006-000700080009 +11111111-2222-3333-4444-555555555555 +44454C4C-2000-1020-8020-A0C04F202020 +4C4C4544-0000-2010-8020-80C04F202020 +4C4C4544-0046-3310-805A-B6C04F4B4D31 +A023157C-F692-11DE-977C-7F0F26276F33 +FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF diff --git a/modules.d/slx-uuid/module-setup.sh b/modules.d/slx-uuid/module-setup.sh new file mode 100755 index 00000000..569b5155 --- /dev/null +++ b/modules.d/slx-uuid/module-setup.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +check() { + # Tell dracut that this module should only be included if it is required + # explicitly. + if ! hash dmidecode; then + echo "dmidecode is missing from this system, please install it." + return 1 + fi + return 255 +} +depends() { + echo busybox +} +install() { + mkdir -p "$initdir/etc/bad-uuid.d" + inst_simple "$moddir/bad-uuid-defaults.conf" "/etc/bad-uuid.d/bad-uuid-defaults.conf" + inst_multiple dmidecode + inst_hook pre-udev 05 "$moddir/scripts/get-system-uuid.sh" + inst_hook pre-pivot 10 "$moddir/scripts/copy-system-uuid-to-newroot.sh" +} diff --git a/modules.d/slx-uuid/scripts/copy-system-uuid-to-newroot.sh b/modules.d/slx-uuid/scripts/copy-system-uuid-to-newroot.sh new file mode 100644 index 00000000..553109fb --- /dev/null +++ b/modules.d/slx-uuid/scripts/copy-system-uuid-to-newroot.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +if [ -s "/run/system-uuid" ]; then + cp "/run/system-uuid" "$NEWROOT/etc/system-uuid" +fi +true diff --git a/modules.d/slx-uuid/scripts/get-system-uuid.sh b/modules.d/slx-uuid/scripts/get-system-uuid.sh new file mode 100644 index 00000000..fd6bb125 --- /dev/null +++ b/modules.d/slx-uuid/scripts/get-system-uuid.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# +# Slighty changed version of: +# http://git.openslx.org/openslx-ng/mltk.git/plain/core/modules/system-uuid/data/bin/get-uuid + +. /lib/dracut-lib.sh + +get_system_uuid() { + if [ -e /run/openslx/network.conf ]; then + . /run/openslx/network.conf + fi + + if [ -z "$SLX_PXE_MAC" ]; then + eval $(grep -Eo BOOTIF=\\S+ /proc/cmdline) + if [ "${#BOOTIF}" -ne "20" ]; then + warn "Getting MAC from /proc/cmdline failed, using 'ip a'..." + BOOTIF=01-$(ip a | grep -A 1 ": ${SLX_BRIDGE:-br0}" | grep -o 'ether ..:..:..:..:..:..' | cut -d' ' -f2 | sed s/:/-/g) + fi + if [ "${#BOOTIF}" -ne "20" ]; then + warn "Getting MAC from 'ip a' failed, using a default value..." + BOOTIF="99-88-77-66-55-44-33" + fi + else + BOOTIF="01-$(tr ':' '-' <<< $SLX_PXE_MAC)" + fi + + local UUID=$(dmidecode -q -s system-uuid | grep -v '^#' | head -n 1 | tr 'a-z' 'A-Z') + if [ "${#UUID}" -ne "36" ]; then + warn "Determined UUID (${UUID}) has not expected length of 36, falling back to MAC..." + # Maybe use /proc/sys/kernel/random/uuid ? + UUID= + else + # Got UUID, check blacklist + local DIR="/etc/bad-uuid.d" + local TMPLIST=$(mktemp) + local BADLIST=$(mktemp) + for file in "$DIR"/*; do + [ -f "$file" ] || continue + # 11111111-2222-3333-4444-555555555555 + < "$file" tr 'a-z' 'A-Z' | grep -Eo '[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}' + done | tee "$TMPLIST" > "$BADLIST" + # Also add flipped version of bad uuids. Found some of them through googling and discovered that sometimes + # users report them in a different order. UUIDs use different endianness for the first three blocks than + # the remaining two, but some tools seem to ignore that fact. + < "$BADLIST" sed -r 's/^(..)(..)(..)(..)\-(..)(..)\-(..)(..)\-([0-9A-F]{4}\-[0-9A-F]{12})$/\4\3\2\1-\6\5-\8\7-\9/' >> "$TMPLIST" + # Finally make unique + sort -u "$TMPLIST" > "$BADLIST" + if grep -Fxq "$UUID" "$BADLIST"; then + warn "WARNING: UUID is blacklisted as potentially not being unique, using MAC fallback" + UUID= + fi + rm -f -- "$TMPLIST" "$BADLIST" + fi + + if [ -z "$UUID" ]; then + UUID=$( echo "$BOOTIF" | sed -r 's/[^0-9A-Fa-f]//g' ) + [ "${#UUID}" -eq 14 ] && UUID="${UUID:2}" + if [ "${#UUID}" -eq 12 ]; then + UUID="baad1d00-9491-4716-b98b-$UUID" + else + UUID="baad1d00-9491-4716-b98b-000000000000" + fi + fi + UUID=$( echo "$UUID" | tr 'a-z' 'A-Z' ) + readonly UUID + echo "$UUID" > "/run/system-uuid" +} + +get_system_uuid diff --git a/modules.d/systemd-networkd-ext/hooks/configure-dhcp-for-newroot.sh b/modules.d/systemd-networkd-ext/hooks/configure-dhcp-for-newroot.sh new file mode 100644 index 00000000..b9803729 --- /dev/null +++ b/modules.d/systemd-networkd-ext/hooks/configure-dhcp-for-newroot.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# +# This hook creates a networkd configuration for the NEWROOT +# * DHCP configuration for the boot interface +# * Set static hostname via /etc/hostname +# This uses the configuration file generated by the parse-kcl-for-networkd.sh +# hook Note: on systemd v219, UseDomains is bugged and does not seem to do +# anything thus that option is complemented with the KCL's domain to hopefully +# garantee one of these will take effect. + +. "/run/openslx/network.conf" + +NETWORKD_DIR="/etc/systemd/network" +mkdir -p "${NEWROOT}/${NETWORKD_DIR}" + +# First, copy over every configuration made so far, +# excluding the physical interface if bridged +cp "${NETWORKD_DIR}/${SLX_BRIDGE}"* "${NEWROOT}/${NETWORKD_DIR}" + +# Now determine which network configuration we are running +# VLANs are already configured to DHCP, so nothing to do +if [ -z "${SLX_VLAN_ID}" ]; then + # In both bridged and non-bridged mode, we need to adjust + # the configuration to DHCP for stage4 + MATCH_LINE= + MATCH_LINE_EXTRA= + MAIN_NET_CONF= + if [ -n "${SLX_BRIDGE}" ]; then + MATCH_LINE="Name=${SLX_BRIDGE}" + MAIN_NETIF_CONF="${NETWORKD_DIR}/${SLX_BRIDGE}.network" + elif [ -n "${SLX_PXE_MAC}" ]; then + MATCH_LINE="MACAddress=${SLX_PXE_MAC}" + MATCH_LINE_EXTRA="Path=pci*" + MAIN_NETIF_CONF="${NETWORKD_DIR}/${SLX_PXE_NETIF}.network" + else + emergency_shell "Could not determine network configuration mode!" + fi + # backup current network config for later reference before overwritting it + if [ -e "${MAIN_NETIF_CONF}" ]; then + mv "${NEWROOT}/${MAIN_NETIF_CONF}" "${NEWROOT}/${MAIN_NETIF_CONF}.stage3" + else + emergency_shell "Failed to find main networkd configuration: ${MAIN_NETIF_CONF}" + fi + # Now generate a DHCP configuration for the main interface + cat <<-EOF > "${NEWROOT}/${MAIN_NETIF_CONF}" + [Match] + ${MATCH_LINE} + ${MATCH_LINE_EXTRA} + + [Network] + DHCP=ipv4 + LinkLocalAddressing=no + IPv6AcceptRA=no + + [DHCP] + UseDNS=true + UseDomains=true + UseHostname=true + CriticalConnection=true + EOF +fi + +# Workaround: UseHostname seems broken, so manually set the hostname for now... +[ -n "${SLX_HOSTNAME}" ] && echo "${SLX_HOSTNAME}" > $NEWROOT/etc/hostname diff --git a/modules.d/systemd-networkd-ext/hooks/copy-networkd-files-to-newroot.sh b/modules.d/systemd-networkd-ext/hooks/copy-networkd-files-to-newroot.sh new file mode 100644 index 00000000..ec61616c --- /dev/null +++ b/modules.d/systemd-networkd-ext/hooks/copy-networkd-files-to-newroot.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# +# This hook copies the core systemd-networkd related service +# files to the NEWROOT and activate them in sysinit.target +# to prevent systemd from killing these while pivot_root +NEWROOT_SYSTEMD_DIR="${NEWROOT}/usr/lib/systemd/system" +NEWROOT_SYSINIT_TARGET_DIR="${NEWROOT_SYSTEMD_DIR}/sysinit.target.wants" +mkdir -p "${NEWROOT_SYSINIT_TARGET_DIR}" + +for UNIT in \ + systemd-networkd.socket \ + systemd-networkd.service \ + systemd-resolved.service +do + UNIT_PATH="$(systemctl show -p FragmentPath $UNIT | cut -c 14-)" + [ -z "${UNIT_PATH}" ] && continue + mkdir -p "${NEWROOT}/${UNIT_PATH%/*}" + cp "${UNIT_PATH}" "${NEWROOT}/${UNIT_PATH}" + ln -sf "${UNIT_PATH}" "${NEWROOT_SYSINIT_TARGET_DIR}/${UNIT}" +done + +if [ -e "${NEWROOT_SYSTEMD_DIR}/systemd-resolved.service" ]; then + # this drop-in is needed to prevent a pull-in loop sysinit.target <-> basic.target + mkdir -p "${NEWROOT_SYSTEMD_DIR}/systemd-resolved.service.d/" + cat <<-EOF > "${NEWROOT_SYSTEMD_DIR}/systemd-resolved.service.d/00-no-default-deps.conf" + [Unit] + DefaultDependencies=no + EOF + + # finally make sure the NEWROOT resolv.conf links to the one managed by resolved. + rm "${NEWROOT}"/etc/resolv.conf + ln -s /run/systemd/resolve/resolv.conf "${NEWROOT}"/etc/resolv.conf +fi diff --git a/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh b/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh new file mode 100644 index 00000000..a64e6efe --- /dev/null +++ b/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh @@ -0,0 +1,251 @@ +#!/bin/bash +# +# This script was mostly stolen from 40network/parse-ip-opts.sh. It was +# adapted to generate .network files for systemd-networkd using the IP +# configuration from PXE/Syslinux in addition to domain, dns and hostname + +command -v getarg >/dev/null || . /lib/dracut-lib.sh + +# static names for the boot interface and its bridge +declare -rg BOOTIF_NAME="boot0" +declare -rg BRIDGE_NAME="br0" + +# Get all the ip-related arguments from the KCL +parse_kernel_command_line() { + ## KCL "BOOTIF": MAC address of the interface that DHCP'ed during PXE + declare -g BOOTIF="$(getarg BOOTIF=)" + # Remove the hardware type prefix of BOOTIF if it has 20 chars to get + # the plain MAC address. The hardware type prefix has length 3, e.g. "01-". + [ -n "${BOOTIF}" ] && [ ${#BOOTIF} -eq 20 ] && BOOTIF="${BOOTIF#???}" + BOOTIF="$(tr '-' ':' <<< $BOOTIF)" + readonly BOOTIF + + ## KCL "ip": is expected in following format (syslinux IPAPPEND3): + declare -rg IPCONF="$(getarg ip=)" + # <CLIENT_IP>:<PXE_SERVER_IP>:<GATEWAY_IP>:<NETMASK> + declare -g CLIENT_IP= + declare -g SERVER_IP= + declare -g GATEWAY_IP= + declare -g NETMASK= + read -r CLIENT_IP SERVER_IP GATEWAY_IP NETMASK <<< $( awk -F: '{print $1" "$2" "$3" "$4}' <<< "${IPCONF}" ) + readonly CLIENT_IP SERVER_IP GATEWAY_IP NETMASK + + + # Taken from parse-ip-opts.sh: Convert the netmask to CIDR notation + declare -g CIDR + if [[ "x$NETMASK" =~ ^x[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + CIDR=$(mask2cidr "$NETMASK") + elif [ -n "$NETMASK" -a "x${NETMASK//[0-9]/}" = 'x' ]; then + # The mask is already a prefix length (uint), so validate it + [[ "x$CLIENT_IP" == x*:*:* && "$NETMASK" -le 128 || "$NETMASK" -le 32 ]] && CIDR=$NETMASK + fi + readonly CIDR + + # KCL "hostname" + declare -rg HOSTNAME="$(getarg hostname=)" + [ -n "$HOSTNAME" ] && echo "$HOSTNAME" > /proc/sys/kernel/hostname + + # KCL "dns" + declare -rg DNS="$(getarg dns=)" + + # KCL "domain" + declare -rg DOMAIN="$(getarg domain=)" + + # VLAN tag + declare -rg VLAN="$(getarg vlan=)" + if [ -n "$VLAN" ]; then + modprobe 8021q || emergency_shell "VLAN mode detected - failed to load 8021q" + fi + + # Bridged mode? + grep -wqE 'bridged' /proc/cmdline && declare -rg BRIDGED="y" +} + +# Dumps the parsed IP configuration to /run/openslx/network.conf +# Creates a list of "KEY=value" type variables to source later on +save_ip_config() { + local IP_RUNTIME_CONFIG="/run/openslx/network.conf" + mkdir -p "${IP_RUNTIME_CONFIG%/*}" # dirname a la bash + cat <<-EOF > "${IP_RUNTIME_CONFIG}" + SLX_PXE_CLIENT_IP=${CLIENT_IP} + SLX_PXE_SERVER_IP=${SERVER_IP} + SLX_PXE_GATEWAY=${GATEWAY_IP} + SLX_PXE_DNS=${DNS} + SLX_PXE_MAC=${BOOTIF} + SLX_PXE_NETIF=${BOOTIF_NAME} + SLX_BRIDGE=${BRIDGED:+${BRIDGE_NAME}} + SLX_VLAN_ID=${VLAN} + SLX_DNS=${DNS} + SLX_HOSTNAME=${HOSTNAME} + SLX_NET_DOMAIN=${DOMAIN} + EOF +} + +# Helper to echo the static configuration, +# including DNS and Domain, if given per KCL +print_static_ip_conf() { + [ $# -ne 2 ] && echo "Need 2 args: <ip/cidr> <gateway>. Given: $@" && return 1 + echo "Address=${1}" + echo "Gateway=${2}" + [ -n "${DNS}" ] && echo "DNS=${DNS}" + [ -n "${DOMAIN}" ] && echo "Domains=${DOMAIN}" +} + +# Create udev rule to rename the PXE boot interface to BOOTIF_NAME +create_udev_bootif_name_rule() { + [ -z "${BOOTIF}" ] && echo "No BOOTIF set, was it present in the kernel command line?" && return 1 + # priority 70 < 80-net-name-slot.rules. + echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'${BOOTIF}'", NAME="'${BOOTIF_NAME}'"' > /etc/udev/rules.d/70-pxe-boot-interface.rules +} + +disable_ipv6() { + cat <<- EOF + LinkLocalAddressing=no + IPv6AcceptRA=no + EOF +} + +dhcp_options() { + cat <<- EOF + [DHCP] + UseDNS=true + UseDomains=true + UseHostname=true + CriticalConnection=true + EOF +} + +## Generate network and link file(s) for networkd +# Checks if an IP configuration was forwarded by +generate_networkd_config() { + mkdir -p "/etc/systemd/network" + local BOOTIF_NETWORK_CONF="/etc/systemd/network/${BOOTIF_NAME}.network" + ( + echo '[Match]' + echo "MACAddress=${BOOTIF}" + echo "Path=pci*" + echo '' + # Currently the boot interface is configured to either: + # * static ip as given by the initial DHCP during PXE + # * bridged + # * vlan-tagged (ethernet interface not configured) + # In particular, configuring both vlan tags and the physical + # interface is not supported (might be needed in some setups) + echo '[Network]' + disable_ipv6 + if [ -n "${BRIDGED}" ]; then + echo "Bridge=${BRIDGE_NAME}" + elif [ -n "${CLIENT_IP}" -a -n "${GATEWAY_IP}" ]; then + print_static_ip_conf "${CLIENT_IP}/${CIDR:-24}" "${GATEWAY_IP}" + elif [ -n "${VLAN}" ]; then + echo "VLAN=$BOOTIF_NAME.$VLAN" + else + echo -e "DHCP=ipv4\n" + dhcp_options + fi + ) > "${BOOTIF_NETWORK_CONF}" + + if [ -n "$VLAN" ]; then + local VLAN_DEV_CONF="/etc/systemd/network/${BOOTIF_NAME}.${VLAN}.netdev" + cat <<- EOF > "${VLAN_DEV_CONF}" + [NetDev] + Name=${BOOTIF_NAME}.${VLAN} + MACAddress=${BOOTIF} + Kind=vlan + + [VLAN] + Id=${VLAN} + EOF + + # Configure the vlan tagged interface for DHCPv4, TODO IPv6 + local VLAN_NETWORK_CONF="/etc/systemd/network/${BOOTIF_NAME}.${VLAN}.network" + cat <<- EOF > "${VLAN_NETWORK_CONF}" + [Match] + Name=${BOOTIF_NAME}.${VLAN} + Type=vlan + + [Link] + MACAddress=${BOOTIF} + + [Network] + DHCP=ipv4 + EOF + ( + disable_ipv6 + echo "" + dhcp_options + ) >> "${VLAN_NETWORK_CONF}" + fi + + # bridge setup + if [ -n "$BRIDGED" ]; then + local BRIDGE_DEV_CONF="/etc/systemd/network/${BRIDGE_NAME}.netdev" + cat <<- EOF > "${BRIDGE_DEV_CONF}" + [NetDev] + Name=${BRIDGE_NAME} + Kind=bridge + MACAddress=${BOOTIF} + EOF + + local BRIDGE_NETWORK_CONF="/etc/systemd/network/${BRIDGE_NAME}.network" + ( + echo '[Match]' + echo "Name=${BRIDGE_NAME}" + echo "" + echo '[Network]' + disable_ipv6 + if [ -n "${CLIENT_IP}" -a -n "${GATEWAY_IP}" ]; then + print_static_ip_conf "${CLIENT_IP}/${CIDR:-24}" "${GATEWAY_IP}" + else + # bad/no IP info, fallback to DHCP + echo -e "DHCP=ipv4\n" + dhcp_options + fi + ) > "${BRIDGE_NETWORK_CONF}" + fi + return 0 +} + +# from parse-ip-opts.sh +# Takes a netmask and outputs the corresponding CIDR +# e.g. +# mask2cidr 255.255.255.0 +# returns: 24 +mask2cidr() { + local -i bits=0 + for octet in ${1//./ }; do + for i in {0..8}; do + [ "$octet" -eq $(( 256 - (1 << i) )) ] && bits+=$((8-i)) && break + done + [ $i -eq 8 -a "$octet" -ne 0 ] && warn "Bad netmask $mask" && return + [ $i -gt 0 ] && break + done + echo $bits +} + +## MAIN ## +# Get IP config from KCL +parse_kernel_command_line + +# Save IP config for later use +save_ip_config + +# Create the udev rule to rename the boot interface to the declared BOOTIF_NAME +create_udev_bootif_name_rule || \ + emergency_shell "Failed to create udev rule for boot interface renaming." + +# Generate config files for networkd +generate_networkd_config || \ + emergency_shell "Failed to generate networkd configuration." + +# Make dracut wait for network during the udev loop (initqueue) to make +# sure we have network access in the pre-mount hook as it is needed +# to get configurations and the root filesystem +NETIF= +[ -n "${BOOTIF_NAME}" ] && NETIF="${BOOTIF_NAME}" +[ -n "${BRIDGED}" ] && [ -n "${BRIDGE_NAME}" ] && NETIF="${BRIDGE_NAME}" +[ -n "${VLAN}" ] && NETIF="${BOOTIF_NAME}.${VLAN}" + +BB=$(command -v busybox) +[ -n "${BB}" ] && BB+=" timeout -t 60" +/sbin/initqueue --finished ${BB} /lib/systemd/systemd-networkd-wait-online -i ${NETIF} diff --git a/modules.d/systemd-networkd-ext/module-setup.sh b/modules.d/systemd-networkd-ext/module-setup.sh new file mode 100755 index 00000000..be50973d --- /dev/null +++ b/modules.d/systemd-networkd-ext/module-setup.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# shameless hacked version of dracut's systemd-networkd module +# called by dracut +check() { + [[ $mount_needs ]] && return 1 + + if dracut_module_included "network"; then + derror "The module 'systemd-networkd' conflicts with 'network'. Use either one not both!" + return 1 + fi + return 255 +} + +# called by dracut +depends() { + echo "systemd kernel-network-modules" +} + +installkernel() { + return 0 +} + +# called by dracut +install() { + # need initqueue to get a clean network start + dracut_need_initqueue + + # install required systemd units + inst_multiple -o \ + $systemdutildir/systemd-networkd \ + $systemdutildir/systemd-networkd-wait-online \ + $systemdutildir/systemd-resolved \ + $systemdsystemunitdir/systemd-networkd-wait-online.service \ + $systemdsystemunitdir/systemd-networkd.service \ + $systemdsystemunitdir/systemd-networkd.socket \ + $systemdsystemunitdir/systemd-resolved.service \ + networkctl ip + + # active them + for i in \ + systemd-networkd-wait-online.service \ + systemd-networkd.service \ + systemd-networkd.socket \ + systemd-resolved.service + do + systemctl --root "$initdir" enable "$i" + done + mkdir $initdir/$systemdsystemunitdir/network.target.wants + ln -s $systemdsystemunitdir/systemd-resolved.service \ + $initdir/$systemdsystemunitdir/network.target.wants/systemd-resolved.service + ln -sf /run/systemd/resolve/resolv.conf $initdir/etc/resolv.conf + + # create system users needed + for user in \ + systemd-network \ + systemd-resolve + do + grep "^${user}:" /etc/passwd 2>/dev/null >> "$initdir/etc/passwd" + grep "^${user}:" /etc/group >> "$initdir/etc/group" + done + + # install basic dns libs + _arch=$(uname -m) + inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libnss_dns.so.*" \ + {"tls/$_arch/",tls/,"$_arch/",}"libnss_mdns4_minimal.so.*" \ + {"tls/$_arch/",tls/,"$_arch/",}"libnss_myhostname.so.*" \ + {"tls/$_arch/",tls/,"$_arch/",}"libnss_resolve.so.*" \ + {"tls/$_arch/",tls/,"$_arch/",}"libresolve.so.*" + + # the hook script that will parse the "ip=" kernel command line + # parameter and generate the .link and .network files needed + # by systemd-networkd. + inst_hook cmdline 10 "$moddir/hooks/parse-kcl-for-networkd.sh" + inst_hook pre-pivot 10 "$moddir/hooks/copy-networkd-files-to-newroot.sh" + inst_hook pre-pivot 20 "$moddir/hooks/configure-dhcp-for-newroot.sh" +} + |