@@ -66,6 +66,11 @@ class ProxyCommandException(Exception):
6666 pass
6767
6868
69+ class SSHException (Exception ):
70+ """Raised on SSHException error - error authenticating with SSH server"""
71+ pass
72+
73+
6974class SSHClient (object ):
7075 """Wrapper class over paramiko.SSHClient with sane defaults
7176 Honours ~/.ssh/config and /etc/ssh/ssh_config entries for host username \
@@ -178,6 +183,10 @@ def _connect(self, retries=1):
178183 except paramiko .ProxyCommandFailure , e :
179184 logger .error ("Error executing ProxyCommand - %s" , e .message ,)
180185 raise ProxyCommandException (e .message )
186+ # SSHException is more general so should below other types
187+ # of SSH failure
188+ except paramiko .SSHException , e :
189+ raise SSHException (e )
181190
182191 def exec_command (self , command , sudo = False , user = None , ** kwargs ):
183192 """Wrapper to :mod:`paramiko.SSHClient.exec_command`
@@ -316,11 +325,11 @@ def __init__(self, hosts,
316325 :param pool_size: (Optional) Greenlet pool size. Controls on how many\
317326 hosts to execute tasks in parallel. Defaults to 10
318327 :type pool_size: int
319-
328+
320329 **Example**
321330
322331 >>> from pssh import ParallelSSHClient, AuthenticationException,\
323- UnknownHostException, ConnectionErrorException
332+ UnknownHostException, ConnectionErrorException
324333 >>> client = ParallelSSHClient(['myhost1', 'myhost2'])
325334 >>> try:
326335 >>> ... cmds = client.exec_command('ls -ltrh /tmp/aasdfasdf', sudo = True)
@@ -335,7 +344,7 @@ def __init__(self, hosts,
335344 **Example with returned stdout and stderr buffers**
336345
337346 >>> from pssh import ParallelSSHClient, AuthenticationException,\
338- UnknownHostException, ConnectionErrorException
347+ UnknownHostException, ConnectionErrorException
339348 >>> client = ParallelSSHClient(['myhost1', 'myhost2'])
340349 >>> try:
341350 >>> ... cmds = client.exec_command('ls -ltrh /tmp/aasdfasdf', sudo = True)
@@ -344,10 +353,10 @@ def __init__(self, hosts,
344353 >>> output = [client.get_stdout(cmd, return_buffers=True) for cmd in cmds]
345354 >>> print output
346355 [{'myhost1': {'exit_code': 2,
347- 'stdout' : <generator object <genexpr>,
356+ 'stdout' : <generator object <genexpr>,
348357 'stderr' : <generator object <genexpr>,}},
349358 {'myhost2': {'exit_code': 2,
350- 'stdout' : <generator object <genexpr>,
359+ 'stdout' : <generator object <genexpr>,
351360 'stderr' : <generator object <genexpr>,}},
352361 ]
353362 >>> for host_stdout in output:
@@ -361,25 +370,25 @@ def __init__(self, hosts,
361370 >>> import paramiko
362371 >>> client_key = paramiko.RSAKey.from_private_key_file('user.key')
363372 >>> client = ParallelSSHClient(['myhost1', 'myhost2'], pkey=client_key)
364-
373+
365374 .. note ::
366375
367376 **Connection persistence**
368-
377+
369378 Connections to hosts will remain established for the duration of the
370379 object's life. To close them, just `del` or reuse the object reference.
371-
380+
372381 >>> client = ParallelSSHClient(['localhost'])
373382 >>> cmds = client.exec_command('ls -ltrh /tmp/aasdfasdf')
374383 >>> cmds[0].join()
375-
384+
376385 :netstat: ``tcp 0 0 127.0.0.1:53054 127.0.0.1:22 ESTABLISHED``
377-
386+
378387 Connection remains active after commands have finished executing. Any \
379388 additional commands will use the same connection.
380-
389+
381390 >>> del client
382-
391+
383392 Connection is terminated.
384393 """
385394 self .pool = gevent .pool .Pool (size = pool_size )
@@ -408,19 +417,19 @@ def exec_command(self, *args, **kwargs):
408417 **Example**:
409418
410419 >>> cmds = client.exec_command('ls -ltrh')
411-
420+
412421 Wait for completion, no stdout:
413-
422+
414423 >>> for cmd in cmds:
415424 >>> cmd.join()
416-
425+
417426 Alternatively/in addition print stdout for each command:
418-
427+
419428 >>> print [get_stdout(cmd) for cmd in cmds]
420429
421430 Retrieving stdout implies join, meaning get_stdout will wait
422431 for completion of all commands before returning output.
423-
432+
424433 You may call get_stdout on already completed greenlets to re-get
425434 their output as many times as you want."""
426435 return [self .pool .spawn (self ._exec_command , host , * args , ** kwargs )
@@ -439,7 +448,7 @@ def _exec_command(self, host, *args, **kwargs):
439448
440449 def get_stdout (self , greenlet , return_buffers = False ):
441450 """Get/print stdout from greenlet and return exit code for host
442-
451+
443452 :mod:`pssh.get_stdout` will close the open SSH channel but this does
444453 **not** close the established connection to the remote host, only the
445454 authenticated SSH channel within it. This is standard practise
@@ -463,7 +472,7 @@ def get_stdout(self, greenlet, return_buffers=False):
463472 for example ``{'myhost1': {'exit_code': 0}}``
464473 :rtype: With ``return_buffers=True``: ``{'myhost1': {'exit_code': 0,
465474 'channel' : None or SSH channel of command if command is still executing,
466- 'stdout' : <iterable>,
475+ 'stdout' : <iterable>,
467476 'stderr' : <iterable>,}}``
468477 """
469478 gevent .sleep (.2 )
0 commit comments