diff mbox series

[bug#43494,2/4] services: guix: Add guix-build-coordinator-service-type.

Message ID 20200918184042.22660-2-mail@cbaines.net
State Accepted
Headers show
Series Add package and services for the Guix Build Coordinator | expand

Checks

Context Check Description
cbaines/comparison success View comparision
cbaines/git branch success View Git branch
cbaines/applying patch success View Laminar job

Commit Message

Christopher Baines Sept. 18, 2020, 6:40 p.m. UTC
* gnu/services/guix.scm (<guix-build-coordinator-configuration>): New record
type.
(guix-build-coordinator-configuration, guix-build-coordinator-configuration?,
guix-build-coordinator-configuration-package,
guix-build-coordinator-configuration-user,
guix-build-coordinator-configuration-group,
guix-build-coordinator-configuration-datastore-uri-string,
guix-build-coordinator-configuration-agent-communication-uri-string,
guix-build-coordinator-configuration-client-communication-uri-string,
guix-build-coordinator-configuration-allocation-strategy,
guix-build-coordinator-configuration-hooks,
guix-build-coordinator-configuration-guile,
make-guix-build-coordinator-start-script,
guix-build-coordinator-shepherd-services, guix-build-coordinator-activation,
guix-build-coordinator-account): New procedures.
(guix-build-coordinator-service-type): New variable.
* gnu/tests/guix.scm (%test-guix-build-coordinator): New variable.
* doc/guix.texi (Guix Services): Document it.
---
 doc/guix.texi         |  55 ++++++++++++
 gnu/services/guix.scm | 204 +++++++++++++++++++++++++++++++++++++++++-
 gnu/tests/guix.scm    |  75 +++++++++++++++-
 3 files changed, 330 insertions(+), 4 deletions(-)

Comments

Ludovic Courtès Sept. 18, 2020, 8:20 p.m. UTC | #1
Christopher Baines <mail@cbaines.net> skribis:

> * gnu/services/guix.scm (<guix-build-coordinator-configuration>): New record
> type.
> (guix-build-coordinator-configuration, guix-build-coordinator-configuration?,
> guix-build-coordinator-configuration-package,
> guix-build-coordinator-configuration-user,
> guix-build-coordinator-configuration-group,
> guix-build-coordinator-configuration-datastore-uri-string,
> guix-build-coordinator-configuration-agent-communication-uri-string,
> guix-build-coordinator-configuration-client-communication-uri-string,
> guix-build-coordinator-configuration-allocation-strategy,
> guix-build-coordinator-configuration-hooks,
> guix-build-coordinator-configuration-guile,
> make-guix-build-coordinator-start-script,
> guix-build-coordinator-shepherd-services, guix-build-coordinator-activation,
> guix-build-coordinator-account): New procedures.
> (guix-build-coordinator-service-type): New variable.
> * gnu/tests/guix.scm (%test-guix-build-coordinator): New variable.
> * doc/guix.texi (Guix Services): Document it.

Yay!

> +@subsubheading Guix Build Coordinator
> +The @uref{https://git.cbaines.net/guix/build-coordinator/,Guix Build
> +Coordinator} aids in building derivations.  The Guix Daemon is still
                     ^
Maybe something like: “in distributing derivation builds among machines
running an @dfn{agent}”.

Also, s/Guix Daemon/build daemon/ or similar.

(In general I’m in favor of avoiding “brands” in documentation and
concept names.)

Maybe add a “@quotation Note” stating that it’s work in progress and
subject to change.

> +(define* (make-guix-build-coordinator-start-script database-uri-string
> +                                                   allocation-strategy
> +                                                   pid-file
> +                                                   guix-build-coordinator-package
> +                                                   #:key
> +                                                   agent-communication-uri-string
> +                                                   client-communication-uri-string
> +                                                   (hooks '())
> +                                                   (guile guile-3.0))
> +  (program-file
> +   "start-guix-build-coordinator"
> +   (with-extensions (cons guix-build-coordinator-package
> +                          ;; This is a poorly constructed Guile load path,
> +                          ;; since it contains things that aren't Guile
> +                          ;; libraries, but it means that the Guile libraries
> +                          ;; needed for the Guix Build Coordinator don't need
> +                          ;; to be individually specified here.
> +                          (map second (package-inputs
> +                                       guix-build-coordinator-package)))

Perhaps there should eventually be a ‘guix-build-coordinator’ command in
the package itself?

Otherwise LGTM, thanks!

One thing we discussed on IRC is the name and ways to set up one’s
monitor so that
guix-build-coordinator-configuration-client-communication-uri-string
fits on one line.  :-)

An idea that came to mind was “(Guix) dispatch(er)”, which is
synonymous.  You could use the (guix dispatch …) name space.
Food for thought!  (No rush, of course!)

Ludo’.
Christopher Baines Sept. 19, 2020, 9:13 a.m. UTC | #2
Ludovic Courtès <ludo@gnu.org> writes:

> Christopher Baines <mail@cbaines.net> skribis:
>
>> * gnu/services/guix.scm (<guix-build-coordinator-configuration>): New record
>> type.
>> (guix-build-coordinator-configuration, guix-build-coordinator-configuration?,
>> guix-build-coordinator-configuration-package,
>> guix-build-coordinator-configuration-user,
>> guix-build-coordinator-configuration-group,
>> guix-build-coordinator-configuration-datastore-uri-string,
>> guix-build-coordinator-configuration-agent-communication-uri-string,
>> guix-build-coordinator-configuration-client-communication-uri-string,
>> guix-build-coordinator-configuration-allocation-strategy,
>> guix-build-coordinator-configuration-hooks,
>> guix-build-coordinator-configuration-guile,
>> make-guix-build-coordinator-start-script,
>> guix-build-coordinator-shepherd-services, guix-build-coordinator-activation,
>> guix-build-coordinator-account): New procedures.
>> (guix-build-coordinator-service-type): New variable.
>> * gnu/tests/guix.scm (%test-guix-build-coordinator): New variable.
>> * doc/guix.texi (Guix Services): Document it.
>
> Yay!
>
>> +@subsubheading Guix Build Coordinator
>> +The @uref{https://git.cbaines.net/guix/build-coordinator/,Guix Build
>> +Coordinator} aids in building derivations.  The Guix Daemon is still
>                      ^
> Maybe something like: “in distributing derivation builds among machines
> running an @dfn{agent}”.
>
> Also, s/Guix Daemon/build daemon/ or similar.
>
> (In general I’m in favor of avoiding “brands” in documentation and
> concept names.)
>
> Maybe add a “@quotation Note” stating that it’s work in progress and
> subject to change.

I've made these changes now.

>> +(define* (make-guix-build-coordinator-start-script database-uri-string
>> +                                                   allocation-strategy
>> +                                                   pid-file
>> +                                                   guix-build-coordinator-package
>> +                                                   #:key
>> +                                                   agent-communication-uri-string
>> +                                                   client-communication-uri-string
>> +                                                   (hooks '())
>> +                                                   (guile guile-3.0))
>> +  (program-file
>> +   "start-guix-build-coordinator"
>> +   (with-extensions (cons guix-build-coordinator-package
>> +                          ;; This is a poorly constructed Guile load path,
>> +                          ;; since it contains things that aren't Guile
>> +                          ;; libraries, but it means that the Guile libraries
>> +                          ;; needed for the Guix Build Coordinator don't need
>> +                          ;; to be individually specified here.
>> +                          (map second (package-inputs
>> +                                       guix-build-coordinator-package)))
>
> Perhaps there should eventually be a ‘guix-build-coordinator’ command in
> the package itself?

There actually is, one thing I've had in mind for a while now though is
to use a scheme script constructed by the Guix service to run the
coordinator.

For guix.cbaines.net, I'm using the script, but with the hooks passed in
on the command line, the command is rather long, and it means that
backtraces don't work well with the hooks.

I'm unsure how well this has worked out, I didn't anticipate the issues
with the Guile load path, and because of the formatting stripping, both
the code and backtraces will be unreadable anyway... but it is useful in
allowing G-expressions to be used as part of the configuration.

> One thing we discussed on IRC is the name and ways to set up one’s
> monitor so that
> guix-build-coordinator-configuration-client-communication-uri-string
> fits on one line.  :-)
>
> An idea that came to mind was “(Guix) dispatch(er)”, which is
> synonymous.  You could use the (guix dispatch …) name space.
> Food for thought!  (No rush, of course!)

Indeed, I think that's a strong candidate :)
Ludovic Courtès Sept. 25, 2020, 9:42 a.m. UTC | #3
Hi!

Christopher Baines <mail@cbaines.net> skribis:

> Ludovic Courtès <ludo@gnu.org> writes:

[...]

>>> +  (program-file
>>> +   "start-guix-build-coordinator"
>>> +   (with-extensions (cons guix-build-coordinator-package
>>> +                          ;; This is a poorly constructed Guile load path,
>>> +                          ;; since it contains things that aren't Guile
>>> +                          ;; libraries, but it means that the Guile libraries
>>> +                          ;; needed for the Guix Build Coordinator don't need
>>> +                          ;; to be individually specified here.
>>> +                          (map second (package-inputs
>>> +                                       guix-build-coordinator-package)))
>>
>> Perhaps there should eventually be a ‘guix-build-coordinator’ command in
>> the package itself?
>
> There actually is, one thing I've had in mind for a while now though is
> to use a scheme script constructed by the Guix service to run the
> coordinator.
>
> For guix.cbaines.net, I'm using the script, but with the hooks passed in
> on the command line, the command is rather long, and it means that
> backtraces don't work well with the hooks.

You mean because the hooks are interpreted, and so all you see in the
backtrace is a bunch of ‘eval’ calls?

> I'm unsure how well this has worked out, I didn't anticipate the issues
> with the Guile load path, and because of the formatting stripping, both
> the code and backtraces will be unreadable anyway... but it is useful in
> allowing G-expressions to be used as part of the configuration.

OK.

Thanks,
Ludo’.
Christopher Baines Sept. 26, 2020, 8:43 a.m. UTC | #4
Ludovic Courtès <ludo@gnu.org> writes:

> Hi!
>
> Christopher Baines <mail@cbaines.net> skribis:
>
>> Ludovic Courtès <ludo@gnu.org> writes:
>
> [...]
>
>>>> +  (program-file
>>>> +   "start-guix-build-coordinator"
>>>> +   (with-extensions (cons guix-build-coordinator-package
>>>> +                          ;; This is a poorly constructed Guile load path,
>>>> +                          ;; since it contains things that aren't Guile
>>>> +                          ;; libraries, but it means that the Guile libraries
>>>> +                          ;; needed for the Guix Build Coordinator don't need
>>>> +                          ;; to be individually specified here.
>>>> +                          (map second (package-inputs
>>>> +                                       guix-build-coordinator-package)))
>>>
>>> Perhaps there should eventually be a ‘guix-build-coordinator’ command in
>>> the package itself?
>>
>> There actually is, one thing I've had in mind for a while now though is
>> to use a scheme script constructed by the Guix service to run the
>> coordinator.
>>
>> For guix.cbaines.net, I'm using the script, but with the hooks passed in
>> on the command line, the command is rather long, and it means that
>> backtraces don't work well with the hooks.
>
> You mean because the hooks are interpreted, and so all you see in the
> backtrace is a bunch of ‘eval’ calls?

Yeah, I haven't done much testing of this, but that's my assumption.
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 88128a4b3a..e83008c177 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -27486,6 +27486,61 @@  The complete list of possible options can be found in the man page for
 @node Guix Services
 @subsection Guix Services
 
+@subsubheading Guix Build Coordinator
+The @uref{https://git.cbaines.net/guix/build-coordinator/,Guix Build
+Coordinator} aids in building derivations.  The Guix Daemon is still
+used to build the derivations, but the Guix Build Coordinator provides
+ways of performing builds across many machines and working with the
+results of builds.
+
+There is a script to run the coordinator component of the Guix Build
+Coordinator, but the Guix service uses a custom Guile script instead, to
+provide better integration with G-expressions used in the configuration.
+
+@defvar {Scheme Variable} guix-build-coordinator-service-type
+Service type for the Guix Build Coordinator.  Its value must be a
+@code{guix-build-coordinator-configuration} object.
+@end defvar
+
+@deftp {Data Type} guix-build-coordinator-configuration
+Data type representing the configuration of the Guix Build Coordinator.
+
+@table @asis
+@item @code{package} (default: @code{guix-build-coordinator})
+The Guix Build Coordinator package to use.
+
+@item @code{user} (default: @code{"guix-build-coordinator"})
+The system user to run the service as.
+
+@item @code{group} (default: @code{"guix-build-coordinator"})
+The system group to run the service as.
+
+@item @code{database-uri-string} (default: @code{"sqlite:///var/lib/guix-build-coordinator/guix_build_coordinator.db"})
+The URI to use for the database.
+
+@item @code{agent-communication-uri} (default: @code{"http://0.0.0.0:8745"})
+The URI describing how to listen to requests from agent processes.
+
+@item @code{client-communication-uri} (default: @code{"http://127.0.0.1:8746"})
+The URI describing how to listen to requests from clients.  The client
+API allows submitting builds and currently isn't authenticated, so take
+care when configuring this value.
+
+@item @code{allocation-strategy} (default: @code{#~basic-build-allocation-strategy})
+A G-expression for the allocation strategy to be used.  This is a
+procedure that takes the datastore as an argument and populates the
+allocation plan in the database.
+
+@item @code{hooks} (default: @var{'()})
+An association list of hooks.  These provide a way to execute arbitrary
+code upon certian events, like a build result being processed.
+
+@item @code{guile} (default: @code{guile-3.0-latest})
+The Guile package with which to run the Guix Build Coordinator.
+
+@end table
+@end deftp
+
 @subsubheading Guix Data Service
 The @uref{http://data.guix.gnu.org,Guix Data Service} processes, stores
 and provides data about GNU Guix.  This includes information about
diff --git a/gnu/services/guix.scm b/gnu/services/guix.scm
index 10a8581a62..de14fcadb2 100644
--- a/gnu/services/guix.scm
+++ b/gnu/services/guix.scm
@@ -17,20 +17,40 @@ 
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu services guix)
+  #:use-module (srfi srfi-1)
   #:use-module (ice-9 match)
   #:use-module (guix gexp)
   #:use-module (guix records)
+  #:use-module (guix packages)
   #:use-module ((gnu packages base)
                 #:select (glibc-utf8-locales))
   #:use-module (gnu packages admin)
+  #:use-module (gnu packages databases)
   #:use-module (gnu packages web)
+  #:use-module (gnu packages guile)
+  #:use-module (gnu packages guile-xyz)
+  #:use-module (gnu packages package-management)
   #:use-module (gnu services)
   #:use-module (gnu services base)
   #:use-module (gnu services admin)
   #:use-module (gnu services shepherd)
   #:use-module (gnu services getmail)
   #:use-module (gnu system shadow)
-  #:export (<guix-data-service-configuration>
+  #:export (guix-build-coordinator-configuration
+            guix-build-coordinator-configuration?
+            guix-build-coordinator-configuration-package
+            guix-build-coordinator-configuration-user
+            guix-build-coordinator-configuration-group
+            guix-build-coordinator-configuration-datastore-uri-string
+            guix-build-coordinator-configuration-agent-communication-uri-string
+            guix-build-coordinator-configuration-client-communication-uri-string
+            guix-build-coordinator-configuration-allocation-strategy
+            guix-build-coordinator-configuration-hooks
+            guix-build-coordinator-configuration-guile
+
+            guix-build-coordinator-service-type
+
+            <guix-data-service-configuration>
             guix-data-service-configuration
             guix-data-service-configuration?
             guix-data-service-package
@@ -45,11 +65,189 @@ 
 
 ;;;; Commentary:
 ;;;
-;;; This module implements a service that to run instances of the Guix Data
-;;; Service, which provides data about Guix over time.
+;;; Services specifically related to GNU Guix.
 ;;;
 ;;;; Code:
 
+(define-record-type* <guix-build-coordinator-configuration>
+  guix-build-coordinator-configuration make-guix-build-coordinator-configuration
+  guix-build-coordinator-configuration?
+  (package                         guix-build-coordinator-configuration-package
+                                   (default guix-build-coordinator))
+  (user                            guix-build-coordinator-configuration-user
+                                   (default "guix-build-coordinator"))
+  (group                           guix-build-coordinator-configuration-group
+                                   (default "guix-build-coordinator"))
+  (database-uri-string
+   guix-build-coordinator-configuration-datastore-uri-string
+   (default "sqlite:///var/lib/guix-build-coordinator/guix_build_coordinator.db"))
+  (agent-communication-uri-string
+   guix-build-coordinator-configuration-agent-communication-uri-string
+   (default "http://0.0.0.0:8745"))
+  (client-communication-uri-string
+   guix-build-coordinator-configuration-client-communication-uri-string
+   (default "http://127.0.0.1:8746"))
+  (allocation-strategy
+   guix-build-coordinator-configuration-allocation-strategy
+   (default #~basic-build-allocation-strategy))
+  (hooks                           guix-build-coordinator-configuration-hooks
+                                   (default '()))
+  (guile                           guix-build-coordinator-configuration-guile
+                                   (default guile-3.0-latest)))
+
+(define* (make-guix-build-coordinator-start-script database-uri-string
+                                                   allocation-strategy
+                                                   pid-file
+                                                   guix-build-coordinator-package
+                                                   #:key
+                                                   agent-communication-uri-string
+                                                   client-communication-uri-string
+                                                   (hooks '())
+                                                   (guile guile-3.0))
+  (program-file
+   "start-guix-build-coordinator"
+   (with-extensions (cons guix-build-coordinator-package
+                          ;; This is a poorly constructed Guile load path,
+                          ;; since it contains things that aren't Guile
+                          ;; libraries, but it means that the Guile libraries
+                          ;; needed for the Guix Build Coordinator don't need
+                          ;; to be individually specified here.
+                          (map second (package-inputs
+                                       guix-build-coordinator-package)))
+     #~(begin
+         (use-modules (srfi srfi-1)
+                      (ice-9 match)
+                      (web uri)
+                      (prometheus)
+                      (guix-build-coordinator hooks)
+                      (guix-build-coordinator datastore)
+                      (guix-build-coordinator build-allocator)
+                      (guix-build-coordinator coordinator))
+
+         ;; Otherwise sqitch can't use SQlite
+         (setenv "PERL5LIB"
+                 #$(file-append perl-dbd-sqlite "/lib/perl5/site_perl"))
+
+         (let* ((metrics-registry (make-metrics-registry
+                                   #:namespace
+                                   "guixbuildcoordinator_"))
+                (datastore (database-uri->datastore
+                            #$database-uri-string
+                            #:metrics-registry metrics-registry))
+                (hooks
+                 (list #$@(map (match-lambda
+                                 ((name . hook-gexp)
+                                  #~(cons name #$hook-gexp)))
+                               hooks)))
+                (hooks-with-defaults
+                 `(,@hooks
+                   ,@(remove (match-lambda
+                               ((name . _) (assq-ref hooks name)))
+                             %default-hooks)))
+                (build-coordinator (make-build-coordinator
+                                    #:datastore datastore
+                                    #:hooks hooks-with-defaults
+                                    #:metrics-registry metrics-registry
+                                    #:allocation-strategy #$allocation-strategy)))
+
+           (run-coordinator-service
+            build-coordinator
+            #:update-datastore? #t
+            #:pid-file #$pid-file
+            #:agent-communication-uri (string->uri
+                                       #$agent-communication-uri-string)
+            #:client-communication-uri (string->uri
+                                        #$client-communication-uri-string)))))
+   #:guile guile))
+
+(define (guix-build-coordinator-shepherd-services config)
+  (match-record config <guix-build-coordinator-configuration>
+    (package user group database-uri-string
+             agent-communication-uri-string
+             client-communication-uri-string
+             allocation-strategy
+             hooks
+             guile)
+    (list
+     (shepherd-service
+      (documentation "Guix Build Coordinator")
+      (provision '(guix-build-coordinator))
+      (requirement '(networking))
+      (start #~(make-forkexec-constructor
+                (list #$(make-guix-build-coordinator-start-script
+                         database-uri-string
+                         allocation-strategy
+                         "/var/run/guix-build-coordinator/pid"
+                         package
+                         #:agent-communication-uri-string
+                         agent-communication-uri-string
+                         #:client-communication-uri-string
+                         client-communication-uri-string
+                         #:hooks hooks
+                         #:guile guile))
+                #:user #$user
+                #:group #$group
+                #:pid-file "/var/run/guix-build-coordinator/pid"
+                ;; Allow time for migrations to run
+                #:pid-file-timeout 60
+                #:environment-variables
+                `(,(string-append
+                    "GUIX_LOCPATH=" #$glibc-utf8-locales "/lib/locale")
+                  "LC_ALL=en_US.utf8")
+                #:log-file "/var/log/guix-build-coordinator/coordinator.log"))
+      (stop #~(make-kill-destructor))))))
+
+(define (guix-build-coordinator-activation config)
+  #~(begin
+      (use-modules (guix build utils))
+
+      (define %user (getpw "guix-build-coordinator"))
+
+      (chmod "/var/lib/guix-build-coordinator" #o755)
+
+      (mkdir-p "/var/log/guix-build-coordinator")
+
+      ;; Allow writing the PID file
+      (mkdir-p "/var/run/guix-build-coordinator")
+      (chown "/var/run/guix-build-coordinator"
+             (passwd:uid %user)
+             (passwd:gid %user))))
+
+(define (guix-build-coordinator-account config)
+  (match-record config <guix-build-coordinator-configuration>
+    (user group)
+    (list (user-group
+           (name group)
+           (system? #t))
+          (user-account
+           (name user)
+           (group group)
+           (system? #t)
+           (comment "Guix Build Coordinator user")
+           (home-directory "/var/lib/guix-build-coordinator")
+           (shell (file-append shadow "/sbin/nologin"))))))
+
+(define guix-build-coordinator-service-type
+  (service-type
+   (name 'guix-build-coordinator)
+   (extensions
+    (list
+     (service-extension shepherd-root-service-type
+                        guix-build-coordinator-shepherd-services)
+     (service-extension activation-service-type
+                        guix-build-coordinator-activation)
+     (service-extension account-service-type
+                        guix-build-coordinator-account)))
+   (default-value
+     (guix-build-coordinator-configuration))
+   (description
+    "Run an instance of the Guix Build Coordinator.")))
+
+
+;;;
+;;; Guix Data Service
+;;;
+
 (define-record-type* <guix-data-service-configuration>
   guix-data-service-configuration make-guix-data-service-configuration
   guix-data-service-configuration?
diff --git a/gnu/tests/guix.scm b/gnu/tests/guix.scm
index 6139e31cf0..20b67d55d3 100644
--- a/gnu/tests/guix.scm
+++ b/gnu/tests/guix.scm
@@ -35,7 +35,80 @@ 
   #:use-module (guix store)
   #:use-module (guix utils)
   #:use-module (ice-9 match)
-  #:export (%test-guix-data-service))
+  #:export (%test-guix-build-coordinator
+            %test-guix-data-service))
+
+;;;
+;;; Guix Build Coordinator
+;;;
+
+(define %guix-build-coordinator-os
+  (simple-operating-system
+   (service dhcp-client-service-type)
+   (service guix-build-coordinator-service-type)))
+
+(define (run-guix-build-coordinator-test)
+  (define os
+    (marionette-operating-system
+     %guix-build-coordinator-os
+     #:imported-modules '((gnu services herd)
+                          (guix combinators))))
+
+  (define forwarded-port 8745)
+
+  (define vm
+    (virtual-machine
+     (operating-system os)
+     (memory-size 1024)
+     (port-forwardings `((,forwarded-port . 8745)))))
+
+  (define test
+    (with-imported-modules '((gnu build marionette))
+      #~(begin
+          (use-modules (srfi srfi-11) (srfi srfi-64)
+                       (gnu build marionette)
+                       (web uri)
+                       (web client)
+                       (web response))
+
+          (define marionette
+            (make-marionette (list #$vm)))
+
+          (mkdir #$output)
+          (chdir #$output)
+
+          (test-begin "guix-build-coordinator")
+
+          (test-assert "service running"
+            (marionette-eval
+             '(begin
+                (use-modules (gnu services herd))
+                (match (start-service 'guix-build-coordinator)
+                  (#f #f)
+                  (('service response-parts ...)
+                   (match (assq-ref response-parts 'running)
+                     ((pid) (number? pid))))))
+             marionette))
+
+          (test-equal "http-get"
+            200
+            (let-values
+                (((response text)
+                  (http-get #$(simple-format
+                               #f "http://localhost:~A/metrics" forwarded-port)
+                            #:decode-body? #t)))
+              (response-code response)))
+
+          (test-end)
+          (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
+
+  (gexp->derivation "guix-build-coordinator-test" test))
+
+(define %test-guix-build-coordinator
+  (system-test
+   (name "guix-build-coordinator")
+   (description "Connect to a running Guix Build Coordinator.")
+   (value (run-guix-build-coordinator-test))))
 
 
 ;;;