From 8c2bc7503f64027b41a58053048bbff4e7e9b422 Mon Sep 17 00:00:00 2001 From: Christoph Johannes Kleine <linux@cj-k.de> Date: Fri, 4 Oct 2019 17:39:43 +0200 Subject: [PATCH] =?UTF-8?q?installer=20hinzuf=C3=BCgen,=20(entwurf)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/bootlocal.sh | 4 +- files/functions.sh | 305 +++++++++++++++++++++++++++++++++++++++ files/installer.sh | 176 ++++++++++++++++++++++ tasks/buildinstaller.yml | 2 + 4 files changed, 484 insertions(+), 3 deletions(-) create mode 100755 files/functions.sh create mode 100755 files/installer.sh diff --git a/files/bootlocal.sh b/files/bootlocal.sh index 548918c..9e44942 100644 --- a/files/bootlocal.sh +++ b/files/bootlocal.sh @@ -1,5 +1,3 @@ #!/bin/sh -useradd -m -s /bin/sh user -echo -n "\n123456\n123456" /tmp/pw -passwd user </tmp/pw +installer.sh diff --git a/files/functions.sh b/files/functions.sh new file mode 100755 index 0000000..bfbc257 --- /dev/null +++ b/files/functions.sh @@ -0,0 +1,305 @@ +INSTALLER_BIND_MOUNTS="/dev /sys /proc" +INSTALLER_BIND_UMOUNTS="/proc /sys /dev" + +# ------------------------------------------------------------------- +# Logging + +log() { + echo "$@" >> $INSTALLER_LOGFILE +} + +exec_log() { + echo "> $@" >> $INSTALLER_LOGFILE + "$@" &>> $INSTALLER_LOGFILE +} + +exec_log_err() { + echo "> $@" >> $INSTALLER_LOGFILE + "$@" 2>> $INSTALLER_LOGFILE +} + +upload_logfile() { + curl -s --capath ./certs -H "Content-Type: text/plain" -T "$INSTALLER_LOGFILE" -m 20 "$INSTALLER_LOGFILE_URL" > /dev/null +} + +# ------------------------------------------------------------------- +# UI + +# Nachricht ohne OK-Button +dialog_info() { + log ">>> $1" + dialog --title "SDM-Installation" --infobox "$1" 15 70 || exit 1 +} + +# Nachricht mit OK-Button +dialog_msg() { + log ">>> $1" + dialog --title "SDM-Installation" --msgbox "$1" 15 70 || exit 1 +} + +dialog_ask_password() { + dialog --title "SDM-Installation" --insecure --nocancel --passwordbox "Passwort:" 15 70 +} + +fatal_error() { + upload_logfile + + log "!!! Installation abgebrochen: " + dialog_msg "$@ Bestätigen, um Rechner neuzustarten." + + exit 1 +} + +# ------------------------------------------------------------------- +# Bind mounts + +bind_mount() { + for DISKS_PARTITIONS_FS in $INSTALLER_BIND_MOUNTS + do + mount --bind $DISKS_PARTITIONS_FS "$target$DISKS_PARTITIONS_FS" + done +} + +bind_umount() { + for DISKS_PARTITIONS_FS in $INSTALLER_BIND_UMOUNTS + do + umount "$target$DISKS_PARTITIONS_FS" + done +} + + +# ------------------------------------------------------------------- +# Paritionierung +# neue Partitionstabelle anlegen + +part_clean() { + # Anfang der Festplatte überschreiben, um GPT Tabelle wegzubekommen + exec_log dd if=/dev/zero of="$1" bs=1M count=16 + sleep 2 + part_rescan + sleep 1 + + if [ "$part" == "msdos" ] + then + exec_log /usr/local/sbin/fdisk "$1" <<EOF +o +w +EOF + elif [ "$part" == "gpt" ] + then + # EFI-Systempartition anlegen ... + exec_log /usr/local/sbin/fdisk "$1" <<EOF +g +w +EOF + fi +} + +# neue Partition anlegen +# $2 = Partitionsnummer +# $3 = Start der Partition +# $4 = Ende der Partition (mit + am Anfang: Größe der Partition) +part_new() { + exec_log /usr/local/sbin/fdisk -u "$1" <<EOF +n +p +$2 +$3 +$4 +w +EOF +} + +part_rescan() { + sleep 2 + exec_log partprobe + sleep 2 +} + +# ------------------------------------------------------------------- +# Partitionierung +# Partitionen anlegen + +frz_partition() { + # Partionstabelle erstellen und Partitionen anlegen ohne Fehlerkontrolle. + # manchmal kommt ein Fehler, dass die Partitionstabelle nicht neu + # eingelesen werden konnte. Das ist aber so ziemlich egal, kann aber + # nicht von anderen Fehlern unterschieden werden. + + if [ "$partclean" == "yes" ] + then + dialog_info "Erstelle neue Partitionstabelle auf $disk ..." + sleep 2 + part_clean "$disk" + part_rescan + fi + + if [ -n "$rootpart" ] + then + dialog_info "Erstelle Root-Partition als Partition $rootpart auf $disk" + sleep 1 + + if [ -n "$rootsize" ] + then part_new "$disk" "$rootpart" "$rootstart" "$rootsize" + else part_new "$disk" "$rootpart" "$rootstart" "$rootend" + fi + fi + + if [ -n "$swappart" ] + then + dialog_info "Erstelle Swap-Partition als Partition $swappart auf $disk" + sleep 1 + if [ -n "$swapsize" ] + then part_new "$disk" "$swappart" "$swapstart" "$swapsize" + else part_new "$disk" "$swappart" "$swapstart" "$swapend" + fi + fi + + part_rescan +} + + +# ------------------------------------------------------------------- +# Formatierung + +frz_format() { + if [ -n "$rootpart" ] + then + dialog_info "Formatiere Root-Partition ${disk}${rootpart} mit ext4" + sleep 1 + + exec_log mkfs.ext4 -q "${disk}${rootpart}" || fatal_error "Formatierung der Root-Partition fehlgeschlagen!" + fi + + if [ -n "$swappart" ] + then + dialog_info "Formatiere Swap-Partition ${disk}${swappart}" + sleep 1 + exec_log mkswap "${disk}${swappart}" || fatal_error "Formatierung der Swap-Partition fehlgeschlagen!" + fi +} + + +# ------------------------------------------------------------------- +# Mount + +frz_mount() { + dialog_info "Mounte Root-Partition ${disk}${rootpart} auf $target" + if [ -n "$rootpart" ] + then + if [ -z "$roottype" ] + then + roottype="ext4" + fi + mkdir -p $target + mount -t "$roottype" "${disk}${rootpart}" "$target" || fatal_error "Das Ziel-Dateisystem konnte nicht eingehangen werden!" + fi +} + + +# ------------------------------------------------------------------- +# Installation + +sdm_install() { + frz_log_vars + frz_pre + frz_partition + frz_format + frz_mount + frz_sync + frz_hostname + frz_bootmgr + frz_provision + frz_post + frz_cleanup +} + + +# ------------------------------------------------------------------- +# + +frz_log_vars() { + log hostname=$hostname + log force_hostname=$force_hostname + log target=$target + log source=$source + log config=$config + log disk=$disk + log part=$part + log efidisk=$efidisk + log efipart=$efipart + log partclean=$partclean + log rootpart=$rootpart + log rootsize=$rootsize + log rootstart=$rootstart + log rootend=$rootend + log swappart=$swappart + log swapsize=$swapsize + log swapstart=$swapstart + log swapend=$swapend + log subdir=$subdir +} + + +# ------------------------------------------------------------------- +# + +frz_pre() { + : +} + + +# ------------------------------------------------------------------- +# + +frz_post() { + : +} + + + +# ------------------------------------------------------------------- +# + +frz_hostname() { + if [ -n "$force_hostname" ] + then + hostname="$force_hostname" + fi + + if [ -n "$target" ] && [ -n "$hostname" ] + then + dialog_info "Setze Hostname auf $hostname" + sleep 1 + + echo $hostname > "$target/etc/hostname" + fi +} + + +# ------------------------------------------------------------------- +# + +provision() { + if [ -n "$provision" ] + then + dialog_info "Provisioniere System mit '$provision' ..." + bind_mount + exec_log chroot "$target" /bin/bash -c "cd /etc/ansible; ansible-playbook ${provision}.yml -i hosts --limit local" + bind_umount + fi +} + + +# ------------------------------------------------------------------- +# + +frz_cleanup() { + dialog_info "Führe ldconfig aus ..." + exec_log chroot $target ldconfig + + umount $target + rmdir $target + + return 0 +} diff --git a/files/installer.sh b/files/installer.sh new file mode 100755 index 0000000..8d242de --- /dev/null +++ b/files/installer.sh @@ -0,0 +1,176 @@ +#!/bin/bash +# Variablen: +export INSTALLER_DNS="tu-dresden.de" +export INSTALLER_CONFIG='' +export INSTALLER_CONFIG_FILE="/tmp/installer-tmpfile.sh" +export INSTALLER_CONFIG_URL='' +export INSTALLER_DEBUGGING='' +export INSTALLER_ERROR_ACTION=reboot +export INSTALLER_LOGFILE="/tmp/installer.log" +export INSTALLER_MODE='sdm_install' +export INSTALLER_NOTIFY_URL='' + +# VERWENDETE VARIABLEN +# OS_DISTRIBUTION + +# ---------------------------------------------------------------------------------------------------------------------- +# Vorbereitung +update-ca-certificates +uname -r +[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS +sleep 5 +export PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin/ + + + +# damit das Skript von überall aus gestartet werden kann: +# in eigenen Ordner wechseln +# dirname: gibt Pfad aus ohne Dateiname +# readlink: kompletter Pfad aus $0 +cd "$(dirname "$(readlink -f "$0")")" + +. ./functions.sh + +# prüfe, wenn uid ungliche Null +if ! [ $EUID -eq 0 ] +then + echo "Der SDM-Installer muss als Benutzer »root« gestartet werden!" + exit 1 +fi + +clear +# dmesg -n: gibt auf Konsole Nr x aus +dmesg -n 1 +# swap auschalten +swapoff -a + + +# ---------------------------------------------------------------------------------------------------------------------- +# Auf Netzwerk warten + +# hier wird mit Status-Anzeige 10x probiert INSTALLER_DNS (tu-dresden.de) aufzulösen (um die DNS-Konfiguration durch DHCP abzuwarten) +( + +counter=0 +while ! nslookup $INSTALLER_DNS 2> /dev/null > /dev/null +do + [ "$counter" -ge 100 ] && exit 1 + + counter=$(expr $counter + 1) + echo $counter + + sleep 1 +done + +echo XXX +echo 100 +echo "Netzwerkverbindung erfolgreich." +echo XXX + +sleep 5 +# Lampda Funktion, die Klammern "fangen" die Ausgabe ab +# --gauge Infobox mit Höhe Breite %Anzeige, XXX ist für dialog erforderlich +) | dialog --title "SDM-Installation" --gauge "Warte auf Netzwerk-Verbindung ..." 15 70 0 + +if [ ${PIPESTATUS[0]} -eq 1 ] +then + dialog_info "Netzwerkverbindung gescheitert! Der Rechner wird neugestartet." && sleep 3 + $INSTALLER_ERROR_ACTION; exit 1 +fi + + +export hostname="$(hostname)" + + +# ---------------------------------------------------------------------------------------------------------------------- +# Parameter + +# Kernel-Parameter in Umgebung übernehmen +export $(cat /proc/cmdline) + +# Debug-Modus -> Installation überspringen und in eine Shell droppen +# verlassen durch? vielleicht reboot oder poweroff +if [ -n "$INSTALLER_DEBUGGING" ] +then + while true + do + bash + done +fi + +# Parameter prüfen +if [ -z "$OS_DISTRIBUTION" ] && [ -n "$INSTALLER_MODE" ] +then + dialog_info "Fehlende Parameter! Der Rechner wird neugestartet." && sleep 3 + $INSTALLER_ERROR_ACTION; exit 1 +fi + +# ---------------------------------------------------------------------------------------------------------------------- +# Konfiguration laden +if [ -n "$INSTALLER_CONFIG_URL" ] +then + if [[ "$INSTALLER_CONFIG_URL" == http* ]] + then + INSTALLER_CONFIG_URL="$INSTALLER_CONFIG_URL?hostname=$hostname" + dialog_info "Hole Installationskonfiguration von Server ..." && sleep 1 + + if ! curl -s --capath ./certs/ -o "$INSTALLER_CONFIG_FILE" "$INSTALLER_CONFIG_URL?hostname=$hostname" > /dev/null + then + dialog_info "Installations-Skript konnten nicht geholt werden!\n\nDer Rechner wird neugestartet." && sleep 3 + $INSTALLER_ERROR_ACTION; exit 1 + fi + chmod +x "$INSTALLER_CONFIG_FILE" + export $INSTALLER_CONFIG="$INSTALLER_CONFIG_FILE" + fi +fi + + +# Konfiguration entweder über URL oder fest in das Tinycore einbauen unter $INSTALLER_CONFIG_FILE +# das . VAR lädt den Inhalt der Datei in die Shell Umgebung +. "$INSTALLER_CONFIG" + + +# nochmal aus cmdline überschreiben +export $(cat /proc/cmdline) + +if [ $(type -t $INSTALLER_MODE) != "function" ] +then + dialog_info "Unbekannte Methode: $INSTALLER_MODE. Der Rechner wird neugestartet." && sleep 3 + $INSTALLER_ERROR_ACTION; exit 1 +fi + +[ -n "$INSTALLER_LOGFILE_URL" ] && INSTALLER_LOGFILE_URL="$INSTALLER_LOGFILE_URL?hostname=$hostname" +[ -n "$INSTALLER_NOTIFY_URL" ] && INSTALLER_NOTIFY_URL="$INSTALLER_NOTIFY_URL?hostname=$hostname" + + +# ---------------------------------------------------------------------------------------------------------------------- + + +dialog_info "Starte Installation ... \n\nHostname: $hostname \nDistribution: $OS_DISTRIBUTION\nModus: $INSTALLER_MODE\nKonfiguration: $INSTALLER_CONFIG" +sleep 5 + +# Installation aufrufen +($INSTALLER_MODE) + +if [ $? -eq 0 ] +then + dialog_info "Installationsprotokolle werden hochgeladen ..." + upload_logfile + + if [ -n "$INSTALLER_NOTIFY_URL" ] + then + dialog_info "Installation erfolgreich.\n\nMelde an Server ..." + + if curl -s --capath ./certs/ "$INSTALLER_NOTIFY_URL" > /dev/null + then + dialog_info "Installation erfolgreich.\n\nDer Rechner wird neugestartet." && sleep 3 + else + dialog_msg "Installation erfolgreich.\n\nServer nicht erreichbar.\n\nBestätigen, um Rechner neuzustarten." + fi + else + dialog_msg "Installation erfolgreich.\n\nBestätigen, um Rechner neuzustarten." + fi +fi + +#reboot +exit 0 diff --git a/tasks/buildinstaller.yml b/tasks/buildinstaller.yml index 432f37f..1f4560e 100644 --- a/tasks/buildinstaller.yml +++ b/tasks/buildinstaller.yml @@ -30,6 +30,8 @@ mode: "{{ _linux_install_file.mode }}" loop: - {"name": "bootlocal.sh", "mode": "0775" } + - {"name": "installer.sh", "mode": "0775" } + - {"name": "function.sh", "mode": "0775" } loop_control: loop_var: _linux_install_file -- GitLab