diff mbox series

[bug#50332] home-services: Add Shepherd.

Message ID 87lf4ffhd6.fsf@trop.in
State Accepted
Headers show
Series [bug#50332] home-services: Add Shepherd. | expand

Checks

Context Check Description
cbaines/applying patch fail View Laminar job
cbaines/issue success View issue

Commit Message

Andrew Tropin Sept. 2, 2021, 9:33 a.m. UTC
* gnu/home-services/shepherd.scm: New file.
* doc/guix.texi: Add documentation about Shepherd Home Service.
---
 doc/guix.texi                  |  31 +++++++-
 gnu/home-services/shepherd.scm | 133 +++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+), 1 deletion(-)
 create mode 100644 gnu/home-services/shepherd.scm

Comments

Xinglu Chen Sept. 2, 2021, 2:59 p.m. UTC | #1
On Thu, Sep 02 2021, Andrew Tropin wrote:

> * gnu/home-services/shepherd.scm: New file.
> * doc/guix.texi: Add documentation about Shepherd Home Service.
> ---
>  doc/guix.texi                  |  31 +++++++-
>  gnu/home-services/shepherd.scm | 133 +++++++++++++++++++++++++++++++++
>  2 files changed, 163 insertions(+), 1 deletion(-)
>  create mode 100644 gnu/home-services/shepherd.scm
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 622a973bdf..51a317e8a7 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -35538,7 +35538,36 @@ mcron info here
>  
>  @node Shepherd Home Service
>  @subsection Managing User's Daemons
> -shepherd info here
> +
> +@cindex shepherd services
> +
> +@defvr {Scheme Variable} shepherd-home-service-type
> +The service type for the userland Shepherd, which allows to manage

“allows one to manage”

> +long-running process or one-shot tasks.  Almost all the information

s/process/processes/

> +described in (@pxref{Shepherd Services}) is applicable here too.

What is not applicable?

> +This is the service type that extensions target when they want to create
> +shepherd services (@pxref{Service Types and Services}, for an example).
> +Each extension must pass a list of @code{<shepherd-service>}.  Its
> +value must be a @code{shepherd-configuration}, as described below.
> +@end defvr
> +
> +@deftp {Data Type} shepherd-configuration
> +This data type represents the Shepherd's configuration.
> +
> +@table @code
> +@item shepherd (default: @code{shepherd})
> +The Shepherd package to use.
> +
> +@item auto-start? (default: @code{#t})
> +Wether or not to start Shepherd on first login.

s/Wether/Whether/

> +@item services (default: @code{'()})
> +A list of @code{<shepherd-service>} to start.
> +You should probably use the service extension
> +mechanism instead (@pxref{Shepherd Services}).
> +@end table
> +@end deftp
>  
>  @node Invoking guix home
>  @section Invoking @code{guix home}
> diff --git a/gnu/home-services/shepherd.scm b/gnu/home-services/shepherd.scm
> new file mode 100644
> index 0000000000..158b50bdb6
> --- /dev/null
> +++ b/gnu/home-services/shepherd.scm
> @@ -0,0 +1,133 @@
> +;;; GNU Guix --- Functional package management for GNU
> +;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
> +;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
> +;;;
> +;;; This file is part of GNU Guix.
> +;;;
> +;;; GNU Guix is free software; you can redistribute it and/or modify it
> +;;; under the terms of the GNU General Public License as published by
> +;;; the Free Software Foundation; either version 3 of the License, or (at
> +;;; your option) any later version.
> +;;;
> +;;; GNU Guix is distributed in the hope that it will be useful, but
> +;;; WITHOUT ANY WARRANTY; without even the implied warranty of
> +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +;;; GNU General Public License for more details.
> +;;;
> +;;; You should have received a copy of the GNU General Public License
> +;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
> +
> +(define-module (gnu home-services shepherd)
> +  #:use-module (gnu home-services)
> +  #:use-module (gnu packages admin)
> +  #:use-module (gnu services shepherd)
> +  #:use-module (guix sets)
> +  #:use-module (guix gexp)
> +  #:use-module (guix i18n)
> +  #:use-module (guix records)
> +
> +  #:use-module (srfi srfi-1)
> +
> +  #:re-export (shepherd-service
> +               shepherd-action))
> +
> +(define-record-type* <home-shepherd-configuration>
> +  home-shepherd-configuration make-home-shepherd-configuration
> +  home-shepherd-configuration?
> +  (shepherd home-shepherd-configuration-shepherd
> +            (default shepherd)) ; package
> +  (auto-start? home-shepherd-configuration-auto-start?
> +               (default #t))
> +  (services home-shepherd-configuration-services
> +            (default '())))
> +
> +(define (home-shepherd-configuration-file services shepherd)
> +  "Return the shepherd configuration file for SERVICES.  SHEPHERD is used
> +as shepherd package."
> +  (assert-valid-graph services)
> +
> +  (let ((files (map shepherd-service-file services))
> +        ;; TODO: Add compilation of services, it can improve start
> +        ;; time.
> +        ;; (scm->go (cute scm->go <> shepherd))
> +        )
> +    (define config
> +      #~(begin
> +          (use-modules (srfi srfi-34)
> +                       (system repl error-handling))
> +          (apply
> +           register-services
> +           (map
> +            (lambda (file) (load file))
> +            '#$files))
> +          (action 'root 'daemonize)
> +          (format #t "Starting services...~%")

Maybe (G_ ...) should be used to make strings translatable?

> +          (for-each
> +           (lambda (service) (start service))
> +           '#$(append-map shepherd-service-provision
> +                          (filter shepherd-service-auto-start?
> +                                  services)))
> +          (newline)))

Is ‘newline’ necessary?

> +    (scheme-file "shepherd.conf" config)))
> +
> +(define (launch-shepherd-gexp config)
> +  (let* ((shepherd (home-shepherd-configuration-shepherd config))
> +         (services (home-shepherd-configuration-services config)))
> +    (if (home-shepherd-configuration-auto-start? config)
> +        (with-imported-modules '((guix build utils))
> +          #~(let ((log-dir (or (getenv "XDG_LOG_HOME")
> +                               (format #f "~a/.local/var/log" (getenv "HOME")))))
> +              ((@ (guix build utils) mkdir-p) log-dir)
> +              (system*
> +               #$(file-append shepherd "/bin/shepherd")
> +               "--logfile"
> +               (string-append
> +                log-dir
> +                "/shepherd.log")
> +               "--config"
> +               #$(home-shepherd-configuration-file services shepherd))))
> +        #~"")))
> +
> +(define (reload-configuration-gexp config)
> +  (let* ((shepherd (home-shepherd-configuration-shepherd config))
> +         (services (home-shepherd-configuration-services config)))
> +    #~(system*
> +       #$(file-append shepherd "/bin/herd")
> +       "load" "root"
> +       #$(home-shepherd-configuration-file services shepherd))))
> +
> +(define (ensure-shepherd-gexp config)
> +  #~(if (file-exists?
> +         (string-append
> +          (or (getenv "XDG_RUNTIME_DIR")
> +              (format #f "/run/user/~a" (getuid)))
> +          "/shepherd/socket"))
> +        #$(reload-configuration-gexp config)
> +        #$(launch-shepherd-gexp config)))
> +
> +(define-public home-shepherd-service-type
> +  (service-type (name 'home-shepherd)
> +                (extensions
> +                 (list (service-extension
> +                        home-run-on-first-login-service-type
> +                        launch-shepherd-gexp)
> +                       (service-extension
> +                        home-activation-service-type
> +                        ensure-shepherd-gexp)
> +                       (service-extension
> +                        home-profile-service-type
> +                        (lambda (config)
> +                          `(,(home-shepherd-configuration-shepherd config))))))

Nit: I would use ‘list’ instead of quasiquoting and unquoting.

> +                (compose concatenate)
> +                (extend
> +                 (lambda (config extra-services)
> +                   (home-shepherd-configuration
> +                    (inherit config)
> +                    (services
> +                     (append (home-shepherd-configuration-services config)
> +                             extra-services)))))
> +                (default-value (home-shepherd-configuration))
> +                (description "Configure and install userland Shepherd.")))
> +
> +
> -- 
> 2.33.0
M Sept. 4, 2021, 8:53 a.m. UTC | #2
Xinglu Chen schreef op do 02-09-2021 om 16:59 [+0200]:
> On Thu, Sep 02 2021, Andrew Tropin wrote:
> [...]
> > +    (define config
> > +      #~(begin
> > +          (use-modules (srfi srfi-34)
> > +                       (system repl error-handling))
> > +          (apply
> > +           register-services
> > +           (map
> > +            (lambda (file) (load file))
> > +            '#$files))
> > +          (action 'root 'daemonize)
> > +          (format #t "Starting services...~%")
> 
> Maybe (G_ ...) should be used to make strings translatable?

AFAIK (G_ ...) cannot be used from within a G-exp.
However, you could do:

     #~(begin
          ...
          (format #t #$(G_ "Starting services...~%")))

but that would make "shepherd.conf" depend on the locale
that was active when "guix home ..." (*) was run,
which may or may not be acceptable.

(*) not sure what the exact command is.

Alternatively, it might be possible to build the .mo from the .po
translations and use bindtextdomain from the G-exp, in which case
the G_ should be usable from the G-exp.

Greetings,
Maxime.
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 622a973bdf..51a317e8a7 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -35538,7 +35538,36 @@  mcron info here
 
 @node Shepherd Home Service
 @subsection Managing User's Daemons
-shepherd info here
+
+@cindex shepherd services
+
+@defvr {Scheme Variable} shepherd-home-service-type
+The service type for the userland Shepherd, which allows to manage
+long-running process or one-shot tasks.  Almost all the information
+described in (@pxref{Shepherd Services}) is applicable here too.
+
+This is the service type that extensions target when they want to create
+shepherd services (@pxref{Service Types and Services}, for an example).
+Each extension must pass a list of @code{<shepherd-service>}.  Its
+value must be a @code{shepherd-configuration}, as described below.
+@end defvr
+
+@deftp {Data Type} shepherd-configuration
+This data type represents the Shepherd's configuration.
+
+@table @code
+@item shepherd (default: @code{shepherd})
+The Shepherd package to use.
+
+@item auto-start? (default: @code{#t})
+Wether or not to start Shepherd on first login.
+
+@item services (default: @code{'()})
+A list of @code{<shepherd-service>} to start.
+You should probably use the service extension
+mechanism instead (@pxref{Shepherd Services}).
+@end table
+@end deftp
 
 @node Invoking guix home
 @section Invoking @code{guix home}
diff --git a/gnu/home-services/shepherd.scm b/gnu/home-services/shepherd.scm
new file mode 100644
index 0000000000..158b50bdb6
--- /dev/null
+++ b/gnu/home-services/shepherd.scm
@@ -0,0 +1,133 @@ 
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
+;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home-services shepherd)
+  #:use-module (gnu home-services)
+  #:use-module (gnu packages admin)
+  #:use-module (gnu services shepherd)
+  #:use-module (guix sets)
+  #:use-module (guix gexp)
+  #:use-module (guix i18n)
+  #:use-module (guix records)
+
+  #:use-module (srfi srfi-1)
+
+  #:re-export (shepherd-service
+               shepherd-action))
+
+(define-record-type* <home-shepherd-configuration>
+  home-shepherd-configuration make-home-shepherd-configuration
+  home-shepherd-configuration?
+  (shepherd home-shepherd-configuration-shepherd
+            (default shepherd)) ; package
+  (auto-start? home-shepherd-configuration-auto-start?
+               (default #t))
+  (services home-shepherd-configuration-services
+            (default '())))
+
+(define (home-shepherd-configuration-file services shepherd)
+  "Return the shepherd configuration file for SERVICES.  SHEPHERD is used
+as shepherd package."
+  (assert-valid-graph services)
+
+  (let ((files (map shepherd-service-file services))
+        ;; TODO: Add compilation of services, it can improve start
+        ;; time.
+        ;; (scm->go (cute scm->go <> shepherd))
+        )
+    (define config
+      #~(begin
+          (use-modules (srfi srfi-34)
+                       (system repl error-handling))
+          (apply
+           register-services
+           (map
+            (lambda (file) (load file))
+            '#$files))
+          (action 'root 'daemonize)
+          (format #t "Starting services...~%")
+          (for-each
+           (lambda (service) (start service))
+           '#$(append-map shepherd-service-provision
+                          (filter shepherd-service-auto-start?
+                                  services)))
+          (newline)))
+
+    (scheme-file "shepherd.conf" config)))
+
+(define (launch-shepherd-gexp config)
+  (let* ((shepherd (home-shepherd-configuration-shepherd config))
+         (services (home-shepherd-configuration-services config)))
+    (if (home-shepherd-configuration-auto-start? config)
+        (with-imported-modules '((guix build utils))
+          #~(let ((log-dir (or (getenv "XDG_LOG_HOME")
+                               (format #f "~a/.local/var/log" (getenv "HOME")))))
+              ((@ (guix build utils) mkdir-p) log-dir)
+              (system*
+               #$(file-append shepherd "/bin/shepherd")
+               "--logfile"
+               (string-append
+                log-dir
+                "/shepherd.log")
+               "--config"
+               #$(home-shepherd-configuration-file services shepherd))))
+        #~"")))
+
+(define (reload-configuration-gexp config)
+  (let* ((shepherd (home-shepherd-configuration-shepherd config))
+         (services (home-shepherd-configuration-services config)))
+    #~(system*
+       #$(file-append shepherd "/bin/herd")
+       "load" "root"
+       #$(home-shepherd-configuration-file services shepherd))))
+
+(define (ensure-shepherd-gexp config)
+  #~(if (file-exists?
+         (string-append
+          (or (getenv "XDG_RUNTIME_DIR")
+              (format #f "/run/user/~a" (getuid)))
+          "/shepherd/socket"))
+        #$(reload-configuration-gexp config)
+        #$(launch-shepherd-gexp config)))
+
+(define-public home-shepherd-service-type
+  (service-type (name 'home-shepherd)
+                (extensions
+                 (list (service-extension
+                        home-run-on-first-login-service-type
+                        launch-shepherd-gexp)
+                       (service-extension
+                        home-activation-service-type
+                        ensure-shepherd-gexp)
+                       (service-extension
+                        home-profile-service-type
+                        (lambda (config)
+                          `(,(home-shepherd-configuration-shepherd config))))))
+                (compose concatenate)
+                (extend
+                 (lambda (config extra-services)
+                   (home-shepherd-configuration
+                    (inherit config)
+                    (services
+                     (append (home-shepherd-configuration-services config)
+                             extra-services)))))
+                (default-value (home-shepherd-configuration))
+                (description "Configure and install userland Shepherd.")))
+
+