From ec9227898fa68bd89de454c87bce8ea051a8d783 Mon Sep 17 00:00:00 2001 From: Ian Kelling Date: Sat, 8 Oct 2016 21:41:04 -0700 Subject: [PATCH] various changes for libreboot having no pxe --- chboot | 3 + fai-redep | 17 +- fai/config/class/50-host-classes | 2 +- fai/config/distro-install-common/end | 2 +- .../.ssh/authorized_keys/.gitignore | 0 fai/config/hooks/instsoft.DEFAULT | 2 +- fai/config/hooks/partition.DEFAULT | 171 ++++++++++++------ fai/config/scripts/GRUB_PC/11-ian | 34 ++-- faiserver-setup | 6 - fresize | 77 +++++--- pxe-server | 2 +- 11 files changed, 213 insertions(+), 103 deletions(-) rename fai/config/files/{home/ian => root}/.ssh/authorized_keys/.gitignore (100%) diff --git a/chboot b/chboot index 426fd9a..eb8b118 100755 --- a/chboot +++ b/chboot @@ -90,6 +90,9 @@ boot_disk=${boot_dev%%[0-9]*} # https://www.gnu.org/software/grub/manual/html_node/Device-map.html e grub-bios-setup -d $mount_point/grub/i386-pc -s -m $mount_point/grub/device.map $boot_disk +# todo, mount_point needs subvolid=0 +e grub-editenv $mount_point/grub2/grubenv set default_subvol=/boot_$distro + e umount $mount_point e rmdir $mount_point diff --git a/fai-redep b/fai-redep index 1f0d92f..2f59ef7 100755 --- a/fai-redep +++ b/fai-redep @@ -30,13 +30,13 @@ cd $(dirname $(readlink -f "$BASH_SOURCE")) # use it, so look it up just to avoid the warning spam. faiserver_host=$(chost faiserver) || faiserver_host=faiserver - -ssh root@$faiserver_host rm -rf /srv/fai/config +shopt -s extglob +ssh root@$faiserver_host rm -rf /srv/fai/config/!(basefiles) scp -r fai/config root@$faiserver_host:/srv/fai scp ~/.ssh/id_rsa.pub \ - root@$faiserver_host:/srv/fai/config/files/home/ian/.ssh/authorized_keys/GRUB_PC + root@$faiserver_host:/srv/fai/config/files/root/.ssh/authorized_keys/GRUB_PC # todo: automatically disable faiserver after a period so # these files are not exposed. s scp -r /q/root/luks /q/root/shadow \ @@ -45,11 +45,18 @@ scp /a/bin/devbyid root@$faiserver_host:/srv/fai/nfsroot/usr/local/bin # built this with mk-basefile -J BELENOS64. it's stored in it's own repo which # is published alongside this one called fai-basefiles due # to being a large binary file. -scp /a/bin/basefiles/BELENOS64.tar.xz root@$faiserver_host:/srv/fai/config/basefiles +scp /a/bin/fai-basefiles/BELENOS64.tar.xz root@$faiserver_host:/srv/fai/config/basefiles ssh root@$faiserver_host bash <<'EOF' set -eE -o pipefail set -x -chmod 644 /srv/fai/config/files/home/ian/.ssh/authorized_keys/GRUB_PC +# make it the root because pxe-kexec only looks there. +# It wouldn't be too hard to change if we needed. +# We could also just dump things in /srv/tftp, but fai +# has some defaults, which I don't even use, which expect +# the other directory, so it's kind of a tossup, whatever. +sed -ri 's,^ *(TFTP_DIRECTORY=).*,\1"/srv/tftp/fai",' /etc/default/tftpd-hpa +systemctl restart tftpd-hpa +chmod 644 /srv/fai/config/files/root/.ssh/authorized_keys/GRUB_PC chmod -R a+rX /srv/fai/config/distro-install-common cd /srv/fai/config/basefiles u=http://fai-project.org/download/basefiles/XENIAL64.tar.xz diff --git a/fai/config/class/50-host-classes b/fai/config/class/50-host-classes index b8226de..49fa2fa 100755 --- a/fai/config/class/50-host-classes +++ b/fai/config/class/50-host-classes @@ -42,7 +42,7 @@ fi # use a list of classes for our demo machine echo "FAIBASE PARTITION_PROMPT" case $HOSTNAME in - x2|frodo|treetowl) + frodo|treetowl) echo "DEBIAN_NON_FREE" if [[ -e /a/bin/fai/fai-wrapper ]] && isdebian-stable; then echo "STABLE_NON_FREE" diff --git a/fai/config/distro-install-common/end b/fai/config/distro-install-common/end index c68be2c..d226af6 100755 --- a/fai/config/distro-install-common/end +++ b/fai/config/distro-install-common/end @@ -27,7 +27,7 @@ chpw() { if [[ $pwfile && -e $pwfile ]]; then printf "$user:" | cat - "$pwfile" | $ROOTCMD chpasswd -e else - echo "$0: warning: no pw set for $user" + echo "$0: warning: no pw set for $user" >&2 fi } au() { diff --git a/fai/config/files/home/ian/.ssh/authorized_keys/.gitignore b/fai/config/files/root/.ssh/authorized_keys/.gitignore similarity index 100% rename from fai/config/files/home/ian/.ssh/authorized_keys/.gitignore rename to fai/config/files/root/.ssh/authorized_keys/.gitignore diff --git a/fai/config/hooks/instsoft.DEFAULT b/fai/config/hooks/instsoft.DEFAULT index b4b3c10..de47766 100755 --- a/fai/config/hooks/instsoft.DEFAULT +++ b/fai/config/hooks/instsoft.DEFAULT @@ -1,7 +1,7 @@ #!/bin/bash # exit for any vm which is not our test vm -if ifclass VM && ! ifclass demohost; then +if ifclass VM && ! ifclass demohost || ifclass STABLE_BOOTSTRAP; then exit 0 fi diff --git a/fai/config/hooks/partition.DEFAULT b/fai/config/hooks/partition.DEFAULT index 8a32c31..f613226 100755 --- a/fai/config/hooks/partition.DEFAULT +++ b/fai/config/hooks/partition.DEFAULT @@ -29,13 +29,13 @@ rootn=1 swapn=2 bootn=3 bios_grubn=4 -boot_mib=1500 +boot_mib=4000 ##### end configuration -add-part() { +add-part() { # add partition suffix to $dev local d ret if [[ $# == 1 ]]; then d=$dev @@ -160,7 +160,9 @@ for dev in ${devs[@]}; do done if [[ ! $DISTRO ]]; then - if ifclass STRETCH64; then + if ifclass STABLE_BOOTSTRAP; then + DISTRO=debianstable_bootstrap + elif ifclass STRETCH64; then DISTRO=debiantesting elif ifclass STABLE; then DISTRO=debianstable @@ -248,14 +250,14 @@ if $partition; then swap_end=$(( root_end + swap_mib)) parted -s $dev mklabel gpt - # gpt ubuntu cloud image uses ~4. fai uses 1 MiB. - # I read something in the parted manual saying cheap flash media - # likes to start at 4. # MiB because parted complains about alignment otherwise. pcmd="parted -a optimal -s -- $dev" $pcmd mkpart primary "ext3" 4MiB ${root_end}MiB $pcmd mkpart primary "linux-swap" ${root_end}MiB ${swap_end}MiB $pcmd mkpart primary "" ${swap_end}MiB ${disk_mib}MiB + # gpt ubuntu cloud image uses ~4. fai uses 1 MiB. + # I read something in the parted manual saying cheap flash media + # likes to start at 4. $pcmd mkpart primary "" 1MiB 4MiB $pcmd set $bios_grubn bios_grub on $pcmd set $bootn boot on # generally not needed on modern systems @@ -288,7 +290,7 @@ if $partition; then cryptsetup luksOpen `rootdev` `root-cryptname` \ --key-file $luks_dir/host-$HOSTNAME done - ls -la /dev/btrfs-control + ls -la /dev/btrfs-control # this was probably for debugging... sleep 1 bpart $(for dev in ${devs[@]}; do root-cryptdev; done) bpart ${boot_devs[@]} @@ -300,81 +302,140 @@ else sleep 1 fi -mount -o subvolid=0 $first_root_crypt /mnt -# systemd creates subvolumes we want to delete. -s=($(btrfs subvolume list --sort=-path /mnt | - sed -rn "s#^.*path\s*(root_$DISTRO/\S+)\s*\$#\1#p")) -for subvol in ${s[@]}; do btrfs subvolume delete /mnt/$subvol; done -btrfs subvolume set-default 0 /mnt -[[ ! -e /mnt/root_$DISTRO ]] || btrfs subvolume delete /mnt/root_$DISTRO -## create subvols ## -cd /mnt -btrfs subvolume create root_$DISTRO -[[ -e q ]] || btrfs subvolume create q -chown root:1000 q - -mkdir -p /mnt/root_$DISTRO/boot -for x in q/a q/i; do - mkdir -p $x - chown 1000:1000 $x - chmod 755 $x -done -# could set default like this, but no reason to. -# btrfs subvolume set-default \ - # $(btrfs subvolume list . | grep "root_$DISTRO$" | awk '{print $2}') . -chattr -Rf +C root_$DISTRO -cd / -umount /mnt +if [[ $DISTRO != debianstable_bootstrap ]]; then + # bootstrap distro doesn't use separate encrypted root. + mount -o subvolid=0 $first_root_crypt /mnt + # systemd creates subvolumes we want to delete. + s=($(btrfs subvolume list --sort=-path /mnt | + sed -rn "s#^.*path\s*(root_$DISTRO/\S+)\s*\$#\1#p")) + for subvol in ${s[@]}; do btrfs subvolume delete /mnt/$subvol; done + btrfs subvolume set-default 0 /mnt + [[ ! -e /mnt/root_$DISTRO ]] || btrfs subvolume delete /mnt/root_$DISTRO + + ## create subvols ## + cd /mnt + + btrfs subvolume create root_$DISTRO + [[ -e q ]] || btrfs subvolume create q + chown root:1000 q + + mkdir -p /mnt/root_$DISTRO/boot + for x in q/a q/i; do + mkdir -p $x + chown 1000:1000 $x + chmod 755 $x + done + # could set default like this, but no reason to. + # btrfs subvolume set-default \ + # $(btrfs subvolume list . | grep "root_$DISTRO$" | awk '{print $2}') . + + # no cow on the root filesystem. it's setup is fully scripted, + # (immutable in buzzwords). if it messes up, we will just recreated it, + # and we can get better perf with this. + # I can't remember exactly why, but this is preferable to mounting with + # -o nodatacow, I think because subvolumes inherit that. + chattr -Rf +C root_$DISTRO + cd / + umount /mnt +fi + mount -o subvolid=0 $first_boot_dev /mnt cd /mnt btrfs subvolume set-default 0 /mnt -[[ ! -e /mnt/boot_$DISTRO ]] || btrfs subvolume delete /mnt/boot_$DISTRO -btrfs subvolume create boot_$DISTRO + +# for libreboot systems +mkdir -p /mnt/grub2 +cat >/mnt/grub2/libreboot_grub.cfg <<'EOF' +#!/bin/sh +# shebang is for editor file mode detection only + +if [ -s $prefix/grubenv ]; then + load_env +fi + +set default="0" +set timeout=1 + +menuentry debianstable_bootstrap { + configfile /$1/boot/grub/grub.cfg +} + +for dir in /boot_*; do + if [ x$dir = x$default_subvol ]; then + default=default_id + menuentry $dir --id=default_id { + configfile $1/grub/grub.cfg + } + else + menuentry $dir { + configfile $1/grub/grub.cfg + } + fi +done +EOF + +if [[ $DISTRO == debianstable_bootstrap ]]; then + # this is just convenience for the libreboot_grub config + # so we can glob the other ones easier. + boot_vol=$DISTRO +else + boot_vol=boot_$DISTRO +fi +[[ ! -e /mnt/$boot_vol ]] || btrfs subvolume delete /mnt/$boot_vol +btrfs subvolume create $boot_vol cd / umount /mnt ## end create subvols ## -# note, the mount point /a seems to get automatically created somewhere -cat > /tmp/fai/fstab < /tmp/fai/fstab </tmp/fai/disk_var.sh < /tmp/fai/fstab <> /tmp/fai/fstab <<'EOF' + # I will avoid using uuid in the future. the other way of specifying is simpler + if ifclass treetowl; then + cat >> /tmp/fai/fstab <<'EOF' $first_root_crypt /i btrfs noatime,subvol=i 0 0 UUID=3f7b31cd-f299-40b4-a86b-7604282e2715 /i btrfs noatime 0 2 EOF -fi + fi -swaps=() -for dev in ${devs[@]}; do - swaps+=(`swap-cryptname`) - cat >>/tmp/fai/crypttab <>/tmp/fai/crypttab <> /tmp/fai/fstab <> /tmp/fai/fstab </tmp/fai/disk_var.sh </tmp/fai/disk_var.sh <&2' ERR if [[ $EUID != 0 ]]; then - echo "$0: error: expected to be root." - exit 1 + echo "$0: error: expected to be root." + exit 1 +fi + +# note: +# fcopy -i = ignore nonmatching class error, always return 0. +fcopy -riM /root/.ssh + +chroot $FAI_ROOT bash <<'EOFOUTER' +debconf-set-selections </dev/null; then - sudo apt-get -y install fai-client + sudo apt-get -y install fai-client fi dir=/q/root/shadow fai_shadow=$FAI/distro-install-common/shadow if [[ ! -e $dir && -e $fai_shadow ]]; then - mkdir -p $dir - mount -o bind $fai_shadow $dir + mkdir -p $dir + mount -o bind $fai_shadow $dir fi $FAI/distro-install-common/end if ifclass STABLE || ifclass LINODESTABLE; then - fcopy -M /etc/apt/preferences + fcopy -M /etc/apt/preferences fi if ifclass DEBIAN; then - fcopy -M /etc/apt/preferences.d/unstable + fcopy -M /etc/apt/preferences.d/unstable fi fcopy -riM /etc/apt/sources.list.d $ROOTCMD apt-get update -# note: -# fcopy -i = ignore nonmatching class error, always return 0. - -# for lj, this will be empty and fail -fcopy -riM /home/ian/.ssh rm -f $FAI_ROOT/etc/apt/sources.list diff --git a/faiserver-setup b/faiserver-setup index aa83685..18933bb 100755 --- a/faiserver-setup +++ b/faiserver-setup @@ -98,12 +98,6 @@ e fai-setup -vf | tr '\n' ' '; ssh-keyscan localhost | grep -o "ecdsa-sha2-nistp256.*"; \ } >>/srv/fai/nfsroot/root/.ssh/known_hosts -# this does not alter the config on a new install -$sed 's#^([[:space:]]*TFTP_DIRECTORY[[:space:]]*=).*#\1"/srv/tftp"#' \ - /etc/default/tftpd-hpa - -service tftpd-hpa restart - # initially did the basic fai-chboot -Iv $std_arg default # but found in console that it wanted to mount nfsroot # to be the same as my dhcp server. diff --git a/fresize b/fresize index f08f4a6..f41e6fb 100755 --- a/fresize +++ b/fresize @@ -46,14 +46,16 @@ errcatch() { errcatch -[[ $EUID == 0 ]] || sudo "$BASH_SOURCE" "$@" +[[ $EUID == 0 ]] || exec sudo "$BASH_SOURCE" "$@" usage() { cat <. -n Dry run -r Reboot now if it's needed. @@ -72,7 +74,7 @@ EOF reboot_not=false dry_run=false -temp=$(getopt -l opt o "$@") || usage 1 +temp=$(getopt -l help rnh "$@") || usage 1 eval set -- "$temp" while true; do case $1 in @@ -110,8 +112,15 @@ boot=true [[ $2 == boot ]] || boot=false op_size=$1 # operator plus size -[[ $op_size != *g ]] || op_size=$(( ${op_size%g} / 1024 )) -size=${op_size#[+-]} +if [[ $op_size == *g ]]; then + op_size=${op_size%g} + size=${op_size#?} + op=${op_size%size} + size=$(( ${size} * 1024 )) + op_size=$op$size +else + size=${op_size#?} +fi if [[ $op_size == +* ]]; then op_size_rev=-$size # rev = reverse @@ -121,7 +130,6 @@ else grow=false fi - ##### end command line parsing ######## rootn=1 @@ -130,12 +138,22 @@ bootn=3 needs_reboot=false reboot_script_initialized=false -pmk() { +pmk() { # partition make part=$1 start_op=$2 end_op=$3 - p mkpart primary "$4" \ - $((${ptable[start$part]} $start_op)) $((${ptable[end$part]} $end_op)) + fs_type="$4" + + # This fails outside a vm, but actually succeeds. also prints this + # message: + # Error: Partition(s) 2 on /dev/sda have been written, but + # we have been unable to inform the kernel of the change, probably + # because it/they are in use. As a result, the old partition(s) + # will remain in use. You should reboot now before making further + # changes. + + p mkpart primary "$fs_type" \ + $((${ptable[start$part]} $start_op)) $((${ptable[end$part]} $end_op)) ||: } def-e() { @@ -150,6 +168,17 @@ def-e e swapoff -a while read devid dev; do + if [[ $dev != /dev/mapper/* ]]; then + # older oses, it points to /dev/dm-x + dev=$(dmsetup info $dev | sed -rn 's/^\s*Name:\s*(\S*)/\1/p') + else + dev=${dev#/dev/mapper/} + fi + dev=${dev#crypt_dev_} + r='-part[0-9]*$' + [[ $dev =~ $r ]] ||: + dev=${dev%$BASH_REMATCH} + devpath=/dev/disk/by-id/$dev echo skip=$size def-e declare -A ptable @@ -158,10 +187,16 @@ while read devid dev; do ptable[start$id]=start=${start%%[^0-9]*} ptable[end$id]=${end%%[^0-9]*} ptable[size$id]=${psize%%[^0-9]*} - done < <(parted -m /dev/$dev unit MiB print) - parted /dev/$dev unit MiB print | tee /root/backup_partition_table_$dev - p() { e parted -a optimal -s -- /dev/$dev unit MiB "$@"; } - e systemctl stop systemd-cryptsetup@crypt_swap_$dev$swapn + done < <(parted -m $devpath unit MiB print) + parted $devpath unit MiB print | tee /root/backup_partition_table_$dev + p() { e parted -a optimal -s -- $devpath unit MiB "$@"; } + unit=systemd-cryptsetup@crypt_dev_$dev-part$swapn + # note systemctl show can test if a unit exists. + e systemctl stop $unit || [[ $? == 5 ]] # fail due to not loaded + # there is a bug in jessie. this and the .swap unit are + # generated from /etc/fstab, and it escapes - to x2d, then doesn't escape it + # when looking for the file to use as swap. so, no swap is working on jessie + # right now. sleep 1 # dunno if this is needed, # but systemd likes to do these kind of things in the background. @@ -209,15 +244,17 @@ EOF $root_resize_cmd fi if $boot; then + # non by-id path, to match what btrfs fi show will tell us + boot_dev_path=$(readlink -f $devpath-part$bootn) boot_devid=$(btrfs fi show /boot | \ - sed -rn "s#^\s*devid\s+(\S+)\s.*$dev[0-9]#\1#p") + sed -rn "s#^\s*devid\s+(\S+)\s.*$boot_dev_path#\1#p") if ! $grow; then # shrink boot, move it to a temp file e btrfs fi resize $boot_devid:${op_size}M /boot e umount /boot temp_boot=/root/temp_boot_$dev - e dd bs=1M if=/dev/$dev$bootn of=$temp_boot \ + e dd bs=1M if=$boot_dev_path of=$temp_boot \ count=$((${ptable[size$bootn]} $op_size)) else e umount /boot @@ -235,11 +272,11 @@ EOF pmk $bootn $op_size_rev "" if $grow; then - e dd bs=1M if=/dev/$dev$bootn of=/dev/$dev$bootn skip=$size + e dd bs=1M if=$boot_dev_path of=$boot_dev_path skip=$size e mount /boot e btrfs fi resize $boot_devid:${op_size}M /boot else - e dd bs=1M if=$temp_boot of=/dev/$dev$bootn + e dd bs=1M if=$temp_boot of=$boot_dev_path e mount /boot fi else @@ -248,8 +285,7 @@ EOF pmk $swapn $op_size_rev "" "linux-swap" e systemctl start systemd-cryptsetup@crypt_swap_$dev$swapn fi -done < <(btrfs fi show / | \ - sed -nr 's#^\s*devid\s*(\S+)\s.*_([^_ ]+)[0-9]\s*$#\1 \2#p') +done < <(btrfs fi show / | sed -nr 's#^\s*devid\s*(\S+).* path (.*)$#\1 \2#p') if $boot; then @@ -270,4 +306,3 @@ if $needs_reboot; then exit fi fi - diff --git a/pxe-server b/pxe-server index 0bdd134..d8cbeb8 100755 --- a/pxe-server +++ b/pxe-server @@ -105,7 +105,7 @@ EOF fai() { cat <