Skip to content

Commit 4d1f326

Browse files
author
Pan
committed
Fixed incorrect timeout being applied to native client socket.
Added native clients integration tests for client timeout connecting to unreachable or unknown host. Resolves #133 Added windows 3.7 wheel builds Updated changelog
1 parent 15c73c2 commit 4d1f326

File tree

5 files changed

+63
-19
lines changed

5 files changed

+63
-19
lines changed

.appveyor.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ environment:
5959
MSVC: "Visual Studio 14 Win64"
6060
ARCH: x64_86
6161

62+
- PYTHON: "C:\\Python37"
63+
PYTHON_VERSION: "3.7"
64+
PYTHON_ARCH: "32"
65+
MSVC: "Visual Studio 14"
66+
ARCH: i386
67+
68+
- PYTHON: "C:\\Python37-x64"
69+
PYTHON_VERSION: "3.7"
70+
PYTHON_ARCH: "64"
71+
MSVC: "Visual Studio 14 Win64"
72+
ARCH: x64_86
73+
6274
install:
6375
# If there is a newer build queued for the same PR, cancel this one.
6476
# The AppVeyor 'rollout builds' option is supposed to serve the same

Changelog.rst

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

4+
1.8.1
5+
++++++
6+
7+
Fixes
8+
------
9+
10+
* Native client socket timeout setting would be longer than expected - #133
11+
12+
Packaging
13+
---------
14+
15+
* Added Windows 3.7 wheels
16+
417
1.8.0
518
++++++
619

pssh/clients/native/single.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def __init__(self, host,
113113
self.port = port if port else 22
114114
self.num_retries = num_retries
115115
self.sock = None
116-
self.timeout = timeout * 1000 if timeout else None
116+
self.timeout = timeout
117117
self.retry_delay = retry_delay
118118
self.allow_agent = allow_agent
119119
self.forward_ssh_agent = forward_ssh_agent
@@ -158,7 +158,8 @@ def _connect_init_retry(self, retries):
158158
def _init(self, retries=1):
159159
self.session = Session()
160160
if self.timeout:
161-
self.session.set_timeout(self.timeout)
161+
# libssh2 timeout is in ms
162+
self.session.set_timeout(self.timeout * 1000)
162163
try:
163164
self.session.handshake(self.sock)
164165
except Exception as ex:
@@ -180,7 +181,8 @@ def _init(self, retries=1):
180181

181182
def _connect(self, host, port, retries=1):
182183
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
183-
self.sock.settimeout(self.timeout)
184+
if self.timeout:
185+
self.sock.settimeout(self.timeout)
184186
logger.debug("Connecting to %s:%s", host, port)
185187
try:
186188
self.sock.connect((host, port))

tests/test_native_parallel_client.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import time
3535

3636

37-
from gevent import joinall
37+
from gevent import joinall, spawn
3838
from pssh.clients.native import ParallelSSHClient
3939
from pssh.exceptions import UnknownHostException, \
4040
AuthenticationException, ConnectionErrorException, SessionError, \
@@ -276,19 +276,29 @@ def test_pssh_client_timeout(self):
276276
self.assertIsInstance(output[self.host].exception,
277277
Timeout)
278278

279-
# def test_pssh_client_run_command_password(self):
280-
# """Test password authentication. Embedded server accepts any password
281-
# even empty string"""
282-
# client = ParallelSSHClient([self.host], port=self.listen_port,
283-
# password='')
284-
# output = client.run_command(self.fake_cmd)
285-
# stdout = list(output[self.host]['stdout'])
286-
# self.assertTrue(self.host in output,
287-
# msg="No output for host")
288-
# self.assertTrue(output[self.host]['exit_code'] == 0,
289-
# msg="Expected exit code 0, got %s" % (
290-
# output[self.host]['exit_code'],))
291-
# self.assertEqual(stdout, [self.fake_resp])
279+
def test_connection_timeout(self):
280+
client_timeout = .01
281+
host = 'fakehost.com'
282+
client = ParallelSSHClient([host], port=self.port,
283+
pkey=self.user_key,
284+
timeout=client_timeout,
285+
num_retries=1)
286+
cmd = spawn(client.run_command, 'sleep 1', stop_on_errors=False)
287+
output = cmd.get(timeout=client_timeout * 200)
288+
self.assertIsInstance(output[host].exception,
289+
ConnectionErrorException)
290+
291+
def test_zero_timeout(self):
292+
host = '127.0.0.2'
293+
server = OpenSSHServer(listen_ip=host, port=self.port)
294+
server.start_server()
295+
client = ParallelSSHClient([self.host, host],
296+
port=self.port,
297+
pkey=self.user_key,
298+
timeout=0)
299+
cmd = spawn(client.run_command, 'sleep 1', stop_on_errors=False)
300+
output = cmd.get(timeout=3)
301+
self.assertTrue(output[self.host].exception is None)
292302

293303
def test_pssh_client_long_running_command_exit_codes(self):
294304
expected_lines = 2

tests/test_native_single_client.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
import time
55
import subprocess
66

7-
from gevent import socket, sleep
7+
from gevent import socket, sleep, spawn
88

99
from .base_ssh2_test import SSH2TestCase
1010
from .embedded_server.openssh import OpenSSHServer
1111
from pssh.clients.native import SSHClient, logger as ssh_logger
1212
from ssh2.session import Session
1313
from ssh2.exceptions import SocketDisconnectError
1414
from pssh.exceptions import AuthenticationException, ConnectionErrorException, \
15-
SessionError, SFTPIOError, SFTPError, SCPError, PKeyFileError
15+
SessionError, SFTPIOError, SFTPError, SCPError, PKeyFileError, Timeout
1616

1717

1818
ssh_logger.setLevel(logging.DEBUG)
@@ -145,3 +145,10 @@ def test_retry_failure(self):
145145
self.assertRaises(ConnectionErrorException,
146146
SSHClient, self.host, port=12345,
147147
num_retries=2, _auth_thread_pool=False)
148+
149+
def test_connection_timeout(self):
150+
cmd = spawn(SSHClient, 'fakehost.com', port=12345,
151+
num_retries=1, timeout=1, _auth_thread_pool=False)
152+
# Should fail within greenlet timeout, otherwise greenlet will
153+
# raise timeout which will fail the test
154+
self.assertRaises(ConnectionErrorException, cmd.get, timeout=1.1)

0 commit comments

Comments
 (0)