#!/bin/bash # ----------------------------------------------------------------------------- # # Copyright (c) 2011 - OpenSLX GmbH # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING # # If you have any feedback please consult http://openslx.org/feedback and # send your suggestions, praise, or complaints to feedback@openslx.org # # General information about OpenSLX can be found at http://openslx.org/ # ----------------------------------------------------------------------------- # # Mini-Linux Toolkit # # ----------------------------------------------------------------------------- SELF="$(readlink -f $0)" ROOT_DIR="$(dirname "${SELF}")" MLTK_PID="$$" # Make apt-get install non-interactive when it comes to postinstall questions # ie. kdm asking which dm you want to set as default export DEBIAN_FRONTEND=noninteractive qnd_exit() { unset_quiet kill "$MLTK_PID" [ $# -ge 1 ] && kill "$1" exit 1 } # source all helper functions files that are found under helper/*.inc for HELPER in $ROOT_DIR/helper/*.inc; do . "$HELPER" && continue unset_quiet echo "Could not source $HELPER" qnd_exit done banner () { echo -e "\033[38;5;202m\t __ __ __ " echo -e "\033[38;5;202m\t.--------.| | | |_| |--." echo -e "\033[38;5;208m\t| || |_| _| < " echo -e "\033[38;5;214m\t|__|__|__||____|____|__|__|" echo -e "\033[38;5;214m\t " echo -e "\033[38;5;220m\t ** OpenSLX Project // 2013 **" echo -e "\033[38;5;226m\t http://lab.openslx.org/" echo -e "\033[0m" } print_usage() { echo -e "" echo -e "Toolkit for creating preboot mini-linux for OpenSLX NG (mltk)" echo -e "Usage: $(basename ${SELF}) remote [-d] [-c [module]*] [-b [module]*] [-p profile]" echo -e " $(basename ${SELF}) server [-s] [] [-e stage31|stage32|addons] [-d] [-c]" echo -e "" echo -e " Mode:" echo -e " server \t server mode: packs stage3.1, stage3.2 or addons as initramfs/squashfs." echo -e " remote \t remote mode: builds a minimal rootfs based on the activated modules in " echo -e "" echo -e " Global options (valid for all modes):" echo -e " -d activates debug output for the task" echo -e " " echo -e " Options for 'remote'-mode:" echo -e " -b build module(s) and copy them to the target build directory" echo -e " -c clean build directory of module(s)." echo -e " -p profile build all modules from given profile (DEPRECATED?)" echo -e " -n bind mount all the local builds under remote/builds to /export/builds." echo -e " Allows for syncing from the server machine using the '-s'-flag." echo -e "" echo -e " In mode 'remote', you can pass names of specific modules to clean/build." echo -e " Otherwise, all modules will be built/cleaned." echo -e "" echo -e " Options for 'server'-mode:" echo -e " -e type export target as 'type'. type can be of 'stage31' (simple initramfs), 'stage32' or 'addons' (both beeing squashfs)" echo -e " -s sync 'builds' directory of remote host" echo -e " -c clean target in remote_builds/ and corresponding files under boot/" echo -e "" echo -e "--------------------------------------------------------------------------------------------------------------------------------------" echo -e "" echo -e " Examples:" echo -e " remote stage31 -c -b (clean all modules and build all linked modules in remote/targets/stage31)" echo -e " remote stage32 -c -b rootfs_stage31 sshd (clean all modules, build base, policykit and sshd in remote/builds/stage32)" echo -e " remote stage32 -c base sshd -b sshd ldm -d (clean base and sshd, build sshd and ldm, be verbose)" echo -e " remote -n (provides bind mount at /export/build for synchronizing)" echo -e " server 1.2.3.4 -s (sync all builds from remote system 1.2.3.4)" echo -e " server 1.2.3.4 stage32 -e stage32 (packs stage32 as squashfs from remote system 1.2.3.4)" echo -e " server 1.2.3.4 stage31 -c (clean stage31 build under server/remote_builds and initramfs under server/boot)" echo -e " server 1.2.3.4 addons-eexam -e addons (pack eexam-addons as squashfs)" echo -e " server 1.2.3.4 -k [configname] (generate config file configs/config.tgz)" echo -e "" echo -e " Existing targets for remote are:" echo -e " $(echo $(ls ${ROOT_DIR}/remote/targets 2>/dev/null || echo "No targets for remote found."))" echo -e "" echo -e " NOTE: Use 'local' as the remote host if you're running the server part on the same machine as the remote part." echo -e "" } check_devtools() { # Checking for needed development tools, compilers etc. # Required: m4 make gcc g++ binutils DEVTOOLS="gcc c++ g++ make m4 strip git depmod patch mksquashfs pkg-config qmake" # 'strip' as marker for binutils for i in $DEVTOOLS; do which "$i" 2>/dev/null 1>&2 || { echo "Essential development tool $i not found - exiting."; exit 1; } done # TODO make the script install the dev-stuff automaticly. # Ubuntu: 'build-essential', 'm4', 'squashfs-tools' # OpenSUSE: ??? } initial_checks() { if [ "x$(whoami)" != "xroot" ]; then perror "ERROR: You need to have root rights to install packages." exit 1 else banner fi pinfo "Arch triplet of this machine: $ARCH_TRIPLET" # source the 2 central scripts: # setup_target # - builds all modules activated under the target directory # (basic targets are 'stage31' and 'stage32') # export_target # - pack given target as a cpio or squashfs depending on # the export type: # stage31 (cpio archive of the complete stage31-filesystem) # stage32 (cpio archive containing the squashfs'ed stage32-filesystem) REMOTE_SETUP_TARGET="${ROOT_DIR}/remote/setup_target" SERVER_EXPORT_TARGET="${ROOT_DIR}/server/export_target" [ ! -e "${REMOTE_SETUP_TARGET}" ] && perror "Missing script remote/setup_target. Exiting." [ ! -e "${SERVER_EXPORT_TARGET}" ] && perror "Missing script server/export_target. Exiting." } read_params() { local MODE="" local SUBMODE="" # mltk knows two modes in which to run: # - remote: functions to be run on the reference system # from which to build the mini-linux # - server: functions for rsyncing the generated stage31/stage32 # to a server, exporting the stage31-/stage32-filesystems case "$1" in server) MODE="SERVER" [ "$#" -lt "2" ] && perror "Missing argument to server-mode flag 'server' (expecting remote host)" REMOTE_IP="$2" shift ;; remote) MODE="REMOTE" ;; *) pwarning "Unknown mode: $1" print_usage exit 1 ;; esac shift # A target represents a set of modules to be build for a specific stage. # i.e. a very basic stage31 target should includes: # - busybox # - kernel # - rootfs-stage31 # a basic stage32 target could add: # - systemd # - dbus # - pam # for a GUI, you could add: # - xorg # - kdm # - plymouth TARGET="" if [[ $1 != "-"* ]]; then TARGET=$1 shift elif [[ $1 != "-s" && $1 != "-n" && $1 != "-k" ]]; then perror "A target is required. None given." fi # handle rest of arguments while [ "$#" -gt "0" ]; do local PARAM="$1" shift # options to current target if [[ "$PARAM" == "-"* ]]; then case "$PARAM" in -k) [ "$MODE" != "SERVER" ] && perror "-k can only be used in server mode" # NOTE: check for validity of config is done in 'inital_checks' of server/export_target SERVER_CONFIG_TYPE="$1" SERVER_CONFIG="1" shift continue ;; -s) SERVER_SYNC="1" continue ;; -c) SUBMODE="CLEAN" ;; -b) [ "$MODE" != "REMOTE" ] && perror "-b can only be used in remote mode" SUBMODE="BUILD" ;; -d) eval ${MODE}_DEBUG="1" continue ;; -p) [ "$#" -lt "1" ] && perror "Missing argument to -p" [ "$MODE" != "REMOTE" ] && perror "-p can only be used in remote mode" . "remote/profiles/${1}.profile" || perror "Profile '$1' not found in remote/profiles/" REMOTE_BUILD="1" REMOTE_LIST_BUILD="$REMOTE_LIST_BUILD $MODULES" unset MODULES shift continue ;; -e) [ "$#" -lt "1" ] && perror "Missing argument to -e" #TODO: rework these types, since now we only have initramfs or squashfs. This makes a distinction between # stage32 and addons obsolete. [[ "stage31|stage32|addons" != *"$1"* ]] && perror "Wrong type specified. Muste be either 'stage31', 'stage32' or 'addons'" SERVER_EXPORT="1" SERVER_EXPORT_TYPE="$1" shift continue ;; -n) if [ "$MODE" == "REMOTE" ]; then [ "x" != "x$1" ] && perror "'-n' accepts no parameters. Given: $1" REMOTE_EXPORT="1" fi continue ;; -a) if [ "$MODE" == "REMOTE" ]; then [ "x" != "x$1" ] && perror "'-a' accepts no parameters. Given: $1" REMOTE_AUTOMATIC_BUILD="1" fi continue ;; *) pwarning "Unknown flag to target: $PARAM" print_usage exit 1 ;; esac eval ${MODE}_${SUBMODE}="1" continue fi # module name [[ $MODE != REMOTE ]] && pwarning "You cannot specify module names in server mode." && print_usage && exit 1 [[ $SUBMODE != CLEAN && $SUBMODE != BUILD ]] && pwarning "Module name given in remote mode, but no action specified (eg. build)" && print_usage && exit 1 eval "${MODE}_LIST_${SUBMODE}=\"\$${MODE}_LIST_${SUBMODE} \$PARAM\"" done # exit if no command [[ $SERVER_CLEAN == 0 && $SERVER_EXPORT == 0 && $REMOTE_CLEAN == 0 && $REMOTE_BUILD == 0 && $SERVER_SYNC == 0 && $REMOTE_EXPORT == 0 && $SERVER_CONFIG == 0 ]] && print_usage && exit 1 } run() { if [[ $REMOTE_CLEAN == 1 || $REMOTE_BUILD == 1 || $REMOTE_EXPORT == 1 ]]; then [[ $REMOTE_DEBUG == 1 ]] && unset_quiet || set_quiet . "${REMOTE_SETUP_TARGET}" || perror "Cannot source ${REMOTE_SETUP_TARGET}" [[ $REMOTE_CLEAN == 1 ]] && clean_modules $TARGET $REMOTE_LIST_CLEAN [[ $REMOTE_BUILD == 1 ]] && generate_target $TARGET $REMOTE_LIST_BUILD [[ $REMOTE_EXPORT == 1 ]] && export_builds fi if [[ $SERVER_CLEAN == 1 || $SERVER_EXPORT == 1 || $SERVER_SYNC == 1 || $SERVER_CONFIG == 1 ]]; then [[ $SERVER_DEBUG == 1 ]] && unset_quiet || set_quiet . "${SERVER_EXPORT_TARGET}" || perror "Cannot source ${SERVER_EXPORT_TARGET}" [[ $SERVER_SYNC == 1 ]] && sync_remote [[ $SERVER_CLEAN == 1 ]] && clean_target $TARGET [[ $SERVER_EXPORT == 1 ]] && export_target $TARGET $SERVER_EXPORT_TYPE [[ $SERVER_CONFIG == 1 ]] && generate_config $SERVER_CONFIG_TYPE fi } SERVER_DEBUG="0" SERVER_EXPORT="0" SERVER_CLEAN="0" SERVER_EXPORT_TYPE="" SERVER_SYNC="0" SERVER_CONFIG="0" REMOTE_DEBUG="0" REMOTE_CLEAN="0" REMOTE_BUILD="0" REMOTE_LIST_CLEAN="" REMOTE_LIST_BUILD="" REMOTE_AUTOMATIC_BUILD=0 initial_checks read_params $@ check_devtools run