[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
A new paradigm for modifying operating system declarations
From: |
raid5atemyhomework |
Subject: |
A new paradigm for modifying operating system declarations |
Date: |
Mon, 04 Jan 2021 15:38:38 +0000 |
Hi guix-developers,
I'd like to propose an idea for constructing `<operating-system>` objects.
First, let me present the `decorate` form:
```scheme
(define-syntax decorate
(syntax-rules ()
((decorate ((x ...)) a ...)
(x ... a ...))
((decorate (x) a ...)
(x a ...))
((decorate ((x ...) y ...) a ...)
(x ... (decorate (y ...) a ...)))
((decorate (x y ...) a ...)
(x (decorate (y ...) a ...)))))
```
Here's an example usage, instead of:
```scheme
(with-output-to-port (current-error-port)
(lambda ()
(system "echo" "an error occurred")))
```
We can use:
```scheme
(decorate ((with-output-to-port (current-error-port))
(lambda ()))
(system "echo" "an error occurred"))
```
The reason why this is relevant, is that when I was tying out
https://issues.guix.gnu.org/45643 , I ended up having several changes to the
base `operating-system` form:
```scheme
(define system-zfs (make-zfs-package linux-libre-5.4))
(operating-system
; ... other fields ...
(kernel linux-libre-5.4)
(kernel-loadable-modules (list (list system-zfs "module")))
(packages (cons* system-zfs
; ... other packages ...
%base-packages))
(services (cons* (service zfs-loader-service-type system-zfs)
; ... other services ...
%desktop-services)))
```
So, I imagined instead of exposing `make-zfs-package` and
`zfs-loader-service-type` and requiring so many modifications to various fields
of `operating-system` form, expose instead a `install-zfs` form, like so:
```scheme
(install-zfs
(operating-system
(kernel linux-libre-5.4)
; ... other fields ...
))
```
This `install-zfs` form would be defined as below:
```scheme
(define-public (install-zfs os)
(define system-zfs (make-zfs-package (operating-system-kernel os)))
(operating-system
(inherit os)
(location (operating-system-location os))
(kernel-loadable-modules (cons (list system-zfs "module")
(operating-system-kernel-loadable-modules
os)))
(packages (cons system-zfs
(operating-system-packages os)))
(services (cons (sevice zfs-loader-service-type system-zfs)
(operating-system-services os)))))
```
This would install ZFS "correctly", by adding the module to kernel loadable
modules, adding the package so that ZFS can be managed at runtime, and adding
the service to load ZFS module and import ZFS pools. The hope is that this
reduces the scope for errors in defining the operating system.
On the other hand, if this kind of pattern becomes common, then consider:
```scheme
(install-foo
(install-bar
(install-zfs
(operating-system
#;...))))
```
Which brings us back to the `decorate` form, which reduces nestedness:
```scheme
(decorate (install-foo
install-bar
install-zfs
operating-system)
#;...)
```
This seems quite elegant to me.
Now for example we can consider that the `"zfs"` module supports various
options as well, which would be put in a `/etc/modprobe.d/zfs.conf` file. We
could consider for example that `install-zfs` could support an `options` keyed
argument, which it will then add to the `modprobe` configuration file in an
`etc-service-type` in a new service that it extends to the given
`<operating-system>`.
```scheme
(define install-zfs-full
(lambda* (#:key (options '()) os)
#;...))
(define-public install-zfs
(match-lambda
((os)
(install-zfs-full #:os os))
(rest
(apply install-zfs-full rest))))
```
Then in a system configuration:
```scheme
(decorate ((install-zfs #:options '(("zfs_arc_max" 5000000000)) #:os)
operating-system)
#;...)
```
Something similar could be done for the `ddcci-driver-linux` example in the
documentation for `kernel-module-loader-service-type`:
```scheme
(define-public install-ddcci
(match-lambda
((os)
(install-ddcci-full #:os os))
(rest
(apply install-ddcci-full rest))))
(define install-ddcci-full
(lambda* (#:key (options '())) os)
(define config-file
(plain-file "ddcci.conf"
(if (null? options)
""
(string-join (cons "options ddcci" options)
" "))))
(operating-system
(inherit os)
(location (operating-system-location os))
(kernel-loadable-modules (cons ddcci-driver-linux
(operating-system-kernel-loadable-modules
os)))
(services
(cons* (service kernel-module-loader-service-type
'("ddcci" "ddcci_backlight"))
(simple-service 'ddcci-config etc-service-type
`(("modprobe.d/ddcci.conf" ,config-file)))
(operating-system-services os))))))
```
Then, in the system configuration file:
```scheme
(decorate (install-zfs
(install-ddcci #:options '("dyndbg" "delay=120") #:os)
operating-system)
(name "example-system")
#;...)
```
Obviously, it's called "decorate" since it's partly inspired by Python
decorators, which use a similar-looking pattern, with different syntax.
What are your opinions? Blech? Yummy? Is it worth exploring this paradigm
for adding particularly complex features to an operating system definition?
Thanks
raid5atemyhomework