liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 2fb4756a7f071f23dc971ee8f9a7454b19ef1e44
parent 04f51744254ce07b231a251fbf01791315b3cf4c
Author: Daniel Barlow <dan@telent.net>
Date:   Thu, 28 Mar 2024 23:45:10 +0000

add soft restart option to liminix-rebuild

instead of doing a full reboot, it runs activate / and uses
s6-rc-update to install the new service database

Diffstat:
Mpkgs/min-copy-closure/liminix-rebuild.sh | 29++++++++++++++++++++++-------
Mpkgs/s6-rc-database/default.nix | 15+++++++++++++--
Mpkgs/systemconfig/default.nix | 4+++-
Apkgs/systemconfig/restart-services.fnl | 37+++++++++++++++++++++++++++++++++++++
Apkgs/systemconfig/test-hashes | 12++++++++++++
Apkgs/systemconfig/test-hashes2 | 12++++++++++++
Mtests/min-copy-closure/test-liminix-rebuild.sh | 24+++++++++++++++++++-----
Atests/min-copy-closure/wait-for-soft-restart.expect | 13+++++++++++++
Mtests/min-copy-closure/with-figlet.nix | 7+++++++
9 files changed, 138 insertions(+), 15 deletions(-)

diff --git a/pkgs/min-copy-closure/liminix-rebuild.sh b/pkgs/min-copy-closure/liminix-rebuild.sh @@ -2,12 +2,18 @@ ssh_command=${SSH_COMMAND-ssh} -if [ "$1" = "--no-reboot" ] ; then - reboot="true" - shift -else - reboot="reboot" -fi +reboot="reboot" + +case "$1" in + "--no-reboot") + unset reboot + shift + ;; + "--fast") + reboot="soft" + shift + ;; +esac target_host=$1 shift @@ -21,7 +27,16 @@ if toplevel=$(nix-build "$@" -A outputs.systemConfiguration --no-out-link); then echo systemConfiguration $toplevel min-copy-closure $target_host $toplevel $ssh_command $target_host $toplevel/bin/install - $ssh_command $target_host "sync; source /etc/profile; reboot" + case "$reboot" in + reboot) + $ssh_command $target_host "sync; source /etc/profile; reboot" + ;; + soft) + $ssh_command $target_host $toplevel/bin/restart-services + ;; + *) + ;; + esac else echo Rebuild failed fi diff --git a/pkgs/s6-rc-database/default.nix b/pkgs/s6-rc-database/default.nix @@ -21,11 +21,22 @@ in stdenvNoCC.mkDerivation { if test -d $i; then for j in $i/* ; do if test -f $j/type ; then + case $(cat $j/type) in + longrun|oneshot) + # s6-rc-update only wants oneshots in its + # restarts file + echo $(basename $j) " " $i >> $out/hashes + ;; + *) + ;; + esac srcs="$srcs $i" fi done fi done s6-rc-compile $out/compiled $srcs - ''; - } + s6-rc-db -c $out/compiled contents default + mv $out/hashes $out/compiled + ''; +} diff --git a/pkgs/systemconfig/default.nix b/pkgs/systemconfig/default.nix @@ -6,6 +6,7 @@ { writeText +, writeFennelScript , lib , s6-init-bin , closureInfo @@ -52,7 +53,7 @@ let chown = if uid>0 || gid>0 then "\nCHOWN(${qpathname},${toString uid},${toString gid});\n" else ""; - in "${cmd} ${chown}"; + in "unlink(${qpathname}); ${cmd} ${chown}"; in mapAttrsToList (makeFile prefix) attrset; activateScript = attrset: writeText "makedevs.c" '' #include "defs.h" @@ -80,6 +81,7 @@ in attrset: cp $closure/store-paths $out/etc/nix-store-paths $STRIP --remove-section=.note --remove-section=.comment --strip-all makedevs -o $out/bin/activate ln -s ${s6-init-bin}/bin/init $out/bin/init + cp -p ${writeFennelScript "restart-services" [] ./restart-services.fnl} $out/bin/restart-services cat > $out/bin/install <<EOF #!/bin/sh -e prefix=\''${1-/} diff --git a/pkgs/systemconfig/restart-services.fnl b/pkgs/systemconfig/restart-services.fnl @@ -0,0 +1,37 @@ +(fn hashes-from-file [name] + (with-open [f (assert (io.open name :r) name)] + (accumulate [h [] + l #(f:read "*l")] + (let [(name hash) (string.match l "([^%s]+) +([^%s]+)")] + (if name + (doto h (tset name hash)) + h))))) + +(fn write-restarts [old new] + (let [old-hashes (hashes-from-file old) + new-hashes (hashes-from-file new)] + (with-open [f (io.open "/tmp/restarts" :w)] + (each [n h (pairs old-hashes)] + (when (not (= h (. new-hashes n))) + (f:write (.. n " restart\n"))))))) + +(fn exec [text command] + (io.write (.. text ": ")) + (match (os.execute command) + res (print "[OK]") + (nil err) (error (.. "[FAILED " err "]")))) + +(let [mypath (: (. arg 0) :match "(.*/)") + activate (.. mypath "activate /") + old-compiled "/run/s6-rc/compiled/" + new-compiled "/etc/s6-rc/compiled/"] + + (exec "installing FHS files" activate) + + (write-restarts (.. old-compiled "hashes") (.. new-compiled "hashes")) + + (exec "updating service database" + (.. "s6-rc-update -f /tmp/restarts " new-compiled)) + + (exec "starting services" (.. "s6-rc -u -p change default")) + ) diff --git a/pkgs/systemconfig/test-hashes b/pkgs/systemconfig/test-hashes @@ -0,0 +1,12 @@ +loopback /nix/store/3k7yp08465k8z8a1514slansj0hbrvbq-loopback +default /nix/store/5247rr0mcr17x9lkaqjiywxmn4q3ibgd-default +lan.link.a.10.3.0.1 /nix/store/99ic5bryzbx12ip4v8sh9cdrv15c8qwl-lan.link.a.10.3.0.1 +lo.link.a.-1 /nix/store/a2yvj42ghcg8iyvi51zcmzmpwwkrx30l-lo.link.a.-1 +sshd /nix/store/afgznmavi6s9dxkv4vnn9xwd7qz5kk35-sshd +lo.link /nix/store/dz0nvlf16lqv9yndas0sk0xqh7jvx8gm-lo.link +lo.link.a.127.0.0.1 /nix/store/jl018kbgxcnyb70s0cfw19q1zqa0pval-lo.link.a.127.0.0.1 +lan.link /nix/store/lxvmhb7ax46s2akj9lsivcq494kmx0hm-lan.link +lan.link.a.10.3.0.1.dnsmasq-log /nix/store/rk8265ikd9lj3fpibyrw0kal32h0ksqg-lan.link.a.10.3.0.1.dnsmasq-log +hostname /nix/store/xfy0ymvnd0zv6wcd26h405f85hfkd8wq-hostname +sshd-log /nix/store/xj58nxvkacsjg3rvwb4bxcqnhaav4d3s-sshd-log +lan.link.a.10.3.0.1.dnsmasq /nix/store/z4l7h9pr4an9aq921cs9wrlvf9b8xr48-lan.link.a.10.3.0.1.dnsmasq diff --git a/pkgs/systemconfig/test-hashes2 b/pkgs/systemconfig/test-hashes2 @@ -0,0 +1,12 @@ +loopback /nix/store/3k7yp08465k8z8a1514slansj0hbrvbq-loopback +default /nix/store/5247rr0mcr17x9lkaqjiywxmn4q3ibgd-default +lan.link.a.10.3.0.1 /nix/store/99ic5bryzbx12ip4v8sh9cdrv15c8qwl-lan.link.a.10.3.0.1 +lo.link.a.-1 /nix/store/a2yvj42ghcg8iyvi51zcmzmpwwkrx30l-lo.link.a.-1 +sshd /nix/store/afgznmavi6s9dxkv4vnn9xwd7qz5kk35-sshd +lo.link /nax/store/dz0nvlf16lqv9yndas0sk0xqh7jvx8gm-lo.link +lo.link.a.127.0.0.1 /nix/store/jl018kbgxcnyb70s0cfw19q1zqa0pval-lo.link.a.127.0.0.1 +lan.link /nix/store/lxvmhb7ax46s2akj9lsivcq494kmx0hm-lan.link +lan.link.a.10.3.0.1.dnsmasq-log /nix/store/rk8265ikd9lj3fpibyrw0kal32h0ksqg-lan.link.a.10.3.0.1.dnsmasq-log +hostname /nax/store/xfy0ymvnd0zv6wcd26h405f85hfkd8wq-hostname +sshd-log /nax/store/xj58nxvkacsjg3rvwb4bxcqnhaav4d3s-sshd-log + diff --git a/tests/min-copy-closure/test-liminix-rebuild.sh b/tests/min-copy-closure/test-liminix-rebuild.sh @@ -10,6 +10,17 @@ set -e +while test -n "$1"; do + case $1 in + --fast) + FAST=true + ;; + *) + ;; + esac + shift +done + here=$(pwd)/tests/min-copy-closure top=$(pwd) @@ -32,7 +43,7 @@ mkdir ./vm cat ${rootfs} > rootfs -truncate -s 24M rootfs +truncate -s 32M rootfs resize2fs rootfs dd if=rootfs of=disk-image bs=512 seek=4 conv=sync @@ -51,9 +62,12 @@ echo "READY" touch known_hosts export SSH_COMMAND="ssh -o UserKnownHostsFile=${work}/known_hosts -o StrictHostKeyChecking=no -p 2022 -i ${here}/id" -(cd ${top} && liminix-rebuild root@localhost -I liminix-config=${here}/with-figlet.nix --arg device "import ./devices/qemu-armv7l") - -ls -l vm +if test -n "$FAST"; then + (cd ${top} && liminix-rebuild --fast root@localhost -I liminix-config=${here}/with-figlet.nix --argstr deviceName qemu-armv7l) + cd ${work} && expect $here/wait-for-soft-restart.expect +else + (cd ${top} && liminix-rebuild root@localhost -I liminix-config=${here}/with-figlet.nix --arg device "import ./devices/qemu-armv7l") + cd ${work} && expect $here/wait-for-reboot.expect +fi -cd ${work} && expect $here/wait-for-reboot.expect cd / ; rm -rf $work diff --git a/tests/min-copy-closure/wait-for-soft-restart.expect b/tests/min-copy-closure/wait-for-soft-restart.expect @@ -0,0 +1,13 @@ +proc chat {instr outstr} { + expect { + $instr { send $outstr } + timeout { exit 1 } + } +} +spawn socat unix-connect:vm/console - + +send "exit\r" +chat "BusyBox" "\r" +chat "#" "stty -echo; type -p figlet\r" +chat "figlet-armv7l-unknown-linux" "s6-rc -a list |grep w\\inkle\r" +chat "winkle" "poweroff\r" diff --git a/tests/min-copy-closure/with-figlet.nix b/tests/min-copy-closure/with-figlet.nix @@ -4,4 +4,11 @@ defaultProfile.packages = with pkgs; [ figlet ]; + services.ripvanwinkle = pkgs.liminix.services.longrun { + name = "winkle"; + run = '' + echo SLEEPING > /dev/console + sleep 3600 + ''; + }; }