diff options
| author | Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org> | 2019-07-05 14:55:21 -0400 |
|---|---|---|
| committer | Christopher Lemmer Webber <cwebber@dustycloud.org> | 2019-07-06 02:10:04 -0400 |
| commit | fa9edf09e992db7510c7471486dffc93e1e707e5 (patch) | |
| tree | d68202454ce7643d26d2b1d1fce7586845094bfe /gnu | |
| parent | a9b09ed7764762f93c1a8b7c96769b9da72dc8c4 (diff) | |
gnu: Add machine type for deployment specifications.
* gnu/machine.scm: New file.
* gnu/machine/ssh.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
Diffstat (limited to 'gnu')
| -rw-r--r-- | gnu/local.mk | 5 | ||||
| -rw-r--r-- | gnu/machine.scm | 107 | ||||
| -rw-r--r-- | gnu/machine/ssh.scm | 369 |
3 files changed, 480 insertions, 1 deletions
diff --git a/gnu/local.mk b/gnu/local.mk index 8d7760cf467..68a43330c49 100644 --- a/gnu/local.mk +++ b/gnu/local.mk | |||
| @@ -565,6 +565,9 @@ GNU_SYSTEM_MODULES = \ | |||
| 565 | %D%/system/uuid.scm \ | 565 | %D%/system/uuid.scm \ |
| 566 | %D%/system/vm.scm \ | 566 | %D%/system/vm.scm \ |
| 567 | \ | 567 | \ |
| 568 | %D%/machine.scm \ | ||
| 569 | %D%/machine/ssh.scm \ | ||
| 570 | \ | ||
| 568 | %D%/build/accounts.scm \ | 571 | %D%/build/accounts.scm \ |
| 569 | %D%/build/activation.scm \ | 572 | %D%/build/activation.scm \ |
| 570 | %D%/build/bootloader.scm \ | 573 | %D%/build/bootloader.scm \ |
| @@ -630,7 +633,7 @@ INSTALLER_MODULES = \ | |||
| 630 | %D%/installer/newt/user.scm \ | 633 | %D%/installer/newt/user.scm \ |
| 631 | %D%/installer/newt/utils.scm \ | 634 | %D%/installer/newt/utils.scm \ |
| 632 | %D%/installer/newt/welcome.scm \ | 635 | %D%/installer/newt/welcome.scm \ |
| 633 | %D%/installer/newt/wifi.scm | 636 | %D%/installer/newt/wifi.scm |
| 634 | 637 | ||
| 635 | # Always ship the installer modules but compile them only when | 638 | # Always ship the installer modules but compile them only when |
| 636 | # ENABLE_INSTALLER is true. | 639 | # ENABLE_INSTALLER is true. |
diff --git a/gnu/machine.scm b/gnu/machine.scm new file mode 100644 index 00000000000..0b79402b0a8 --- /dev/null +++ b/gnu/machine.scm | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2019 David Thompson <davet@gnu.org> | ||
| 3 | ;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org> | ||
| 4 | ;;; | ||
| 5 | ;;; This file is part of GNU Guix. | ||
| 6 | ;;; | ||
| 7 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 8 | ;;; under the terms of the GNU General Public License as published by | ||
| 9 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 10 | ;;; your option) any later version. | ||
| 11 | ;;; | ||
| 12 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 13 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;;; GNU General Public License for more details. | ||
| 16 | ;;; | ||
| 17 | ;;; You should have received a copy of the GNU General Public License | ||
| 18 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | (define-module (gnu machine) | ||
| 21 | #:use-module (gnu system) | ||
| 22 | #:use-module (guix derivations) | ||
| 23 | #:use-module (guix monads) | ||
| 24 | #:use-module (guix records) | ||
| 25 | #:use-module (guix store) | ||
| 26 | #:use-module ((guix utils) #:select (source-properties->location)) | ||
| 27 | #:export (environment-type | ||
| 28 | environment-type? | ||
| 29 | environment-type-name | ||
| 30 | environment-type-description | ||
| 31 | environment-type-location | ||
| 32 | |||
| 33 | machine | ||
| 34 | machine? | ||
| 35 | this-machine | ||
| 36 | |||
| 37 | machine-system | ||
| 38 | machine-environment | ||
| 39 | machine-configuration | ||
| 40 | machine-display-name | ||
| 41 | |||
| 42 | deploy-machine | ||
| 43 | machine-remote-eval)) | ||
| 44 | |||
| 45 | ;;; Commentary: | ||
| 46 | ;;; | ||
| 47 | ;;; This module provides the types used to declare individual machines in a | ||
| 48 | ;;; heterogeneous Guix deployment. The interface allows users of specify system | ||
| 49 | ;;; configurations and the means by which resources should be provisioned on a | ||
| 50 | ;;; per-host basis. | ||
| 51 | ;;; | ||
| 52 | ;;; Code: | ||
| 53 | |||
| 54 | |||
| 55 | ;;; | ||
| 56 | ;;; Declarations for resources that can be provisioned. | ||
| 57 | ;;; | ||
| 58 | |||
| 59 | (define-record-type* <environment-type> environment-type | ||
| 60 | make-environment-type | ||
| 61 | environment-type? | ||
| 62 | |||
| 63 | ;; Interface to the environment type's deployment code. Each procedure | ||
| 64 | ;; should take the same arguments as the top-level procedure of this file | ||
| 65 | ;; that shares the same name. For example, 'machine-remote-eval' should be | ||
| 66 | ;; of the form '(machine-remote-eval machine exp)'. | ||
| 67 | (machine-remote-eval environment-type-machine-remote-eval) ; procedure | ||
| 68 | (deploy-machine environment-type-deploy-machine) ; procedure | ||
| 69 | |||
| 70 | ;; Metadata. | ||
| 71 | (name environment-type-name) ; symbol | ||
| 72 | (description environment-type-description ; string | ||
| 73 | (default #f)) | ||
| 74 | (location environment-type-location ; <location> | ||
| 75 | (default (and=> (current-source-location) | ||
| 76 | source-properties->location)) | ||
| 77 | (innate))) | ||
| 78 | |||
| 79 | |||
| 80 | ;;; | ||
| 81 | ;;; Declarations for machines in a deployment. | ||
| 82 | ;;; | ||
| 83 | |||
| 84 | (define-record-type* <machine> machine | ||
| 85 | make-machine | ||
| 86 | machine? | ||
| 87 | this-machine | ||
| 88 | (system machine-system) ; <operating-system> | ||
| 89 | (environment machine-environment) ; symbol | ||
| 90 | (configuration machine-configuration ; configuration object | ||
| 91 | (default #f))) ; specific to environment | ||
| 92 | |||
| 93 | (define (machine-display-name machine) | ||
| 94 | "Return the host-name identifying MACHINE." | ||
| 95 | (operating-system-host-name (machine-system machine))) | ||
| 96 | |||
| 97 | (define (machine-remote-eval machine exp) | ||
| 98 | "Evaluate EXP, a gexp, on MACHINE. Ensure that all the elements EXP refers to | ||
| 99 | are built and deployed to MACHINE beforehand." | ||
| 100 | (let ((environment (machine-environment machine))) | ||
| 101 | ((environment-type-machine-remote-eval environment) machine exp))) | ||
| 102 | |||
| 103 | (define (deploy-machine machine) | ||
| 104 | "Monadic procedure transferring the new system's OS closure to the remote | ||
| 105 | MACHINE, activating it on MACHINE and switching MACHINE to the new generation." | ||
| 106 | (let ((environment (machine-environment machine))) | ||
| 107 | ((environment-type-deploy-machine environment) machine))) | ||
diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm new file mode 100644 index 00000000000..a7d1a967aec --- /dev/null +++ b/gnu/machine/ssh.scm | |||
| @@ -0,0 +1,369 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (gnu machine ssh) | ||
| 20 | #:use-module (gnu bootloader) | ||
| 21 | #:use-module (gnu machine) | ||
| 22 | #:autoload (gnu packages gnupg) (guile-gcrypt) | ||
| 23 | #:use-module (gnu services) | ||
| 24 | #:use-module (gnu services shepherd) | ||
| 25 | #:use-module (gnu system) | ||
| 26 | #:use-module (guix derivations) | ||
| 27 | #:use-module (guix gexp) | ||
| 28 | #:use-module (guix i18n) | ||
| 29 | #:use-module (guix modules) | ||
| 30 | #:use-module (guix monads) | ||
| 31 | #:use-module (guix records) | ||
| 32 | #:use-module (guix remote) | ||
| 33 | #:use-module (guix ssh) | ||
| 34 | #:use-module (guix store) | ||
| 35 | #:use-module (ice-9 match) | ||
| 36 | #:use-module (srfi srfi-19) | ||
| 37 | #:use-module (srfi srfi-35) | ||
| 38 | #:export (managed-host-environment-type | ||
| 39 | |||
| 40 | machine-ssh-configuration | ||
| 41 | machine-ssh-configuration? | ||
| 42 | machine-ssh-configuration | ||
| 43 | |||
| 44 | machine-ssh-configuration-host-name | ||
| 45 | machine-ssh-configuration-port | ||
| 46 | machine-ssh-configuration-user | ||
| 47 | machine-ssh-configuration-session)) | ||
| 48 | |||
| 49 | ;;; Commentary: | ||
| 50 | ;;; | ||
| 51 | ;;; This module implements remote evaluation and system deployment for | ||
| 52 | ;;; machines that are accessable over SSH and have a known host-name. In the | ||
| 53 | ;;; sense of the broader "machine" interface, we describe the environment for | ||
| 54 | ;;; such machines as 'managed-host. | ||
| 55 | ;;; | ||
| 56 | ;;; Code: | ||
| 57 | |||
| 58 | |||
| 59 | ;;; | ||
| 60 | ;;; Parameters for the SSH client. | ||
| 61 | ;;; | ||
| 62 | |||
| 63 | (define-record-type* <machine-ssh-configuration> machine-ssh-configuration | ||
| 64 | make-machine-ssh-configuration | ||
| 65 | machine-ssh-configuration? | ||
| 66 | this-machine-ssh-configuration | ||
| 67 | (host-name machine-ssh-configuration-host-name) ; string | ||
| 68 | (port machine-ssh-configuration-port ; integer | ||
| 69 | (default 22)) | ||
| 70 | (user machine-ssh-configuration-user ; string | ||
| 71 | (default "root")) | ||
| 72 | (identity machine-ssh-configuration-identity ; path to a private key | ||
| 73 | (default #f)) | ||
| 74 | (session machine-ssh-configuration-session ; session | ||
| 75 | (default #f))) | ||
| 76 | |||
| 77 | (define (machine-ssh-session machine) | ||
| 78 | "Return the SSH session that was given in MACHINE's configuration, or create | ||
| 79 | one from the configuration's parameters if one was not provided." | ||
| 80 | (maybe-raise-unsupported-configuration-error machine) | ||
| 81 | (let ((config (machine-configuration machine))) | ||
| 82 | (or (machine-ssh-configuration-session config) | ||
| 83 | (let ((host-name (machine-ssh-configuration-host-name config)) | ||
| 84 | (user (machine-ssh-configuration-user config)) | ||
| 85 | (port (machine-ssh-configuration-port config)) | ||
| 86 | (identity (machine-ssh-configuration-identity config))) | ||
| 87 | (open-ssh-session host-name | ||
| 88 | #:user user | ||
| 89 | #:port port | ||
| 90 | #:identity identity))))) | ||
| 91 | |||
| 92 | |||
| 93 | ;;; | ||
| 94 | ;;; Remote evaluation. | ||
| 95 | ;;; | ||
| 96 | |||
| 97 | (define (managed-host-remote-eval machine exp) | ||
| 98 | "Internal implementation of 'machine-remote-eval' for MACHINE instances with | ||
| 99 | an environment type of 'managed-host." | ||
| 100 | (maybe-raise-unsupported-configuration-error machine) | ||
| 101 | (remote-eval exp (machine-ssh-session machine))) | ||
| 102 | |||
| 103 | |||
| 104 | ;;; | ||
| 105 | ;;; System deployment. | ||
| 106 | ;;; | ||
| 107 | |||
| 108 | (define (switch-to-system machine) | ||
| 109 | "Monadic procedure creating a new generation on MACHINE and execute the | ||
| 110 | activation script for the new system configuration." | ||
| 111 | (define (remote-exp drv script) | ||
| 112 | (with-extensions (list guile-gcrypt) | ||
| 113 | (with-imported-modules (source-module-closure '((guix config) | ||
| 114 | (guix profiles) | ||
| 115 | (guix utils))) | ||
| 116 | #~(begin | ||
| 117 | (use-modules (guix config) | ||
| 118 | (guix profiles) | ||
| 119 | (guix utils)) | ||
| 120 | |||
| 121 | (define %system-profile | ||
| 122 | (string-append %state-directory "/profiles/system")) | ||
| 123 | |||
| 124 | (let* ((system #$drv) | ||
| 125 | (number (1+ (generation-number %system-profile))) | ||
| 126 | (generation (generation-file-name %system-profile number))) | ||
| 127 | (switch-symlinks generation system) | ||
| 128 | (switch-symlinks %system-profile generation) | ||
| 129 | ;; The implementation of 'guix system reconfigure' saves the | ||
| 130 | ;; load path and environment here. This is unnecessary here | ||
| 131 | ;; because each invocation of 'remote-eval' runs in a distinct | ||
| 132 | ;; Guile REPL. | ||
| 133 | (setenv "GUIX_NEW_SYSTEM" system) | ||
| 134 | ;; The activation script may write to stdout, which confuses | ||
| 135 | ;; 'remote-eval' when it attempts to read a result from the | ||
| 136 | ;; remote REPL. We work around this by forcing the output to a | ||
| 137 | ;; string. | ||
| 138 | (with-output-to-string | ||
| 139 | (lambda () | ||
| 140 | (primitive-load #$script)))))))) | ||
| 141 | |||
| 142 | (let* ((os (machine-system machine)) | ||
| 143 | (script (operating-system-activation-script os))) | ||
| 144 | (mlet* %store-monad ((drv (operating-system-derivation os))) | ||
| 145 | (machine-remote-eval machine (remote-exp drv script))))) | ||
| 146 | |||
| 147 | ;; XXX: Currently, this does NOT attempt to restart running services. This is | ||
| 148 | ;; also the case with 'guix system reconfigure'. | ||
| 149 | ;; | ||
| 150 | ;; See <https://issues.guix.info/issue/33508>. | ||
| 151 | (define (upgrade-shepherd-services machine) | ||
| 152 | "Monadic procedure unloading and starting services on the remote as needed | ||
| 153 | to realize the MACHINE's system configuration." | ||
| 154 | (define target-services | ||
| 155 | ;; Monadic expression evaluating to a list of (name output-path) pairs for | ||
| 156 | ;; all of MACHINE's services. | ||
| 157 | (mapm %store-monad | ||
| 158 | (lambda (service) | ||
| 159 | (mlet %store-monad ((file ((compose lower-object | ||
| 160 | shepherd-service-file) | ||
| 161 | service))) | ||
| 162 | (return (list (shepherd-service-canonical-name service) | ||
| 163 | (derivation->output-path file))))) | ||
| 164 | (service-value | ||
| 165 | (fold-services (operating-system-services (machine-system machine)) | ||
| 166 | #:target-type shepherd-root-service-type)))) | ||
| 167 | |||
| 168 | (define (remote-exp target-services) | ||
| 169 | (with-imported-modules '((gnu services herd)) | ||
| 170 | #~(begin | ||
| 171 | (use-modules (gnu services herd) | ||
| 172 | (srfi srfi-1)) | ||
| 173 | |||
| 174 | (define running | ||
| 175 | (filter live-service-running (current-services))) | ||
| 176 | |||
| 177 | (define (essential? service) | ||
| 178 | ;; Return #t if SERVICE is essential and should not be unloaded | ||
| 179 | ;; under any circumstance. | ||
| 180 | (memq (first (live-service-provision service)) | ||
| 181 | '(root shepherd))) | ||
| 182 | |||
| 183 | (define (obsolete? service) | ||
| 184 | ;; Return #t if SERVICE can be safely unloaded. | ||
| 185 | (and (not (essential? service)) | ||
| 186 | (every (lambda (requirements) | ||
| 187 | (not (memq (first (live-service-provision service)) | ||
| 188 | requirements))) | ||
| 189 | (map live-service-requirement running)))) | ||
| 190 | |||
| 191 | (define to-unload | ||
| 192 | (filter obsolete? | ||
| 193 | (remove (lambda (service) | ||
| 194 | (memq (first (live-service-provision service)) | ||
| 195 | (map first '#$target-services))) | ||
| 196 | running))) | ||
| 197 | |||
| 198 | (define to-start | ||
| 199 | (remove (lambda (service-pair) | ||
| 200 | (memq (first service-pair) | ||
| 201 | (map (compose first live-service-provision) | ||
| 202 | running))) | ||
| 203 | '#$target-services)) | ||
| 204 | |||
| 205 | ;; Unload obsolete services. | ||
| 206 | (for-each (lambda (service) | ||
| 207 | (false-if-exception | ||
| 208 | (unload-service service))) | ||
| 209 | to-unload) | ||
| 210 | |||
| 211 | ;; Load the service files for any new services and start them. | ||
| 212 | (load-services/safe (map second to-start)) | ||
| 213 | (for-each start-service (map first to-start)) | ||
| 214 | |||
| 215 | #t))) | ||
| 216 | |||
| 217 | (mlet %store-monad ((target-services target-services)) | ||
| 218 | (machine-remote-eval machine (remote-exp target-services)))) | ||
| 219 | |||
| 220 | (define (machine-boot-parameters machine) | ||
| 221 | "Monadic procedure returning a list of 'boot-parameters' for the generations | ||
| 222 | of MACHINE's system profile, ordered from most recent to oldest." | ||
| 223 | (define bootable-kernel-arguments | ||
| 224 | (@@ (gnu system) bootable-kernel-arguments)) | ||
| 225 | |||
| 226 | (define remote-exp | ||
| 227 | (with-extensions (list guile-gcrypt) | ||
| 228 | (with-imported-modules (source-module-closure '((guix config) | ||
| 229 | (guix profiles))) | ||
| 230 | #~(begin | ||
| 231 | (use-modules (guix config) | ||
| 232 | (guix profiles) | ||
| 233 | (ice-9 textual-ports)) | ||
| 234 | |||
| 235 | (define %system-profile | ||
| 236 | (string-append %state-directory "/profiles/system")) | ||
| 237 | |||
| 238 | (define (read-file path) | ||
| 239 | (call-with-input-file path | ||
| 240 | (lambda (port) | ||
| 241 | (get-string-all port)))) | ||
| 242 | |||
| 243 | (map (lambda (generation) | ||
| 244 | (let* ((system-path (generation-file-name %system-profile | ||
| 245 | generation)) | ||
| 246 | (boot-parameters-path (string-append system-path | ||
| 247 | "/parameters")) | ||
| 248 | (time (stat:mtime (lstat system-path)))) | ||
| 249 | (list generation | ||
| 250 | system-path | ||
| 251 | time | ||
| 252 | (read-file boot-parameters-path)))) | ||
| 253 | (reverse (generation-numbers %system-profile))))))) | ||
| 254 | |||
| 255 | (mlet* %store-monad ((generations (machine-remote-eval machine remote-exp))) | ||
| 256 | (return | ||
| 257 | (map (lambda (generation) | ||
| 258 | (match generation | ||
| 259 | ((generation system-path time serialized-params) | ||
| 260 | (let* ((params (call-with-input-string serialized-params | ||
| 261 | read-boot-parameters)) | ||
| 262 | (root (boot-parameters-root-device params)) | ||
| 263 | (label (boot-parameters-label params))) | ||
| 264 | (boot-parameters | ||
| 265 | (inherit params) | ||
| 266 | (label | ||
| 267 | (string-append label " (#" | ||
| 268 | (number->string generation) ", " | ||
| 269 | (let ((time (make-time time-utc 0 time))) | ||
| 270 | (date->string (time-utc->date time) | ||
| 271 | "~Y-~m-~d ~H:~M")) | ||
| 272 | ")")) | ||
| 273 | (kernel-arguments | ||
| 274 | (append (bootable-kernel-arguments system-path root) | ||
| 275 | (boot-parameters-kernel-arguments params)))))))) | ||
| 276 | generations)))) | ||
| 277 | |||
| 278 | (define (install-bootloader machine) | ||
| 279 | "Create a bootloader entry for the new system generation on MACHINE, and | ||
| 280 | configure the bootloader to boot that generation by default." | ||
| 281 | (define bootloader-installer-script | ||
| 282 | (@@ (guix scripts system) bootloader-installer-script)) | ||
| 283 | |||
| 284 | (define (remote-exp installer bootcfg bootcfg-file) | ||
| 285 | (with-extensions (list guile-gcrypt) | ||
| 286 | (with-imported-modules (source-module-closure '((gnu build install) | ||
| 287 | (guix store) | ||
| 288 | (guix utils))) | ||
| 289 | #~(begin | ||
| 290 | (use-modules (gnu build install) | ||
| 291 | (guix store) | ||
| 292 | (guix utils)) | ||
| 293 | (let* ((gc-root (string-append "/" %gc-roots-directory "/bootcfg")) | ||
| 294 | (temp-gc-root (string-append gc-root ".new"))) | ||
| 295 | |||
| 296 | (switch-symlinks temp-gc-root gc-root) | ||
| 297 | |||
| 298 | (unless (false-if-exception | ||
| 299 | (begin | ||
| 300 | ;; The implementation of 'guix system reconfigure' | ||
| 301 | ;; saves the load path here. This is unnecessary here | ||
| 302 | ;; because each invocation of 'remote-eval' runs in a | ||
| 303 | ;; distinct Guile REPL. | ||
| 304 | (install-boot-config #$bootcfg #$bootcfg-file "/") | ||
| 305 | ;; The installation script may write to stdout, which | ||
| 306 | ;; confuses 'remote-eval' when it attempts to read a | ||
| 307 | ;; result from the remote REPL. We work around this | ||
| 308 | ;; by forcing the output to a string. | ||
| 309 | (with-output-to-string | ||
| 310 | (lambda () | ||
| 311 | (primitive-load #$installer))))) | ||
| 312 | (delete-file temp-gc-root) | ||
| 313 | (error "failed to install bootloader")) | ||
| 314 | |||
| 315 | (rename-file temp-gc-root gc-root) | ||
| 316 | #t))))) | ||
| 317 | |||
| 318 | (mlet* %store-monad ((boot-parameters (machine-boot-parameters machine))) | ||
| 319 | (let* ((os (machine-system machine)) | ||
| 320 | (bootloader ((compose bootloader-configuration-bootloader | ||
| 321 | operating-system-bootloader) | ||
| 322 | os)) | ||
| 323 | (bootloader-target (bootloader-configuration-target | ||
| 324 | (operating-system-bootloader os))) | ||
| 325 | (installer (bootloader-installer-script | ||
| 326 | (bootloader-installer bootloader) | ||
| 327 | (bootloader-package bootloader) | ||
| 328 | bootloader-target | ||
| 329 | "/")) | ||
| 330 | (menu-entries (map boot-parameters->menu-entry boot-parameters)) | ||
| 331 | (bootcfg (operating-system-bootcfg os menu-entries)) | ||
| 332 | (bootcfg-file (bootloader-configuration-file bootloader))) | ||
| 333 | (machine-remote-eval machine (remote-exp installer bootcfg bootcfg-file))))) | ||
| 334 | |||
| 335 | (define (deploy-managed-host machine) | ||
| 336 | "Internal implementation of 'deploy-machine' for MACHINE instances with an | ||
| 337 | environment type of 'managed-host." | ||
| 338 | (maybe-raise-unsupported-configuration-error machine) | ||
| 339 | (mbegin %store-monad | ||
| 340 | (switch-to-system machine) | ||
| 341 | (upgrade-shepherd-services machine) | ||
| 342 | (install-bootloader machine))) | ||
| 343 | |||
| 344 | |||
| 345 | ;;; | ||
| 346 | ;;; Environment type. | ||
| 347 | ;;; | ||
| 348 | |||
| 349 | (define managed-host-environment-type | ||
| 350 | (environment-type | ||
| 351 | (machine-remote-eval managed-host-remote-eval) | ||
| 352 | (deploy-machine deploy-managed-host) | ||
| 353 | (name 'managed-host-environment-type) | ||
| 354 | (description "Provisioning for machines that are accessable over SSH | ||
| 355 | and have a known host-name. This entails little more than maintaining an SSH | ||
| 356 | connection to the host."))) | ||
| 357 | |||
| 358 | (define (maybe-raise-unsupported-configuration-error machine) | ||
| 359 | "Raise an error if MACHINE's configuration is not an instance of | ||
| 360 | <machine-ssh-configuration>." | ||
| 361 | (let ((config (machine-configuration machine)) | ||
| 362 | (environment (environment-type-name (machine-environment machine)))) | ||
| 363 | (unless (and config (machine-ssh-configuration? config)) | ||
| 364 | (raise (condition | ||
| 365 | (&message | ||
| 366 | (message (format #f (G_ "unsupported machine configuration '~a' | ||
| 367 | for environment of type '~a'") | ||
| 368 | config | ||
| 369 | environment)))))))) | ||
