unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
From: "Ludovic Courtès" <ludo@gnu.org>
To: Mathieu Othacehe <othacehe@gnu.org>
Cc: 42849@debbugs.gnu.org
Subject: [bug#42849] [PATCH 3/3] installer: Run the installation inside a container.
Date: Sun, 30 Aug 2020 22:40:08 +0200	[thread overview]
Message-ID: <87eennhnpz.fsf@gnu.org> (raw)
In-Reply-To: <20200813123419.263639-3-othacehe@gnu.org> (Mathieu Othacehe's message of "Thu, 13 Aug 2020 14:34:19 +0200")

Hi,

Mathieu Othacehe <othacehe@gnu.org> skribis:

> When the store overlay is mounted, other processes such as kmscon, udev
> and guix-daemon may open files from the store, preventing the
> underlying install support from being umounted. See:
> https://lists.gnu.org/archive/html/guix-devel/2018-12/msg00161.html.
>
> To avoid this situation, mount the store overlay inside a container,
> and run the installation from within that container.
>
> * gnu/services/base.scm (guix-shepherd-service): Support an optional PID
> argument passed to the "start" method. If that argument is passed, ensure that
> guix-daemon enters the given PID MNT namespace.
> * gnu/installer/final.scm (umount-cow-store): Remove it,
> (install-system): run the installation from within a container.
> * gnu/installer/newt/final.scm (run-install-shell): Remove the display hack.

Smart!

> +    ;; When the store overlay is mounted, other processes such as kmscon, udev
> +    ;; and guix-daemon may open files from the store, preventing the
> +    ;; underlying install support from being umounted. See:
> +    ;; https://lists.gnu.org/archive/html/guix-devel/2018-12/msg00161.html.
> +    ;;
> +    ;; To avoid this situation, mount the store overlay inside a container,
> +    ;; and run the installation from within that container.
> +    (zero?
> +     (call-with-container '()
> +       (lambda ()
> +         (dynamic-wind
> +           (lambda ()
> +             ;; Save the database, so that it can be restored once the
> +             ;; cow-store is umounted.
> +             (copy-file database-file saved-database)
> +             (mount-cow-store (%installer-target-dir) backing-directory))
> +           (lambda ()
> +             ;; We need to drag the guix-daemon to the container MNT
> +             ;; namespace, so that it can operate on the cow-store.
> +             (stop-service 'guix-daemon)
> +             (start-service 'guix-daemon (list (number->string (getpid))))
> +
> +             (setvbuf (current-output-port) 'none)
> +             (setvbuf (current-error-port) 'none)
> +
> +             ;; If there are any connected clients, assume that we are running
> +             ;; installation tests. In that case, dump the standard and error
> +             ;; outputs to syslog.
> +             (set! ret
> +                   (if (not (null? (current-clients)))
> +                       (with-output-to-file "/dev/console"
> +                         (lambda ()
> +                           (with-error-to-file "/dev/console"
> +                             (lambda ()
> +                               (run-command install-command
> +                                            #:locale locale)))))
> +                       (run-command install-command #:locale locale))))
> +           (lambda ()
> +             ;; Restart guix-daemon so that it does no keep the MNT namespace
> +             ;; alive.
> +             (restart-service 'guix-daemon)
> +             (copy-file saved-database database-file)
> +
> +             ;; Finally umount the cow-store and exit the container.
> +             (umount-cow-store (%installer-target-dir) backing-directory)
> +             (assert-exit ret))))

Should ‘mount-cow-store’ also make an overlay for /var/guix/db?  That
way, changes to that directory would go to /mnt/var/guix/db and the
original database would remain unchanged.

> --- a/gnu/services/base.scm
> +++ b/gnu/services/base.scm
> @@ -1558,36 +1558,50 @@ proxy of 'guix-daemon'...~%")
>             (provision '(guix-daemon))
>             (requirement '(user-processes))
>             (actions (list shepherd-set-http-proxy-action))
> -           (modules '((srfi srfi-1)))
> +           (modules '((srfi srfi-1)
> +                      (ice-9 match)))
>             (start
> -            #~(lambda _
> +            #~(lambda args
>                  (define proxy
>                    ;; HTTP/HTTPS proxy.  The 'http_proxy' variable is set by
>                    ;; the 'set-http-proxy' action.
>                    (or (getenv "http_proxy") #$http-proxy))
>  
>                  (fork+exec-command
> -                 (cons* #$(file-append guix "/bin/guix-daemon")
> -                        "--build-users-group" #$build-group
> -                        "--max-silent-time" #$(number->string max-silent-time)
> -                        "--timeout" #$(number->string timeout)
> -                        "--log-compression" #$(symbol->string log-compression)
> -                        #$@(if use-substitutes?
> -                               '()
> -                               '("--no-substitutes"))
> -                        "--substitute-urls" #$(string-join substitute-urls)
> -                        #$@extra-options
> -
> -                        ;; Add CHROOT-DIRECTORIES and all their dependencies
> -                        ;; (if these are store items) to the chroot.
> -                        (append-map (lambda (file)
> -                                      (append-map (lambda (directory)
> -                                                    (list "--chroot-directory"
> -                                                          directory))
> -                                                  (call-with-input-file file
> -                                                    read)))
> -                                    '#$(map references-file
> -                                            chroot-directories)))
> +                 ;; When running the installer, we need guix-daemon to operate
> +                 ;; from within the same MNT namespace as the installation
> +                 ;; container. In that case only, enter the namespace of the
> +                 ;; process PID passed as start argument.
> +                 (append
> +                  (match args
> +                    ((pid)
> +                     (list #$(file-append util-linux "/bin/nsenter")
> +                           "-t" pid "-m"))

We should use ‘container-excursion’ instead of nsenter.

> +                    (else '()))
> +                  (cons* #$(file-append guix "/bin/guix-daemon")
> +                         "--build-users-group" #$build-group
> +                         "--max-silent-time"
> +                         #$(number->string max-silent-time)
> +                         "--timeout" #$(number->string timeout)
> +                         "--log-compression"
> +                         #$(symbol->string log-compression)
> +                         #$@(if use-substitutes?
> +                                '()
> +                                '("--no-substitutes"))
> +                         "--substitute-urls" #$(string-join substitute-urls)
> +                         #$@extra-options
> +
> +                         ;; Add CHROOT-DIRECTORIES and all their dependencies
> +                         ;; (if these are store items) to the chroot.
> +                         (append-map
> +                          (lambda (file)
> +                            (append-map (lambda (directory)
> +                                          (list "--chroot-directory"
> +                                                directory))
> +                                        (call-with-input-file file
> +                                          read)))
> +                          '#$(map references-file

Hmm, that seems quite complex, and it’s not great that we have to tweak
guix-daemon-service “just” for this.

*scratches head*

Is there a way we can identify processes that have open overlay files,
so we could terminate them?

Alternately, something that might simplify the code would be to always
run guix-daemon in a separate mount namespace.  We could add a
‘fork+exec-command/container’ procedure in (gnu build shepherd) to help
with that.

That way, all we’d need to do is to run ‘guix system init’ in that same
mount namespace, which can be achieved using ‘container-excursion’.

Too bad we can’t use setns for a process other than the calling process.
:-/

Thoughts?

Ludo’.




  reply	other threads:[~2020-08-30 20:41 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-13 12:23 [bug#42849] [PATCH 0/3] installer: Run the installation inside a container Mathieu Othacehe
2020-08-13 12:34 ` [bug#42849] [PATCH 1/3] install: Factorize cow-store procedure Mathieu Othacehe
2020-08-13 12:34   ` [bug#42849] [PATCH 2/3] linux-container: Add a jail? argument Mathieu Othacehe
2020-08-30 19:53     ` Ludovic Courtès
2020-08-31  6:27       ` Mathieu Othacehe
2020-08-31 13:36         ` Ludovic Courtès
2020-09-07 22:02           ` Ludovic Courtès
2020-09-10  7:46             ` Mathieu Othacehe
2020-09-11 15:07               ` Ludovic Courtès
2020-08-13 12:34   ` [bug#42849] [PATCH 3/3] installer: Run the installation inside a container Mathieu Othacehe
2020-08-30 20:40     ` Ludovic Courtès [this message]
2020-08-31  6:44       ` Mathieu Othacehe
2020-09-01  8:48         ` Ludovic Courtès
2020-09-02 15:15           ` bug#42849: " Mathieu Othacehe
2020-09-02 20:17             ` [bug#42849] " Ludovic Courtès
2020-09-02 21:25             ` Ludovic Courtès
2020-08-30 19:51   ` [bug#42849] [PATCH 1/3] install: Factorize cow-store procedure Ludovic Courtès

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=87eennhnpz.fsf@gnu.org \
    --to=ludo@gnu.org \
    --cc=42849@debbugs.gnu.org \
    --cc=othacehe@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).