Skip to content

Commit 893193d

Browse files
author
Dan
committed
Revert "Removed deprecated API endpoints. Resolves #73"
This reverts commit b53749f.
1 parent b53749f commit 893193d

File tree

2 files changed

+120
-9
lines changed

2 files changed

+120
-9
lines changed

pssh/pssh_client.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,22 @@ def run_command(self, *args, **kwargs):
594594
raise
595595
return output
596596

597+
def exec_command(self, *args, **kwargs):
598+
"""Run command on all hosts in parallel, honoring `self.pool_size`
599+
600+
**Deprecated by** :mod:`pssh.pssh_client.ParallelSSHClient.run_command`
601+
602+
:param args: Position arguments for command
603+
:type args: tuple
604+
:param kwargs: Keyword arguments for command
605+
:type kwargs: dict
606+
607+
:rtype: List of :mod:`gevent.Greenlet`"""
608+
warnings.warn("This method is being deprecated and will be removed in \
609+
future releases - use self.run_command instead", DeprecationWarning)
610+
return [self.pool.spawn(self._exec_command, host, *args, **kwargs)
611+
for host in self.hosts]
612+
597613
def _get_host_config_values(self, host):
598614
_user = self.host_config.get(host, {}).get('user', self.user)
599615
_port = self.host_config.get(host, {}).get('port', self.port)
@@ -751,6 +767,47 @@ def _get_exit_code(self, channel):
751767
channel.close()
752768
return channel.recv_exit_status()
753769

770+
def get_stdout(self, greenlet, return_buffers=False):
771+
"""Get/print stdout from greenlet and return exit code for host
772+
773+
**Deprecated** - use :mod:`pssh.pssh_client.ParallelSSHClient.get_output` instead.
774+
775+
:param greenlet: Greenlet object containing an \
776+
SSH channel reference, hostname, stdout and stderr buffers
777+
:type greenlet: :mod:`gevent.Greenlet`
778+
:param return_buffers: Flag to turn on returning stdout and stderr \
779+
buffers along with exit code. Defaults to off.
780+
:type return_buffers: bool
781+
:rtype: Dictionary containing ``{host: {'exit_code': exit code}}`` entry \
782+
for example ``{'myhost1': {'exit_code': 0}}``
783+
:rtype: With ``return_buffers=True``: ``{'myhost1': {'exit_code': 0,
784+
'channel' : None or SSH channel of command if command is still executing,
785+
'stdout' : <iterable>,
786+
'stderr' : <iterable>,}}``
787+
"""
788+
warnings.warn("This method is being deprecated and will be removed in"
789+
"future releases - use self.get_output instead", DeprecationWarning)
790+
gevent.sleep(.2)
791+
channel, host, stdout, stderr, stdin = greenlet.get()
792+
if channel.exit_status_ready():
793+
channel.close()
794+
else:
795+
logger.debug("Command still executing on get_stdout call - not closing channel and returning None as exit code.")
796+
# If channel is not closed we cannot get full stdout/stderr so must return buffers
797+
return_buffers = True
798+
# Channel must be closed or reading stdout/stderr will block forever
799+
if not return_buffers and channel.closed:
800+
for _ in stdout:
801+
pass
802+
for _ in stderr:
803+
pass
804+
return {host: {'exit_code': channel.recv_exit_status(),}}
805+
gevent.sleep(.2)
806+
return {host: {'exit_code': channel.recv_exit_status() if channel.exit_status_ready() else None,
807+
'channel' : channel if not channel.closed else None,
808+
'stdout' : stdout,
809+
'stderr' : stderr, }}
810+
754811
def copy_file(self, local_file, remote_file, recurse=False):
755812
"""Copy local file to remote file in parallel
756813

tests/test_pssh_client.py

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ def tearDown(self):
6868
del self.listen_socket
6969
del self.client
7070

71+
def test_pssh_client_exec_command(self):
72+
cmd = self.client.exec_command(self.fake_cmd)[0]
73+
output = self.client.get_stdout(cmd)
74+
self.assertTrue(self.host in output,
75+
msg="No output for host")
76+
self.assertTrue(output[self.host]['exit_code'] == 0)
77+
7178
def test_pssh_client_no_stdout_non_zero_exit_code_immediate_exit(self):
7279
output = self.client.run_command('exit 1')
7380
expected_exit_code = 1
@@ -78,6 +85,31 @@ def test_pssh_client_no_stdout_non_zero_exit_code_immediate_exit(self):
7885
(exit_code,
7986
expected_exit_code,))
8087

88+
def test_pssh_client_exec_command_get_buffers(self):
89+
client = ParallelSSHClient([self.host], port=self.listen_port,
90+
pkey=self.user_key,
91+
agent=self.agent)
92+
cmd = client.exec_command(self.fake_cmd)[0]
93+
output = client.get_stdout(cmd, return_buffers=True)
94+
expected_exit_code = 0
95+
expected_stdout = [self.fake_resp]
96+
expected_stderr = []
97+
exit_code = output[self.host]['exit_code']
98+
stdout = list(output[self.host]['stdout'])
99+
stderr = list(output[self.host]['stderr'])
100+
self.assertEqual(expected_exit_code, exit_code,
101+
msg="Got unexpected exit code - %s, expected %s" %
102+
(exit_code,
103+
expected_exit_code,))
104+
self.assertEqual(expected_stdout, stdout,
105+
msg="Got unexpected stdout - %s, expected %s" %
106+
(stdout,
107+
expected_stdout,))
108+
self.assertEqual(expected_stderr, stderr,
109+
msg="Got unexpected stderr - %s, expected %s" %
110+
(stderr,
111+
expected_stderr,))
112+
81113
def test_pssh_client_run_command_get_output(self):
82114
client = ParallelSSHClient([self.host], port=self.listen_port,
83115
pkey=self.user_key,
@@ -143,15 +175,21 @@ def test_pssh_client_run_long_command(self):
143175
del client
144176

145177
def test_pssh_client_auth_failure(self):
146-
self.server.kill()
147-
server_socket = make_socket(self.host)
148-
listen_port = server_socket.getsockname()[1]
149-
server = start_server(server_socket, fail_auth=True)
178+
listen_socket = make_socket(self.host)
179+
listen_port = listen_socket.getsockname()[1]
180+
server = start_server(listen_socket, fail_auth=True)
150181
client = ParallelSSHClient([self.host], port=listen_port,
151182
pkey=self.user_key,
152183
agent=self.agent)
153-
self.assertRaises(AuthenticationException, client.run_command, self.fake_cmd)
184+
cmd = client.exec_command(self.fake_cmd)[0]
185+
# Handle exception
186+
try:
187+
cmd.get()
188+
raise Exception("Expected AuthenticationException, got none")
189+
except AuthenticationException:
190+
pass
154191
del client
192+
server.kill()
155193

156194
def test_pssh_client_hosts_list_part_failure(self):
157195
"""Test getting output for remainder of host list in the case where one
@@ -200,7 +238,6 @@ def test_pssh_client_ssh_exception(self):
200238
server.kill()
201239

202240
def test_pssh_client_timeout(self):
203-
self.server.kill()
204241
listen_socket = make_socket(self.host)
205242
listen_port = listen_socket.getsockname()[1]
206243
server_timeout=0.2
@@ -221,23 +258,40 @@ def test_pssh_client_timeout(self):
221258
raise server.exception
222259
except gevent.Timeout:
223260
pass
261+
# chan_timeout = output[self.host]['channel'].gettimeout()
262+
# self.assertEqual(client_timeout, chan_timeout,
263+
# msg="Channel timeout %s does not match requested timeout %s" %(
264+
# chan_timeout, client_timeout,))
224265
del client
225266
server.kill()
226267

227-
def test_pssh_client_run_command_password(self):
268+
def test_pssh_client_exec_command_password(self):
228269
"""Test password authentication. Embedded server accepts any password
229270
even empty string"""
230271
client = ParallelSSHClient([self.host], port=self.listen_port,
231272
password='')
232-
output = client.run_command(self.fake_cmd)
233-
client.join(output)
273+
cmd = client.exec_command(self.fake_cmd)[0]
274+
output = client.get_stdout(cmd)
234275
self.assertTrue(self.host in output,
235276
msg="No output for host")
236277
self.assertTrue(output[self.host]['exit_code'] == 0,
237278
msg="Expected exit code 0, got %s" % (
238279
output[self.host]['exit_code'],))
239280
del client
240281

282+
def test_pssh_client_long_running_command(self):
283+
expected_lines = 5
284+
client = ParallelSSHClient([self.host], port=self.listen_port,
285+
pkey=self.user_key)
286+
cmd = client.exec_command(self.long_cmd(expected_lines))[0]
287+
output = client.get_stdout(cmd, return_buffers=True)
288+
self.assertTrue(self.host in output, msg="Got no output for command")
289+
stdout = list(output[self.host]['stdout'])
290+
self.assertTrue(len(stdout) == expected_lines,
291+
msg="Expected %s lines of response, got %s" % (
292+
expected_lines, len(stdout)))
293+
del client
294+
241295
def test_pssh_client_long_running_command_exit_codes(self):
242296
expected_lines = 5
243297
client = ParallelSSHClient([self.host], port=self.listen_port,

0 commit comments

Comments
 (0)