Compare commits

...

2 Commits

Author SHA1 Message Date
Daniel Barlow 5df5c822ea convert mount service to trigger
Good: this means it's not hanging holding the s6 dataase lock.

Bad: it's the ugliest implementation and doesn't deserve to be preserved

(tbf the ugliness is not new)
2024-04-03 23:17:36 +01:00
Daniel Barlow 4795dd05b7 unconditionally restart trigger services on liminix-rebuild
We call s6-rc -u -p default to restart/start the base services
on a rebuild, otherwise services that are only in the new
configuration won't come up. However, this stops any service
started by a trigger. So, workaround is to restart the trigger
service and expect it to restart the services it manages if they're
needed
2024-04-03 23:07:56 +01:00
10 changed files with 170 additions and 11 deletions

View File

@ -9,6 +9,7 @@ let
in longrun {
name = "ifwait.${interface.name}";
buildInputs = [ service ];
isTrigger = true;
run = ''
${ifwait}/bin/ifwait -s ${service.name} $(output ${interface} ifname) ${state}
'';

View File

@ -4,15 +4,28 @@
}:
{ device, mountpoint, options, fstype }:
let
inherit (liminix.services) oneshot;
in oneshot {
name = "mount.${lib.escapeURL mountpoint}";
up = ''
inherit (liminix.services) longrun oneshot;
options_string =
if options == [] then "" else "-o ${lib.concatStringsSep "," options}";
mount_service = oneshot {
name = "mount.${lib.escapeURL mountpoint}";
timeout-up = 3600;
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";
down = "umount ${mountpoint}";
};
in longrun {
name = "watch-mount.${lib.strings.sanitizeDerivationName mountpoint}";
isTrigger = true;
buildInputs = [ mount_service ];
# This accommodates bringing the service up when the device appears.
# It doesn't bring it down on unplug because unmount will probably
# fail anyway (so don't do that)
run = ''
while ! findfs ${device}; do
echo waiting for device ${device}
sleep 1
done
mount -t ${fstype} -o ${lib.concatStringsSep "," options} ${device} ${mountpoint}
s6-rc -b -u change ${mount_service.name}
'';
down = "umount ${mountpoint}";
}

View File

@ -11,7 +11,7 @@ test -n "$contents" && for d in $contents; do
touch $out/${name}/contents.d/$d
done
for i in timeout-up timeout-down run notification-fd up down consumer-for producer-for pipeline-name ; do
for i in timeout-up timeout-down run notification-fd up down consumer-for producer-for pipeline-name restart-on-upgrade; do
test -n "$(printenv $i)" && (echo "$(printenv $i)" > $out/${name}/$i)
done

View File

@ -36,12 +36,14 @@ let
, dependencies ? []
, contents ? []
, buildInputs ? []
, isTrigger ? false
} @ args:
stdenvNoCC.mkDerivation {
# we use stdenvNoCC to avoid generating derivations with names
# like foo.service-mips-linux-musl
inherit name serviceType up down run notification-fd
producer-for consumer-for pipeline-name timeout-up timeout-down;
restart-on-upgrade = isTrigger;
buildInputs = buildInputs ++ dependencies ++ contents;
dependencies = builtins.map (d: d.name) dependencies;
contents = builtins.map (d: d.name) contents;

View File

@ -21,11 +21,16 @@ in stdenvNoCC.mkDerivation {
if test -d $i; then
for j in $i/* ; do
if test -f $j/type ; then
if test -e $j/restart-on-upgrade; then
flag=force-restart
else
unset flag
fi
case $(cat $j/type) in
longrun|oneshot)
# s6-rc-update only wants oneshots in its
# s6-rc-update only wants atomics in its
# restarts file
echo $(basename $j) " " $i >> $out/hashes
echo $(basename $j) " " ''${flag-$i} >> $out/hashes
;;
*)
;;

View File

@ -12,8 +12,11 @@
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")))))))
(let [new (. new-hashes n)]
(when (or (= h "force-restart")
(= new "force-restart")
(not (= h new)))
(f:write (.. n " restart\n"))))))))
(fn exec [text command]
(io.write (.. text ": "))

View File

@ -9,4 +9,5 @@
fennel = import ./fennel/test.nix;
tftpboot = import ./tftpboot/test.nix;
updown = import ./updown/test.nix;
inout = import ./inout/test.nix;
}

View File

@ -0,0 +1,61 @@
{ config, pkgs, lib, modulesPath, ... } :
let
inherit (pkgs.liminix.services) bundle oneshot longrun;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {
imports = [
"${modulesPath}/dhcp6c"
"${modulesPath}/dnsmasq"
"${modulesPath}/firewall"
"${modulesPath}/hostapd"
"${modulesPath}/network"
"${modulesPath}/ssh"
"${modulesPath}/mount"
];
filesystem = dir { srv = dir {}; };
kernel = {
config = {
USB = "y";
USB_EHCI_HCD = "y";
USB_EHCI_HCD_PLATFORM = "y";
USB_OHCI_HCD = "y";
USB_OHCI_HCD_PLATFORM = "y";
USB_SUPPORT = "y";
USB_COMMON = "y";
USB_STORAGE = "y";
USB_STORAGE_DEBUG = "n";
USB_UAS = "y";
USB_ANNOUNCE_NEW_DEVICES = "y";
SCSI = "y";
BLK_DEV_SD = "y";
USB_PRINTER = "y";
MSDOS_PARTITION = "y";
EFI_PARTITION = "y";
EXT4_FS = "y";
EXT4_USE_FOR_EXT2 = "y";
FS_ENCRYPTION = "y";
};
};
rootfsType = "jffs2";
hostname = "inout";
services.mount_external_disk = svc.mount.build {
device = "LABEL=backup-disk";
mountpoint = "/srv";
fstype = "ext4";
};
services.sshd = svc.ssh.build { };
defaultProfile.packages = with pkgs; [
min-collect-garbage
tcpdump
];
}

47
tests/inout/script.expect Normal file
View File

@ -0,0 +1,47 @@
set timeout 10
proc chat {instr outstr} {
expect {
$instr { send $outstr }
timeout { exit 1 }
}
}
spawn socat -,echo=0,icanon=1 unix-connect:vm/monitor
set monitor_id $spawn_id
# expect "(qemu)"
# send "set_link virtio-net-pci.1 off\n"
# expect "(qemu)"
# send "set_link virtio-net-pci.0 off\n"
# expect "(qemu)"
# send "c\r\n"
spawn socat unix-connect:vm/console -
set console_id $spawn_id
expect "BusyBox"
chat "#" "PS1=RE\\ADY_\\ ; stty -echo \r"
chat "READY_" "s6-rc -b -a list\r"
chat "watch-mount" "\r"
set spawn_id $monitor_id
chat "QEMU" "device_add usb-storage,bus=xhci.0,drive=usbstick\n"
chat "(qemu)" "version\r"
set spawn_id $console_id
expect {
"mounted filesystem" { }
timeout { exit 1 }
}
send "\r"
chat "READY_" "s6-rc -b -a list\r"
chat "READY_" "cat /proc/mounts\r"
expect {
"/srv" { }
timeout { exit 1 }
}

26
tests/inout/test.nix Normal file
View File

@ -0,0 +1,26 @@
{
liminix
, nixpkgs
}:
let img = (import liminix {
device = import "${liminix}/devices/qemu/";
liminix-config = ./configuration.nix;
}).outputs.vmroot;
pkgs = import <nixpkgs> { overlays = [(import ../../overlay.nix)]; };
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [
expect
socat
e2fsprogs
util-linux # for sfdisk, fallocate
] ;
} ''
mkdir vm
dd if=/dev/zero of=./vm/stick.e2fs bs=1M count=32
mkfs.ext2 -L backup-disk ./vm/stick.e2fs
cat <(dd if=/dev/zero bs=512 count=4) ./vm/stick.e2fs > ./vm/stick.img
echo '4,-,L,*' | sfdisk ./vm/stick.img
${img}/run.sh --background ./vm --flag -device --flag usb-ehci,id=xhci --flag -drive --flag if=none,id=usbstick,format=raw,file=$(pwd)/vm/stick.img
expect ${./script.expect} | tee $out
''