Skip to content

Commit 55b9775

Browse files
author
Dan
committed
Updated readme and docstrings
1 parent 8b86428 commit 55b9775

File tree

3 files changed

+65
-36
lines changed

3 files changed

+65
-36
lines changed

README.rst

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Installation
2929

3030
pip install parallel-ssh
3131

32-
As of version ``0.93.0`` pip version >= ``6.0.0`` is required for Python 2.6 compatibility with latest versions of gevent which have dropped 2.6 support. This limitation will be removed post ``1.0.0`` releases which will deprecate ``2.6`` support.
32+
As of version ``0.93.0`` ``pip`` version >= ``6.0.0`` is required for Python 2.6 compatibility with latest versions of gevent which have dropped 2.6 support. This limitation will be removed post ``1.0.0`` releases which will deprecate ``2.6`` support.
3333

3434
To upgrade ``pip`` run the following - use of ``virtualenv`` is recommended so as not to override system provided packages::
3535

@@ -47,31 +47,27 @@ Run ``ls`` on two remote hosts in parallel with ``sudo``.
4747
::
4848

4949
from pprint import pprint
50-
from pssh import ParallelSSHClient
50+
from pssh.pssh_client import ParallelSSHClient
5151

5252
hosts = ['myhost1', 'myhost2']
5353
client = ParallelSSHClient(hosts)
5454
output = client.run_command('ls -ltrh /tmp/', sudo=True)
5555
pprint(output)
56-
{'myhost1':
56+
{'myhost1':
5757
host=myhost1
5858
cmd=<Greenlet>
5959
channel=<channel>
6060
stdout=<generator>
6161
stderr=<generator>
6262
stdin=<channel>
6363
exception=None
64-
'myhost2':
65-
host=myhost2
66-
cmd=<Greenlet>
67-
channel=<channel>
68-
stdout=<generator>
69-
stderr=<generator>
70-
stdin=<channel>
71-
exception=None
64+
'myhost2':
65+
<..>
7266
}
7367

74-
Stdout and stderr buffers are available in output. Iterating on them can be used to get output as it becomes available. Iteration ends *only when command has finished*, though it may be interrupted and resumed at any point.
68+
Standard output buffers are available in output object. Iterating on them can be used to get output as it becomes available. Iteration ends *only when command has finished*, though it may be interrupted and resumed at any point.
69+
70+
`Host output <http://parallel-ssh.readthedocs.io/en/latest/output.html>`_ attributes are available in per-host output dictionary, for example ``output['myhost1'].stdout``.
7571

7672
::
7773

@@ -83,7 +79,7 @@ Stdout and stderr buffers are available in output. Iterating on them can be used
8379
Host myhost2 - output: drwxr-xr-x 6 xxx xxx 4.0K Jan 1 00:00 xxx
8480
Host myhost2 - output: <..>
8581

86-
Exit codes become available once stdout/stderr is iterated on or ``client.join(output)`` is called.
82+
Exit codes become available once output is iterated on to completion *or* ``client.join(output)`` is called.
8783

8884
::
8985

@@ -96,13 +92,17 @@ The client's ``join`` function can be used to block and wait for all parallel co
9692

9793
client.join(output)
9894

99-
Similarly, exit codes are available after ``client.join`` is called::
95+
Similarly, output and exit codes are available after ``client.join`` is called::
10096

10197
output = client.run_command('exit 0')
10298
# Block and gather exit codes. Output is updated in-place
10399
client.join(output)
104-
pprint(output[client.hosts[0]].exit_code)
100+
pprint(output.values()[0].exit_code)
105101
0
102+
# Output is available
103+
for line in output.values()[0].stdout:
104+
pprint(line)
105+
<..stdout..>
106106

107107
.. note::
108108

@@ -171,6 +171,8 @@ There is similar capability to copy remote files to local ones suffixed with the
171171

172172
Directory recursion is supported in both cases via the ``recurse`` parameter - defaults to off.
173173

174+
See `copy_file <http://parallel-ssh.readthedocs.io/en/latest/pssh_client.html#pssh.pssh_client.ParallelSSHClient.copy_file>`_ and `copy_remote_file <http://parallel-ssh.readthedocs.io/en/latest/pssh_client.html#pssh.pssh_client.ParallelSSHClient.copy_remote_file>`_ documentation for more examples.
175+
174176
**************************
175177
Frequently asked questions
176178
**************************
@@ -195,56 +197,60 @@ Frequently asked questions
195197

196198
Furthermore, Fabric's use as a library is non-standard and in `many <https://github.com/fabric/fabric/issues/521>`_ `cases <https://github.com/fabric/fabric/pull/674>`_ `just <https://github.com/fabric/fabric/pull/1215>`_ `plain <https://github.com/fabric/fabric/issues/762>`_ `broken <https://github.com/fabric/fabric/issues/1068>`_ and currently stands at over 7,000 lines of code most of which is lacking code testing.
197199

198-
In addition, Fabric's parallel command implementation uses a combination of both threads and processes with extremely high CPU usage and system load while running with as little as tens of hosts.
200+
In addition, Fabric's parallel command implementation uses a combination of both threads and processes with extremely high CPU usage and system load while running with as little as hosts in the single digits.
199201

200202
:Q:
201-
Is Windows supported?
203+
Is Windows supported?
202204

203205
:A:
204-
The library installs and works on Windows though not formally supported as unit tests are currently Posix system based.
206+
The library installs and works on Windows though not formally supported as unit tests are currently Posix system based.
205207

206-
Pip versions >= 8.0 are required for binary package installation of ``gevent`` on Windows, a dependency of ``ParallelSSH``.
208+
Pip versions >= 8.0 are required for binary package installation of ``gevent`` on Windows, a dependency of ``ParallelSSH``.
207209

208-
Though ``ParallelSSH`` is pure python code and will run on any platform that has a working Python interpreter, its ``gevent`` dependency contains native code which either needs a binary package to be provided for the platform or to be built from source. Binary packages for ``gevent`` are provided for OSX, Linux and Windows platforms as of this time of writing.
210+
Though ``ParallelSSH`` is pure python code and will run on any platform that has a working Python interpreter, its ``gevent`` dependency and certain dependencies of ``paramiko`` contain native code which either needs a binary package to be provided for the platform or to be built from source. Binary packages for ``gevent`` are provided for OSX, Linux and Windows platforms as of this time of writing.
209211

210212
:Q:
211-
Are SSH agents used?
213+
Are SSH agents used?
212214

213215
:A:
214-
All available keys in a system configured SSH agent in addition to SSH keys in the user's home directory, `~/.ssh/id_dsa`, `~/.ssh/id_rsa` et al are automatically used by ParallelSSH.
216+
All available keys in a system configured SSH agent in addition to SSH keys in the user's home directory, `~/.ssh/id_dsa`, `~/.ssh/id_rsa` et al are automatically used by ParallelSSH.
215217

216-
Use of SSH agent can be disabled by creating a client as ``ParallelSSHClient(allow_agent=False)``. `See documentation <http://parallel-ssh.readthedocs.org/en/latest/>`_ for more information.
218+
Use of SSH agent can be disabled by creating a client as ``ParallelSSHClient(allow_agent=False)``. `See documentation <http://parallel-ssh.readthedocs.org/en/latest/>`_ for more information.
217219

218220
:Q:
219-
Can ParallelSSH forward my SSH agent?
221+
Can ParallelSSH forward my SSH agent?
220222

221223
:A:
222-
SSH agent forwarding, what ``ssh -A`` does on the command line, is supported and enabled by default. Creating an object as ``ParallelSSHClient(forward_ssh_agent=False)`` will disable this behaviour.
224+
SSH agent forwarding, what ``ssh -A`` does on the command line, is supported and enabled by default. Creating an object as ``ParallelSSHClient(forward_ssh_agent=False)`` will disable this behaviour.
223225

224226
:Q:
225-
Is tunneling/proxying supported?
227+
Is tunneling/proxying supported?
226228

227229
:A:
228-
Yes, `ParallelSSH` natively supports tunelling - also known as proxying - through an intermediate SSH server. Connecting to a remote host is accomplished via an SSH tunnel using the SSH's protocol direct TCP tunneling feature, using local port forwarding. This is done natively in python and tunnel connections are asynchronous like all other connections in the `ParallelSSH` library. For example, client -> proxy SSH server -> remote SSH destination.
230+
Yes, `ParallelSSH` natively supports tunelling - also known as proxying - through an intermediate SSH server. Connecting to a remote host is accomplished via an SSH tunnel using the SSH's protocol direct TCP tunneling feature, using local port forwarding. This is done natively in python and tunnel connections are asynchronous like all other connections in the `ParallelSSH` library. For example, client -> proxy SSH server -> remote SSH destination.
229231

230-
Use the ``proxy_host`` and ``proxy_port`` parameters to configure your proxy::
232+
Use the ``proxy_host`` and ``proxy_port`` parameters to configure your proxy::
231233

232-
client = ParallelSSHClient(hosts, proxy_host='my_ssh_proxy_host')
234+
client = ParallelSSHClient(hosts, proxy_host='my_ssh_proxy_host')
233235

234-
Note that while connections from the ParallelSSH `client` to the tunnel host are asynchronous, connections from the tunnel host to the remote destination(s) may not be, depending on the SSH server implementation. If the SSH server uses threading to implement its tunelling and that server is used to tunnel to a large number of remote destinations system load on the tunnel server will increase linearly with number of threads used.
236+
Note that while connections from the ParallelSSH `client` to the tunnel host are asynchronous, connections from the tunnel host to the remote destination(s) may not be, depending on the SSH server implementation. If the SSH server uses threading to implement its tunelling and that server is used to tunnel to a large number of remote destinations system load on the tunnel server will increase linearly with number of threads used.
235237

236238
:Q:
237-
Is there a way to programmatically provide an SSH key?
239+
Is there a way to programmatically provide an SSH key?
238240

239241
:A:
240-
Yes, use the ``pkey`` parameter of the `ParallelSSHClient class <http://parallel-ssh.readthedocs.org/en/latest/#pssh.ParallelSSHClient>`_. There is a ``load_private_key`` helper function in ``pssh.utils`` that can be used to load any supported key type. For example::
242+
Yes, use the ``pkey`` parameter of the `ParallelSSHClient class`_. There is also a ``load_private_key`` helper function in ``pssh.utils`` that can be used to load any supported key type. See `ParallelSSHClient class`_ documentation for examples.
243+
244+
:Q:
245+
Is there a way to programmatically provide an SSH agent?
241246

242-
from pssh import ParallelSSHClient, utils
243-
client_key = utils.load_private_key('user.key')
244-
client = ParallelSSHClient(['myhost1', 'myhost2'], pkey=client_key)
247+
:A:
248+
Yes, with the ``SSHAgent`` class that can be provided via the ``agent`` class parameter of `ParallelSSHClient class`_. Supplying an agent object in this way overrides use of the system's SSH agent, if any. See `SSHAgent documentation <http://parallel-ssh.readthedocs.io/en/latest/agent.html>`_ for an example.
245249

246250
:Q:
247251
Is there a user's group for feedback and discussion about ParallelSSH?
248252

249253
:A:
250254
There is a public `ParallelSSH Google group <https://groups.google.com/forum/#!forum/parallelssh>`_ setup for this purpose - both posting and viewing are open to the public.
255+
256+
.. _`ParallelSSHClient class`: http://parallel-ssh.readthedocs.io/en/latest/pssh_client.html#module-pssh.pssh_client

pssh/output.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,24 @@ class HostOutput(dict):
3030

3131
def __init__(self, host, cmd, channel, stdout, stderr, stdin,
3232
exit_code=None, exception=None):
33+
"""
34+
:param host: Host name output is for
35+
:type host: str
36+
:param cmd: Command execution object
37+
:type cmd: :py:class:`gevent.Greenlet`
38+
:param channel: SSH channel used for command execution
39+
:type channel: :py:class:`paramiko.channel.Channel`
40+
:param stdout: Standard output buffer
41+
:type stdout: generator
42+
:param stderr: Standard error buffer
43+
:type stderr: generator
44+
:param stdin: Standard input buffer
45+
:type stdin: :py:func:`file`-like object
46+
:param exit_code: Exit code of command
47+
:type exit_code: int or None
48+
:param exception: Exception from host if any
49+
:type exception: Exception or None
50+
"""
3351
dict.__init__(self, (('host', host), ('cmd', cmd), ('channel', channel),
3452
('stdout', stdout), ('stderr', stderr),
3553
('stdin', stdin), ('exit_code', exit_code),

pssh/pssh_client.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ def run_command(self, command, sudo=False, user=None, stop_on_errors=True,
463463
from __future__ import print_function
464464
465465
for host in output:
466-
stdout = list(output[host]stdout)
466+
stdout = list(output[host].stdout)
467467
print("Complete stdout for host %s is %s" % (host, stdout,))
468468
469469
**Command with per-host arguments**
@@ -887,6 +887,11 @@ def copy_remote_file(self, remote_file, local_file, recurse=False,
887887
be ``myfile_myhost`` for the file from host ``myhost``
888888
:type suffix_separator: str
889889
890+
:raises: :py:class:`ValueError` when a directory is supplied to local_file \
891+
and recurse is not set
892+
:raises: :py:class:`IOError` on I/O errors writing files
893+
:raises: :py:class:`OSError` on OS errors like permission denied
894+
890895
.. note ::
891896
Local directories in `local_file` that do not exist will be
892897
created as long as permissions allow.

0 commit comments

Comments
 (0)