Skip to content

Commit

Permalink
Merge pull request #178 from xcp-ng/sftp-support
Browse files Browse the repository at this point in the history
sftp support
  • Loading branch information
stormi authored Nov 6, 2023
2 parents 4475d6a + e070cbb commit 80556b1
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
23 changes: 23 additions & 0 deletions lib/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,29 @@ def scp(hostname_or_ip, src, dest, check=True, suppress_fingerprint_warnings=Tru

return res

def sftp(hostname_or_ip, cmds, check=True, suppress_fingerprint_warnings=True):
if suppress_fingerprint_warnings:
# Suppress warnings and questions related to host key fingerprints
# because on a test network IPs get reused, VMs are reinstalled, etc.
# Based on https://unix.stackexchange.com/a/365976/257493
opts = '-o "StrictHostKeyChecking no" -o "LogLevel ERROR" -o "UserKnownHostsFile /dev/null"'

args = "sftp {} -b - root@{}".format(opts, hostname_or_ip)
input = bytes("\n".join(cmds), 'utf-8')
res = subprocess.run(
args,
input=input,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=False
)

if check and res.returncode:
raise SSHCommandFailed(res.returncode, res.stdout.decode(), "{} -- {}".format(args, cmds))

return res

def local_cmd(cmd, check=True, decode=True):
""" Run a command locally on tester end. """
res = subprocess.run(
Expand Down
16 changes: 15 additions & 1 deletion lib/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,20 @@ def ssh_with_result(self, cmd):
return self.ssh(cmd, check=False, simple_output=False)

def scp(self, src, dest, check=True, suppress_fingerprint_warnings=True, local_dest=False):
# Stop execution if scp() is used on Windows VMs as some OpenSSH releases for Windows don't
# have support for the scp legacy protocol. Callers must use vm.sftp_put() instead
assert not self.is_windows, "You cannot use scp() on Windows VMs. Please use vm.sftp_put() instead"

return commands.scp(
self.ip, src, dest, check=check,
suppress_fingerprint_warnings=suppress_fingerprint_warnings,
local_dest=local_dest
)

def sftp_put(self, src, dest, check=True, suppress_fingerprint_warnings=True):
cmd = f"put {src} {dest}"
return commands.sftp(self.ip, [cmd], check, suppress_fingerprint_warnings)

def is_ssh_up(self):
try:
return self.ssh_with_result(['true']).returncode == 0
Expand Down Expand Up @@ -234,7 +242,13 @@ def start_background_process(self, cmd):
cmd + '\n'
])
f.flush()
self.scp(f.name, script)
if self.is_windows:
# Use sftp instead of scp for lack of legacy scp protocol in OpenSSH for Windows 11.
# sftp doesn't know /tmp from the git-bash environment which is mapped to
# /Users/root/AppData/Local/Temp for the user root so copy the script there.
self.sftp_put(f.name, script.replace("/tmp/", "/Users/root/AppData/Local/Temp/"))
else:
self.scp(f.name, script)
# Use bash to run the script, to avoid being hit by differences between shells, for example on FreeBSD
# It is a documented requirement that bash is present on all test VMs.
self.ssh(['bash', script], background=True)
Expand Down

0 comments on commit 80556b1

Please sign in to comment.