From debbugs-submit-bounces@debbugs.gnu.org Sun Aug 30 16:40:19 2020 Received: (at 42849) by debbugs.gnu.org; 30 Aug 2020 20:40:19 +0000 Received: from localhost ([127.0.0.1]:50832 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCU7f-0006kJ-1H for submit@debbugs.gnu.org; Sun, 30 Aug 2020 16:40:19 -0400 Received: from eggs.gnu.org ([209.51.188.92]:36566) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCU7d-0006k7-E6 for 42849@debbugs.gnu.org; Sun, 30 Aug 2020 16:40:17 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]:44859) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kCU7Y-0003zG-3e for 42849@debbugs.gnu.org; Sun, 30 Aug 2020 16:40:12 -0400 Received: from [2a01:e0a:1d:7270:af76:b9b:ca24:c465] (port=43732 helo=ribbon) by fencepost.gnu.org with esmtpsa (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1kCU7W-0007UY-Ln; Sun, 30 Aug 2020 16:40:11 -0400 From: =?utf-8?Q?Ludovic_Court=C3=A8s?= To: Mathieu Othacehe Subject: Re: [bug#42849] [PATCH 3/3] installer: Run the installation inside a container. References: <20200813123419.263639-1-othacehe@gnu.org> <20200813123419.263639-3-othacehe@gnu.org> Date: Sun, 30 Aug 2020 22:40:08 +0200 In-Reply-To: <20200813123419.263639-3-othacehe@gnu.org> (Mathieu Othacehe's message of "Thu, 13 Aug 2020 14:34:19 +0200") Message-ID: <87eennhnpz.fsf@gnu.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 42849 Cc: 42849@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) Hi, Mathieu Othacehe 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 ha= ck. 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.ht= ml. > + ;; > + ;; To avoid this situation, mount the store overlay inside a contain= er, > + ;; 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 r= unning > + ;; 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 name= space > + ;; 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 =E2=80=98mount-cow-store=E2=80=99 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)) >=20=20 > (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-compre= ssion) > - #$@(if use-substitutes? > - '() > - '("--no-substitutes")) > - "--substitute-urls" #$(string-join substitute-ur= ls) > - #$@extra-options > - > - ;; Add CHROOT-DIRECTORIES and all their dependen= cies > - ;; (if these are store items) to the chroot. > - (append-map (lambda (file) > - (append-map (lambda (directory) > - (list "--chroot-dire= ctory" > - directory)) > - (call-with-input-file = file > - read))) > - '#$(map references-file > - chroot-directories))) > + ;; When running the installer, we need guix-daemon to o= perate > + ;; from within the same MNT namespace as the installati= on > + ;; 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 =E2=80=98container-excursion=E2=80=99 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-u= rls) > + #$@extra-options > + > + ;; Add CHROOT-DIRECTORIES and all their depende= ncies > + ;; (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=E2=80=99s not great that we have to t= weak guix-daemon-service =E2=80=9Cjust=E2=80=9D 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 =E2=80=98fork+exec-command/container=E2=80=99 procedure in (gnu build sheph= erd) to help with that. That way, all we=E2=80=99d need to do is to run =E2=80=98guix system init= =E2=80=99 in that same mount namespace, which can be achieved using =E2=80=98container-excursion= =E2=80=99. Too bad we can=E2=80=99t use setns for a process other than the calling pro= cess. :-/ Thoughts? Ludo=E2=80=99.