Skip to content

Commit a63e430

Browse files
committed
add custom options to sshdriver
added the possibility to define custom option for the SSHDriver in the environment yaml Signed-off-by: Nikolaj Rahbel <[email protected]>
1 parent 9f723bd commit a63e430

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

CHANGES.rst

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ New Features in 0.5.0
3535
forwarding to/from the exporter.
3636
- The SSH connection timeout can now be globally controlled using the
3737
``LG_SSH_CONNECT_TIMEOUT`` environment variable.
38+
- Possible to define extra option for ssh connection
3839

3940
Bug fixes in 0.5.0
4041
~~~~~~~~~~~~~~~~~~

doc/configuration.rst

+6
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,10 @@ Implements:
14831483
14841484
SSHDriver:
14851485
keyfile: example.key
1486+
extra_options:
1487+
- "-o option1"
1488+
- "-o options2"
1489+
- "-4"
14861490
14871491
Arguments:
14881492
- keyfile (str): optional, filename of private key to login into the remote system
@@ -1491,6 +1495,8 @@ Arguments:
14911495
stdout, and an empty list as second element.
14921496
- connection_timeout (float, default=30.0): timeout when trying to establish connection to
14931497
target.
1498+
- options (list or str): optional, a list of extra options required for the ssh
1499+
connection, e.g. defining host key algorithms.
14941500

14951501
UBootDriver
14961502
~~~~~~~~~~~

labgrid/driver/sshdriver.py

+7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class SSHDriver(CommandMixin, Driver, CommandProtocol, FileTransferProtocol):
3030
bindings = {"networkservice": "NetworkService", }
3131
priorities = {CommandProtocol: 10, FileTransferProtocol: 10}
3232
keyfile = attr.ib(default="", validator=attr.validators.instance_of(str))
33+
extra_options = attr.ib(default="", validator=attr.validators.instance_of((str, list)))
3334
stderr_merge = attr.ib(default=False, validator=attr.validators.instance_of(bool))
3435
connection_timeout = attr.ib(default=float(get_ssh_connect_timeout()), validator=attr.validators.instance_of(float))
3536

@@ -48,6 +49,12 @@ def on_activate(self):
4849
if not self.networkservice.password:
4950
self.ssh_prefix += ["-o", "PasswordAuthentication=no"]
5051

52+
if isinstance(self.extra_options, str) and len(self.extra_options) > 0:
53+
self.ssh_prefix += shlex.split(self.extra_options)
54+
elif isinstance(self.extra_options, list) and len(self.extra_options) > 0:
55+
for eo in self.extra_options:
56+
self.ssh_prefix += shlex.split(eo)
57+
5158
self.control = self._start_own_master()
5259
self.ssh_prefix += ["-F", "none"]
5360
if self.control:

tests/test_sshdriver.py

+40
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,46 @@ def test_create(target, mocker):
3838
s = SSHDriver(target, "ssh")
3939
assert isinstance(s, SSHDriver)
4040

41+
def test_can_define_ssh_options(target, mocker):
42+
NetworkService(target, "service", "1.2.3.4", "root")
43+
call = mocker.patch('subprocess.call')
44+
call.return_value = 0
45+
popen = mocker.patch('subprocess.Popen', autospec=True)
46+
path = mocker.patch('os.path.exists')
47+
path.return_value = True
48+
instance_mock = mocker.MagicMock()
49+
popen.return_value = instance_mock
50+
instance_mock.wait = mocker.MagicMock(return_value=0)
51+
52+
tp = SSHDriver(target, "ssh")
53+
tp.extra_options = "-o HostKeyAlgorithms=+ssh-rsa"
54+
s = target.get_driver("SSHDriver")
55+
assert "HostKeyAlgorithms=+ssh-rsa" in s.ssh_prefix
56+
57+
def test_extra_options_can_be_a_list(target, mocker):
58+
NetworkService(target, "service", "1.2.3.4", "root")
59+
call = mocker.patch('subprocess.call')
60+
call.return_value = 0
61+
popen = mocker.patch('subprocess.Popen', autospec=True)
62+
path = mocker.patch('os.path.exists')
63+
path.return_value = True
64+
instance_mock = mocker.MagicMock()
65+
popen.return_value = instance_mock
66+
instance_mock.wait = mocker.MagicMock(return_value=0)
67+
68+
tp = SSHDriver(target, "ssh")
69+
tp.extra_options = [
70+
"-o HostKeyAlgorithms=+ssh-rsa",
71+
"-o HostKeyAlgorithms=+ssh-dsa",
72+
]
73+
s = target.get_driver("SSHDriver")
74+
assert "HostKeyAlgorithms=+ssh-rsa" in s.ssh_prefix
75+
assert "HostKeyAlgorithms=+ssh-dsa" in s.ssh_prefix
76+
77+
def test_no_options_will_not_result_in_none_prefix(ssh_driver_mocked_and_activated, mocker):
78+
s = ssh_driver_mocked_and_activated
79+
assert not '' in s.ssh_prefix
80+
4181
def test_run_check(ssh_driver_mocked_and_activated, mocker):
4282
s = ssh_driver_mocked_and_activated
4383
s._run = mocker.MagicMock(return_value=(['success'], [], 0))

0 commit comments

Comments
 (0)