summaryrefslogtreecommitdiff
path: root/gnu/installer
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/installer')
-rw-r--r--gnu/installer/final.scm124
-rw-r--r--gnu/installer/newt/final.scm7
-rw-r--r--gnu/installer/newt/partition.scm2
-rw-r--r--gnu/installer/parted.scm24
4 files changed, 84 insertions, 73 deletions
diff --git a/gnu/installer/final.scm b/gnu/installer/final.scm
index 685aa81d89..11143b2adb 100644
--- a/gnu/installer/final.scm
+++ b/gnu/installer/final.scm
@@ -26,6 +26,8 @@
#:use-module (guix build syscalls)
#:use-module (guix build utils)
#:use-module (gnu build accounts)
+ #:use-module (gnu build install)
+ #:use-module (gnu build linux-container)
#:use-module ((gnu system shadow) #:prefix sys:)
#:use-module (rnrs io ports)
#:use-module (srfi srfi-1)
@@ -133,49 +135,18 @@ USERS."
(_ #f))))))
pids)))
-(define (umount-cow-store)
- "Remove the store overlay and the bind-mount on /tmp created by the
-cow-store service. This procedure is very fragile and a better approach would
-be much appreciated."
- (catch #t
- (lambda ()
- (let ((tmp-dir "/remove"))
- (syslog "Unmounting cow-store.~%")
-
- (mkdir-p tmp-dir)
- (mount (%store-directory) tmp-dir "" MS_MOVE)
-
- ;; The guix-daemon has possibly opened files from the cow-store,
- ;; restart it.
- (restart-service 'guix-daemon)
-
- (syslog "Killing cow users.")
-
- ;; Kill all processes started while the cow-store was active (logins
- ;; on other TTYs for instance).
- (kill-cow-users tmp-dir)
-
- ;; Try to umount the store overlay. Some process such as udevd
- ;; workers might still be active, so do some retries.
- (let loop ((try 5))
- (syslog "Umount try ~a~%" (- 5 try))
- (sleep 1)
- (let ((umounted? (false-if-exception (umount tmp-dir))))
- (if (and (not umounted?) (> try 0))
- (loop (- try 1))
- (if umounted?
- (syslog "Umounted ~a successfully.~%" tmp-dir)
- (syslog "Failed to umount ~a.~%" tmp-dir)))))
-
- (umount "/tmp")))
- (lambda args
- (syslog "~a~%" args))))
-
(define* (install-system locale #:key (users '()))
"Create /etc/shadow and /etc/passwd on the installation target for USERS.
Start COW-STORE service on target directory and launch guix install command in
a subshell. LOCALE must be the locale name under which that command will run,
or #f. Return #t on success and #f on failure."
+ (define backing-directory
+ ;; Sub-directory used as the backing store for copy-on-write.
+ "/tmp/guix-inst")
+
+ (define (assert-exit x)
+ (primitive-exit (if x 0 1)))
+
(let* ((options (catch 'system-error
(lambda ()
;; If this file exists, it can provide
@@ -188,7 +159,11 @@ or #f. Return #t on success and #f on failure."
"--fallback")
options
(list (%installer-configuration-file)
- (%installer-target-dir)))))
+ (%installer-target-dir))))
+ (database-dir "/var/guix/db")
+ (database-file (string-append database-dir "/db.sqlite"))
+ (saved-database (string-append database-dir "/db.save"))
+ (ret #f))
(mkdir-p (%installer-target-dir))
;; We want to initialize user passwords but we don't want to store them in
@@ -198,27 +173,50 @@ or #f. Return #t on success and #f on failure."
;; passwords that we've put in there.
(create-user-database users (%installer-target-dir))
- (dynamic-wind
- (lambda ()
- (start-service 'cow-store (list (%installer-target-dir))))
- (lambda ()
- ;; If there are any connected clients, assume that we are running
- ;; installation tests. In that case, dump the standard and error
- ;; outputs to syslog.
- (if (not (null? (current-clients)))
- (with-output-to-file "/dev/console"
- (lambda ()
- (with-error-to-file "/dev/console"
- (lambda ()
- (setvbuf (current-output-port) 'none)
- (setvbuf (current-error-port) 'none)
- (run-command install-command #:locale locale)))))
- (run-command install-command #:locale locale)))
- (lambda ()
- (stop-service 'cow-store)
- ;; Remove the store overlay created at cow-store service start.
- ;; Failing to do that will result in further umount calls to fail
- ;; because the target device is seen as busy. See:
- ;; https://lists.gnu.org/archive/html/guix-devel/2018-12/msg00161.html.
- (umount-cow-store)
- #f))))
+ ;; 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.
+ (unmount-cow-store (%installer-target-dir) backing-directory)
+ (assert-exit ret))))
+ #:namespaces '(mnt)))))
diff --git a/gnu/installer/newt/final.scm b/gnu/installer/newt/final.scm
index fa8d6fea71..89684c4d8a 100644
--- a/gnu/installer/newt/final.scm
+++ b/gnu/installer/newt/final.scm
@@ -102,13 +102,6 @@ a specific step, or restart the installer."))
#:key (users '()))
(clear-screen)
(newt-suspend)
- ;; XXX: Force loading 'bold' font files before mouting the
- ;; cow-store. Otherwise, if the file is loaded by kmscon after the cow-store
- ;; in mounted, it will be necessary to kill kmscon to umount to cow-store.
- (display
- (colorize-string
- (format #f (G_ "Installing Guix System ...~%"))
- (color BOLD)))
(let ((install-ok? (install-system locale #:users users)))
(newt-resume)
install-ok?))
diff --git a/gnu/installer/newt/partition.scm b/gnu/installer/newt/partition.scm
index c925e410a9..54d595f54e 100644
--- a/gnu/installer/newt/partition.scm
+++ b/gnu/installer/newt/partition.scm
@@ -121,7 +121,7 @@ Be careful, all data on the disk will be lost.")
(run-listbox-selection-page
#:info-text (G_ "Please select the file-system type for this partition.")
#:title (G_ "File-system type")
- #:listbox-items '(ext4 btrfs fat16 fat32 jfs swap)
+ #:listbox-items '(ext4 btrfs fat16 fat32 jfs ntfs swap)
#:listbox-item->text user-fs-type-name
#:sort-listbox-items? #f
#:button-text (G_ "Exit")
diff --git a/gnu/installer/parted.scm b/gnu/installer/parted.scm
index 6c805cc053..ff5f6afd19 100644
--- a/gnu/installer/parted.scm
+++ b/gnu/installer/parted.scm
@@ -222,7 +222,8 @@ inferior to MAX-SIZE, #f otherwise."
((btrfs) "btrfs")
((fat16) "fat16")
((fat32) "fat32")
- ((jfs) "jfs")
+ ((jfs) "jfs")
+ ((ntfs) "ntfs")
((swap) "linux-swap")))
(define (user-fs-type->mount-type fs-type)
@@ -232,7 +233,8 @@ inferior to MAX-SIZE, #f otherwise."
((btrfs) "btrfs")
((fat16) "fat")
((fat32) "vfat")
- ((jfs) "jfs")))
+ ((jfs) "jfs")
+ ((ntfs) "ntfs")))
(define (partition-filesystem-user-type partition)
"Return the filesystem type of PARTITION, to be stored in the FS-TYPE field
@@ -246,6 +248,7 @@ of <user-partition> record."
((string=? name "fat16") 'fat16)
((string=? name "fat32") 'fat32)
((string=? name "jfs") 'jfs)
+ ((string=? name "ntfs") 'ntfs)
((or (string=? name "swsusp")
(string=? name "linux-swap(v0)")
(string=? name "linux-swap(v1)"))
@@ -327,6 +330,11 @@ fail. See rereadpt function in wipefs.c of util-linux for an explanation."
(device-sync device)
(device-close device))
+(define (remove-logical-devices)
+ "Remove all active logical devices."
+ (with-null-output-ports
+ (invoke "dmsetup" "remove_all")))
+
(define (non-install-devices)
"Return all the available devices, except the busy one, allegedly the
install device. DEVICE-IS-BUSY? is a parted call, checking if the device is
@@ -1040,6 +1048,11 @@ bit bucket."
(with-null-output-ports
(invoke "jfs_mkfs" "-f" partition)))
+(define (create-ntfs-file-system partition)
+ "Create a JFS file-system for PARTITION file-name."
+ (with-null-output-ports
+ (invoke "mkfs.ntfs" "-F" "-f" partition)))
+
(define (create-swap-partition partition)
"Set up swap area on PARTITION file-name."
(with-null-output-ports
@@ -1117,6 +1130,10 @@ NEED-FORMATING? field set to #t."
(and need-formatting?
(not (eq? type 'extended))
(create-jfs-file-system file-name)))
+ ((ntfs)
+ (and need-formatting?
+ (not (eq? type 'extended))
+ (create-ntfs-file-system file-name)))
((swap)
(create-swap-partition file-name))
(else
@@ -1328,6 +1345,9 @@ USER-PARTITIONS, or return nothing."
(define (init-parted)
"Initialize libparted support."
(probe-all-devices!)
+ ;; Remove all logical devices, otherwise "device-is-busy?" will report true
+ ;; on all devices containaing active logical volumes.
+ (remove-logical-devices)
(exception-set-handler (lambda (exception)
EXCEPTION-OPTION-UNHANDLED)))