Skip to content

Commit 2f08520

Browse files
author
Dan
committed
Updated documentation. Added utilities, advanced and api documents
1 parent da2eaca commit 2f08520

File tree

10 files changed

+780
-106
lines changed

10 files changed

+780
-106
lines changed

doc/advanced.html

Lines changed: 531 additions & 0 deletions
Large diffs are not rendered by default.

doc/advanced.rst

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
.. contents::
22

33

4-
***************
54
Advanced Usage
6-
***************
5+
=================
76

87
There are several more advanced use cases of `ParallelSSH`, such as tunneling (aka proxying) via an intermediate SSH server and per-host configuration and command substitution among others.
98

9+
Agents and Private Keys
10+
*************************
11+
1012
SSH Agent forwarding
11-
*********************
13+
-----------------------
1214

1315
SSH agent forwarding, what ``ssh -A`` does on the command line, is supported and enabled by default. Creating an object as ``ParallelSSHClient(hosts, forward_ssh_agent=False)`` will disable this behaviour.
1416

1517
Programmatic Private Keys
16-
**************************
18+
--------------------------
1719

18-
By default, `ParallelSSH` will use all keys in an available SSH agent and all available keys under the user's SSH directory (`~/.ssh`).
20+
By default, ``ParallelSSH`` will use all keys in an available SSH agent and identity keys under the user's SSH directory - ``id_rsa`` and ``id_dsa`` in ``~/.ssh``.
1921

2022
A private key can also be provided programmatically.
2123

@@ -26,21 +28,32 @@ A private key can also be provided programmatically.
2628
2729
client = ParallelSSHClient(hosts, pkey=load_private_key('my_key'))
2830
29-
Where `my_key` is a private key file in current working directory.
31+
Where ``my_key`` is a private key file in current working directory.
32+
33+
The helper function :py:func:`load_private_key <pssh.utils.load_private_key>` will attempt to load all available key types and raises :mod:`SSHException <pssh.exceptions.SSHException>` if it cannot load the key file.
3034

31-
The helper function :py:func:`pssh.utils.load_private_key` will attempt to load all available key types and raises :mod:`pssh.exceptions.SSHException` if it cannot load the key file.
35+
Disabling use of system SSH Agent
36+
----------------------------------
3237

33-
Using an available SSH agent can also be disabled programmatically.
38+
Use of an available SSH agent can also be disabled.
3439

3540
.. code-block:: python
3641
3742
client = ParallelSSHClient(hosts, pkey=load_private_key('my_key'),
3843
allow_agent=False)
3944
45+
.. warning::
46+
47+
For large number of hosts, it is recommended that private keys are provided programmatically and use of SSH agent is disabled via ``allow_agent=False`` as above.
48+
49+
If the number of hosts is large enough, available connections to the system SSH may be exhausted which will stop the client from working on a subset of hosts.
50+
51+
This is a limitation of the underlying SSH client used by ``ParallelSSH``.
52+
4053
Programmatic SSH Agent
41-
***********************
54+
-----------------------
4255

43-
It is also possible to programmatically provide an SSH agent for the client to use, instead of a system provided one. This is useful in cases where different hosts in the host list need different private keys and a system SSH agent is not available.
56+
It is also possible to programmatically provide an SSH agent for the client to use, instead of a system provided one. This is useful in cases where hosts need different private keys and a system SSH agent is not available.
4457

4558
.. code-block:: python
4659
@@ -56,22 +69,26 @@ It is also possible to programmatically provide an SSH agent for the client to u
5669
client = ParallelSSHClient(hosts, agent=agent)
5770
client.run_command(<..>)
5871
59-
Supplying an agent object programmatically implies that a system SSH agent will *not* be used if available.
72+
.. note::
73+
74+
Supplying an agent programmatically implies that a system SSH agent will *not* be used even if available.
6075

6176

6277
Tunneling
6378
**********
6479

6580
This is used in cases where the client does not have direct access to the target host and has to authenticate via an intermediary, also called a bastion host, commonly used for additional security as only the bastion host needs to have access to the target host.
6681

67-
ParallelSSHClient ------> SSH Proxy server --------> SSH target host
82+
ParallelSSHClient ------> Proxy host --------> Target host
6883

69-
Proxy server can be configured as follows in the simplest case::
84+
Proxy host can be configured as follows in the simplest case:
85+
86+
.. code-block:: python
7087
7188
hosts = [<..>]
7289
client = ParallelSSHClient(hosts, proxy_host=bastion)
7390
74-
Configuration for the proxy host's user name, port, password and private key can also be provided, separete from target host user name.
91+
Configuration for the proxy host's user name, port, password and private key can also be provided, separate from target host user name.
7592

7693
.. code-block:: python
7794
@@ -83,7 +100,15 @@ Configuration for the proxy host's user name, port, password and private key can
83100
proxy_port=2222,
84101
proxy_pkey=load_private_key('proxy.key'))
85102
86-
Where `proxy.key` is a filename containing private key to use for proxy host authentication.
103+
Where ``proxy.key`` is a filename containing private key to use for proxy host authentication.
104+
105+
In the above example, connection to the target host is made via ``my_proxy_user@bastion`` -> ``target_host_user@<host>``.
106+
107+
.. note::
108+
109+
Proxy host connections are asynchronous and use the SSH protocol's native TCP tunneling - aka local port forward. No external commands are used for the proxy connection, unlike the `ProxyCommand` directive in OpenSSH and other utilities.
110+
111+
While the connections initiated by ``ParallelSSH`` are asynchronous, the connections from proxy host -> target hosts may not be, depending on SSH server implementation. If only one proxy host is used to connect to a large number of target hosts and proxy SSH server connections are *not* asynchronous, this may adversely impact performance on the proxy host.
87112

88113
Per-Host Configuration
89114
***********************
@@ -109,21 +134,25 @@ Sometimes, different hosts require different configuration like user names and p
109134
client.run_command('uname')
110135
<..>
111136
112-
In the above example, `host1` will use user name `user1` and private key from `my_key.pem` and `host2` will use user name `user2` and private key from `my_other_key.pem`.
137+
In the above example, ``host1`` will use user name ``user1`` and private key from ``my_key.pem`` and ``host2`` will use user name ``user2`` and private key from ``my_other_key.pem``.
138+
139+
.. note::
140+
141+
Proxy host cannot be provided via per-host configuration at this time.
113142

114143
Per-Host Command substitution
115144
******************************
116145

117146
For cases where different commands should be run each host, or the same command with different arguments, functionality exists to provide per-host command arguments for substitution.
118147

119-
The `host_args` keyword parameter to `run_command` can be used to provide arguments to use to format the command string.
148+
The ``host_args`` keyword parameter to :py:func:`run_command <pssh.pssh_client.ParallelSSHClient.run_command>` can be used to provide arguments to use to format the command string.
120149

121-
Number of `host_args` items should be at least as many as number of hosts.
150+
Number of ``host_args`` items should be at least as many as number of hosts.
122151

123152
Any Python string format specification characters may be used in command string.
124153

125154

126-
In the following example, first host in hosts list will use cmd `host1_cmd` second host `host2_cmd` and so on
155+
In the following example, first host in hosts list will use cmd ``host1_cmd`` second host ``host2_cmd`` and so on
127156

128157
.. code-block:: python
129158
@@ -140,12 +169,55 @@ Command can also have multiple arguments to be substituted.
140169
('host2_cmd1', 'host2_cmd2'),
141170
('host3_cmd1', 'host3_cmd2'),))
142171
143-
A list of dictionaries can also be used as `host_args` for named argument substitution.
172+
A list of dictionaries can also be used as ``host_args`` for named argument substitution.
144173

145-
In the following example, first host in host list will use cmd `host-index-0`, second host `host-index-1` and so on.
174+
In the following example, first host in host list will use cmd ``host-index-0``, second host ``host-index-1`` and so on.
146175

147176
.. code-block:: python
148177
149178
host_args=[{'cmd': 'host-index-%s' % (i,))
150179
for i in range(len(client.hosts))]
151180
output = client.run_command('%(cmd)s', host_args=host_args)
181+
182+
183+
Hosts filtering and overriding
184+
*******************************
185+
186+
Iterators and filtering
187+
------------------------
188+
189+
Any type of iterator may be used as hosts list, including generator and list comprehension expressions.
190+
191+
:List comprehension:
192+
.. code-block:: python
193+
194+
hosts = ['dc1.myhost1', 'dc2.myhost2']
195+
client = ParallelSSHClient([h for h in hosts if h.find('dc1')])
196+
197+
:Generator:
198+
.. code-block:: python
199+
200+
hosts = ['dc1.myhost1', 'dc2.myhost2']
201+
client = ParallelSSHClient((h for h in hosts if h.find('dc1')))
202+
203+
:Filter:
204+
.. code-block:: python
205+
206+
hosts = ['dc1.myhost1', 'dc2.myhost2']
207+
client = ParallelSSHClient(filter(lambda h: h.find('dc1'), hosts))
208+
client.run_command(<..>)
209+
210+
.. note ::
211+
212+
Since generators by design only iterate over a sequence once then stop, ``client.hosts`` should be re-assigned after each call to ``run_command`` when using generators as target of `client.hosts`.
213+
214+
Overriding hosts list
215+
----------------------
216+
217+
Hosts list can be modified in place. A call to ``run_command`` will create new connections as necessary and output will only contain output for the hosts ``run_command`` executed on.
218+
219+
.. code-block:: python
220+
221+
client.hosts = ['otherhost']
222+
print(client.run_command('exit 0'))
223+
{'otherhost': exit_code=None, <..>}

doc/api.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
******************
2+
API Documentation
3+
******************
4+
5+
.. toctree::
6+
7+
pssh_client
8+
ssh_client
9+
output
10+
agent
11+
utils
12+
exceptions

doc/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
#html_split_index = False
176176

177177
# If true, links to the reST sources are added to the pages.
178-
#html_show_sourcelink = True
178+
html_show_sourcelink = False
179179

180180
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
181181
#html_show_sphinx = True

doc/front_page.rst

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,13 @@ Parallel-SSH Documentation
1616
:alt: Latest documentation
1717

1818

19-
`Parallel-SSH` is a parallel SSH client library. It makes use of gevent to make asynchronous SSH connections for its client and is, to date, the only publicly available asynchronous SSH client library for Python, as well as the only asynchronous *parallel* SSH client library available for Python.
20-
21-
22-
***********
23-
User Guide
24-
***********
19+
`Parallel-SSH` is a parallel SSH client library. It uses asynchronous SSH connections and is, to date, the only publicly available asynchronous SSH client library for Python, as well as the only asynchronous *parallel* SSH client library available for Python.
2520

2621
.. toctree::
22+
:maxdepth: 1
2723

28-
introduction
29-
installation
30-
quickstart
31-
advanced
24+
introduction
25+
installation
26+
quickstart
27+
advanced
28+
api

doc/index.rst

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,31 @@
33
You can adapt this file completely to your liking, but it should at least
44
contain the root `toctree` directive.
55
6+
============================
67
Parallel-SSH's documentation
78
============================
89

910
.. toctree::
11+
:maxdepth: 3
1012

1113
front_page
1214

13-
In a nutshell::
15+
In a nutshell
16+
**************
1417

15-
client = ParallelSSHClient(['localhost'])
16-
output = client.run_command('whoami')
17-
for line in output['localhost'].stdout:
18-
print(line)
18+
.. code-block:: python
19+
20+
from pssh.pssh_client import ParallelSSHClient
21+
22+
client = ParallelSSHClient(['localhost'])
23+
output = client.run_command('whoami')
24+
for line in output['localhost'].stdout:
25+
print(line)
1926
20-
Output::
27+
:Output:
28+
.. code-block:: python
2129
22-
<your username here>
30+
<your username here>
2331
2432
Indices and tables
2533
==================

doc/pssh_client.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
ParallelSSHClient API Documentation
2-
===================================
1+
ParallelSSHClient
2+
=================
33

44
.. automodule:: pssh.pssh_client
55
:member-order: groupwise

0 commit comments

Comments
 (0)