This is a fix for issue #11, reported by Kamil Paral on the
old trac issue tracker about 10 months ago. Please refer
to the issue description on:
https://fedorahosted.org/pipermail/autoqa-devel/2011-January/001548.html
And on the issue itself:
https://github.com/autotest/autotest/issues/11
We have the method send_file on abstract_ssh.py, that has
the AbstractSSHHost class. This method sends a file, dir
or list of files and/or dirs to a host. First, it will try
to use rsync, and if that's not possible, it will fall
back to scp. Well, it turns out that if the destination
has to be a directory and it does not exist on the
remote machine, the scp will fail.
The patch fixes the issue with heuristics on whether to
create or not the destination directory on the remote
machine. Then the autoqa directory copy can be made
reliably with:
host.send_file('/etc/autoqa/', '/etc/autoqa/', delete_dest=True)
The form:
host.send_file('/etc/autoqa', '/etc/autoqa', delete_dest=True)
Does not work on purpose (see the method docstring).
Risk: Low - Fixes a code path expected behavior (ssh fallback
behaves the same as the rsync counterpart), and I don't seem
to get unittest regressions
Tested: Unittests + testing send.file with scp fallback + running
autoserv with scp fallback
Signed-off-by: Lucas Meneghel Rodrigues <lmr(a)redhat.com>
---
server/hosts/abstract_ssh.py | 35 ++++++++++++++++++++++++++++++-----
1 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/server/hosts/abstract_ssh.py b/server/hosts/abstract_ssh.py
index 0f61391..582fa40 100644
--- a/server/hosts/abstract_ssh.py
+++ b/server/hosts/abstract_ssh.py
@@ -347,6 +347,7 @@ class AbstractSSHHost(SiteHost):
self.start_master_ssh()
if isinstance(source, basestring):
+ source_is_dir = os.path.isdir(source)
source = [source]
remote_dest = self._encode_remote_paths([dest])
@@ -365,11 +366,35 @@ class AbstractSSHHost(SiteHost):
if try_scp:
# scp has no equivalent to --delete, just drop the entire dest dir
if delete_dest:
- is_dir = self.run("ls -d %s/" % dest,
- ignore_status=True).exit_status == 0
- if is_dir:
- cmd = "rm -rf %s && mkdir %s"
- cmd %= (dest, dest)
+ dest_exists = False
+ try:
+ self.run("test -x %s" % dest)
+ dest_exists = True
+ except error.AutoservRunError:
+ pass
+
+ dest_is_dir = False
+ if dest_exists:
+ try:
+ self.run("test -d %s" % dest)
+ dest_is_dir = True
+ except error.AutoservRunError:
+ pass
+
+ # If there is a list of more than one path, destination *has*
+ # to be a dir. If there's a single path being transfered and
+ # it is a dir, the destination also has to be a dir. Therefore
+ # it has to be created on the remote machine in case it doesn't
+ # exist, otherwise we will have an scp failure.
+ if len(source) > 1 or source_is_dir:
+ dest_is_dir = True
+
+ if dest_exists and dest_is_dir:
+ cmd = "rm -rf %s && mkdir %s" % (dest, dest)
+ self.run(cmd)
+
+ elif not dest_exists and dest_is_dir:
+ cmd = "mkdir %s" % dest
self.run(cmd)
local_sources = self._make_rsync_compatible_source(source, True)
--
1.7.6