File: api-dist.texi

package info (click to toggle)
guile-ssh 0.18.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,996 kB
  • sloc: ansic: 4,821; lisp: 4,171; makefile: 310; sh: 259
file content (295 lines) | stat: -rw-r--r-- 10,040 bytes parent folder | download
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
@c -*-texinfo-*-
@c This file is part of Guile-SSH Reference Manual.
@c Copyright (C) 2015-2024 Artyom V. Poptsov
@c See the file guile-ssh.texi for copying conditions.

@node Distributed Forms
@section Distributed Forms

@cindex secure distributed computing

The @code{(ssh dist)} module provides the spirit of distributed computing for
Guile.

To make use of the procedures listed in this section you will need an SSH
daemon and a GNU Guile @abbr{REPL, Read-Eval-Print Loop} server both running
on the remote host.

Also note that currently there may be cases in which distributed procedures
may fail to (de)serialise data; namely @code{make-vector} is one of such
procedures which output may be troublesome for @code{with-ssh}.  To overcome
this specific case one could pass the @code{fill} argument to
@code{make-vector} to fill the newly created vector with the specified filling
instead of @code{#<unspecified>}.

Node management procedures:

@deffn {Scheme Procedure} make-node session
Make a new node that uses an SSH @var{session} to connect to a freshly started
Guile REPL on the remote side.  Return the new @code{<node>} instance.
@end deffn

@deffn {Scheme Procedure} node? x
Return @code{#t} if @var{x} is a node object, @code{#f} otherwise.
@end deffn

@deffn {Scheme Procedure} node-session node
Get underlying SSH session from @var{node}.
@end deffn

@deffn {Scheme Procedure} node-repl-port node
Get REPL port number from a @var{node}.
@end deffn

@deffn {Scheme Procedure} node-loadavg node
Get average load of a @var{node}.  Return multiple values.  The 1st value is
an alist of five elements as described in proc(5) man page.  The rest of
values are as described in documentation for @code{node-eval} procedure.

For example:

@lisp
(use-modules (ssh auth)
             (ssh session)
             (ssh dist node))

(let ((s (make-session #:host "example.org")))
  (connect! s)
  (userauth-agent! s)
  (let ((n (make-node s)))
    (node-loadavg n)))
@result{} ((one . 0.15) (five . 0.14) (fifteen . 0.16) (scheduling-entities 1 189) (last-pid . 15629))
@result{} 1
@result{} "(guile-user)"
@result{} "scheme"
@end lisp

@end deffn

Interaction with remote REPLs:

@deffn {Scheme Procedure} distribute nodes expr ...
Evaluate each @var{expr} in parallel, using distributed computation.  Split
the job to nearly equal parts and hand out each of resulting sub-jobs to
@var{nodes} list.  Return the results of N expressions as a set of N multiple
values (@pxref{Multiple Values,,, guile, The GNU Guile Reference Manual}).
@end deffn

@deffn {Scheme Procedure} dist-map nodes proc lst
Do list mapping using distributed computation.  Split the work into nearly
equal parts and hand out the resulting jobs to @var{nodes} list.  Return the
result of computation.

If for some reason a job could not be executed on a node (for example, if
connection to a remote REPL fails), @code{dist-map} transfers the job to
another node from the @var{nodes} list.  When job execution failed on all
nodes, an error is reported.

In a case when an error that occurred during job execution is considered
non-recoverable (eg. when evaluation of @var{proc} on a node failed due to an
unbound variable) then execution of a job stops immediately.
@end deffn

@deffn {Scheme Procedure} with-ssh node exp ...
Evaluate expressions on a remote REPL using a @var{node}, return four values:
an evaluation result, a number of the evaluation, a module name and a language
name.  Throw @code{node-error} or @code{node-repl-error} on an error.

Example:
@lisp
(use-modules (ssh session)
             (ssh auth)
             (ssh dist))

(let ((session (make-session #:user "alice" #:host "www.example.org")))
  (connect! session)
  (userauth-agent! session)
  (display (with-ssh (make-node session)
             (gethostname)))
  (newline))
@end lisp

If an expression is evaluated to multiple values then the 1st value returned
by @code{with-ssh} will be a vector of the evaluated values and the 2nd value
will be a vector of evaluation numbers.  In this case the 2nd value can be
used to check whether @code{with-ssh} body evaluated to multiple values or
not.  For example:

@lisp
(use-modules (ssh session)
             (ssh auth)
             (ssh dist))

(let ((session (make-session #:user "alice" #:host "www.example.org")))
  (connect! session)
  (userauth-agent! session)
  (with-ssh (make-node session)
    (values 1 2)))
=> #(1 2)
=> #(39 40)
=> "(guile-user)"
=> "scheme"
@end lisp

@end deffn

@deffn {Scheme Procedure} rrepl node
Start an interactive remote REPL (RREPL) session using @var{node}.
@end deffn

@c -----------------------------------------------------------------------------
@subsection Low-level API

@subsubsection Nodes
@tindex node

The module @code{(ssh dist node)} provides low-level API for node management.
Here's the description of the format of node type printed representation:

@example
#<node avp@@127.0.0.1:22/37146 a0dbdc0>
       A   A         A  A     A
       |   |         |  |     |
   ,---'   |       ,-'  '---. '-----------.
   |       |       |        |             |
 user     host   port   REPL port    object address
@end example

There are two types of node errors: recoverable and non-recoverable.  The
first group is represented by @code{node-error} exceptions.  If an exception
of this kind is occurred then there is a chance that a job can be executed on
another node.  That's because such an exception occures in cases when a node
is unreachable, for example.  The second group is represented by
@code{node-repl-error} exceptions.  Such exceptions mean that an error is
occurred during execution of a job on a node's REPL -- eg. due to the malformed
job.  Those errors are non-recoverable because if the job is broken it will
likely fail on another nodes as well.

In addition to @code{make-node}, @code{node?}, @code{node-session} and
@code{node-repl-port} the module provides:

@deffn {Scheme Procedure} node-eval node quoted-exp
Evaluate a @var{quoted-exp} on a @var{node} and return four values: an
evaluation result, a number of the evaluation, a module name and a language
name.  Throw @code{node-repl-error} if a non-recoverable error occurred, or
@code{node-error} if the evaluation potentially could be succesfully evaluated
on another node.

@strong{Note} that @url{https://gitlab.com/procps-ng/procps, procps} version
3.3.12 or later is needed on the server side in case of either
@code{start-repl-server?} or @code{stop-repl-server?} was set to @code{#t} for
a @var{NODE} (see the documentation for @code{make-node}.)

@end deffn

@deffn {Scheme Procedure} node-open-rrepl node
Open a remote REPL (RREPL).  Return a new RREPL channel.
@end deffn

@deffn {Scheme Procedure} node-run-server node
Run a REPL server on a @var{node}. Throw @code{node-error} with the current
node and the Guile return code from a server on an error.
@end deffn

@deffn {Scheme Procedure} node-stop-server node
Stop a RREPL server on a @var{node}.
@end deffn

@deffn {Scheme Procedure} node-guile-version node
Get Guile version installed on a @var{node}, return the version string.
Return @code{#f} if Guile is not installed.
@end deffn

@deffn {Scheme Procedure} node-server-running? node
Check if a REPL server is running on a @var{node}, return @code{#t} if it is
running and listens on an expected port, return @code{#f} otherwise.
@end deffn

@deffn {Scheme Procedure} rrepl-eval rrepl-channel expr
Evaluate expression @var{expr} using @var{rrepl-channel}, return four values:
an evaluation result, a number of the evaluation, a module name and a language
name.  Throw @code{node-repl-error} on an error.
@end deffn

@deffn {Scheme Procedure} rrepl-skip-to-prompt rrepl-channel
Read from @var{rrepl-channel} until REPL is observed.  Throw @code{node-error}
on an error.
@end deffn

@c -----------------------------------------------------------------------------
@subsubsection Jobs
@tindex job

The module @code{(ssh dist job)} provides low-level API for job management.

Here's the description of the format of node type printed representation:

@example
#<job map #<node avp@@127.0.0.1:22/37147 a0dbdc0> a1345a0>
      A   A                                      A
      |   |                                      |
      |   '----------.                           |
      |              |                           |
   job type   node (see above)           job object address
@end example

@deffn {Scheme Procedure} split lst count
Split a list @var{lst} into @var{count} chunks.  Return a list of chunks.

Example:
@lisp
(split '(a b c d) 2)
@result{} '((a b) (c d))
@end lisp
@end deffn

@deffn {Scheme Procedure} make-job type node data proc
Make a new job of @var{type} using @var{node}.
@end deffn

@deffn {Scheme Procedure} job? x
Return @code{#t} if @var{x} is a job object, @code{#f} otherwise.
@end deffn

@deffn {Scheme Procedure} job-type job
Get type of a @var{job}.
@end deffn

@deffn {Scheme Procedure} job-node job
Get a @var{job} node.
@end deffn

@deffn {Scheme Procedure} set-job-node job node
Transfer @var{job} to a new @var{node}.  Return a new job object.
@end deffn

@deffn {Scheme Procedure} job-data job
Get a @var{job} data.
@end deffn

@deffn {Scheme Procedure} job-proc job
Get a @var{job} procedure.
@end deffn

@deffn {Scheme Procedure} assign-eval nodes expressions
Split an @var{expressions} list to nearly equal parts according to the length
of a @var{nodes} list and assign each evaluation job to a node.  Return a list
of assigned jobs.
@end deffn

@deffn {Scheme Procedure} assign-map nodes lst proc
Split the work to nearly equal parts according to length of @var{nodes} list
and assign each part of work to a node.  Return list of assigned jobs.
@end deffn

@deffn {Scheme Procedure} hand-out-job job
Hand out @var{job} to the assigned node and return the result of computation.
@end deffn

@deffn {Scheme Procedure} job->sexp job
Convert a @var{job} to an equivalent symbolic expression.
@end deffn

@c Local Variables:
@c TeX-master: "guile-ssh.texi"
@c End: