Skip to content

Commit 2420134

Browse files
author
Pan
committed
Added exception raising on join timeout reached with command still running, tests.
Updated docs, added base parallel client class. Updated changelog.Resolves #101
1 parent 7d4bd57 commit 2420134

File tree

9 files changed

+65
-25
lines changed

9 files changed

+65
-25
lines changed

Changelog.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
Change Log
22
============
33

4+
1.4.0
5+
++++++
6+
7+
Changes
8+
----------
9+
10+
* ``ParallelSSH2Client.join`` now raises ``pssh.exceptions.Timeout`` exception when timeout is requested and reached with command still running.
11+
12+
13+
Fixes
14+
--------
15+
16+
* ``ParallelSSH2Client.join`` timeout duration was incorrectly for per-host rather than total.
17+
418
1.3.2
519
++++++
620

doc/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ API Documentation
88
ssh_client
99
pssh2_client
1010
ssh2_client
11+
base_pssh
1112
output
1213
agent
1314
utils

doc/base_pssh.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
BaseParallelSSHClient
2+
======================
3+
4+
API documentation for common parallel client functionality.
5+
6+
.. automodule:: pssh.base_pssh
7+
:member-order: groupwise

doc/ssh2.rst

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,24 @@ For the ``ssh2-python`` (``libssh2``) based clients, not all features supported
55

66
Below is a comparison of feature support for the two client types.
77

8-
=============================== ========= ======================
9-
Feature paramiko ssh2-python (libssh2)
10-
=============================== ========= ======================
11-
Agent forwarding Yes Not supported
12-
Proxying/tunnelling Yes Not yet implemented
13-
Kerberos (GSS) authentication Yes Not supported
14-
Private key file authentication Yes Yes
15-
Private key from memory Yes Not yet implemented
16-
Agent authentication Yes Yes
17-
Password authentication Yes Yes
18-
SFTP copy to/from hosts Yes Yes
19-
Session timeout setting Yes Yes
20-
Per-channel timeout setting Yes Not supported
21-
Programmatic SSH agent Yes Not supported
22-
OpenSSH config parsing Yes Not yet implemented
23-
=============================== ========= ======================
8+
=============================== ============== ======================
9+
Feature paramiko ssh2-python (libssh2)
10+
=============================== ============== ======================
11+
Agent forwarding Yes Not supported (*PR Pending*)
12+
Proxying/tunnelling Yes Yes
13+
Kerberos (GSS) authentication Yes Not supported
14+
Private key file authentication Yes Yes
15+
Private key from memory Yes Not yet implemented
16+
Agent authentication Yes Yes
17+
Password authentication Yes Yes
18+
SFTP copy to/from hosts Yes Yes
19+
Session timeout setting Yes Yes
20+
Per-channel timeout setting Yes Yes
21+
Programmatic SSH agent Yes Not supported
22+
OpenSSH config parsing Yes Not yet implemented
23+
ECSA keys support Yes Not supported (*PR Pending*)
24+
SCP functionality Not supported Not yet implemented
25+
=============================== ============== ======================
2426

2527
If any of missing features are required for a use case, then the paramiko based clients should be used instead.
2628

pssh/base_pssh.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is part of parallel-ssh.
22

3-
# Copyright (C) 2014-2017 Panos Kittenis
3+
# Copyright (C) 2014-2018 Panos Kittenis
44

55
# This library is free software; you can redistribute it and/or
66
# modify it under the terms of the GNU Lesser General Public
@@ -40,6 +40,8 @@
4040

4141
class BaseParallelSSHClient(object):
4242

43+
"""Parallel client base class."""
44+
4345
def __init__(self, hosts, user=None, password=None, port=None, pkey=None,
4446
allow_agent=True,
4547
num_retries=DEFAULT_RETRIES,

pssh/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,7 @@ class SFTPIOError(SFTPError):
6161

6262
class ProxyError(Exception):
6363
"""Raised on proxy errors"""
64+
65+
66+
class Timeout(Exception):
67+
"""Raised on timeout requested and reached"""

pssh/pssh2_client.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is part of parallel-ssh.
22

3-
# Copyright (C) 2014-2017 Panos Kittenis
3+
# Copyright (C) 2014-2018 Panos Kittenis
44

55
# This library is free software; you can redistribute it and/or
66
# modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,7 @@
2121
from .base_pssh import BaseParallelSSHClient
2222
from .constants import DEFAULT_RETRIES, RETRY_DELAY
2323
from .ssh2_client import SSHClient
24-
from .exceptions import ProxyError
24+
from .exceptions import ProxyError, Timeout
2525
from .tunnel import Tunnel
2626

2727

@@ -207,13 +207,20 @@ def join(self, output, consume_output=False, timeout=None):
207207
finished.
208208
:type timeout: int
209209
210+
:raises: :py:class:`pssh.exceptions.Timeout` on timeout requested and
211+
reached with commands still running.
212+
210213
:rtype: ``None``"""
211214
for host in output:
212215
if host not in self.host_clients or self.host_clients[host] is None:
213216
continue
214217
self.host_clients[host].wait_finished(output[host].channel,
215218
timeout=timeout)
216-
if consume_output:
219+
if timeout and not output[host].channel.eof():
220+
raise Timeout(
221+
"Timeout of %s sec(s) reached on host %s with command "
222+
"still running", timeout, host)
223+
elif consume_output:
217224
for line in output[host].stdout:
218225
pass
219226
for line in output[host].stderr:

pssh/utils.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is part of parallel-ssh.
22

3-
# Copyright (C) 2014-2017 Panos Kittenis
3+
# Copyright (C) 2014-2018 Panos Kittenis
44

55
# This library is free software; you can redistribute it and/or
66
# modify it under the terms of the GNU Lesser General Public
@@ -16,7 +16,7 @@
1616
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1717

1818

19-
"""Package containing static utility functions for parallel-ssh module."""
19+
"""Module containing static utility functions for parallel-ssh."""
2020

2121

2222
import logging
@@ -54,7 +54,9 @@ def enable_host_logger():
5454

5555

5656
def load_private_key(_pkey):
57-
"""Load private key from pkey file object or filename
57+
"""Load private key from pkey file object or filename.
58+
59+
For Paramiko based clients only.
5860
5961
:param pkey: File object or file name containing private key
6062
:type pkey: file/str"""

tests/test_pssh_ssh2_client.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from pssh.pssh2_client import ParallelSSHClient, logger as pssh_logger
4040
from pssh.exceptions import UnknownHostException, \
4141
AuthenticationException, ConnectionErrorException, SessionError, \
42-
HostArgumentException, SFTPError, SFTPIOError
42+
HostArgumentException, SFTPError, SFTPIOError, Timeout
4343

4444
from .embedded_server.embedded_server import make_socket
4545
from .embedded_server.openssh import OpenSSHServer
@@ -1167,10 +1167,11 @@ def test_join_timeout(self):
11671167
client = ParallelSSHClient([self.host], port=self.port,
11681168
pkey=self.user_key)
11691169
output = client.run_command('sleep 2')
1170-
client.join(output, timeout=1)
1170+
self.assertRaises(Timeout, client.join, output, timeout=1)
11711171
self.assertFalse(output[self.host].channel.eof())
11721172
client.join(output, timeout=2)
11731173
self.assertTrue(output[self.host].channel.eof())
1174+
self.assertTrue(client.finished(output))
11741175

11751176
def test_read_timeout(self):
11761177
client = ParallelSSHClient([self.host], port=self.port,

0 commit comments

Comments
 (0)