Skip to content

Commit 9636068

Browse files
authored
Merge pull request #1558 from ARM-software/ssh-driver-tools
driver/sshdriver: read from tools
2 parents de5257d + 2a703fa commit 9636068

File tree

4 files changed

+80
-14
lines changed

4 files changed

+80
-14
lines changed

labgrid/driver/sshdriver.py

+26-14
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ class SSHDriver(CommandMixin, Driver, CommandProtocol, FileTransferProtocol):
4141
def __attrs_post_init__(self):
4242
super().__attrs_post_init__()
4343
self._keepalive = None
44+
self._ssh = self._get_tool("ssh")
45+
self._scp = self._get_tool("scp")
46+
self._sshfs = self._get_tool("sshfs")
47+
self._rsync = self._get_tool("rsync")
48+
49+
def _get_tool(self, name):
50+
if self.target.env:
51+
return self.target.env.config.get_tool(name)
52+
return name
4453

4554
def _get_username(self):
4655
"""Get the username from this class or from NetworkService"""
@@ -105,7 +114,7 @@ def _start_own_master_once(self, timeout):
105114
self.tmpdir, f'control-{self.networkservice.address}'
106115
)
107116

108-
args = ["ssh", "-f", *self.ssh_prefix, "-x", "-o", f"ConnectTimeout={timeout}",
117+
args = [self._ssh, "-f", *self.ssh_prefix, "-x", "-o", f"ConnectTimeout={timeout}",
109118
"-o", "ControlPersist=300", "-o",
110119
"UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no",
111120
"-o", "ServerAliveInterval=15", "-MN", "-S", control.replace('%', '%%'), "-p",
@@ -203,7 +212,7 @@ def _run(self, cmd, codec="utf-8", decodeerrors="strict", timeout=None):
203212
if not self._check_keepalive():
204213
raise ExecutionError("Keepalive no longer running")
205214

206-
complete_cmd = ["ssh", "-x", *self.ssh_prefix,
215+
complete_cmd = [self._ssh, "-x", *self.ssh_prefix,
207216
"-p", str(self.networkservice.port), "-l", self._get_username(),
208217
self.networkservice.address
209218
] + cmd.split(" ")
@@ -238,7 +247,7 @@ def interact(self, cmd=None):
238247
if not self._check_keepalive():
239248
raise ExecutionError("Keepalive no longer running")
240249

241-
complete_cmd = ["ssh", "-x", *self.ssh_prefix,
250+
complete_cmd = [self._ssh, "-x", *self.ssh_prefix,
242251
"-t",
243252
self.networkservice.address
244253
]
@@ -252,7 +261,7 @@ def interact(self, cmd=None):
252261

253262
@contextlib.contextmanager
254263
def _forward(self, forward):
255-
cmd = ["ssh", *self.ssh_prefix,
264+
cmd = [self._ssh, *self.ssh_prefix,
256265
"-O", "forward", forward,
257266
self.networkservice.address
258267
]
@@ -261,7 +270,7 @@ def _forward(self, forward):
261270
try:
262271
yield
263272
finally:
264-
cmd = ["ssh", *self.ssh_prefix,
273+
cmd = [self._ssh, *self.ssh_prefix,
265274
"-O", "cancel", forward,
266275
self.networkservice.address
267276
]
@@ -361,7 +370,8 @@ def scp(self, *, src, dst):
361370
if dst.startswith(':'):
362371
dst = '_' + dst
363372

364-
complete_cmd = ["scp",
373+
complete_cmd = [self._scp,
374+
"-S", self._ssh,
365375
"-F", "none",
366376
"-o", f"ControlPath={self.control.replace('%', '%%')}",
367377
src, dst,
@@ -391,12 +401,12 @@ def rsync(self, *, src, dst, extra=[]):
391401
if dst.startswith(':'):
392402
dst = '_' + dst
393403

394-
ssh_cmd = ["ssh",
404+
ssh_cmd = [self._ssh,
395405
"-F", "none",
396406
"-o", f"ControlPath={self.control.replace('%', '%%')}",
397407
]
398408

399-
complete_cmd = ["rsync",
409+
complete_cmd = [self._rsync,
400410
"-v",
401411
f"--rsh={' '.join(ssh_cmd)}",
402412
"-rlpt", # --recursive --links --perms --times
@@ -417,7 +427,7 @@ def sshfs(self, *, path, mountpoint):
417427
if not self._check_keepalive():
418428
raise ExecutionError("Keepalive no longer running")
419429

420-
complete_cmd = ["sshfs",
430+
complete_cmd = [self._sshfs,
421431
"-F", "none",
422432
"-f",
423433
"-o", f"ControlPath={self.control.replace('%', '%%')}",
@@ -445,7 +455,7 @@ def get_status(self):
445455

446456
@cached_property
447457
def _ssh_version(self):
448-
version = subprocess.run(["ssh", "-V"], capture_output=True, text=True)
458+
version = subprocess.run([self._ssh, "-V"], capture_output=True, text=True)
449459
version = re.match(r"^OpenSSH_(\d+)\.(\d+)", version.stderr)
450460
return tuple(int(x) for x in version.groups())
451461

@@ -472,7 +482,8 @@ def _scp_supports_explicit_scp_mode(self):
472482
@step(args=['filename', 'remotepath'])
473483
def put(self, filename, remotepath=''):
474484
transfer_cmd = [
475-
"scp",
485+
self._scp,
486+
"-S", self._ssh,
476487
*self.ssh_prefix,
477488
"-P", str(self.networkservice.port),
478489
"-r",
@@ -502,7 +513,8 @@ def put(self, filename, remotepath=''):
502513
@step(args=['filename', 'destination'])
503514
def get(self, filename, destination="."):
504515
transfer_cmd = [
505-
"scp",
516+
self._scp,
517+
"-S", self._ssh,
506518
*self.ssh_prefix,
507519
"-P", str(self.networkservice.port),
508520
"-r",
@@ -530,7 +542,7 @@ def get(self, filename, destination="."):
530542

531543
def _cleanup_own_master(self):
532544
"""Exit the controlmaster and delete the tmpdir"""
533-
complete_cmd = f"ssh -x -o ControlPath={self.control.replace('%', '%%')} -O exit -p {self.networkservice.port} -l {self._get_username()} {self.networkservice.address}".split(' ') # pylint: disable=line-too-long
545+
complete_cmd = f"{self._ssh} -x -o ControlPath={self.control.replace('%', '%%')} -O exit -p {self.networkservice.port} -l {self._get_username()} {self.networkservice.address}".split(' ') # pylint: disable=line-too-long
534546
res = subprocess.call(
535547
complete_cmd,
536548
stdin=subprocess.DEVNULL,
@@ -547,7 +559,7 @@ def _cleanup_own_master(self):
547559

548560
def _start_keepalive(self):
549561
"""Starts a keepalive connection via the own or external master."""
550-
args = ["ssh", *self.ssh_prefix, self.networkservice.address, "cat"]
562+
args = [self._ssh, *self.ssh_prefix, self.networkservice.address, "cat"]
551563

552564
assert self._keepalive is None
553565
self._keepalive = subprocess.Popen(

man/labgrid-device-config.5

+16
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ See: <https://www.intel.com/content/www/us/en/docs/programmable/683039/22\-3/hp
132132
Path to the rk\-usb\-loader binary, used by the RKUSBDriver.
133133
See: <https://git.pengutronix.de/cgit/barebox/tree/scripts/rk\-usb\-loader.c>
134134
.TP
135+
.B \fBrsync\fP
136+
Path to the rsync binary, used by the SSHDriver.
137+
See: <https://github.com/rsyncproject/rsync>
138+
.TP
139+
.B \fBscp\fP
140+
Path to the scp binary, used by the SSHDriver.
141+
See: <https://github.com/openssh/openssh\-portable>
142+
.TP
135143
.B \fBsd\-mux\-ctrl\fP
136144
Path to the sd\-mux\-ctrl binary, used by the USBSDWireDriver.
137145
See: <https://git.tizen.org/cgit/tools/testlab/sd\-mux/>
@@ -140,6 +148,14 @@ See: <https://git.tizen.org/cgit/tools/testlab/sd\-mux/>
140148
Path to the sispmctl binary, used by the SiSPMPowerDriver.
141149
See: <https://sispmctl.sourceforge.net/>
142150
.TP
151+
.B \fBssh\fP
152+
Path to the ssh binary, used by the SSHDriver.
153+
See: <https://github.com/openssh/openssh\-portable>
154+
.TP
155+
.B \fBsshfs\fP
156+
Path to the sshfs binary, used by the SSHDriver.
157+
See: <https://github.com/libfuse/sshfs>
158+
.TP
143159
.B \fBuhubctl\fP
144160
Path to the uhubctl binary, used by the USBPowerDriver.
145161
See: <https://github.com/mvp/uhubctl>

man/labgrid-device-config.rst

+16
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ TOOLS KEYS
130130
Path to the rk-usb-loader binary, used by the RKUSBDriver.
131131
See: https://git.pengutronix.de/cgit/barebox/tree/scripts/rk-usb-loader.c
132132

133+
``rsync``
134+
Path to the rsync binary, used by the SSHDriver.
135+
See: https://github.com/rsyncproject/rsync
136+
137+
``scp``
138+
Path to the scp binary, used by the SSHDriver.
139+
See: https://github.com/openssh/openssh-portable
140+
133141
``sd-mux-ctrl``
134142
Path to the sd-mux-ctrl binary, used by the USBSDWireDriver.
135143
See: https://git.tizen.org/cgit/tools/testlab/sd-mux/
@@ -138,6 +146,14 @@ TOOLS KEYS
138146
Path to the sispmctl binary, used by the SiSPMPowerDriver.
139147
See: https://sispmctl.sourceforge.net/
140148

149+
``ssh``
150+
Path to the ssh binary, used by the SSHDriver.
151+
See: https://github.com/openssh/openssh-portable
152+
153+
``sshfs``
154+
Path to the sshfs binary, used by the SSHDriver.
155+
See: https://github.com/libfuse/sshfs
156+
141157
``uhubctl``
142158
Path to the uhubctl binary, used by the USBPowerDriver.
143159
See: https://github.com/mvp/uhubctl

tests/test_sshdriver.py

+22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22
import socket
33

4+
from labgrid import Environment
45
from labgrid.driver import SSHDriver, ExecutionError
56
from labgrid.exceptions import NoResourceFoundError
67
from labgrid.resource import NetworkService
@@ -58,6 +59,27 @@ def test_run_check_raise(target, ssh_driver_mocked_and_activated, mocker):
5859
assert res == (['error'], [], 1)
5960
target.deactivate(s)
6061

62+
def test_default_tools(target):
63+
NetworkService(target, "service", "1.2.3.4", "root")
64+
s = SSHDriver(target, "ssh")
65+
assert [s._ssh, s._scp, s._sshfs, s._rsync] == ["ssh", "scp", "sshfs", "rsync"]
66+
67+
def test_custom_tools(target, tmpdir):
68+
p = tmpdir.join("config.yaml")
69+
p.write(
70+
"""
71+
tools:
72+
ssh: "/path/to/ssh"
73+
scp: "/path/to/scp"
74+
sshfs: "/path/to/sshfs"
75+
rsync: "/path/to/rsync"
76+
"""
77+
)
78+
target.env = Environment(str(p))
79+
NetworkService(target, "service", "1.2.3.4", "root")
80+
s = SSHDriver(target, "ssh")
81+
assert [s._ssh, s._scp, s._sshfs, s._rsync] == [f"/path/to/{t}" for t in ("ssh", "scp", "sshfs", "rsync")]
82+
6183
@pytest.fixture(scope='function')
6284
def ssh_localhost(target, pytestconfig):
6385
name = pytestconfig.getoption("--ssh-username")

0 commit comments

Comments
 (0)