all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
blob 5fecd954e947355a405d57e32c65e29f69097a97 5300 bytes (raw)
name: guix/remote.scm 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (guix remote)
  #:use-module (guix ssh)
  #:use-module (guix gexp)
  #:use-module (guix inferior)
  #:use-module (guix store)
  #:use-module (guix monads)
  #:use-module (guix modules)
  #:use-module (guix derivations)
  #:use-module (ssh popen)
  #:use-module (srfi srfi-1)
  #:use-module (ice-9 match)
  #:export (remote-eval))

;;; Commentary:
;;;
;;; Note: This API is experimental and subject to change!
;;;
;;; Evaluate a gexp on a remote machine, over SSH, ensuring that all the
;;; elements the gexp refers to are deployed beforehand.  This is useful for
;;; expressions that have side effects; for pure expressions, you would rather
;;; build a derivation remotely or offload it.
;;;
;;; Code:

(define (remote-pipe-for-gexp lowered session)
  "Return a remote pipe for the given SESSION to evaluate LOWERED."
  (define shell-quote
    (compose object->string object->string))

  (apply open-remote-pipe* session OPEN_READ
         (string-append (derivation-input-output-path
                         (lowered-gexp-guile lowered))
                        "/bin/guile")
         "--no-auto-compile"
         (append (append-map (lambda (directory)
                               `("-L" ,directory))
                             (lowered-gexp-load-path lowered))
                 (append-map (lambda (directory)
                               `("-C" ,directory))
                             (lowered-gexp-load-path lowered))
                 `("-c"
                   ,(shell-quote (lowered-gexp-sexp lowered))))))

(define (%remote-eval lowered session)
  "Evaluate LOWERED, a lowered gexp, in SESSION.  This assumes that all the
prerequisites of EXP are already available on the host at SESSION."
  (let* ((pipe   (remote-pipe-for-gexp lowered session))
         (result (read-repl-response pipe)))
    (close-port pipe)
    result))

(define (trampoline exp)
  "Return a \"trampoline\" gexp that evaluates EXP and writes the evaluation
result to the current output port using the (guix repl) protocol."
  (define program
    (scheme-file "remote-exp.scm" exp))

  (with-imported-modules (source-module-closure '((guix repl)))
    #~(begin
        (use-modules (guix repl))

        ;; We use CURRENT-OUTPUT-PORT for REPL messages, so redirect PROGRAM's
        ;; output to CURRENT-ERROR-PORT so that it does not interfere.
        (send-repl-response '(with-output-to-port (current-error-port)
                               (lambda ()
                                 (primitive-load #$program)))
                            (current-output-port))

        (force-output))))

(define* (remote-eval exp session
                      #:key
                      (build-locally? #t)
                      (module-path %load-path)
                      (socket-name "/var/guix/daemon-socket/socket"))
  "Evaluate EXP, a gexp, on the host at SESSION, an SSH session.  Ensure that
all the elements EXP refers to are built and deployed to SESSION beforehand.
When BUILD-LOCALLY? is true, said dependencies are built locally and sent to
the remote store afterwards; otherwise, dependencies are built directly on the
remote store."
  (mlet %store-monad ((lowered (lower-gexp (trampoline exp)
                                           #:module-path %load-path))
                      (remote -> (connect-to-remote-daemon session
                                                           socket-name)))
    (define inputs
      (cons (lowered-gexp-guile lowered)
            (lowered-gexp-inputs lowered)))

    (define sources
      (lowered-gexp-sources lowered))

    (if build-locally?
        (let ((to-send (append (append-map derivation-input-output-paths
                                           inputs)
                               sources)))
          (mbegin %store-monad
            (built-derivations inputs)
            ((store-lift send-files) to-send remote #:recursive? #t)
            (return (close-connection remote))
            (return (%remote-eval lowered session))))
        (let ((to-send (append (map (compose derivation-file-name
                                             derivation-input-derivation)
                                    inputs)
                               sources)))
          (mbegin %store-monad
            ((store-lift send-files) to-send remote #:recursive? #t)
            (return (build-derivations remote inputs))
            (return (close-connection remote))
            (return (%remote-eval lowered session)))))))

debug log:

solving 5fecd954e9 ...
found 5fecd954e9 in https://git.savannah.gnu.org/cgit/guix.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.