Skip to content

Commit ba7c403

Browse files
author
Dan
committed
Updated documentation. Removed sleep to speed up parallel connects. Updated tests.
1 parent d652fd9 commit ba7c403

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

pssh/pssh_client.py

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def __init__(self, hosts,
103103
>>> ... pass
104104
105105
>>> # Commands have started executing at this point
106-
>>> # Exit code will probably not be available immediately
106+
>>> # Exit code will not be available immediately
107107
>>> print output
108108
109109
::
@@ -135,10 +135,24 @@ def __init__(self, hosts,
135135
[myhost1] drwxrwxr-x 6 user group 4.0K Jan 1 HH:MM x
136136
[myhost2] drwxrwxr-x 6 user group 4.0K Jan 1 HH:MM x
137137
138-
Retrieve exit codes after commands have finished as below. This is
139-
only necessary for long running commands that do not exit immediately.
138+
Retrieve exit codes after commands have finished as below.
140139
141-
``exit_code`` in ``output`` will be ``None`` if command has not finished.
140+
`parallel-ssh` starts commands asynchronously to enable running multiple
141+
commands in parallel without blocking.
142+
143+
Because of this, exit codes will not be immediately available even for
144+
commands that exit immediately.
145+
146+
At least one of ::
147+
148+
* Iterating over stdout/stderr
149+
* Calling `client.join(output)`
150+
* Calling `client.pool.join()` if no output is needed
151+
152+
is necessary to cause `parallel-ssh` to wait for commands to finish and
153+
be able to gather exit codes.
154+
155+
``exit_code`` in ``output`` will be ``None`` if command has not yet finished.
142156
143157
``get_exit_codes`` is not a blocking function and will not wait for commands
144158
to finish. Use ``client.join(output)`` to block until all commands have
@@ -172,6 +186,12 @@ def __init__(self, hosts,
172186
>>> hosts = ['dc1.myhost1', 'dc2.myhost2']
173187
>>> client = ParallelSSHClient([h for h in hosts if h.find('dc1')])
174188
>>> client.run_command(<..>)
189+
190+
**Overriding host list**
191+
192+
>>> client.hosts = ['otherhost']
193+
>>> print client.run_command('exit 0')
194+
>>> {'otherhost': {'exit_code':0}, <..>}
175195
176196
.. note ::
177197
@@ -276,6 +296,34 @@ def run_command(self, *args, **kwargs):
276296
>>> for host in output:
277297
>>> stdout = list(output[host]['stdout'])
278298
>>> print "Complete stdout for host %s is %s" % (host, stdout,)
299+
300+
**Run multiple commands in parallel**
301+
302+
This short example demonstrates running long running commands in parallel
303+
and how long it takes for all commands to start, blocking until they
304+
complete and how long it takes for all commands to complete.
305+
306+
See examples directory for complete example script. ::
307+
308+
output = []
309+
310+
start = datetime.datetime.now()
311+
cmds = ['sleep 5' for _ in xrange(10)]
312+
for cmd in cmds:
313+
output.append(client.run_command(cmd, stop_on_errors=False))
314+
end = datetime.datetime.now()
315+
print "Started %s commands in %s" % (len(cmds), end-start,)
316+
start = datetime.datetime.now()
317+
for _output in output:
318+
for line in _output[host]['stdout']:
319+
print line
320+
end = datetime.datetime.now()
321+
print "All commands finished in %s" % (end-start,)
322+
323+
*Output*
324+
325+
Started 10 commands in 0:00:00.428629
326+
All commands finished in 0:00:05.014757
279327
280328
**Example Output**
281329

pssh/ssh_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,14 @@ def _connect_tunnel(self):
139139
proxy_channel = self.proxy_client.get_transport().\
140140
open_channel('direct-tcpip', (self.host, self.port,),
141141
('127.0.0.1', 0))
142+
gevent.sleep(0)
142143
return self._connect(self.client, self.host, self.port, sock=proxy_channel)
143144
except channel_exception, ex:
144145
error_type = ex.args[1] if len(ex.args) > 1 else ex.args[0]
145146
raise ConnectionErrorException("Error connecting to host '%s:%s' - %s",
146147
self.host, self.port,
147148
str(error_type))
149+
148150
def _connect(self, client, host, port, sock=None, retries=1):
149151
"""Connect to host
150152
@@ -229,7 +231,7 @@ def exec_command(self, command, sudo=False, user=None, **kwargs):
229231
logger.debug("Running command %s on %s", command, self.host)
230232
channel.exec_command(command, **kwargs)
231233
logger.debug("Command started")
232-
gevent.sleep(.2)
234+
gevent.sleep(0)
233235
return channel, self.host, stdout, stderr
234236

235237
def _read_output_buffer(self, output_buffer, prefix=''):

tests/test_pssh_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def test_pssh_client_exec_command(self):
7373
def test_pssh_client_no_stdout_non_zero_exit_code_immediate_exit(self):
7474
output = self.client.run_command('exit 1')
7575
expected_exit_code = 1
76+
self.client.join(output)
7677
exit_code = output[self.host]['exit_code']
7778
self.assertEqual(expected_exit_code, exit_code,
7879
msg="Got unexpected exit code - %s, expected %s" %
@@ -112,9 +113,9 @@ def test_pssh_client_run_command_get_output(self):
112113
expected_exit_code = 0
113114
expected_stdout = [self.fake_resp]
114115
expected_stderr = []
115-
exit_code = output[self.host]['exit_code']
116116
stdout = list(output[self.host]['stdout'])
117117
stderr = list(output[self.host]['stderr'])
118+
exit_code = output[self.host]['exit_code']
118119
self.assertEqual(expected_exit_code, exit_code,
119120
msg="Got unexpected exit code - %s, expected %s" %
120121
(exit_code,
@@ -439,6 +440,7 @@ def test_ssh_proxy(self):
439440
proxy_host='127.0.0.2',
440441
proxy_port=proxy_server_port
441442
)
443+
gevent.sleep(2)
442444
output = client.run_command(self.fake_cmd)
443445
stdout = list(output[self.host]['stdout'])
444446
expected_stdout = [self.fake_resp]

0 commit comments

Comments
 (0)