unofficial mirror of guix-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: raid5atemyhomework <raid5atemyhomework@protonmail.com>
To: "guix-devel@gnu.org" <guix-devel@gnu.org>
Subject: A new paradigm for modifying operating system declarations
Date: Mon, 04 Jan 2021 15:38:38 +0000	[thread overview]
Message-ID: <ewUh5vMEW_m5K1m9xYSvxi0_o92wTXSO8pAoyBec8LDT45bZmrNXc6hPH4_3ZXWTyqe91NDltmJgH5mEDbpsu-A6Ar0vpDqky8F4kCrhlcI=@protonmail.com> (raw)

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


             reply	other threads:[~2021-01-04 16:09 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-04 15:38 raid5atemyhomework [this message]
2021-01-04 20:21 ` A new paradigm for modifying operating system declarations Taylan Kammer
2021-01-05  0:32   ` raid5atemyhomework
2021-01-05  6:12     ` Carlo Zancanaro
2021-01-05 10:01       ` raid5atemyhomework
2021-01-04 23:26 ` Jan Wielkiewicz
2021-01-05  0:46   ` raid5atemyhomework

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='ewUh5vMEW_m5K1m9xYSvxi0_o92wTXSO8pAoyBec8LDT45bZmrNXc6hPH4_3ZXWTyqe91NDltmJgH5mEDbpsu-A6Ar0vpDqky8F4kCrhlcI=@protonmail.com' \
    --to=raid5atemyhomework@protonmail.com \
    --cc=guix-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).