add uevent-watch, which toggles services based on uevent msgs
This commit is contained in:
parent
5564cf0554
commit
ea2b25168e
6 changed files with 297 additions and 0 deletions
|
@ -33,4 +33,5 @@
|
||||||
: mktree
|
: mktree
|
||||||
: rmtree
|
: rmtree
|
||||||
: directory?
|
: directory?
|
||||||
|
:symlink (fn [from to] (lfs.link from to true))
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,7 @@ in {
|
||||||
swconfig = callPackage ./swconfig {};
|
swconfig = callPackage ./swconfig {};
|
||||||
systemconfig = callPackage ./systemconfig {};
|
systemconfig = callPackage ./systemconfig {};
|
||||||
tufted = callPackage ./tufted {};
|
tufted = callPackage ./tufted {};
|
||||||
|
uevent-watch = callPackage ./uevent-watch {};
|
||||||
writeAshScript = callPackage ./write-ash-script {};
|
writeAshScript = callPackage ./write-ash-script {};
|
||||||
writeFennel = callPackage ./write-fennel {};
|
writeFennel = callPackage ./write-fennel {};
|
||||||
writeFennelScript = callPackage ./write-fennel-script {};
|
writeFennelScript = callPackage ./write-fennel-script {};
|
||||||
|
|
23
pkgs/uevent-watch/default.nix
Normal file
23
pkgs/uevent-watch/default.nix
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
lua
|
||||||
|
, nellie
|
||||||
|
, writeFennelScript
|
||||||
|
, runCommand
|
||||||
|
, anoia
|
||||||
|
, fennel
|
||||||
|
, stdenv
|
||||||
|
, fennelrepl
|
||||||
|
}:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "uevent-watch";
|
||||||
|
src = ./.;
|
||||||
|
nativeBuildInputs = [ fennelrepl ];
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp -p ${writeFennelScript "uevent-watch" [fennel anoia nellie lua.pkgs.luafilesystem] ./watch.fnl} $out/bin/uevent-watch
|
||||||
|
'';
|
||||||
|
checkPhase = ''
|
||||||
|
fennelrepl ./test.fnl
|
||||||
|
'';
|
||||||
|
doCheck = true;
|
||||||
|
}
|
154
pkgs/uevent-watch/events.txt
Normal file
154
pkgs/uevent-watch/events.txt
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1
|
||||||
|
SUBSYSTEM=usb
|
||||||
|
MAJOR=189
|
||||||
|
MINOR=1
|
||||||
|
DEVNAME=bus/usb/001/002
|
||||||
|
DEVTYPE=usb_device
|
||||||
|
PRODUCT=46f4/1/0
|
||||||
|
TYPE=0/0/0
|
||||||
|
BUSNUM=001
|
||||||
|
DEVNUM=002
|
||||||
|
SEQNUM=1513
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0
|
||||||
|
SUBSYSTEM=usb
|
||||||
|
DEVTYPE=usb_interface
|
||||||
|
PRODUCT=46f4/1/0
|
||||||
|
TYPE=0/0/0
|
||||||
|
INTERFACE=8/6/80
|
||||||
|
MODALIAS=usb:v46F4p0001d0000dc00dsc00dp00ic08isc06ip50in00
|
||||||
|
SEQNUM=1514
|
||||||
|
|
||||||
|
add@/devices/virtual/workqueue/scsi_tmf_0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/virtual/workqueue/scsi_tmf_0
|
||||||
|
SUBSYSTEM=workqueue
|
||||||
|
SEQNUM=1515
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0
|
||||||
|
SUBSYSTEM=scsi
|
||||||
|
DEVTYPE=scsi_host
|
||||||
|
SEQNUM=1516
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/scsi_host/host0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/scsi_host/host0
|
||||||
|
SUBSYSTEM=scsi_host
|
||||||
|
SEQNUM=1517
|
||||||
|
|
||||||
|
bind@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0
|
||||||
|
ACTION=bind
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0
|
||||||
|
SUBSYSTEM=usb
|
||||||
|
DEVTYPE=usb_interface
|
||||||
|
DRIVER=usb-storage
|
||||||
|
PRODUCT=46f4/1/0
|
||||||
|
TYPE=0/0/0
|
||||||
|
INTERFACE=8/6/80
|
||||||
|
MODALIAS=usb:v46F4p0001d0000dc00dsc00dp00ic08isc06ip50in00
|
||||||
|
SEQNUM=1518
|
||||||
|
|
||||||
|
bind@/devices/pci0000:00/0000:00:13.0/usb1/1-1
|
||||||
|
ACTION=bind
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1
|
||||||
|
SUBSYSTEM=usb
|
||||||
|
MAJOR=189
|
||||||
|
MINOR=1
|
||||||
|
DEVNAME=bus/usb/001/002
|
||||||
|
DEVTYPE=usb_device
|
||||||
|
DRIVER=usb
|
||||||
|
PRODUCT=46f4/1/0
|
||||||
|
TYPE=0/0/0
|
||||||
|
BUSNUM=001
|
||||||
|
DEVNUM=002
|
||||||
|
SEQNUM=1519
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0
|
||||||
|
SUBSYSTEM=scsi
|
||||||
|
DEVTYPE=scsi_target
|
||||||
|
SEQNUM=1520
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0
|
||||||
|
SUBSYSTEM=scsi
|
||||||
|
DEVTYPE=scsi_device
|
||||||
|
MODALIAS=scsi:t-0x00
|
||||||
|
SEQNUM=1521
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0
|
||||||
|
SUBSYSTEM=scsi_device
|
||||||
|
SEQNUM=1522
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0
|
||||||
|
SUBSYSTEM=scsi_disk
|
||||||
|
SEQNUM=1523
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0
|
||||||
|
SUBSYSTEM=bsg
|
||||||
|
MAJOR=252
|
||||||
|
MINOR=0
|
||||||
|
DEVNAME=bsg/0:0:0:0
|
||||||
|
SEQNUM=1524
|
||||||
|
|
||||||
|
change@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0
|
||||||
|
ACTION=change
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0
|
||||||
|
SUBSYSTEM=scsi
|
||||||
|
SDEV_UA=POWER_ON_RESET_OCCURRED
|
||||||
|
DEVTYPE=scsi_device
|
||||||
|
DRIVER=sd
|
||||||
|
MODALIAS=scsi:t-0x00
|
||||||
|
SEQNUM=1525
|
||||||
|
|
||||||
|
add@/devices/virtual/bdi/8:0
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/virtual/bdi/8:0
|
||||||
|
SUBSYSTEM=bdi
|
||||||
|
SEQNUM=1526
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda
|
||||||
|
SUBSYSTEM=block
|
||||||
|
MAJOR=8
|
||||||
|
MINOR=0
|
||||||
|
DEVNAME=sda
|
||||||
|
DEVTYPE=disk
|
||||||
|
DISKSEQ=2
|
||||||
|
SEQNUM=1527
|
||||||
|
|
||||||
|
add@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1
|
||||||
|
ACTION=add
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1
|
||||||
|
SUBSYSTEM=block
|
||||||
|
MAJOR=8
|
||||||
|
MINOR=1
|
||||||
|
DEVNAME=sda1
|
||||||
|
DEVTYPE=partition
|
||||||
|
DISKSEQ=2
|
||||||
|
PARTN=1
|
||||||
|
SEQNUM=1528
|
||||||
|
|
||||||
|
bind@/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0
|
||||||
|
ACTION=bind
|
||||||
|
DEVPATH=/devices/pci0000:00/0000:00:13.0/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0
|
||||||
|
SUBSYSTEM=scsi
|
||||||
|
DEVTYPE=scsi_device
|
||||||
|
DRIVER=sd
|
||||||
|
MODALIAS=scsi:t-0x00
|
||||||
|
SEQNUM=1529
|
48
pkgs/uevent-watch/test.fnl
Normal file
48
pkgs/uevent-watch/test.fnl
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
(local { : view} (require :fennel))
|
||||||
|
|
||||||
|
(set _G.arg (doto [] (tset 0 "test")))
|
||||||
|
(local subject (require :watch))
|
||||||
|
|
||||||
|
(macro expect= [actual expected]
|
||||||
|
`(let [ve# (view ,expected)
|
||||||
|
va# (view ,actual)]
|
||||||
|
(when (not (= ve# va#))
|
||||||
|
(assert false
|
||||||
|
(.. "\nexpected " ve# "\ngot " va#)
|
||||||
|
))))
|
||||||
|
|
||||||
|
(let [params
|
||||||
|
{:matches {:devname "foo" :partname "my-usbstick"}}]
|
||||||
|
(expect= (subject.event-matches? params {}) false)
|
||||||
|
(expect= (subject.event-matches? params {:devname "bill"}) false)
|
||||||
|
(expect= (subject.event-matches? params {:devname "foo" :partname "my-usbstick"}) true)
|
||||||
|
(expect= (subject.event-matches? params {:devname "foo" :otherthing "bar" :partname "my-usbstick"}) true)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
;; Events come from the netlink socket as an initial summary line
|
||||||
|
;; followed by a NUL character followed by newline-separated key=value
|
||||||
|
;; pairs. For ease of editing we don't have NULs in events.txt,
|
||||||
|
;; so we need to massage it into shape here
|
||||||
|
|
||||||
|
(local events
|
||||||
|
(with-open [f (io.open "./events.txt" :r)]
|
||||||
|
(let [text (string.gsub (f:read "*a") "\n\n" "\0") ]
|
||||||
|
(icollect [n (string.gmatch text "([^\0]+)")]
|
||||||
|
(string.gsub n "\n" "\0" 1)))))
|
||||||
|
|
||||||
|
|
||||||
|
(fn next-event []
|
||||||
|
(var i 0)
|
||||||
|
(fn []
|
||||||
|
(let [i_ (+ 1 i)
|
||||||
|
e (. events i_)]
|
||||||
|
(set i i_)
|
||||||
|
e)))
|
||||||
|
|
||||||
|
;; this tests event parsing but not whether anything
|
||||||
|
;; happens as a result of processing them
|
||||||
|
(subject.run
|
||||||
|
["-s" "foo" "-n" (os.getenv "TMPDIR") "partname=backup-disk" ]
|
||||||
|
{ :read (next-event) }
|
||||||
|
)
|
70
pkgs/uevent-watch/watch.fnl
Normal file
70
pkgs/uevent-watch/watch.fnl
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
(local { : assoc : system : dirname } (require :anoia))
|
||||||
|
(local { : mktree : rmtree : symlink } (require :anoia.fs))
|
||||||
|
|
||||||
|
(fn parse-match [s] (string.match s "(.-)=(.+)"))
|
||||||
|
|
||||||
|
(fn parse-args [args]
|
||||||
|
(match args
|
||||||
|
["-s" service & rest] (assoc (parse-args rest) :service service)
|
||||||
|
["-n" path & rest] (assoc (parse-args rest) :linkname path)
|
||||||
|
matches { :matches (collect [_ m (ipairs matches)] (parse-match m)) }
|
||||||
|
_ nil))
|
||||||
|
|
||||||
|
(fn %% [fmt ...] (string.format fmt ...))
|
||||||
|
|
||||||
|
(fn event-matches? [params e]
|
||||||
|
(and
|
||||||
|
e
|
||||||
|
(accumulate [match? true
|
||||||
|
name value (pairs params.matches)]
|
||||||
|
(and match? (= value (. e name))))))
|
||||||
|
|
||||||
|
|
||||||
|
(var up :unknown)
|
||||||
|
|
||||||
|
(fn start-service [devname linkname service]
|
||||||
|
(match (symlink (.. "/dev/" devname ) linkname)
|
||||||
|
ok (pcall system (%% "s6-rc -b -u change %q" service))
|
||||||
|
(nil err) false))
|
||||||
|
|
||||||
|
(fn stop-service [linkname service]
|
||||||
|
(match (pcall system (%% "s6-rc -b -d change %q" linkname service))
|
||||||
|
ok (os.remove linkname)
|
||||||
|
(nil err) false))
|
||||||
|
|
||||||
|
(fn toggle-service [devname linkname service wanted?]
|
||||||
|
(when (not (= up wanted?))
|
||||||
|
(set up
|
||||||
|
(if wanted?
|
||||||
|
(start-service devname linkname service)
|
||||||
|
(not (stop-service linkname service))))))
|
||||||
|
|
||||||
|
(fn parse-uevent [s]
|
||||||
|
(when s
|
||||||
|
(let [(nl nxt) (string.find s "\0" 1 true)]
|
||||||
|
(collect [k v (string.gmatch
|
||||||
|
(string.sub s (+ 1 nxt))
|
||||||
|
"(%g-)=(%g+)")]
|
||||||
|
(k:lower) v))))
|
||||||
|
|
||||||
|
(fn run [args fh]
|
||||||
|
(set up :unknown)
|
||||||
|
(let [parameters
|
||||||
|
(assert (parse-args args) (.. "can't parse args: " (table.concat args " ")))]
|
||||||
|
(mktree (dirname parameters.linkname))
|
||||||
|
(var finished? false)
|
||||||
|
|
||||||
|
(while (not finished?)
|
||||||
|
(let [e (parse-uevent (fh:read 5000))]
|
||||||
|
(when (event-matches? parameters e)
|
||||||
|
(let [wanted? (. {:add true :change true} e.action)]
|
||||||
|
(toggle-service e.devname parameters.linkname parameters.service wanted?)))
|
||||||
|
(set finished? (= e nil))
|
||||||
|
))))
|
||||||
|
|
||||||
|
(when (not (= (. arg 0) "test"))
|
||||||
|
(let [nellie (require :nellie)
|
||||||
|
netlink (nellie.open 4)]
|
||||||
|
(run arg netlink)))
|
||||||
|
|
||||||
|
{ : run : event-matches? }
|
Loading…
Reference in a new issue