api-dist.texi 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. @c -*-texinfo-*-
  2. @c This file is part of Guile-SSH Reference Manual.
  3. @c Copyright (C) 2015, 2016 Artyom V. Poptsov
  4. @c See the file guile-ssh.texi for copying conditions.
  5. @node Distributed Forms
  6. @section Distributed Forms
  7. @cindex secure distributed computing
  8. The @code{(ssh dist)} module provides the spirit of distributed computing for
  9. Guile.
  10. To make use of the procedures listed in this section you will need an SSH
  11. daemon and a GNU Guile REPL server both running on the remote host.
  12. Also note that currently there may be cases in which distributed procedures
  13. may fail to (de)serialise data; namely @code{make-vector} is one of such
  14. procedures which output may be troublesome for @code{with-ssh}. To overcome
  15. this specific case one could pass the @code{fill} argument to
  16. @code{make-vector} to fill the newly created vector with the specified filling
  17. instead of @code{#<unspecified>}.
  18. Node management procedures:
  19. @deffn {Scheme Procedure} make-node session [repl-port=37146] [#:start-repl-server?=#t] [#:stop-repl-server?=#f]
  20. Make a new node that uses an SSH @var{session} to connect to a @var{repl-port}
  21. number on the remote side. Return a new node.
  22. If @var{start-repl-server?} is set to @code{#t} (which is by default) then
  23. start a REPL server on a remote host automatically in case when it is not
  24. started yet.
  25. If @var{stop-repl-server?} is set to #t then a REPL server will be stopped as
  26. soon as an evaluation is done. Alternatively you could use
  27. @code{node-stop-server} procedure from @code{(ssh dist node)} to stop the
  28. server when it is not needed anymore.
  29. Note that when either @var{start-repl-server?} or @var{stop-repl-server?} are
  30. specified, Guile-SSH tries to use @command{pgrep}/@command{pkill} from
  31. @url{https://gitlab.com/procps-ng/procps, procps} package first to start/stop
  32. a remote Guile process, but if the package is missing then the Guile-SSH falls
  33. back to its own implementation of the commands (for more details see
  34. @pxref{Shell, Guile-SSH shell API})
  35. @end deffn
  36. @deffn {Scheme Procedure} node? x
  37. Return @code{#t} if @var{x} is a node object, @code{#f} otherwise.
  38. @end deffn
  39. @deffn {Scheme Procedure} node-session node
  40. Get underlying SSH session from @var{node}.
  41. @end deffn
  42. @deffn {Scheme Procedure} node-repl-port node
  43. Get REPL port number from a @var{node}.
  44. @end deffn
  45. @deffn {Scheme Procedure} node-loadavg node
  46. Get average load of a @var{node}. Return multiple values. The 1st value is
  47. an alist of five elements as described in proc(5) man page. The rest of
  48. values are as described in documentation for @code{node-eval} procedure.
  49. For example:
  50. @lisp
  51. (use-modules (ssh auth)
  52. (ssh session)
  53. (ssh dist node))
  54. (let ((s (make-session #:host "example.org")))
  55. (connect! s)
  56. (userauth-agent! s)
  57. (let ((n (make-node s)))
  58. (node-loadavg n)))
  59. @result{} ((one . 0.15) (five . 0.14) (fifteen . 0.16) (scheduling-entities 1 189) (last-pid . 15629))
  60. @result{} 1
  61. @result{} "(guile-user)"
  62. @result{} "scheme"
  63. @end lisp
  64. @end deffn
  65. Interaction with remote REPLs:
  66. @deffn {Scheme Procedure} distribute nodes expr ...
  67. Evaluate each @var{expr} in parallel, using distributed computation. Split
  68. the job to nearly equal parts and hand out each of resulting sub-jobs to
  69. @var{nodes} list. Return the results of N expressions as a set of N multiple
  70. values (@pxref{Multiple Values,,, guile, The GNU Guile Reference Manual}).
  71. @end deffn
  72. @deffn {Scheme Procedure} dist-map nodes proc lst
  73. Do list mapping using distributed computation. Split the work into nearly
  74. equal parts and hand out the resulting jobs to @var{nodes} list. Return the
  75. result of computation.
  76. If for some reason a job could not be executed on a node (for example, if
  77. connection to a remote REPL fails), @code{dist-map} transfers the job to
  78. another node from the @var{nodes} list. When job execution failed on all
  79. nodes, an error is reported.
  80. In a case when an error that occured during job execution is considered
  81. non-recoverable (eg. when evaluation of @var{proc} on a node failed due to an
  82. unbound variable) then execution of a job stops immediately.
  83. @end deffn
  84. @deffn {Scheme Procedure} with-ssh node exp ...
  85. Evaluate expressions on a remote REPL using a @var{node}, return four values:
  86. an evaluation result, a number of the evaluation, a module name and a language
  87. name. Throw @code{node-error} or @code{node-repl-error} on an error.
  88. Example:
  89. @lisp
  90. (use-modules (ssh session)
  91. (ssh auth)
  92. (ssh dist))
  93. (let ((session (make-session #:user "alice" #:host "www.example.org")))
  94. (connect! session)
  95. (userauth-agent! session)
  96. (display (with-ssh (make-node session)
  97. (gethostname)))
  98. (newline))
  99. @end lisp
  100. If an expression is evaluated to multiple values then the 1st value returned
  101. by @code{with-ssh} will be a vector of the evaluated values and the 2nd value
  102. will be a vector of evaluation numbers. In this case the 2nd value can be
  103. used to check whether @code{with-ssh} body evaluated to multiple values or
  104. not. For example:
  105. @lisp
  106. (use-modules (ssh session)
  107. (ssh auth)
  108. (ssh dist))
  109. (let ((session (make-session #:user "alice" #:host "www.example.org")))
  110. (connect! session)
  111. (userauth-agent! session)
  112. (with-ssh (make-node session)
  113. (values 1 2)))
  114. => #(1 2)
  115. => #(39 40)
  116. => "(guile-user)"
  117. => "scheme"
  118. @end lisp
  119. @end deffn
  120. @deffn {Scheme Procedure} rrepl node
  121. Start an interactive remote REPL (RREPL) session using @var{node}.
  122. @end deffn
  123. @subsection Low-level API
  124. @subsubsection Nodes
  125. @tindex node
  126. The module @code{(ssh dist node)} provides low-level API for node management.
  127. Here's the description of the format of node type printed representation:
  128. @example
  129. #<node avp@@127.0.0.1:22/37146 a0dbdc0>
  130. A A A A A
  131. | | | | |
  132. ,---' | ,-' '---. '-----------.
  133. | | | | |
  134. user host port REPL port object address
  135. @end example
  136. There are two types of node errors: recoverable and non-recoverable. The
  137. first group is represented by @code{node-error} exceptions. If an exception
  138. of this kind is occured then there is a chance that a job can be executed on
  139. another node. That's because such an exception occures in cases when a node
  140. is unreachable, for example. The second group is represented by
  141. @code{node-repl-error} exceptions. Such exceptions mean that an error is
  142. occured during execution of a job on a node's REPL -- eg. due to the malformed
  143. job. Those errors are non-recoverable because if the job is broken it will
  144. likely fail on another nodes as well.
  145. In addition to @code{make-node}, @code{node?}, @code{node-session} and
  146. @code{node-repl-port} the module provides:
  147. @deffn {Scheme Procedure} node-eval node quoted-exp
  148. Evaluate a @var{quoted-exp} on a @var{node} and return four values: an
  149. evaluation result, a number of the evaluation, a module name and a language
  150. name. Throw @code{node-repl-error} if a non-recoverable error occured, or
  151. @code{node-error} if the evaluation potentially could be succesfully evaluated
  152. on another node.
  153. @strong{Note} that @url{https://gitlab.com/procps-ng/procps, procps} version
  154. 3.3.12 or later is needed on the server side in case of either
  155. @code{start-repl-server?} or @code{stop-repl-server?} was set to @code{#t} for
  156. a @var{NODE} (see the documentation for @code{make-node}.)
  157. @end deffn
  158. @deffn {Scheme Procedure} node-open-rrepl node
  159. Open a remote REPL (RREPL). Return a new RREPL channel.
  160. @end deffn
  161. @deffn {Scheme Procedure} node-run-server node
  162. Run a REPL server on a @var{node}.
  163. @end deffn
  164. @deffn {Scheme Procedure} node-stop-server node
  165. Stop a RREPL server on a @var{node}.
  166. @end deffn
  167. @deffn {Scheme Procedure} node-guile-version node
  168. Get Guile version installed on a @var{node}, return the version string.
  169. Return @code{#f} if Guile is not installed.
  170. @end deffn
  171. @deffn {Scheme Procedure} node-server-running? node
  172. Check if a REPL server is running on a @var{node}, return @code{#t} if it is
  173. running and listens on an expected port, return @code{#f} otherwise.
  174. @end deffn
  175. @deffn {Scheme Procedure} rrepl-eval rrepl-channel expr
  176. Evaluate expression @var{expr} using @var{rrepl-channel}, return four values:
  177. an evaluation result, a number of the evaluation, a module name and a language
  178. name. Throw @code{node-repl-error} on an error.
  179. @end deffn
  180. @deffn {Scheme Procedure} rrepl-skip-to-prompt rrepl-channel
  181. Read from @var{rrepl-channel} until REPL is observed. Throw @code{node-error}
  182. on an error.
  183. @end deffn
  184. @subsubsection Jobs
  185. @tindex job
  186. The module @code{(ssh dist job)} provides low-level API for job management.
  187. Here's the description of the format of node type printed representation:
  188. @example
  189. #<job map #<node avp@@127.0.0.1:22/37147 a0dbdc0> a1345a0>
  190. A A A
  191. | | |
  192. | '----------. |
  193. | | |
  194. job type node (see above) job object address
  195. @end example
  196. @deffn {Scheme Procedure} split lst count
  197. Split a list @var{lst} into @var{count} chunks. Return a list of chunks.
  198. Example:
  199. @lisp
  200. (split '(a b c d) 2)
  201. @result{} '((a b) (c d))
  202. @end lisp
  203. @end deffn
  204. @deffn {Scheme Procedure} make-job type node data proc
  205. Make a new job of @var{type} using @var{node}.
  206. @end deffn
  207. @deffn {Scheme Procedure} job? x
  208. Return @code{#t} if @var{x} is a job object, @code{#f} otherwise.
  209. @end deffn
  210. @deffn {Scheme Procedure} job-type job
  211. Get type of a @var{job}.
  212. @end deffn
  213. @deffn {Scheme Procedure} job-node job
  214. Get a @var{job} node.
  215. @end deffn
  216. @deffn {Scheme Procedure} set-job-node job node
  217. Transfer @var{job} to a new @var{node}. Return a new job object.
  218. @end deffn
  219. @deffn {Scheme Procedure} job-data job
  220. Get a @var{job} data.
  221. @end deffn
  222. @deffn {Scheme Procedure} job-proc job
  223. Get a @var{job} procedure.
  224. @end deffn
  225. @deffn {Scheme Procedure} assign-eval nodes expressions
  226. Split an @var{expressions} list to nearly equal parts according to the length
  227. of a @var{nodes} list and assign each evaluation job to a node. Return a list
  228. of assigned jobs.
  229. @end deffn
  230. @deffn {Scheme Procedure} assign-map nodes lst proc
  231. Split the work to nearly equal parts according to length of @var{nodes} list
  232. and assign each part of work to a node. Return list of assigned jobs.
  233. @end deffn
  234. @deffn {Scheme Procedure} hand-out-job job
  235. Hand out @var{job} to the assigned node and return the result of computation.
  236. @end deffn
  237. @deffn {Scheme Procedure} job->sexp job
  238. Convert a @var{job} to an equivalent symbolic expression.
  239. @end deffn
  240. @c Local Variables:
  241. @c TeX-master: "guile-ssh.texi"
  242. @c End: