~ruther/guix-local

48083c8c951f9726a241acdbe3b2af00f16c2b6e — Ludovic Courtès 1 year, 3 months ago 100c1e1
services: unattended-upgrade: Rewrite as a Shepherd timer.

This is a semi-incompatible change: gexps previously provided in the
‘schedule’ field will no longer work.

* gnu/services/admin.scm (unattended-upgrade-mcron-jobs): Rename to…
(unattended-upgrade-shepherd-services): … this.  Return a list of one
Shepherd service.  Remove custom logging and time limitation facilities
from ‘code’.
(unattended-upgrade-service-type): Extend ‘shepherd-root-service-type’
instead of ‘mcron-service-type’.
(<unattended-upgrade-configuration>)[services-to-restart]: Change
default.
* doc/guix.texi (Unattended Upgrades): Adjust ‘schedule’ and
‘services-to-restart’ documentation.

Change-Id: I1b239c5946e71cf9e2af9b24fe4b01366b57fb7a
2 files changed, 45 insertions(+), 37 deletions(-)

M doc/guix.texi
M gnu/services/admin.scm
M doc/guix.texi => doc/guix.texi +7 -6
@@ 23472,9 23472,9 @@ service.  The following fields are available:

@table @asis
@item @code{schedule} (default: @code{"30 01 * * 0"})
This is the schedule of upgrades, expressed as a gexp containing an
mcron job schedule (@pxref{Guile Syntax, mcron job specifications,,
mcron, GNU@tie{}mcron}).
This is the schedule of upgrades, expressed as a string in traditional
cron syntax or as a gexp evaluating to a Shepherd calendar event
(@pxref{Timers,,, shepherd, The GNU Shepherd Manual}).

@item @code{channels} (default: @code{#~%default-channels})
This gexp specifies the channels to use for the upgrade


@@ 23523,7 23523,7 @@ When @code{reboot?} is @code{#t}, services are not restarted before
rebooting.  This means that the value for @code{services-to-restart} is
ignored.  The updated services will be started after the system reboots.

@item @code{services-to-restart} (default: @code{'(mcron)})
@item @code{services-to-restart} (default: @code{'(unattended-upgrade)})
This field specifies the Shepherd services to restart when the upgrade
completes.



@@ 23538,8 23538,9 @@ Use @command{herd status} to find out candidates for restarting.
@xref{Services}, for general information about services.  Common
services to restart would include @code{ntpd} and @code{ssh-daemon}.

By default, the @code{mcron} service is restarted.  This ensures that
the latest version of the unattended upgrade job will be used next time.
By default, the @code{unattended-upgrade} service is restarted.  This
ensures that the latest version of the unattended upgrade job will be
used next time.

@item @code{system-expiration} (default: @code{(* 3 30 24 3600)})
This is the expiration time in seconds for system generations.  System

M gnu/services/admin.scm => gnu/services/admin.scm +38 -31
@@ 553,7 553,7 @@ which lets you search for packages that provide a given file.")
  (reboot?              unattended-upgrade-configuration-reboot?
                        (default #f))
  (services-to-restart  unattended-upgrade-configuration-services-to-restart
                        (default '(mcron)))
                        (default '(unattended-upgrade)))
  (system-expiration    unattended-upgrade-system-expiration
                        (default (* 3 30 24 3600)))
  (maximum-duration     unattended-upgrade-maximum-duration


@@ 564,7 564,7 @@ which lets you search for packages that provide a given file.")
(define %unattended-upgrade-log-file
  "/var/log/unattended-upgrade.log")

(define (unattended-upgrade-mcron-jobs config)
(define (unattended-upgrade-shepherd-services config)
  (define channels
    (scheme-file "channels.scm"
                 (unattended-upgrade-configuration-channels config)))


@@ 572,6 572,9 @@ which lets you search for packages that provide a given file.")
  (define log
    (unattended-upgrade-configuration-log-file config))

  (define schedule
    (unattended-upgrade-configuration-schedule config))

  (define services
    (unattended-upgrade-configuration-services-to-restart config))



@@ 598,35 601,17 @@ which lets you search for packages that provide a given file.")
      #~(begin
          (use-modules (guix build utils)
                       (gnu services herd)
                       (srfi srfi-19)
                       (srfi srfi-34))

          (define log
            (open-file #$log "a0"))

          (define (timestamp)
            (date->string (time-utc->date (current-time time-utc))
                          "[~4]"))

          (define (alarm-handler . _)
            (format #t "~a time is up, aborting upgrade~%"
                    (timestamp))
            (exit 1))
          (setvbuf (current-output-port) 'line)
          (setvbuf (current-error-port) 'line)

          ;; 'guix time-machine' needs X.509 certificates to authenticate the
          ;; Git host.
          (setenv "SSL_CERT_DIR"
                  #$(file-append nss-certs "/etc/ssl/certs"))

          ;; Make sure the upgrade doesn't take too long.
          (sigaction SIGALRM alarm-handler)
          (alarm #$(unattended-upgrade-maximum-duration config))

          ;; Redirect stdout/stderr to LOG to save the output of 'guix' below.
          (redirect-port log (current-output-port))
          (redirect-port log (current-error-port))

          (format #t "~a starting upgrade...~%" (timestamp))
          (format #t "starting upgrade...~%")
          (guard (c ((invoke-error? c)
                     (report-invoke-error c)))
            (apply invoke #$(file-append guix "/bin/guix")


@@ 645,23 630,45 @@ which lets you search for packages that provide a given file.")
            (unless #$reboot?
              ;; Rebooting effectively restarts services anyway and execution
              ;; would be halted here if mcron is restarted.
              (format #t "~a restarting services...~%" (timestamp))
              (format #t "restarting services...~%")
              (for-each restart-service '#$services))

            ;; XXX: If 'mcron' has been restarted, this is not reached.
            (format #t "~a upgrade complete~%" (timestamp))
            ;; XXX: If this service has been restarted, this is not reached.
            (format #t "upgrade complete~%")

            ;; Stopping the root shepherd service triggers a reboot.
            (when #$reboot?
              (format #t "~a rebooting system~%" (timestamp))
              (format #t "rebooting system~%")
              (force-output) ;ensure the entire log is written.
              (stop-service 'root))))))

  (define upgrade
    (program-file "unattended-upgrade" code))

  (list #~(job #$(unattended-upgrade-configuration-schedule config)
               #$upgrade)))
  (list (shepherd-service
         (provision '(unattended-upgrade))
         (requirement '(user-processes networking))
         (modules '((shepherd service timer)))
         (start #~(make-timer-constructor
                   #$(if (string? schedule)
                         #~(cron-string->calendar-event #$schedule)
                         schedule)
                   (command '(#$upgrade))

                   #:log-file #$log

                   ;; Make sure the upgrade doesn't take too long.
                   #:max-duration
                   #$(unattended-upgrade-maximum-duration config)

                   ;; Wait for the previous attempt to terminate before trying
                   ;; again.
                   #:wait-for-termination? #t))
         (stop #~(make-timer-destructor))
         (actions (list (shepherd-action
                         (name 'trigger)
                         (documentation "Trigger unattended system upgrade.")
                         (procedure #~trigger-timer)))))))

(define (unattended-upgrade-log-rotations config)
  (list (log-rotation


@@ 672,8 679,8 @@ which lets you search for packages that provide a given file.")
  (service-type
   (name 'unattended-upgrade)
   (extensions
    (list (service-extension mcron-service-type
                             unattended-upgrade-mcron-jobs)
    (list (service-extension shepherd-root-service-type
                             unattended-upgrade-shepherd-services)
          (service-extension rottlog-service-type
                             unattended-upgrade-log-rotations)))
   (description