Skip to content

Commit 16d392f

Browse files
Kincaid Savoiepkittenis
authored andcommitted
Implemented copy_file_to_local in pssh_client and created accompanying test.
1 parent 129fc8f commit 16d392f

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

pssh/pssh_client.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,4 +857,39 @@ def _copy_file(self, host, local_file, remote_file, recurse=False):
857857
agent=self.agent,
858858
channel_timeout=self.channel_timeout)
859859
return self.host_clients[host].copy_file(local_file, remote_file,
860-
recurse=recurse)
860+
861+
def copy_file_to_local(self, remote_file, local_file):
862+
"""Copy remote file to local file in parallel
863+
864+
:param remote_file: remote filepath to copy to local host
865+
:type remote_file: str
866+
:param local_file: local filepath on local host to copy file to
867+
:type local_file: str
868+
869+
.. note ::
870+
Local directories in `local_file` that do not exist will be
871+
created as long as permissions allow.
872+
873+
.. note ::
874+
Path separation is handled client side so it is possible to copy
875+
to/from hosts with differing path separators, like from/to Linux
876+
and Windows.
877+
878+
.. note ::
879+
File names will be de-duplicated by appending the hostname to the
880+
filepath.
881+
882+
:rtype: List(:mod:`gevent.Greenlet`) of greenlets for remote copy \
883+
commands
884+
"""
885+
return [self.pool.spawn(self._copy_file_to_local, host, remote_file, local_file)
886+
for host in self.hosts]
887+
888+
def _copy_file_to_local(self, host, remote_file, local_file):
889+
"""Make sftp client, copy file to local"""
890+
if not self.host_clients[host]:
891+
self.host_clients[host] = SSHClient(host, user=self.user,
892+
password=self.password,
893+
port=self.port, pkey=self.pkey,
894+
forward_ssh_agent=self.forward_ssh_agent)
895+
return self.host_clients[host].copy_file_to_local(remote_file, local_file + '_' + host)

tests/test_pssh_client.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,31 @@ def test_pssh_client_copy_file_failure(self):
450450
for path in [local_test_path, remote_test_path]:
451451
shutil.rmtree(path)
452452

453+
def test_pssh_copy_file_to_local(self):
454+
"""Test parallel copy file to local host"""
455+
test_file_data = 'test'
456+
remote_filename = 'test_file'
457+
local_test_dir, local_filename = 'local_test_dir', 'test_file_copy'
458+
local_filename = os.path.sep.join([local_test_dir, local_filename])
459+
test_file = open(remote_filename, 'w')
460+
test_file.writelines([test_file_data + os.linesep])
461+
test_file.close()
462+
server = start_server({ self.fake_cmd : self.fake_resp },
463+
self.listen_socket)
464+
client = ParallelSSHClient([self.host], port=self.listen_port,
465+
pkey=self.user_key)
466+
cmds = client.copy_file_to_local(remote_filename, local_filename)
467+
cmds[0].get()
468+
local_filename += '_' + self.host
469+
self.assertTrue(os.path.isdir(local_test_dir),
470+
msg="SFTP create local directory failed")
471+
self.assertTrue(os.path.isfile(local_filename),
472+
msg="SFTP copy failed")
473+
for filepath in [remote_filename, local_filename]:
474+
os.unlink(filepath)
475+
del client
476+
server.join()
477+
453478
def test_pssh_pool_size(self):
454479
"""Test setting pool size to non default values"""
455480
hosts = ['host-%01d' % d for d in xrange(5)]

0 commit comments

Comments
 (0)