diff options
author | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2019-09-19 22:38:13 +0200 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2019-09-19 22:42:12 +0200 |
commit | 6ecb19ada66d54cc0afeb3d27d89700473cde70a (patch) | |
tree | a3b57044b04aad7613757aa96697f4afa89c1b85 | |
download | debian-edu-fai+itzks-6ecb19ada66d54cc0afeb3d27d89700473cde70a.tar.gz debian-edu-fai+itzks-6ecb19ada66d54cc0afeb3d27d89700473cde70a.tar.bz2 debian-edu-fai+itzks-6ecb19ada66d54cc0afeb3d27d89700473cde70a.zip |
initial draft of getting FAI install a Debian Edu system (profile: Minimal)
56 files changed, 2565 insertions, 0 deletions
diff --git a/fai/config/basefiles/mk-basefile b/fai/config/basefiles/mk-basefile new file mode 100755 index 0000000..deb12d4 --- /dev/null +++ b/fai/config/basefiles/mk-basefile @@ -0,0 +1,303 @@ +#! /bin/bash + +# mk-basefile, create basefiles for some distributions +# +# Thomas Lange, Uni Koeln, 2011-2018 +# based on the Makefile implementation of Michael Goetze +# +# Usage example: mk-basefile -J STRETCH64 +# This will create a STRETCH64.tar.xz basefile. + +# Supported distributions (each i386/amd64): +# Debian GNU/Linux +# Ubuntu 14.04/16.04 +# CentOS 5/6/7 +# Scientific Linux Cern 5/6 +# +# Packages you might want to install to use this command: +# debootstrap, rinse, xz-utils + + +# Define your local mirros here +# For the first stage, set the CentOS/SLC mirror in /etc/rinse/rinse.conf +MIRROR_DEBIAN=http://deb.debian.org/debian/ +MIRROR_UBUNTU=http://mirror.netcologne.de/ubuntu/ +MIRROR_CENTOS=http://mirror.netcologne.de/ + +EXCLUDE_SQUEEZE=isc-dhcp-client,isc-dhcp-common,info +EXCLUDE_WHEEZY=info +EXCLUDE_JESSIE=info +EXCLUDE_STRETCH=info +EXCLUDE_BUSTER= +EXCLUDE_SID= + +EXCLUDE_TRUSTY=dhcp3-client,dhcp3-common,info +EXCLUDE_XENIAL=udhcpc,dibbler-client,info +EXCLUDE_BIONIC=udhcpc,dibbler-client,info + +# here you can add packages, that are needed very early +INCLUDE_DEBIAN= + + +setarch() { + + l32= + if [ X$1 = Xi386 ]; then + l32=linux32 + fi +} + +check() { + + if [ `id -u` != 0 ]; then + echo "You must be root to create chroots." + exit 1 + fi + mknod $xtmp/test-dev-null c 1 3 + if [ $? -eq 1 ]; then + echo "Cannot create device files on $xtmp, aborting." + echo "Perhaps this directory is mounted with option nodev." + rm -rf $xtmp + exit 1 + fi + echo test > $xtmp/test-dev-null + if [ $? -eq 1 ]; then + echo "Cannot create device files on $xtmp, aborting." + echo "Perhaps this directory is mounted with option nodev." + rm -rf $xtmp + exit 1 + fi + rm -f $xtmp/test-dev-null +} + + +mkpost-centos() { + + # set local mirror for rinse post script + [ -z "$MIRROR_CENTOS" ] && return + cat <<EOM > $xtmp/post +#! /bin/sh +mkdir -p $xtmp/etc/yum.repos.d/orig +cp -p $xtmp/etc/yum.repos.d/*.repo $xtmp/etc/yum.repos.d/orig +perl -pi -e 's,mirrorlist=,#mirrorlist=,; s,#baseurl=http://mirror.centos.org,baseurl=$MIRROR_CENTOS,;' $xtmp/etc/yum.repos.d/CentOS-Base.repo +EOM + chmod 555 $xtmp/post +} + + +mkpost-slc() { + + # set local mirror for rinse post script + ver=$1 + [ -z "$MIRROR_SLC" ] && return + cat <<EOM > $xtmp/post +#! /bin/sh +mkdir -p $xtmp/etc/yum.repos.d/orig +cp -p $xtmp/etc/yum.repos.d/*.repo $xtmp/etc/yum.repos.d/orig +perl -pi -e 's,baseurl=http://linuxsoft.cern.ch,baseurl=$MIRROR_SLC,;' $xtmp/etc/yum.repos.d/slc$ver-os.repo +perl -pi -e 's,baseurl=http://linuxsoft.cern.ch,baseurl=$MIRROR_SLC,;' $xtmp/etc/yum.repos.d/slc$ver-updates.repo + +EOM + chmod 555 $xtmp/post +} + + +cleanup-deb() { + + chroot $xtmp apt-get clean + rm -f $xtmp/etc/hostname $xtmp/etc/resolv.conf \ + $xtmp/var/lib/apt/lists/*_* $xtmp/usr/bin/qemu-*-static \ + $xtmp/etc/udev/rules.d/70-persistent-net.rules + > $xtmp/etc/machine-id +} + + +cleanup-rinse() { + + # check if chroot works + echo "Installed packages in chroot:" + chroot $xtmp rpm -qa|sort + echo -n "CHROOT rpm -qa: " + chroot $xtmp rpm -qa|wc -l + + rm -f $xtmp/etc/resolv.conf $xtmp/post + if [ -d $xtmp/etc/yum.repos.d/orig ]; then + mv $xtmp/etc/yum.repos.d/orig/* $xtmp/etc/yum.repos.d/ + rm -rf $xtmp/etc/yum.repos.d/orig + fi +} + + +tarit() { + + tar $attributes --one-file-system -C $xtmp -cf - . | $zip > $target.$ext +} + + +centos() { + + local arch=$1 + local vers=$2 + local domain=$(domainname) + + check + setarch $arch + mkpost-centos + $l32 rinse --directory $xtmp --distribution centos-$vers --arch $arch --before-post-install $xtmp/post + domainname $domain # workaround for #613377 + cleanup-rinse + tarit +} + + +slc() { + + local arch=$1 + local vers=$2 + + check + setarch $arch + mkpost-slc $vers + $l32 rinse --directory $xtmp --distribution slc-$vers --arch $arch --before-post-install $xtmp/post + cleanup-rinse + tarit +} + + +debgeneric() { + + local DIST=$1 + shift + local mirror=$1 + shift + local arch=$1 + + dist=${DIST%%[0-9][0-9]} + local exc="EXCLUDE_$dist" + [ -n "${!exc}" ] && exc="--exclude=${!exc}" || unset exc + dist=${dist,,} + + check + if [ -n "$INCLUDE_DEBIAN" ]; then + local inc="--include=$INCLUDE_DEBIAN" + fi + + if [ -n "$arch" ]; then + qemu-debootstrap --arch $arch ${exc} $inc $dist $xtmp $mirror + target="${target}_${arch^^}" + else + if [[ $DIST =~ 64 ]]; then + arch=amd64 + else + arch=i386 + fi + debootstrap --arch $arch ${exc} $inc $dist $xtmp $mirror + fi + cleanup-deb + tarit +} + +prtdists() { + + echo "Available: + + CENTOS5_32 CENTOS5_64 + CENTOS6_32 CENTOS6_64 + CENTOS7_32 CENTOS7_64 + SLC5_32 SLC5_64 + SLC6_32 SLC6_64 + SLC7_64 + TRUSTY32 TRUSTY64 + XENIAL32 XENIAL64 + BIONIC64 + SQUEEZE32 SQUEEZE64 + WHEEZY32 WHEEZY64 + JESSIE32 JESSIE64 + STRETCH32 STRETCH64 + BUSTER32 BUSTER64 + SID32 SID64 +" +} + +usage() { + + cat <<EOF +mk-basefile, create minimal base files for a Linux distritubtion + + Copyright (C) 2011-2018 by Thomas Lange + +Usage: mk-basefile [OPTION] ... DISTRIBUTION + + -s Show list of supported linux distributions + -f ARCH Build for foreign architecture ARCH. + -d DIR Use DIR for creating the temporary subtree structure. + -z Use gzip for compressing the tar file. + -J Use xz for compressing the tar file. + -k Keep the temporary subtree structure, do not remove it. + -h Print help. + + Usage example: mk-basefile -J STRETCH64 + This will create a STRETCH64.tar.xz basefile. + +EOF + exit 0 +} + +# main routine + +ext=tar +zip=cat +attributes= +cleanup=1 +attributes="--xattrs --selinux --acls" + +while getopts ashzJd:kf: opt ; do + case "$opt" in + a) echo "$0: Warning. -a is ignored, because xtattrs, acls and selinux are always added." ;; + d) export TMPDIR=$OPTARG ;; + f) export ARCH=$OPTARG ;; + z) zip="gzip -9"; ext=tar.gz ;; + J) zip="xz -8" ext=tar.xz ;; + k) cleanup=0 ;; + h) usage ;; + s) prtdists ; exit 0;; + ?) exit 3 ;; # error in option parsing + esac +done +shift $(($OPTIND - 1)) + +xtmp=$(mktemp --tmpdir -d basefiles.XXXXXXXX) +if [ $? -eq 1 ]; then + echo "mktemp failed. Aborting." + exit 2 +fi +chmod 755 $xtmp + +target=$1 # also the name of the output file + +[ -z "$target" ] && usage +case "$target" in + CENTOS5_32) centos i386 5 ;; + CENTOS5_64) centos amd64 5 ;; + CENTOS6_32) centos i386 6 ;; + CENTOS6_64) centos amd64 6 ;; + CENTOS7_32) centos i386 7 ;; + CENTOS7_64) centos amd64 7 ;; + SLC5_32) slc i386 5 ;; + SLC5_64) slc amd64 5 ;; + SLC6_32) slc i386 6 ;; + SLC6_64) slc amd64 6 ;; + SLC7_64) slc amd64 7 ;; + TRUSTY*|XENIAL*|BIONIC*) + debgeneric $target $MIRROR_UBUNTU ;; + SQUEEZE*|WHEEZY*|JESSIE*|STRETCH*|BUSTER*|SID*) + debgeneric $target $MIRROR_DEBIAN $ARCH;; + *) echo "Unknown distribution. Aborting." + prtdists + exit 99 ;; +esac + +# cleanup +if [ $cleanup -eq 1 ]; then + rm -rf $xtmp +fi diff --git a/fai/config/class/01-classes b/fai/config/class/01-classes new file mode 100755 index 0000000..a435e05 --- /dev/null +++ b/fai/config/class/01-classes @@ -0,0 +1,8 @@ +#! /bin/bash + +[ "$cmdlineclasses" ] || exit 0 + +# define the classes given on the cmdline (using -c) very early +echo $cmdlineclasses + +exit 0 diff --git a/fai/config/class/10-base-classes b/fai/config/class/10-base-classes new file mode 100755 index 0000000..3d03c8f --- /dev/null +++ b/fai/config/class/10-base-classes @@ -0,0 +1,21 @@ +#! /bin/bash + +# do only execute if this is called on the client being installed. Do not use during fai-diskimage +if [ X$FAI_ACTION = Xinstall -a $do_init_tasks -eq 0 ]; then + exit 0 +fi + +# Echo architecture and OS name in uppercase. Do NOT remove these two lines. +uname -s | tr '[:lower:]' '[:upper:]' +[ -x "`which dpkg`" ] && dpkg --print-architecture | tr a-z A-Z + +# determin if we are a DHCP client or not +# count the : chars in the argument of ip= +n="${ip//[^:]}" +if [[ $ip =~ ^(on|any|dhcp)$ ]]; then + echo DHCPC +elif [ ${#n} -lt 6 ]; then + echo DHCPC +fi + +exit 0 diff --git a/fai/config/class/20-hwdetect.sh b/fai/config/class/20-hwdetect.sh new file mode 100755 index 0000000..8ba48d4 --- /dev/null +++ b/fai/config/class/20-hwdetect.sh @@ -0,0 +1,35 @@ +#! /bin/bash + +# (c) Thomas Lange, 2002-2013, lange@informatik.uni-koeln.de + +# NOTE: Files named *.sh will be evaluated, but their output ignored. + +[ $do_init_tasks -eq 1 ] || return 0 # Do only execute when doing install + +echo 0 > /proc/sys/kernel/printk + +#kernelmodules= +# here, you can load modules depending on the kernel version +case $(uname -r) in + 2.6*) kernelmodules="$kernelmodules mptspi dm-mod md-mod aes dm-crypt" ;; + [3456]*) kernelmodules="$kernelmodules mptspi dm-mod md-mod aes dm-crypt" ;; +esac + +for mod in $kernelmodules; do + [ X$verbose = X1 ] && echo Loading kernel module $mod + modprobe -a $mod 1>/dev/null 2>&1 +done + +ip ad show up | egrep -iv 'loopback|127.0.0.1|::1/128|_lft' + +echo $printk > /proc/sys/kernel/printk + +odisklist=$disklist +set_disk_info # recalculate list of available disks +if [ "$disklist" != "$odisklist" ]; then + echo New disklist: $disklist + echo disklist=\"$disklist\" >> $LOGDIR/additional.var +fi + +save_dmesg # save new boot messages (from loading modules) + diff --git a/fai/config/class/40-parse-profiles.sh b/fai/config/class/40-parse-profiles.sh new file mode 100755 index 0000000..c80cf7a --- /dev/null +++ b/fai/config/class/40-parse-profiles.sh @@ -0,0 +1,165 @@ +#! /bin/bash + +# parse *.profile and build a curses menu, so the user can select a profile +# +# (c) 2015 by Thomas Lange, lange@informatik.uni-koeln.de +# Universitaet zu Koeln + +if [ X$FAI_ACTION = Xinstall -o X$FAI_ACTION = Xdirinstall -o X$FAI_ACTION = X ]; then + : +else + return 0 +fi + +[ "$flag_menu" ] || return 0 + +out=$(tty) +tempfile=`(tempfile) 2>/dev/null` +tempfile2=`(tempfile) 2>/dev/null` +trap "rm -f $tempfile $tempfile2" EXIT INT QUIT + +# declare the data structure, use associative arrays +declare -A arshort +declare -A ardesc +declare -A arlong +declare -A arclasses +declare -a list + + +parse_profile() { + + # read a profile and add all info to the data structure + + local short + local long + local desc + local name + local classes + local lflag=0 + + # disable word splitting when reading a line, this helps reading a keyword without a value + local OIF=$IFS + IFS= + + while read -r line || [[ -n $line ]]; do + + if [[ $line =~ "Name: " ]]; then + if [ -n "$long" ]; then + arlong[$name]="$long" + fi + short= + desc= + long= + classes= + lflag=0 + name=${line##Name: } + [ $debug ] && echo "XX NAME $name found" + list+=("$name") # add new item to list + continue + fi + + if [[ $line =~ "Description: " ]]; then + lflag=0 + desc=${line##Description: } + [ $debug ] && echo "XX $desc found" + ardesc[$name]="$desc" + continue + fi + + if [[ $line =~ "Short: " ]]; then + lflag=0 + short=${line##Short: } + [ $debug ] && echo "XX $short found" + arshort[$name]="$short" + continue + fi + + if [[ $line =~ "Classes: " ]]; then + lflag=0 + classes=${line##Classes: } + [ $debug ] && echo "XX classes found" + arclasses[$name]="$classes" + continue + fi + + if [[ $line =~ "Long: " ]]; then + lflag=1 + long=${line##Long: } + [ $debug ] && echo "XX long found" + + # else it's another long line + elif [ $lflag -eq 1 ]; then + long+="\n$line" + fi + + if [[ $line =~ "Default: " ]]; then + lflag=0 + default=${line##Default: } + continue + fi + + done < $1 + + if [ -n "$long" ]; then + arlong[$name]="$long" + fi + IFS=$OIF +} + +prtresult() { + + # set newclasses which is used by fai-class(1) + local res=$(<$tempfile) + echo "$BASH_SOURCE defined new classes: ${arclasses[$res]}" + newclasses="${arclasses[$res]}" +} + + +# read all files with name matching *.profile +_parsed=0 +shopt -s nullglob +for _f in *.profile; do + parse_profile $_f + _parsed=1 +done +unset _f + +# do nothing if no profile was read +if [ $_parsed -eq 0 ]; then + unset _parsed + return 0 +fi + +# create the argument list containing the menu entries +# and the help text file +for i in "${list[@]}"; do + par+=("$i") + par+=("${ardesc[${i}]}") + par+=("${arshort[${i}]}") + echo "Name: ${i}" >> $tempfile2 + echo -e ${arlong[${i}]} >> $tempfile2 + echo -e "Classes: " ${arclasses[${i}]} "\n" >> $tempfile2 +done +unset i + +while true; do + + dialog --clear --item-help --title "FAI - Fully Automatic Installation" --help-button \ + --default-item "$default" \ + --menu "\nSelect your FAI profile\n\nThe profile will define a list of classes,\nwhich are used by FAI.\n\n\n"\ + 15 70 0 "${par[@]}" 2> $tempfile 1> $out + + _retval=$? + case $_retval in + 0) + prtresult + break ;; + 1) + echo "No profile selected." + break ;; + 2) + dialog --title "Description of all profiles" --textbox $tempfile2 0 0 1> $out;; + esac + +done +unset par ardesc arshort arlong arclasses list tempfile tempfile2 _parsed _retval line diff --git a/fai/config/class/41-warning.sh b/fai/config/class/41-warning.sh new file mode 100755 index 0000000..e9f9ec5 --- /dev/null +++ b/fai/config/class/41-warning.sh @@ -0,0 +1,28 @@ +#! /bin/bash + +if [ X$FAI_ACTION = Xinstall -o X$FAI_ACTION = X ]; then + : +else + return 0 +fi +if [ X$action = Xdirinstall ]; then + return 0 +fi + +grep -q INSTALL $LOGDIR/FAI_CLASSES || return 0 +[ "$flag_menu" ] || return 0 + +out=$(tty) +red=$(mktemp) +echo 'screen_color = (CYAN,RED,ON)' > $red + +DIALOGRC=$red dialog --colors --clear --aspect 6 --title "FAI - Fully Automatic Installation" --trim \ + --msgbox "\n\n If you continue, \n all your data on the disk \n \n|\Zr\Z1 WILL BE DESTROYED \Z0\Zn|\n\n" 0 0 1>$out + +# stop on any error, or if ESC was hit +if [ $? -ne 0 ]; then + task_error 999 +fi + +rm $red +unset red diff --git a/fai/config/class/50-host-classes b/fai/config/class/50-host-classes new file mode 100755 index 0000000..3c3765d --- /dev/null +++ b/fai/config/class/50-host-classes @@ -0,0 +1,13 @@ +#! /bin/bash + +# assign classes to hosts based on their hostname + +# do not use this if a menu will be presented +[ "$flag_menu" ] && exit 0 + +# use a list of classes for our demo machine +case $HOSTNAME in + *) +# echo "FAIBASE DEBIAN EDU WORKSTATION XORG MATE LVM" ;; + echo "FAIBASE DEBIAN EDU LVM" ;; +esac diff --git a/fai/config/class/60-misc b/fai/config/class/60-misc new file mode 100755 index 0000000..01eb252 --- /dev/null +++ b/fai/config/class/60-misc @@ -0,0 +1,9 @@ +#! /bin/bash + +ifclass -o GRUB_PC GRUB_EFI && exit 0 + +if [ -d /sys/firmware/efi ]; then + echo GRUB_EFI +elif ifclass -o I386 AMD64 ; then + echo GRUB_PC +fi diff --git a/fai/config/class/70-itzks b/fai/config/class/70-itzks new file mode 100755 index 0000000..9c0caa7 --- /dev/null +++ b/fai/config/class/70-itzks @@ -0,0 +1,3 @@ +#! /bin/bash + +echo ITZKS GERMAN diff --git a/fai/config/class/DEBIAN.var b/fai/config/class/DEBIAN.var new file mode 100644 index 0000000..eea3103 --- /dev/null +++ b/fai/config/class/DEBIAN.var @@ -0,0 +1,19 @@ +release=buster +apt_cdn=http://deb.debian.org +security_cdn=http://security.debian.org + +CONSOLEFONT= +KEYMAP=us-latin1 + +# MODULESLIST contains modules that will be loaded by the new system, +# not during installation these modules will be written to /etc/modules +# If you need a module during installation, add it to $kernelmodules +# in 20-hwdetect.sh. +MODULESLIST="usbhid psmouse" + +# if you have enough RAM (>2GB) you may want to enable this line. It +# also puts /var/cache into a ramdisk. +#FAI_RAMDISKS="$target/var/lib/dpkg $target/var/cache" + +# if you want to use the faiserver as APT proxy +APTPROXY=http://faiserver:3142 diff --git a/fai/config/class/FAIBASE.var b/fai/config/class/FAIBASE.var new file mode 100644 index 0000000..3112039 --- /dev/null +++ b/fai/config/class/FAIBASE.var @@ -0,0 +1,22 @@ +# default values for installation. You can override them in your *.var files + +# allow installation of packages from unsigned repositories +FAI_ALLOW_UNSIGNED=1 + +# Set UTC=yes if your system clock is set to UTC (GMT), and UTC=no if not. +UTC=yes +TIMEZONE=Europe/Berlin + +# the hash of the root password for the new installed linux system +# pw is "fai" +ROOTPW='$1$kBnWcO.E$djxB128U7dMkrltJHPf6d1' + +# errors in tasks greater than this value will cause the installation to stop +STOP_ON_ERROR=700 + +# set parameter for install_packages(8) +MAXPACKAGES=800 + +# a user account will be created +username=demo +USERPW='$1$kBnWcO.E$djxB128U7dMkrltJHPf6d1' diff --git a/fai/config/class/GERMAN.var b/fai/config/class/GERMAN.var new file mode 100644 index 0000000..8638a75 --- /dev/null +++ b/fai/config/class/GERMAN.var @@ -0,0 +1,3 @@ +# german environment (for Debian) +KEYMAP=de-latin1-nodeadkeys + diff --git a/fai/config/class/INSTALL.var b/fai/config/class/INSTALL.var new file mode 100644 index 0000000..f0c4cbd --- /dev/null +++ b/fai/config/class/INSTALL.var @@ -0,0 +1 @@ +FAI_ACTION=install diff --git a/fai/config/class/INVENTORY.var b/fai/config/class/INVENTORY.var new file mode 100644 index 0000000..6afe995 --- /dev/null +++ b/fai/config/class/INVENTORY.var @@ -0,0 +1 @@ +FAI_ACTION=inventory diff --git a/fai/config/class/SYSINFO.var b/fai/config/class/SYSINFO.var new file mode 100644 index 0000000..617b88d --- /dev/null +++ b/fai/config/class/SYSINFO.var @@ -0,0 +1 @@ +FAI_ACTION=sysinfo diff --git a/fai/config/class/debian-edu.profile b/fai/config/class/debian-edu.profile new file mode 100644 index 0000000..0e11891 --- /dev/null +++ b/fai/config/class/debian-edu.profile @@ -0,0 +1,40 @@ +Default: Edu/MATE + +Name: Edu/Minimal +Description: Minimal Debian Edu installation via FAI +Short: Installs a Debian Edu client system, text console only +Long: Installs a Debian Edu client system, text console only. +Use this installation profile for server-like systems that don't +need a graphical login. +Classes: INSTALL FAIBASE DEBIAN EDU + +Name: Edu/MATE +Description: Debian Edu workstation, powered by Mate Desktop +Short: Debian Edu workstation with Mate desktop will be installed +Long: Debian Edu workstation with Mate desktop will be installed. +Classes: INSTALL FAIBASE DEBIAN EDU WORKSTATION XORG MATE LVM + +Name: Edu/GNOME +Description: Debian Edu workstation, powered by Gnome Desktop +Short: Debian Edu workstation with Gnome desktop will be installed +Long: Debian Edu workstation with Gnome desktop will be installed. +Classes: INSTALL FAIBASE DEBIAN EDU WORKSTATION XORG GNOME LVM + +Name: Edu/GNOME +Description: Debian Edu workstation, powered by Xfce Desktop +Short: Debian Edu workstation with Xfce desktop will be installed +Long: Debian Edu workstation with Xfce desktop will be installed. +Classes: INSTALL FAIBASE DEBIAN EDU WORKSTATION XORG XFCE LVM + +Name: Inventory +Description: Show hardware info +Short: Show some basic hardware infos +Long: Execute commands for showing hardware info +Classes: INVENTORY + +Name: Sysinfo +Description: Show detailed system information +Short: Show detailed hardware and system information +Long: Execute a lot of commands for collecting system information +Classes: SYSINFO + diff --git a/fai/config/debconf/DEBIAN b/fai/config/debconf/DEBIAN new file mode 100644 index 0000000..cd4d08c --- /dev/null +++ b/fai/config/debconf/DEBIAN @@ -0,0 +1,45 @@ +# Use MD5 passwords, use shadow passords and skip creating local user +# Local users should be stored in LDAP +passwd passwd/md5 boolean true +passwd passwd/make-user boolean false +passwd passwd/shadow boolean true + +# Don't ask for disabling root login +passwd passwd/root-login boolean true + +# Skip the exim4 config. +exim4-config exim4/dc_eximconfig_configtype select local delivery only; not on a network +exim4-config exim4/dc_postmaster string root + +# Yes, we want to put grub on the master boot record (MBR) +d-i grub-installer/only_debian boolean true + +# Keep old style (aka unpredictable) network interfaces names. +grub-pc grub2/linux_cmdline_default string net.ifnames=0 quiet + +# Pick a random workgroup setting to avoid question during installation +samba-common samba-common/workgroup string skolelinux + +# Get those using popcon to submit to us too +popularity-contest popularity-contest/submiturls string https://popcon.debian.org/cgi-bin/popcon.cgi + +# Always use UTC system clock +d-i clock-setup/utc boolean true + +# Avoid question about encrypting the suspend image on laptops. Should we +# enable it instead, or wait until we start using encrypted file systems? +uswsusp uswsusp/encrypt boolean false + +# Enable cpufrequtils frequency scaling, to save power +cpufrequtils cpufrequtils/enable boolean true + +# Keep default (no) for hddtemp daemon setting +hddtemp hddtemp/daemon boolean false + +# Set up APT sources, see also our +# /usr/lib/apt-setup/generators/70debian-edu-install script. This +# remove the need to set up APT sources using cfengine. +choose-mirror-bin mirror/http/hostname string deb.debian.org +choose-mirror-bin mirror/http/directory string /debian/ +apt-mirror-setup apt-setup/non-free boolean true +apt-mirror-setup apt-setup/contrib boolean true diff --git a/fai/config/debconf/EDU b/fai/config/debconf/EDU new file mode 100644 index 0000000..933be9b --- /dev/null +++ b/fai/config/debconf/EDU @@ -0,0 +1,49 @@ +# Common values for servers and workstations (non-standalone install) + +# Kerberos client +krb5-config krb5-config/default_realm string INTERN +krb5-config krb5-config/dns_for_default boolean true +krb5-config krb5-config/add_servers boolean false +krb5-config krb5-config/kerberos_servers string kerberos +krb5-config krb5-config/admin_server string kerberos + +# Settings for nss-ldap replacement nss-ldapd +libnss-ldapd libnss-ldapd/nsswitch multiselect group, netgroup, networks, passwd, shadow + +# Some of the libnss-ldapd settings moved to nslcd in Squeeze +nslcd nslcd/ldap-base string dc=skole,dc=skolelinux,dc=no +nslcd nslcd/ldap-uris string ldap://ldap +nslcd nslcd/ldap-starttls boolean true +nslcd nslcd/ldap-reqcert string demand +nslcd nslcd/ldap-cacertfile string /etc/ssl/certs/debian-edu-server.crt + +# Update hostname from DNS +debian-edu-config debian-edu-config/update-hostname boolean true + +# Send sitesummary reports to the central collector +sitesummary-client sitesummary-client/collector_url string http://sitesummary/cgi-bin/sitesummary-collector.cgi +# Enable NRPE for Nagios configuration generated using sitesummary +sitesummary-client sitesummary-client/nagios-server string sitesummary +sitesummary-client sitesummary-client/enable-nagios-nrpe-config boolean true + +# enable the WINS settings feature for addresses via DHCP +samba-common samba-common/dhcp boolean true + +# Configure gosa-desktop +gosa-desktop gosa-desktop/url string https://www.intern/gosa/ + +# Initial exim4 configuration for clients +# FIXME find out if this is correct and enough. +exim4-config exim4/dc_eximconfig_configtype select mail sent by smarthost; no local mail +exim4-config exim4/dc_smarthost string postoffice.intern +exim4-config exim4/dc_local_interfaces string 127.0.0.1 ; ::1 +exim4-config exim4/dc_postmaster string root +exim4-config exim4/dc_readhost string postoffice.intern +exim4-config exim4/use_split_config boolean true +exim4-config exim4/mailname string postoffice.intern +exim4-config exim4/dc_minimaldns boolean false +exim4-config exim4/dc_other_hostnames string intern + +# Prefer lightdm, sddm doesn't provide a language chooser +lightdm shared/default-x-display-manager select lightdm +sddm shared/default-x-display-manager select lightdm diff --git a/fai/config/debconf/ENGLISH b/fai/config/debconf/ENGLISH new file mode 100644 index 0000000..4423e02 --- /dev/null +++ b/fai/config/debconf/ENGLISH @@ -0,0 +1,8 @@ +locales locales/default_environment_locale select en_US.UTF-8 +locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8 +keyboard-configuration keyboard-configuration/modelcode string pc105 +keyboard-configuration keyboard-configuration/xkb-keymap select us +keyboard-configuration keyboard-configuration/variant select USA +keyboard-configuration keyboard-configuration/model select Generic 105-key (Intl) PC +keyboard-configuration keyboard-configuration/layoutcode string us +keyboard-configuration keyboard-configuration/optionscode string ctrl:nocaps,terminate:ctrl_alt_bksp diff --git a/fai/config/debconf/GERMAN b/fai/config/debconf/GERMAN new file mode 100644 index 0000000..cca0416 --- /dev/null +++ b/fai/config/debconf/GERMAN @@ -0,0 +1,8 @@ +locales locales/default_environment_locale select de_DE.UTF-8 +locales locales/locales_to_be_generated multiselect de_DE.UTF-8 UTF-8 +keyboard-configuration keyboard-configuration/modelcode string pc105 +keyboard-configuration keyboard-configuration/xkb-keymap select de +keyboard-configuration keyboard-configuration/variant select Germany +keyboard-configuration keyboard-configuration/model select Generic 105-key (Intl) PC +keyboard-configuration keyboard-configuration/layoutcode string de +keyboard-configuration keyboard-configuration/optionscode string ctrl:nocaps,terminate:ctrl_alt_bksp diff --git a/fai/config/debconf/WORKSTATION b/fai/config/debconf/WORKSTATION new file mode 100644 index 0000000..6d0b6f9 --- /dev/null +++ b/fai/config/debconf/WORKSTATION @@ -0,0 +1,3 @@ +# All non-default debconf answers for workstation installation + +sitesummary-client sitesummary-client/hostclass string workstation diff --git a/fai/config/disk_config/FAIBASE b/fai/config/disk_config/FAIBASE new file mode 100644 index 0000000..0c66cbc --- /dev/null +++ b/fai/config/disk_config/FAIBASE @@ -0,0 +1,9 @@ +# example of new config file for setup-storage +# +# <type> <mountpoint> <size> <fs type> <mount options> <misc options> + +disk_config disk1 disklabel:msdos bootable:1 fstabkey:uuid + +primary / 2G-50G ext4 rw,noatime,errors=remount-ro +logical swap 200-10G swap sw +logical /home 100- ext4 rw,noatime,nosuid,nodev createopts="-L home -m 1" tuneopts="-c 0 -i 0" diff --git a/fai/config/files/etc/apt/apt.conf.d/force_confdef/DEBIAN b/fai/config/files/etc/apt/apt.conf.d/force_confdef/DEBIAN new file mode 100644 index 0000000..deb7948 --- /dev/null +++ b/fai/config/files/etc/apt/apt.conf.d/force_confdef/DEBIAN @@ -0,0 +1,5 @@ +DPkg { + Options { + "--force-confdef"; + } +}; diff --git a/fai/config/files/etc/apt/sources.list/DEBIAN b/fai/config/files/etc/apt/sources.list/DEBIAN new file mode 100644 index 0000000..f016a99 --- /dev/null +++ b/fai/config/files/etc/apt/sources.list/DEBIAN @@ -0,0 +1,3 @@ +deb {%apt_cdn%}/debian {%release%} main +deb {%security_cdn%}/debian-security {%release%}/updates main +deb {%apt_cdn%}/debian {%release%}-updates main diff --git a/fai/config/files/etc/motd/FAIBASE b/fai/config/files/etc/motd/FAIBASE new file mode 100644 index 0000000..3584c2f --- /dev/null +++ b/fai/config/files/etc/motd/FAIBASE @@ -0,0 +1,3 @@ + +Debian Edu 10.x installed with FAI... + diff --git a/fai/config/hooks/instsoft.DEBIAN b/fai/config/hooks/instsoft.DEBIAN new file mode 100755 index 0000000..35ac306 --- /dev/null +++ b/fai/config/hooks/instsoft.DEBIAN @@ -0,0 +1,25 @@ +#! /bin/bash + +# if package locales will be installed, then install it early, before +# other packages +if [ $FAI_ACTION != "install" -a $FAI_ACTION != "dirinstall" ]; then + exit 0 +fi + +fcopy -Bi /etc/apt/apt.conf.d/force_confdef +ainsl -a /etc/ucf.conf "^conf_force_conffold=YES" + +# in case the locales are already included inside the base file (Ubuntu) +if [ -f $target/usr/sbin/locale-gen ]; then + exit +fi + +# if we want to install locales, install them now +install_packages -l 2>/dev/null | egrep -q ' locales|locales ' +if [ $? -eq 0 ]; then + if [ X$verbose = X1 ]; then + $ROOTCMD apt-get -y install locales + else + $ROOTCMD apt-get -y install locales > /dev/null + fi +fi diff --git a/fai/config/hooks/instsoft.EDU b/fai/config/hooks/instsoft.EDU new file mode 100755 index 0000000..d92c602 --- /dev/null +++ b/fai/config/hooks/instsoft.EDU @@ -0,0 +1,21 @@ +#! /bin/bash + +# if package locales will be installed, then install it early, before +# other packages +if [ $FAI_ACTION != "install" -a $FAI_ACTION != "dirinstall" ]; then + exit 0 +fi + +# for Debian Edu installations, we need the hostname before debian-edu-config gets installed +fcopy -Mv /etc/hostname || echo $HOSTNAME > $target/etc/hostname + +# create dummy /etc/debian-edu/config file (to make debian-edu-install.postinst happy) +mkdir -p $target/etc/debian-edu + +cat > $target/etc/debian-edu/config << EOF +VERSION="$(cat $target/etc/debian_version)" +PROFILE="Minimal" +LANGCODE="en" +LOCALE="en_US.UTF-8" +EOF + diff --git a/fai/config/hooks/instsoft.WORKSTATION b/fai/config/hooks/instsoft.WORKSTATION new file mode 100755 index 0000000..d934883 --- /dev/null +++ b/fai/config/hooks/instsoft.WORKSTATION @@ -0,0 +1,7 @@ +#!/bin/bash + +# tag Debian Edu machine as a workstation +if [ -f $target/etc/debian-edu/config ]; then + sed -i $target/etc/debian-edu/config -e "s/^PROFILE=.*$/PROFILE=\"Workstation\"/" +fi + diff --git a/fai/config/hooks/mountdisks.DEFAULT b/fai/config/hooks/mountdisks.DEFAULT new file mode 100755 index 0000000..95e6a2b --- /dev/null +++ b/fai/config/hooks/mountdisks.DEFAULT @@ -0,0 +1,9 @@ +#! /bin/bash + +# stop resync of soft raid +if [ $do_init_tasks -eq 1 ]; then + if grep -q active /proc/mdstat 2>/dev/null; then + echo "frozen" | tee /sys/block/md*/md/sync_action >/dev/null + fi +fi +exit 0 diff --git a/fai/config/hooks/savelog.LAST.sh b/fai/config/hooks/savelog.LAST.sh new file mode 100755 index 0000000..2db5ecb --- /dev/null +++ b/fai/config/hooks/savelog.LAST.sh @@ -0,0 +1,209 @@ +#! /bin/bash + +# parse all log files for error messages +# print errors and warnings found to error.log +# WARNING: This will only work with english error messages! + +errfile=$LOGDIR/error.log + +# Define grep patterns. Do not start or end with an empty line! +globalerrorpatterns="error +fail +warn + bad +bad +no space +syntax +Couldn't stat +Cannot access + conflict +is bigger than the limit +did not exist +non existent +not found +couldn't +can't +E: Sorry, broken packages +^E: +operator expected +ambiguous redirect +No previous regular expression +No such +Device or resource busy +unknown option +[a-z]\+\.log:E: +No candidate version found +segfault +Couldn't find any package whose name or description matched +cannot create +The following packages have unmet dependencies" + +globalignorepatterns="[a-z]\+\.log:# +Error: Driver 'pcspkr' is already registered, aborting +: bytes packets errors dropped +:+ error=0 +:+ trap error= +task_error_func= +STOP_ON_ERROR= +courier-webadmin +plugins-bad +Enabling conf localized-error-pages +ibwebadmin +kernel-patch-badram +kolab-webadmin +kolabadmin +gstreamer.\+-plugins-really-bad +liberrors.so +liberrors-samba +libsamba-errors +gsambad +libad +libtest-nowarnings-perl +libtest-warn-perl +libclass-errorhandler-perl +zope-ploneerrorreporting +libroxen-errormessage +liberror-perl +libgpg-error-dev +libgpg-error0 +Opts:.\+errors=remount +[RT]X packets: +WARNING: unexpected IO-APIC +warned about = ( ) +daemon.warn +kern.warn +rw,errors= +Expect some cache +no error +failmsg +RPC call returned error 101 +deverror.out +(floppy), sector 0 +mount version older than kernel +Can't locate module +Warning only .\+MB will be used. +hostname: Host name lookup failure +I can't tell the difference. +warning, not much extra random data, consider using the -rand option +confC._FILE +Warning: 3 database(s) sources +were not found, (but were created) +removing exim +The home dir you specified already exists. +No Rule for /usr/lib/ispell/default.hash. +/usr/sbin/update-fonts-.\+: warning: absolute path +hostname: Unknown server error +EXT2-fs warning: checktime reached +RPC: sendmsg returned error 101 +can't print them to stdout. Define these classes +warning: downgrading +suppress emacs errors +echo Error: +Can't open dependencies file +documents in /usr/doc are no longer supported +if you have both a SCSI and an IDE CD-ROM +Warning: /proc/ide/hd?/settings interface is obsolete, and will be removed soon +Monitoring disabled +Error: only one processor found. +Error Recovery Strategy: +sector 0 does not have an +syslogin_perform_logout: logout() returned an error +grub is not in an XFS filesystem. +grub-install: line 374: +grub-probe: error: Cannot open \`/boot/grub/device.map' +is harmless +not updating .\+ font directory data. +register_serial(): autoconfig failed +Fontconfig error: Cannot load default config file +asking for cache data failed +However, I can not read the target: +Warning: The partition table looks like it was made +task_error=0 +task_local_error=0 +^info: Trying to set +warning: /usr/lib/X11/fonts +can't read /etc/udev/rules.d/z25_persistent-net.rules +/cow': No such file or directory +Dummy start-stop-daemon called +X: bytes packets errors +ACPI Error +ACPI Warning +AE_NOT_FOUND +conflicts with ACPI region +cannot stat \`/etc/modprobe.d/\*.conf' +cdrom: open failed. +libgpg-error +process \`kudzu' used the deprecated sysctl system call +PM: Resume from disk failed +JBD: barrier-based sync failed +aufs: module is from the staging directory, the quality is unknown +warning: linuxlogo stop runlevel arguments (none) do not match +insserv: warning: script .\+ missing LSB tags and overrides +live-premount.\+ If this fails +cannot read table of mounted file systems +error: no alternatives for +ERST: Error Record Serialization Table (ERST) support is initialized +ERST: Table is not found +HEST: Table not found +failed to stat /dev/pts +Failed to connect to socket /var/run/dbus/system_bus_socket +fail to add MMCONFIG information +can't initialize iptables table +can't initialize ip6tables table +Authentication warning overridden +41-warning.sh +PCCT header not found +Download is performed unsandboxed as root as file +update-alternatives: warning: skip creation of +loop: module verification failed: signature +Warning: apt-key output should not be parsed +WARNING: Failed to connect to lvmetad. Falling back to device scanning +Warning: The home dir /var/lib/usbmux you specified +diff: /var/lib/apparmor/profiles/.apparmor.md5sums: No such file or directory +error reporting disabled +Enabling Firmware First mode for corrected errors +errors: 0 + 0 errors +Memory Error Correction: +Memory Controller 0 - Channel . Error +IIO RAS/Control Status/Global Errors +__stack_chk_fail +grub.cfg.new: Directory nonexistent +update-rc.d: warning: start and stop actions are no longer supported" + +# add pattern on some conditions +if [ -n $FAI_ALLOW_UNSIGNED ] ; then + globalignorepatterns="$globalignorepatterns +WARNING: untrusted versions +WARNING: The following packages cannot be authenticated +Ignoring these trust violations" +fi +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Here you can define your own patterns. Put one pattern in a line, +# do not create empty lines. +myerrorpatterns="X_X-X_XX" +myignorepatterns="X_X-X_XX" +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# The main routine +errorpatterns="$globalerrorpatterns +$myerrorpatterns" +ignorepatterns="$globalignorepatterns +$myignorepatterns" + +cd $LOGDIR || exit 3 +if [ -s $errfile ]; then + echo "Errorfile already exists. Aborting." >&2 + exit +fi + +grep -i "$errorpatterns" *.log | grep -vi "$ignorepatterns" > $errfile +if [ X$verbose = X1 ]; then + egrep -v '^software.log:' $errfile > $LOGDIR/tempfile + mv $LOGDIR/tempfile $errfile +fi + +if [ -s $errfile ]; then + echo "ERRORS found in log files. See $errfile" >&2 +else + echo "Congratulations! No errors found in log files." +fi diff --git a/fai/config/hooks/setup.DEFAULT.sh b/fai/config/hooks/setup.DEFAULT.sh new file mode 100755 index 0000000..00a1df2 --- /dev/null +++ b/fai/config/hooks/setup.DEFAULT.sh @@ -0,0 +1,7 @@ +#! /bin/bash + +# use short hostname instead of FQDN +export HOSTNAME=${HOSTNAME%%.*} +if [ $do_init_tasks -eq 1 ]; then + echo $HOSTNAME > /proc/sys/kernel/hostname +fi diff --git a/fai/config/hooks/updatebase.DEBIAN b/fai/config/hooks/updatebase.DEBIAN new file mode 100755 index 0000000..e828eef --- /dev/null +++ b/fai/config/hooks/updatebase.DEBIAN @@ -0,0 +1,14 @@ +#! /bin/bash + +if [ -n "$APTPROXY" ]; then + echo "Acquire::http::Proxy \"$APTPROXY\";" > $target/etc/apt/apt.conf.d/02proxy +else + rm -f $target/etc/apt/apt.conf.d/02proxy +fi + +echo force-unsafe-io > $target/etc/dpkg/dpkg.cfg.d/unsafe-io + +# you may want to add i386 arch to amd64 hosts +# if ifclass AMD64; then +# $ROOTCMD dpkg --add-architecture i386 +# fi diff --git a/fai/config/package_config/DEBIAN b/fai/config/package_config/DEBIAN new file mode 100644 index 0000000..38160a7 --- /dev/null +++ b/fai/config/package_config/DEBIAN @@ -0,0 +1,46 @@ +PACKAGES install-norec +apt-transport-https # is only needed for stretch +debconf-utils +file +less +linuxlogo +rsync +openssh-client openssh-server +time +procinfo +nullmailer +eject +locales +console-setup kbd +pciutils usbutils +unattended-upgrades + +PACKAGES install NONFREE +# you may want these non-free kernel drivers +firmware-bnx2 firmware-bnx2x firmware-realtek +firmware-linux-nonfree + +PACKAGES install I386 +linux-image-686-pae +memtest86+ + +PACKAGES install CHROOT +linux-image-686-pae- +linux-image-amd64- + +PACKAGES install AMD64 +linux-image-amd64 +memtest86+ + +PACKAGES install ARM64 +grub-efi-arm64 +linux-image-arm64 + +PACKAGES install GRUB_PC +grub-pc + +PACKAGES install GRUB_EFI +grub-efi + +PACKAGES install LVM +lvm2 diff --git a/fai/config/package_config/DEBIAN.asc b/fai/config/package_config/DEBIAN.asc new file mode 100644 index 0000000..72c34ca --- /dev/null +++ b/fai/config/package_config/DEBIAN.asc @@ -0,0 +1,687 @@ +# gpg key of fai-project.org repository: 4096R/074BCDE4 + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +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 +Bjx0CB7rV1AiU3+Nw/9SRlg2peJGhoi9yIhaLcnmNzLP24E48hhZBx3zf050gmcY +Dwsy+mKQI0iE9VMlLYFbng8KzEKOCX+G7Tzs48ItQ6dn9y3SkV5YIaJEAIpYNa+/ +xry1ARSXviZxJCfsx5YH108/DI9aPLThX34n4fUBGpPDR90wxokC8AQTAQoA2gUC +UgoEBsASGmh0dHA6Ly9tYXJ0aW4ta3JhZmZ0Lm5ldC9ncGcvY2VydC1wb2xpY3kv +NTVjOTg4MmQ5OTliYmNjNC8yMDA5MDcxMjE4MzM/c2hhNTEyc3VtPWYzM2IxN2M5 +YWY1MTViZDk4YjI5MjdjYjQ1M2E5OTJkM2Q3NTAwZTlmNjcxOTY2NjE2ZTkwNTEw +Yjk5NDA4OTUxMDhkMjQxNjQ4ZDFhMGViNDZiMzJiY2JmMzI1MWExMzZhNmVlMWUy +Mjc1NzQ1ZTExYmIzMjhjMTRlN2U3MjYzAAoJEFXJiC2Zm7zEE1EP/1QC4Meh6+1N +xVnnr3/DTbEg0kzYCV/BkYr9F7ELyb3j8djzjujKPQDVmrQhqMIVjkJnkpUOnr1A +QHweMDdWwN0XSPyFiiOqVKvzTHg5+DxVUWr8mVqr83nuNcgkSjrYgs7WAAQutpFw +5KOhxMhZocLIXq5wckW3FcrkVCA67hnG8JFovgD2GSCEGbpVM8yDzo4TGIcZt8Vt +SxbEnfjGMZoQZ5IxowPMAWc52sz9VNFK1xU3cO30pcTr15LogZbZLnUb88nfHr88 +fvEAeIFGVMchaP2IWo0LShVSfThf1YhNC35E+RQjfzK1gaLiUkgVaj5+cEfnvcjp +dhFrZNMTCdo8bAllxMxldZkZlaLJPXFxx8LlsDzZPClHSTqfDUA9IUj+q4bsGdq9 +n6dYUGJcTZ83ohhZqE1wHyuSzhCgBClPvpe9Hpvpfxnpm+wDC6xJkdn9rA2CjDmB +3vUH5vKuZQ9jLj7Dp7K/4BTUPcRMn5Gg/eyHR9dNKAF31lydo/nZIGOaqUIXdXkC +ktKlAkPgrW4vUcF3Nxx4kDDNoaw/RK1hekEPVMKMwRiMQ/xw6ltfiAeqRIaYZXod +rVJZLznov22d7Wvv0tSaV6ACc0dKq7xf5qNOakiz5q9JrQUdAV6XctQCfOcup0/+ +gBfGF/4WChaHYzH+7bevnxk7ZkoozhSRiQIcBBABCAAGBQJSChWAAAoJEK7IKHSd +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 +mrrwI2VHtBVOyb18Nb8+o1xOy/4nk5q5JxznNA6e/X5QkUklz9To2gQ1HvbUU24q +hUE5h0JniyTay6zl7CP4I5TT/MMDkZ9jBLuoUT7NL8BHmR9n3hNQyTh401nInVsE +DbHi3DWbiOEBmnFdKA1MkSRu/vFL90trpA7rt8UmXbXbd3ijWKCc1cREX3DmWP13 +xDTL0xVfdtiNINY8f4QuG5JDF61nTaLF4wyPz/no96zFzrjper5zMJ3clcCWiQIc +BBABAgAGBQJSCVHtAAoJEIMBYBQlHR2wd9gP/j3abEoMu1PYsFehQYnwdZcRmY7P +dZYCB7SagmoE4SG3avsIps8eRBfqApP7LwHaT6V+ZtF3u/FCVfFwmGyJaKmH2ZuR +z4sZPnKvhAzzGgL4NTVUnfOFw+fodQyTNeG11xFOFo3XOQz8nKNXh4M404jPde1F +E+4jerOqjM4bDOpZNoywYiJF11cx6/pQPEETUHe5h4TxqRRKrHPuk2OK2znaNzB5 +N/sDG1smkxAUdccRkvbetEOjCeBPKmcpDM2oXZ3lysOILEnNqW1it6Zsudju0rRL +SATFY8nGkG15e+FDUkv+Uw39mkp1aXfbfqfX3Q26DeG0GotF5uFhKYm1pMQws+t3 +UkvfmCVihvxiV6gqwaR8Expc40Oa+7n51DmoKzcq/UHPUEuvtwny+GSVJE9KMl3w +hKtqHGs6bqWdE3Kmr+KnkIrBvBDibk6T8VsBPlVxUwvvNMC8J9uGi1wsRaD6KPkl ++LPcW9U1TM80s7BNzctIO39bSNx6MZBCm0lmNQ4Q0qG9ePca5o/20wJR6y3Vu6/4 +EThESDoyBgEyAKMAxWyomBmxoSS2EuikeE7/tFXoY+CDvqTgZSqYK8W1wrF7sk7L +gecpulvWtadioPoD3ZMo3mdFYwRsdpxdzOx70NzbWtiJ4bx9dnWPG9OBOlpNuFSA +fHd4SnQKR++woHNEiQIcBBABCAAGBQJSCWkzAAoJED9qGiAYq/jD31wQAIub6DCa +pCtHWLru7ytWTmVQ04yBalq10TEs3FwTcjgFVDEC1SO8H8woryPhXPhHB4r8xush +aHLgGjJ2kUqoI/1WTiMzi5L6xQIJQ/hreFNl2LU2bs02Ysncf660S8uYQIxBbcpx +jrFpouNhOM2tLdBenNdzuv5QnSnbiBTOzOXctf2ILWQa4r47KdUXdBpK2U2/pwoq ++GCTPJLymUs2zLlMWXCZhDQUaHQ9/7QVwFpjdi/gcIvJJ2DSEyIB5zjpZ3SQSz6s +GjBLdKJFWw6qHCf//ithAOSZH3YY4To4jGYMVkXD4GgoeZEmHQNYtdv2p5mnmw1T +ORApJRh0iA+vAGg7EMDKFAsqtxRNxPmjGeLRAxc3jqFFPw4rUdpBhaYvcXJE/7Ad +U+O8nzZMXqkbCX+14ICC2JDxR7n+HnP6/KZ7E0aB/xRpYUL2yBUvCqk8aOTiXxGX +Mf85e2GvDk1UdfiAe27qN9eCxpMX/nSfvyH+6M0CQLVeoJjZsqshHMLk4f+lsINw +HKstBM4tMOOEKtYKsCZ4Tnk3+b4xYsF4HftDLEsEYJQaJg3s3Ajfn2p61KDtxTkd +6njl8v+mJldqTvTrzqNIf/VFKgRavLcVOcsMc69TFZeVevwPsJWS/oZuHFPFkx5H +TeLF7fJmOf/ki+uboFYscCK261sb9pJoV2UTiEYEEBEIAAYFAlIJaUUACgkQGc/R +GrFqUYNMlQCffJpk47YGn4L1/U73qi4e6cu0IosAnROJEn49yaRNXejzOsYCgUQf +nAZmiEYEEBEIAAYFAlIJbKQACgkQJwRJTy3zZoEHCgCeMtpU3NJBNg9z3Tq6sz1L +3P8UzIgAn3xkMycT/vhAdQrYwRiodLUalPoSiQIcBBABCAAGBQJSCWypAAoJELog +ZmLR+sd/SiYP/0xmYtSOYSN00cKsyiHSAqvx+n/iGjsi7gvdI0NS3HI/3OWvw1UX +ZfuTerOvzsqo0N8WLWzlGFpuIt+fLoBNcxHwD156CUgC36X5Gex0l5v8qQQuNYsI +qxvrI2gLWPip8bKfeE6jpNxLWeEzhwzTk8Lhs6KWMjjfyw979r/0Vkvob/oqjnYC +xO1oydVwJ7SlXmU1PCC659ogwXzh9DNf60h0AFotgOiURqdswy8ImpOkIEfxJAUb +TBRTXOgELjjar5b9UGRCXJ4gI4UihTpSyPICJEMUxZLwjn6c3F9pWq5T+QGE+8Zf +PCM4ahaMKiwR79bP1O7C4rY1Lhjm0Ydev3NIyA3qWZ+Z+fALWgMEViJl3YnbKG8p +OSlhb7ihPf4KbGHAvCwnd8azJJB3/HeGwfejmaMtS1+W5u4A0Z2TTc7bmjpETATF +92qgdqbW3rMEVO49FwyV1gLtZdxJ1s3j6XUBcSsH9D+pMV0+D0iVmkXMcBerT+Xg +AAGEOJKOZU0TzOn4S/B4IhTXNxZbfXJnEVNp79ezfDqDSgPYnPuG4sctTAfGXHRe +FjPR5fQCAOVkkgQrezpOUwpXP44ozyKlEQs6d698uhJUCKcmnEviY11O8ZMQYpYr +ReWt7orepOhUtJ2WNpDgTjg4bwEjC3jFsTML7H9i5+LzzJ0YD34R7tsRiQLwBBMB +CgDaBQJSCgQGwBIaaHR0cDovL21hcnRpbi1rcmFmZnQubmV0L2dwZy9jZXJ0LXBv +bGljeS81NWM5ODgyZDk5OWJiY2M0LzIwMDkwNzEyMTgzMz9zaGE1MTJzdW09ZjMz +YjE3YzlhZjUxNWJkOThiMjkyN2NiNDUzYTk5MmQzZDc1MDBlOWY2NzE5NjY2MTZl +OTA1MTBiOTk0MDg5NTEwOGQyNDE2NDhkMWEwZWI0NmIzMmJjYmYzMjUxYTEzNmE2 +ZWUxZTIyNzU3NDVlMTFiYjMyOGMxNGU3ZTcyNjMACgkQVcmILZmbvMTaXQ/+JVjn +1Wlt8sm7wTkiKIFVxYwqDa4xTfQKFMAMO+n/LJnvAEcK77X5F121sdXKcNtBSfMQ +QrplNClqVbd9wd1ix4D0auggnGaMUtgfwP5SBOf/zrYB6w5Ej1uhdLZl5YRmqOEt +7yY61TK8fGB6i5osgJE47P6OYep28Q2qK1jOtIt6HaNkKOtmfsq0wWTg7Iq/DXHS +twozq3Wi4QTLl2QAtLhKoNrmzDg4jsPQhbXARJtTnL9eHCZTML+OtJb7aca60thZ +VxEkzSElQNikJCNtlCF5PCWCvZCwGDyAMo8UGlTgjVnIunVeAWBEva4GcJJduC1M +bFpzoQyWJXtwIwD+QC71Dhl+vlmwN3wb7qnwZ5vEb5un/010v+AdMvRXpuDJs6oc +WXOrw00Fmg0AjaD9ly0dTPTYtH8olvpUO9shDd0EXr3uNFtBgJLu+X/QGhNOEzZC +YHZL8/osVgnXNfktczEI+pcnkXa06YhA6CvFgGG7s3BDMUafNsobw2hXCj2zNGbv +8Vve4po6en+pzafTFVUnsGYREv9v3eSc6R6zb4YSYSxMXCAIS4Osq5ZnMwjTHRx3 +32AYDeGlNp3tx6dzPSBCFksCdpVQzwQYh74Z+bVx9wK/10meQYEZwgXxlngy9bb8 +b6yD5pff8hHneLkaiLwwEjQuovuO0nhJGj4PTa2JAhwEEAEIAAYFAlIKFYAACgkQ +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 +=a+eH +-----END PGP PUBLIC KEY BLOCK----- diff --git a/fai/config/package_config/EDU b/fai/config/package_config/EDU new file mode 100644 index 0000000..32c8a3e --- /dev/null +++ b/fai/config/package_config/EDU @@ -0,0 +1,7 @@ +PACKAGES install +education-networked +debian-edu-config +debian-edu-artwork +debian-edu-install +cfengine3 +wget diff --git a/fai/config/package_config/GERMAN b/fai/config/package_config/GERMAN new file mode 100644 index 0000000..a9731eb --- /dev/null +++ b/fai/config/package_config/GERMAN @@ -0,0 +1,5 @@ +PACKAGES install +task-german + +PACKAGES install GNOME +firefox-esr-l10n-de thunderbird-l10n-de diff --git a/fai/config/package_config/GNOME b/fai/config/package_config/GNOME new file mode 100644 index 0000000..847b7d2 --- /dev/null +++ b/fai/config/package_config/GNOME @@ -0,0 +1,3 @@ +PACKAGES install +education-workstation +education-desktop-gnome diff --git a/fai/config/package_config/MATE b/fai/config/package_config/MATE new file mode 100644 index 0000000..84ff9a9 --- /dev/null +++ b/fai/config/package_config/MATE @@ -0,0 +1,3 @@ +PACKAGES install +education-workstation +education-desktop-mate diff --git a/fai/config/package_config/STANDARD b/fai/config/package_config/STANDARD new file mode 100644 index 0000000..48b60b5 --- /dev/null +++ b/fai/config/package_config/STANDARD @@ -0,0 +1,30 @@ +PACKAGES install-norec +# the list of standard packages, without any libs and a few packages removed +apt-listchanges +bash-completion +bind9-host +dbus +dnsutils +doc-debian +file +gettext-base +groff-base +hdparm +less +locales +lsof +man-db +manpages +mime-support +ncurses-term +netcat-traditional +openssh-client +pciutils +perl +python +python-minimal +reportbug +telnet +traceroute +ucf +xz-utils diff --git a/fai/config/package_config/XFCE b/fai/config/package_config/XFCE new file mode 100644 index 0000000..07066b0 --- /dev/null +++ b/fai/config/package_config/XFCE @@ -0,0 +1,5 @@ +PACKAGES install +education-workstation +education-desktop-xfce +xscreensaver +xscreensaver-gl diff --git a/fai/config/package_config/XORG b/fai/config/package_config/XORG new file mode 100644 index 0000000..f5d85b7 --- /dev/null +++ b/fai/config/package_config/XORG @@ -0,0 +1,5 @@ +PACKAGES install-norec DEBIAN +xorg xserver-xorg-video-all xserver-xorg-input-all +fonts-freefont-ttf +xterm +desktop-base diff --git a/fai/config/scripts/DEBIAN/10-rootpw b/fai/config/scripts/DEBIAN/10-rootpw new file mode 100755 index 0000000..8fdf4c8 --- /dev/null +++ b/fai/config/scripts/DEBIAN/10-rootpw @@ -0,0 +1,15 @@ +#! /bin/bash + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +# set root password +if [ -n "$ROOTPW" ]; then + $ROOTCMD usermod -p "$ROOTPW" root +else + $ROOTCMD usermod -L root + # enable sudo for user + ainsl /etc/sudoers "$username ALL = ALL" +fi + +exit $error + diff --git a/fai/config/scripts/DEBIAN/20-capabilities b/fai/config/scripts/DEBIAN/20-capabilities new file mode 100755 index 0000000..ea650fa --- /dev/null +++ b/fai/config/scripts/DEBIAN/20-capabilities @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Capabilities get lost when creating the fai base.tar.xz image. +# Restore them here. +# + +set -e + +if [ ! -x $target/sbin/setcap ] ; then + exit 0 +fi + +for FILE in /bin/ping /bin/ping6 /usr/bin/fping /usr/bin/fping6; do + if [ -x $target/$FILE -a ! -h $target/$FILE ] ; then + if $ROOTCMD /sbin/setcap cap_net_raw+ep $FILE; then + echo "Setcap worked! $FILE is not suid!" + fi + fi +done +if [ -x $target/usr/bin/systemd-detect-virt ] ; then + $ROOTCMD /sbin/setcap cap_dac_override,cap_sys_ptrace+ep /usr/bin/systemd-detect-virt +fi diff --git a/fai/config/scripts/DEBIAN/30-interface b/fai/config/scripts/DEBIAN/30-interface new file mode 100755 index 0000000..34c98e8 --- /dev/null +++ b/fai/config/scripts/DEBIAN/30-interface @@ -0,0 +1,118 @@ +#! /bin/bash + +netplan_yaml() { + # network configuration using ubuntu's netplan.io + local IFNAME="$1" + local METHOD="$2" + echo "Generating netplan configuration for $IFNAME ($METHOD)" >&2 + echo "# generated by FAI" + echo "network:" + echo " version: 2" + echo " renderer: $RENDERER" + case "$RENDERER" in + networkd) + echo " ethernets:" + echo " $IFNAME:" + case "$METHOD" in + dhcp) + echo " dhcp4: true" + ;; + static) + echo " addresses: [$CIDR]" + echo " gateway4: $GATEWAYS_1" + echo " nameservers:" + echo " search: [$DOMAIN]" + echo " addresses: [${DNSSRVS// /, }]" + ;; + esac + esac +} + +iface_stanza() { + # classic network configuration using /etc/network/interfaces + local IFNAME="$1" + local METHOD="$2" + echo "Generating interface configuration for $IFNAME ($METHOD)" >&2 + echo "# generated by FAI" + echo "auto $IFNAME" + echo "iface $IFNAME inet $METHOD" + case "$METHOD" in + static) + echo " address $IPADDR" + echo " netmask $NETMASK" + echo " broadcast $BROADCAST" + echo " gateway $GATEWAYS" + ;; + esac +} + +newnicnames() { + + # determine predictable network names only for stretch and above + + [ $do_init_tasks -eq 0 ] && return + [ -z "$NIC1" ] && return + ver=$($ROOTCMD dpkg-query --showformat='${Version}' --show udev) + if dpkg --compare-versions $ver lt 220-7; then + return + fi + + + fields="ID_NET_NAME_FROM_DATABASE ID_NET_NAME_ONBOARD ID_NET_NAME_SLOT ID_NET_NAME_PATH" + for field in $fields; do + name=$(udevadm info /sys/class/net/$NIC1 | sed -rn "s/^E: $field=(.+)/\1/p") + if [[ $name ]]; then + NIC1=$name + break + fi + done + if [[ ! $name ]]; then + echo "$0: error: could not find systemd predictable network name. Using $NIC1." + fi +} + +if [ -z "$NIC1" ]; then + echo "WARNING: \$NIC1 is not defined. Cannot add ethernet to /etc/network/interfaces." +fi +CIDR=$(ip -o -f inet addr show $NIC1 | awk '{print $4}') +newnicnames + +case "$FAI_ACTION" in + install|dirinstall) + ifclass DHCPC && METHOD=dhcp || METHOD=static + ifclass XORG && RENDERER=NetworkManager || RENDERER=networkd + + if [ -d $target/etc/netplan ]; then + # Ubuntu >= 17.10 with netplan.io + if [ -n "$NIC1" ]; then + netplan_yaml $NIC1 $METHOD > $target/etc/netplan/01-${NIC1}.yaml + fi + elif [ -d $target/etc/network/interfaces.d ]; then + # ifupdown >= 0.7.41 (Debian >= 8, Ubuntu >= 14.04) + iface_stanza lo loopback > $target/etc/network/interfaces.d/lo + + if [ -n "$NIC1" -a ! -f $target/etc/NetworkManager/NetworkManager.conf ]; then + iface_stanza $NIC1 $METHOD > $target/etc/network/interfaces.d/$NIC1 + fi + else + ( + iface_stanza lo loopback + iface_stanza $NIC1 $METHOD + ) > $target/etc/network/interfaces + fi + + if ! ifclass DHCPC ; then + [ -n "$NETWORK" ] && echo "localnet $NETWORK" > $target/etc/networks + if [ ! -L $target/etc/resolv.conf -a -e /etc/resolv.conf ]; then + cp -p /etc/resolv.conf $target/etc + fi + fi + ;; +esac + +# here fcopy is mostly used, when installing a client for running in a +# different subnet than during the installation +fcopy -iM /etc/resolv.conf +fcopy -iM /etc/network/interfaces /etc/networks + +exit $error diff --git a/fai/config/scripts/DEBIAN/40-misc b/fai/config/scripts/DEBIAN/40-misc new file mode 100755 index 0000000..4376ab4 --- /dev/null +++ b/fai/config/scripts/DEBIAN/40-misc @@ -0,0 +1,50 @@ +#! /bin/bash + +# (c) Thomas Lange, 2001-2016, lange@debian.org +# (c) Michael Goetze, 2010-2011, mgoetze@mgoetze.net + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +# a list of modules which are loaded at boot time +for module in $MODULESLIST; do + ainsl -a /etc/modules "^$module$" +done + +fcopy -Mv /etc/hostname || echo $HOSTNAME > $target/etc/hostname +ainsl -a /etc/mailname ${HOSTNAME} +if [ ! -e $target/etc/adjtime ]; then + printf "0.0 0 0.0\n0\nUTC\n" > $target/etc/adjtime +fi +if [ "$UTC" = "yes" ]; then + sed -i -e 's:^LOCAL$:UTC:' $target/etc/adjtime +else + sed -i -e 's:^UTC$:LOCAL:' $target/etc/adjtime +fi + +# enable linuxlogo +if [ -f $target/etc/inittab ]; then + sed -i -e 's#/sbin/getty 38400#/sbin/getty -f /etc/issue.linuxlogo 38400#' ${target}/etc/inittab +elif [ -f $target/lib/systemd/system/getty@.service ]; then + sed -i -e 's#sbin/agetty --noclear#sbin/agetty -f /etc/issue.linuxlogo --noclear#' $target/lib/systemd/system/getty@.service +fi + +# make sure a machine-id exists +if [ ! -f $target/etc/machine-id ]; then + > $target/etc/machine-id +fi +# recreate machine-id if the file is empty +if [ X"$(stat -c '%s' $target/etc/machine-id 2>/dev/null)" = X0 -a -f /bin/systemd-machine-id-setup ]; then + $ROOTCMD systemd-machine-id-setup +fi + +ln -fs /proc/mounts $target/etc/mtab + +rm -f $target/etc/dpkg/dpkg.cfg.d/fai $target/etc/dpkg/dpkg.cfg.d/unsafe-io + +if [ -d /etc/fai ]; then + ainsl -a /etc/fai/fai.conf "FAI_CONFIG_SRC=$FAI_CONFIG_SRC" + fcopy -Miv /etc/fai/fai.conf +fi +fcopy -iv /etc/rc.local + +exit $error diff --git a/fai/config/scripts/EDU/10-update-debian-edu-config b/fai/config/scripts/EDU/10-update-debian-edu-config new file mode 100755 index 0000000..4cf18d7 --- /dev/null +++ b/fai/config/scripts/EDU/10-update-debian-edu-config @@ -0,0 +1,6 @@ +#!/bin/bash + +if [ -f /etc/debian-edu/config ] && [ -x /usr/share/doc/debian-edu-install ]; then + sed -i /etc/debian-edu/config -e "s/^VERSION=.*$/VERSION=\"$(/usr/lib/debian-edu-install/version)\"/" +fi + diff --git a/fai/config/scripts/EDU/40-cfengine-install-workstation b/fai/config/scripts/EDU/40-cfengine-install-workstation new file mode 100755 index 0000000..9a1ff13 --- /dev/null +++ b/fai/config/scripts/EDU/40-cfengine-install-workstation @@ -0,0 +1,27 @@ +#! /bin/bash + +set -x + +# Let's make sure that we have correct http proxy settings. +if [ -x $target/usr/share/debian-edu-config/tools/update-proxy-from-wpad ]; then + chroot $target /usr/share/debian-edu-config/tools/update-proxy-from-wpad +fi + +# The proxy settings should not have been written to /etc/environment. +# Let's export those settings to the current shell, so that cf-agent +# has them... +for line in $(cat $target/etc/environment | grep -v -E "^#.*" | grep -E ".+=.*"); do + export $line; +done + +# Now let's assume, we have http_proxy, https_proxy and ftp_proxy set in our +# environment. We need to pass them on into the chroot... + +echo http_proxy=$http_proxy +echo https_proxy=$https_proxy +echo ftp_proxy=$ftp_proxy + +# Do the conversion of the vanilla Debian system to a Debian Edu system +chroot $target strace -f /usr/sbin/cf-agent -I -D installation + +set +x diff --git a/fai/config/scripts/FAIBASE/10-misc b/fai/config/scripts/FAIBASE/10-misc new file mode 100755 index 0000000..fbf85c1 --- /dev/null +++ b/fai/config/scripts/FAIBASE/10-misc @@ -0,0 +1,36 @@ +#! /bin/bash + +# (c) Thomas Lange, 2001-2012, lange@debian.org + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +echo $TIMEZONE > $target/etc/timezone +if [ -L $target/etc/localtime ]; then + ln -sf /usr/share/zoneinfo/${TIMEZONE} $target/etc/localtime +else + cp -f /usr/share/zoneinfo/${TIMEZONE} $target/etc/localtime +fi + +if [ -n "$IPADDR" ]; then + ifclass DHCPC || ainsl -s /etc/hosts "$IPADDR $HOSTNAME.$DOMAIN $HOSTNAME" +else + ifclass DHCPC && ainsl -s /etc/hosts "127.0.0.1 $HOSTNAME" +fi + +if [ -f $target/etc/hosts.orig ]; then + mv $target/etc/hosts.orig $target/etc/hosts +fi +fcopy -iM /etc/hosts /etc/motd + +# make /root accessible only by root +chmod -c 0700 $target/root +chown -c root:root $target/root +# copy default dotfiles for root account +fcopy -ir /root + +# use tmpfs for /tmp +ainsl /etc/fstab "tmpfs /tmp tmpfs nodev,nosuid,size=50%,mode=1777 0 0" +chmod -c 1777 ${target}/tmp +chown -c 0:0 ${target}/tmp + +exit $error diff --git a/fai/config/scripts/FAIBASE/20-removable_media b/fai/config/scripts/FAIBASE/20-removable_media new file mode 100755 index 0000000..4ba258f --- /dev/null +++ b/fai/config/scripts/FAIBASE/20-removable_media @@ -0,0 +1,27 @@ +#! /bin/bash + +# (c) Thomas Lange, 2006,2009, lange@debian.org +# create entries for removable media in fstab and directories in /media + +[ -b $target/dev/fd0 ] && ainsl /etc/fstab "/dev/fd0 /media/floppy auto users,noauto 0 0" + +cdromlist() { + [ -f /proc/sys/dev/cdrom/info ] || return + devs=$(grep 'drive name:' /proc/sys/dev/cdrom/info | cut -d ":" -f 2) + for d in $devs; do + echo $d + done +} + +fstabline () { + line=$(printf "%-15s %-15s %-7s %-15s %-7s %s\n" "$1" "$2" "$3" "$4" "$5" "$6") + ainsl /etc/fstab "$line" +} + +i=0 +for cdrom in $(cdromlist | tac); do + [ $i -eq 0 ] && ln -sfn cdrom0 $target/media/cdrom + mkdir -p $target/media/cdrom$i + fstabline /dev/$cdrom /media/cdrom$i udf,iso9660 ro,user,noauto 0 0 + i=$(($i + 1)) +done diff --git a/fai/config/scripts/GERMAN/10-update-debian-edu-config b/fai/config/scripts/GERMAN/10-update-debian-edu-config new file mode 100755 index 0000000..d896799 --- /dev/null +++ b/fai/config/scripts/GERMAN/10-update-debian-edu-config @@ -0,0 +1,7 @@ +#!/bin/bash + +if [ -f $target/etc/debian-edu/config ]; then + sed -i $target/etc/debian-edu/config -e "s/^LANGCODE=.*$/LANGCODE=\"de\"/" + sed -i $target/etc/debian-edu/config -e "s/^LOCALE=.*$/LOCALE=\"de_DE.UTF-8\"/" +fi + diff --git a/fai/config/scripts/GRUB_EFI/10-setup b/fai/config/scripts/GRUB_EFI/10-setup new file mode 100755 index 0000000..f586ba1 --- /dev/null +++ b/fai/config/scripts/GRUB_EFI/10-setup @@ -0,0 +1,68 @@ +#! /bin/bash +# support for GRUB version 2 + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +# This script assumes that the disk has a GPT partition table and +# that the extended system partition (ESP) is mounted on /boot/efi. +# When building a disk image, we don't change the NVRAM to point at +# the boot image we made available, because the disk image is likely +# not installed on the current system. As a result, we force +# installation into the removable media paths as well as the standard +# debian path. + +set -a + +# do not set up grub during dirinstall +if [ "$FAI_ACTION" = "dirinstall" ] ; then + exit 0 +fi +# during softupdate use this file +[ -r $LOGDIR/disk_var.sh ] && . $LOGDIR/disk_var.sh + +if [ -z "$BOOT_DEVICE" ]; then + exit 189 +fi + +# disable os-prober because of #788062 +ainsl /etc/default/grub 'GRUB_DISABLE_OS_PROBER=true' + +# skip the rest, if not an initial installation +if [ $FAI_ACTION != "install" ]; then + $ROOTCMD update-grub + exit $error +fi + +GROOT=$($ROOTCMD grub-probe -tdrive -d $BOOT_DEVICE) + +# handle /boot in lvm-on-md +_bdev=$(readlink -f $BOOT_DEVICE) +if [ "${_bdev%%-*}" = "/dev/dm" ]; then + BOOT_DEVICE=$( lvs --noheadings -o devices $BOOT_DEVICE | sed -e 's/^*\([^(]*\)(.*$/\1/' ) +fi + +# Check if RAID is used for the boot device +if [[ $BOOT_DEVICE =~ '/dev/md' ]]; then + raiddev=${BOOT_DEVICE#/dev/} + # install grub on all members of RAID + for device in `LC_ALL=C perl -ne 'if(/^'$raiddev'\s.+raid\d+\s(.+)/){ $_=$1; s/\d+\[\d+\]//g; print }' /proc/mdstat`; do + echo Install grub on /dev/$device + $ROOTCMD grub-install --no-floppy --force-extra-removable "/dev/$device" + done + +elif [[ $BOOT_DEVICE =~ '/dev/loop' ]]; then + # do not update vmram when using a loop device + $ROOTCMD grub-install --no-floppy --force-extra-removable --modules=part_gpt --no-nvram $BOOT_DEVICE + if [ $? -eq 0 ]; then + echo "Grub installed on hostdisk $BOOT_DEVICE" + fi + +else + $ROOTCMD grub-install --no-floppy --modules=part_gpt "$GROOT" + if [ $? -eq 0 ]; then + echo "Grub installed on $BOOT_DEVICE = $GROOT" + fi +fi +$ROOTCMD update-grub + +exit $error diff --git a/fai/config/scripts/GRUB_PC/10-setup b/fai/config/scripts/GRUB_PC/10-setup new file mode 100755 index 0000000..5563275 --- /dev/null +++ b/fai/config/scripts/GRUB_PC/10-setup @@ -0,0 +1,52 @@ +#! /bin/bash +# support for GRUB version 2 + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +set -a + +# do not set up grub during dirinstall +if [ "$FAI_ACTION" = "dirinstall" ] ; then + exit 0 +fi +# during softupdate use this file +[ -r $LOGDIR/disk_var.sh ] && . $LOGDIR/disk_var.sh + +if [ -z "$BOOT_DEVICE" ]; then + exit 189 +fi + +# disable os-prober because of #788062 +ainsl /etc/default/grub 'GRUB_DISABLE_OS_PROBER=true' + +# skip the rest, if not an initial installation +if [ $FAI_ACTION != "install" ]; then + $ROOTCMD update-grub + exit $error +fi + +GROOT=$($ROOTCMD grub-probe -tdrive -d $BOOT_DEVICE) + +# handle /boot in lvm-on-md +_bdev=$(readlink -f $BOOT_DEVICE) +if [ "${_bdev%%-*}" = "/dev/dm" ]; then + BOOT_DEVICE=$( lvs --noheadings -o devices $BOOT_DEVICE | sed -e 's/^*\([^(]*\)(.*$/\1/' ) +fi + +# Check if RAID is used for the boot device +if [[ $BOOT_DEVICE =~ '/dev/md' ]]; then + raiddev=${BOOT_DEVICE#/dev/} + # install grub on all members of RAID + for device in `LC_ALL=C perl -ne 'if(/^'$raiddev'\s.+raid\d+\s(.+)/){ $_=$1; s/\d+\[\d+\]//g; print }' /proc/mdstat`; do + echo Install grub on /dev/$device + $ROOTCMD grub-install --no-floppy "/dev/$device" + done +else + $ROOTCMD grub-install --no-floppy "$GROOT" + if [ $? -eq 0 ]; then + echo "Grub installed on $BOOT_DEVICE = $GROOT" + fi +fi +$ROOTCMD update-grub + +exit $error diff --git a/fai/config/scripts/LAST/50-misc b/fai/config/scripts/LAST/50-misc new file mode 100755 index 0000000..eebb379 --- /dev/null +++ b/fai/config/scripts/LAST/50-misc @@ -0,0 +1,103 @@ +#! /bin/bash + +# copyright Thomas Lange 2001-2016, lange@debian.org + +error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code + +if [ "$FAI_ACTION" = "dirinstall" -o $do_init_tasks -eq 0 ] ; then + : +else + # check if mdadm has been forgotten + if grep -q active /proc/mdstat 2>/dev/null; then + if [ ! -d $target/etc/mdadm ]; then + echo ERROR: Found Software RAID, but the mdadm package was not installed + error=1 + fi + fi + + usedm=$(dmsetup ls 2>/dev/null | egrep -v '^live-rw|^live-base|^No devices found' | wc -l) + if [ $usedm -ne 0 ]; then + if [ ! -d $target/etc/lvm ]; then + echo ERROR: Found lvm devices, but the lvm2 package was not installed + error=1 + fi + fi +fi + +# remove backup files from cfengine, but only if cfengine is installed +if [ -x /usr/sbin/cfagent ] || [ -x $target/usr/sbin/cfagent ] ; then + dirs="root etc var" + for path in $dirs; do + find $target/$path -maxdepth 20 -name \*.cfedited -o -name \*.cfsaved | xargs -r rm + done +fi + +[ "$FAI_DEBMIRROR" ] && + ainsl /etc/fstab "#$FAI_DEBMIRROR $MNTPOINT nfs ro 0 0" + +# set bios clock +if [ $do_init_tasks -eq 1 ] ; then + case "$UTC" in + no|"") hwopt="--localtime" ;; + yes) hwopt="--utc" ;; + esac + hwclock $hwopt --systohc || true +fi + +# Make sure everything is configured properly +if ifclass DEBIAN ; then + $ROOTCMD apt-get -f install +fi + +if [ $FAI_ACTION = "install" ]; then + lskernels=$(echo $target/boot/vmlinu*) + if [ ! -f ${lskernels%% *} ]; then + echo "ERROR: No kernel was installed. Have a look at shell.log" >&2 + error=1 + fi +fi + +# copy sources.list +fcopy -iSM /etc/apt/sources.list + + +setrel() { + + # if release is not set, try to determine it + + if [ -n "$release" ]; then + return + fi + if [ ! -f $target/etc/os-release ]; then + return + fi + + dists="jessie stretch buster bullseye bookworm bionic xenial trusty" + for d in $dists; do + if grep -iq $d $target/etc/os-release; then + release=$d + break + fi + done +} + +# if installation was done from CD, replace useless sources.list +setrel +if [ -f $target/etc/apt/sources.list -a -n "$release" ]; then + grep -q 'file generated by fai-cd' $target/etc/apt/sources.list && cat <<EOF > $target/etc/apt/sources.list +deb $apt_cdn/debian $release main contrib non-free +deb $apt_cdn/debian-security $release/updates main contrib non-free +#deb [trusted=yes] http://fai-project.org/download $release koeln +EOF + # if the package fai-server was installed, enable the project's repository + if [ -f $target/var/lib/dpkg/info/fai-server.list ]; then + sed -i -e '/fai-project.org/s/^#//' $target/etc/apt/sources.list + fi +fi + +# for ARM architecture, we may need the kernel and initrd to boot or flash the device +if ifclass ARM64; then + cp -pv $target/boot/vmlinuz* $target/boot/initrd* $FAI_RUNDIR +fi + +exit $error diff --git a/fai/config/scripts/WORKSTATION/10-update-debian-edu-config b/fai/config/scripts/WORKSTATION/10-update-debian-edu-config new file mode 100755 index 0000000..45062b9 --- /dev/null +++ b/fai/config/scripts/WORKSTATION/10-update-debian-edu-config @@ -0,0 +1,6 @@ +#!/bin/bash + +# tag Debian Edu machine as a workstation +if [ -f /etc/debian-edu/config ]; then + sed -i /etc/debian-edu/config -e "s/^PROFILE=.*$/PROFILE=\"Workstation\"/" +fi diff --git a/fai/config/tests/FAIBASE_TEST b/fai/config/tests/FAIBASE_TEST new file mode 100755 index 0000000..79bfab2 --- /dev/null +++ b/fai/config/tests/FAIBASE_TEST @@ -0,0 +1,44 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use Faitest; +package FAITEST; + +setup_test(); +# - - - - - - - - - - - - - - - - - - - - - - - - - - +# now comes the test itself + +my $dev = &getDevByMount("/target/home"); +&checkE2fsAttribute($dev,"Filesystem volume name","home"); +&checkE2fsAttribute($dev,"Maximum mount count","-1"); +&checkE2fsAttribute($dev,"Check interval","0 (<none>)"); + +exit printresult(); +# - - - - - - - - - - - - - - - - - - - - - - - - - - +__END__ + +=head1 NAME + +FAIBASE_TEST - regression test for setup-storage disk layout FAIBASE + +=head1 SYNOPSIS + +FAIBASE_TEST checks some important aspects of setup-storage. The +disk_config/FAIBASE tunes some filesystem parameters upon creation. We +check only the last partition since we expect prior errors to make +creation of the last partition fail. + + Options: + -help simple help + -verbose=n increase verbosity of test script + +=head1 OPTIONS + +=over 8 + +=item B<-help> +simple help + +=item B<-verbose> +increase verbosity of test script diff --git a/fai/config/tests/Faitest.pm b/fai/config/tests/Faitest.pm new file mode 100644 index 0000000..022b407 --- /dev/null +++ b/fai/config/tests/Faitest.pm @@ -0,0 +1,96 @@ +#! /usr/bin/perl + +# Subroutines for automatic tests +# +# Copyright (C) 2009 Thomas Lange, lange@informatik.uni-koeln.de +# Based on the first version by Sebastian Hetze, 08/2008 + +package FAITEST; + +my $errors = 0; + +use strict; +use Getopt::Long; +use Pod::Usage; +# - - - - - - - - - - - - - - - - - - - - - - - - - - +sub setup_test { + + my $verbose = 0; + my $help = 0; + my $man = 0; + $verbose = $ENV{'debug'} if $ENV{'debug'}; + + my $result = GetOptions ( + "verbose=i" => \$verbose, + "help" => \$help, + "man" => \$man, + + ); + + pod2usage(1) if $help; + pod2usage(-exitstatus => 0, -verbose => 2) if $man; + + open(LOGFILE,">> $ENV{LOGDIR}/test.log") || die "Can't open test.log. $!"; + print LOGFILE "------------ Test $0 starting ------------\n"; +} + +sub printresult { + + # write test result and set next test + my ($nexttest) = @_; + + if ($errors > 0) { + print STDERR "\n===> $0 FAILED with $errors errors\n"; + print LOGFILE "\n===> $0 FAILED with $errors errors\n"; + } else { + print STDERR "\n===> $0 PASSED successfully\n"; + print LOGFILE "\n===> $0 PASSED successfully\n"; + print LOGFILE "NEXTTEST=$nexttest\n" if $nexttest; + } + close (LOGFILE); + return $errors; +} + +sub getDevByMount { + + my $mount = shift; + my $dev = qx#mount|grep $mount|cut -d' ' -f1#; + chomp $dev; + return $dev +} + +sub checkMdStat { + + my ($device, $expected) = @_; + my ($value) = qx#grep -i "^$device\\b" /proc/mdstat# =~ m/$device\s*:\s*(.*)/i; + + if ($value eq $expected) { + print LOGFILE "Check raid $device success\n"; + return 0; + } else { + print LOGFILE "Check raid $device FAILED.\n Expect <$expected>\n Found <$value>\n"; + $errors++; + return 1; + } +} + +sub checkE2fsAttribute { + + my ($device, $attribute, $expected) = @_; + + # since attribute is a space separated list of attributes, IMO we must loop over + # the list. Ask Sebastian again + my ($value) = qx#tune2fs -l $device |grep -i "$attribute"# =~ m/$attribute:\s+(.*)/i; + + if ($value eq $expected) { + print LOGFILE "Check $attribute for $device success\n"; + return 0; + } else { + print LOGFILE "Check $attribute for $device FAILED.\n Expect <$expected>\n Found <$value>\n"; + + $errors++; + return 1; + } +} + +1; |