container: Pass a list of <file-system> objects as things to mount.

* gnu/build/linux-container.scm (mount-file-systems): 'mounts' is now a
list of <file-system> objects instead of a list of lists ("specs").
Add call to 'file-system->spec' as the argument to 'mount-file-system'.
(run-container, call-with-container): Adjust docstring accordingly.
* gnu/system/file-systems.scm (spec->file-system): New procedure.
* gnu/system/linux-container.scm (container-script)[script]: Call
'spec->file-system' inside gexp.
* guix/scripts/environment.scm (launch-environment/container): Remove
call to 'file-system->spec'.
* tests/containers.scm ("call-with-container, mnt namespace")
("call-with-container, mnt namespace, wrong bind mount"): Pass a list of
<file-system> objects.
This commit is contained in:
Ludovic Courtès 2016-11-10 17:45:54 +01:00
parent 5e7eaccb14
commit 5970e8e248
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5
5 changed files with 35 additions and 13 deletions

View file

@ -24,6 +24,7 @@ (define-module (gnu build linux-container)
#:use-module (guix utils) #:use-module (guix utils)
#:use-module (guix build utils) #:use-module (guix build utils)
#:use-module (guix build syscalls) #:use-module (guix build syscalls)
#:use-module (gnu system file-systems) ;<file-system>
#:use-module ((gnu build file-systems) #:select (mount-file-system)) #:use-module ((gnu build file-systems) #:select (mount-file-system))
#:export (user-namespace-supported? #:export (user-namespace-supported?
unprivileged-user-namespace-supported? unprivileged-user-namespace-supported?
@ -72,8 +73,9 @@ (define (purify-environment)
;; specification: ;; specification:
;; https://raw.githubusercontent.com/docker/libcontainer/master/SPEC.md ;; https://raw.githubusercontent.com/docker/libcontainer/master/SPEC.md
(define* (mount-file-systems root mounts #:key mount-/sys? mount-/proc?) (define* (mount-file-systems root mounts #:key mount-/sys? mount-/proc?)
"Mount the essential file systems and the those in the MOUNTS list relative "Mount the essential file systems and the those in MOUNTS, a list of
to ROOT, then make ROOT the new root directory for the process." <file-system> objects, relative to ROOT; then make ROOT the new root directory
for the process."
(define (scope dir) (define (scope dir)
(string-append root dir)) (string-append root dir))
@ -141,8 +143,9 @@ (define* (mount* source target type #:optional (flags 0) options
(symlink "/proc/self/fd/2" (scope "/dev/stderr")) (symlink "/proc/self/fd/2" (scope "/dev/stderr"))
;; Mount user-specified file systems. ;; Mount user-specified file systems.
(for-each (lambda (spec) (for-each (lambda (file-system)
(mount-file-system spec #:root root)) (mount-file-system (file-system->spec file-system)
#:root root))
mounts) mounts)
;; Jail the process inside the container's root file system. ;; Jail the process inside the container's root file system.
@ -197,8 +200,8 @@ (define (namespaces->bit-mask namespaces)
(define (run-container root mounts namespaces host-uids thunk) (define (run-container root mounts namespaces host-uids thunk)
"Run THUNK in a new container process and return its PID. ROOT specifies "Run THUNK in a new container process and return its PID. ROOT specifies
the root directory for the container. MOUNTS is a list of file system specs the root directory for the container. MOUNTS is a list of <file-system>
that specify the mapping of host file systems into the container. NAMESPACES objects that specify file systems to mount inside the container. NAMESPACES
is a list of symbols that correspond to the possible Linux namespaces: mnt, is a list of symbols that correspond to the possible Linux namespaces: mnt,
ipc, uts, user, and net. HOST-UIDS specifies the number of ipc, uts, user, and net. HOST-UIDS specifies the number of
host user identifiers to map into the user namespace." host user identifiers to map into the user namespace."
@ -256,8 +259,8 @@ (define (run-container root mounts namespaces host-uids thunk)
(define* (call-with-container mounts thunk #:key (namespaces %namespaces) (define* (call-with-container mounts thunk #:key (namespaces %namespaces)
(host-uids 1)) (host-uids 1))
"Run THUNK in a new container process and return its exit status. "Run THUNK in a new container process and return its exit status.
MOUNTS is a list of file system specs that specify the mapping of host file MOUNTS is a list of <file-system> objects that specify file systems to mount
systems into the container. NAMESPACES is a list of symbols corresponding to inside the container. NAMESPACES is a list of symbols corresponding to
the identifiers for Linux namespaces: mnt, ipc, uts, pid, user, and net. By the identifiers for Linux namespaces: mnt, ipc, uts, pid, user, and net. By
default, all namespaces are used. HOST-UIDS is the number of host user default, all namespaces are used. HOST-UIDS is the number of host user
identifiers to map into the container's user namespace, if there is one. By identifiers to map into the container's user namespace, if there is one. By

View file

@ -40,6 +40,7 @@ (define-module (gnu system file-systems)
file-system-dependencies file-system-dependencies
file-system->spec file-system->spec
spec->file-system
specification->file-system-mapping specification->file-system-mapping
uuid uuid
@ -107,6 +108,16 @@ (define (file-system->spec fs)
(($ <file-system> device title mount-point type flags options _ _ check?) (($ <file-system> device title mount-point type flags options _ _ check?)
(list device title mount-point type flags options check?)))) (list device title mount-point type flags options check?))))
(define (spec->file-system sexp)
"Deserialize SEXP, a list, to the corresponding <file-system> object."
(match sexp
((device title mount-point type flags options check?)
(file-system
(device device) (title title)
(mount-point mount-point) (type type)
(flags flags) (options options)
(check? check?)))))
(define (specification->file-system-mapping spec writable?) (define (specification->file-system-mapping spec writable?)
"Read the SPEC and return the corresponding <file-system-mapping>. SPEC is "Read the SPEC and return the corresponding <file-system-mapping>. SPEC is
a string of the form \"SOURCE\" or \"SOURCE=TARGET\". The former specifies a string of the form \"SOURCE\" or \"SOURCE=TARGET\". The former specifies

View file

@ -94,9 +94,10 @@ (define script
(gnu build linux-container))) (gnu build linux-container)))
#~(begin #~(begin
(use-modules (gnu build linux-container) (use-modules (gnu build linux-container)
(gnu system file-systems) ;spec->file-system
(guix build utils)) (guix build utils))
(call-with-container '#$specs (call-with-container (map spec->file-system '#$specs)
(lambda () (lambda ()
(setenv "HOME" "/root") (setenv "HOME" "/root")
(setenv "TMPDIR" "/tmp") (setenv "TMPDIR" "/tmp")

View file

@ -427,7 +427,7 @@ (define* (launch-environment/container #:key command bash user-mappings
(file-systems (append %container-file-systems (file-systems (append %container-file-systems
(map mapping->file-system mappings)))) (map mapping->file-system mappings))))
(exit/status (exit/status
(call-with-container (map file-system->spec file-systems) (call-with-container file-systems
(lambda () (lambda ()
;; Setup global shell. ;; Setup global shell.
(mkdir-p "/bin") (mkdir-p "/bin")

View file

@ -20,6 +20,7 @@ (define-module (test-containers)
#:use-module (guix utils) #:use-module (guix utils)
#:use-module (guix build syscalls) #:use-module (guix build syscalls)
#:use-module (gnu build linux-container) #:use-module (gnu build linux-container)
#:use-module (gnu system file-systems)
#:use-module (srfi srfi-64) #:use-module (srfi srfi-64)
#:use-module (ice-9 match)) #:use-module (ice-9 match))
@ -80,7 +81,10 @@ (define (skip-if-unsupported)
(skip-if-unsupported) (skip-if-unsupported)
(test-assert "call-with-container, mnt namespace" (test-assert "call-with-container, mnt namespace"
(zero? (zero?
(call-with-container '(("none" device "/testing" "tmpfs" () #f #f)) (call-with-container (list (file-system
(device "none")
(mount-point "/testing")
(type "tmpfs")))
(lambda () (lambda ()
(assert-exit (file-exists? "/testing"))) (assert-exit (file-exists? "/testing")))
#:namespaces '(user mnt)))) #:namespaces '(user mnt))))
@ -91,8 +95,11 @@ (define (skip-if-unsupported)
;; An exception should be raised; see <http://bugs.gnu.org/23306>. ;; An exception should be raised; see <http://bugs.gnu.org/23306>.
(catch 'system-error (catch 'system-error
(lambda () (lambda ()
(call-with-container '(("/does-not-exist" device "/foo" (call-with-container (list (file-system
"none" (bind-mount) #f #f)) (device "/does-not-exist")
(mount-point "/foo")
(type "none")
(flags '(bind-mount))))
(const #t) (const #t)
#:namespaces '(user mnt))) #:namespaces '(user mnt)))
(lambda args (lambda args