-
Notifications
You must be signed in to change notification settings - Fork 80
ssh: Use paramiko instead of pxssh #450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ssh: Use paramiko instead of pxssh #450
Conversation
4a8adf0
to
6c2447e
Compare
A quick timeit benchmark on
That's 4.4 times faster with paramiko. This difference in speed allows a LISA test to go from |
Looks good. Thanks for doing this! Given the nature of the change, this will need to be thoroughly tested across a range of devices and applications before we merge. |
Of course, I'm currently testing the following setups:
Expected compat breakages:
TODO:
Opened questions:
|
That is probably fine.
Yeah, it's to deal with TTY weirdness that seemed to leave |
6c2447e
to
6d92f13
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed this seems like a good option.
Regarding the SSH options features @mpekatsoula would you be able to provide us with some of your use cases to see how they could be mapped onto this?
devlib/utils/ssh.py
Outdated
source = '{}@{}:{}'.format(self.username, self.host, source) | ||
return self._scp(source, dest, timeout) | ||
sftp = self._get_sftp(timeout) | ||
sftp.get(source, dest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The paramiko sftp implementation doesn't seem to be able to deal with pushing/pulling directories directly so we might need to add support for this manually for convenience.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the destination already exists when pushing a folder, should it be wiped or should the new content overlayed on the existing folder ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think overlaying would make sense, this would at least preserve the existing behaviour of scp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect, that's also easier to implement :)
6d92f13
to
2457271
Compare
Updated with:
|
@marcbonnici |
This can be achieved by not loading the host keys (currently done here: https://github.com/ARM-software/devlib/pull/450/files#diff-d0a4376874b01b42b478cb7119010811R206)
This handled by the |
Updating from the offline chat with @setrofim and @marcbonnici about TODO:
1.1) Use
From @setrofim : This handled by the AutoAddPolicy set here: https://github.com/ARM-software/devlib/pull/450/files#diff-d0a4376874b01b42b478cb7119010811R207
This leaves us with the following user-visible change:
|
That's a bit of a tricky question since that means that the user will have to read stdout and stderr, otherwise the command might get blocked until the user does so, leading to a timeout triggering. |
Getting rid of them is not an option. Can Paramiko be monkey-patched to allow redirection? If not, then go with the thread. From the user's perspective, the behaviour of |
OK, having had a brief look through Paramiko, monkey-patching isn't going to work, and given its implementation, |
After experimenting a bit, it appears that with the current default That would mean we only need to spawn a thread if someone gives one of these:
(list taken from https://docs.python.org/3/library/subprocess.html#subprocess.Popen) |
2457271
to
9aeeded
Compare
Updated with remaining TODOs:
|
d4611ca
to
7e0b08b
Compare
@marcbonnici @setrofim The PR should now be finished feature-wise and somewhat ready for testing. It will need some polishing for review (I'll try to break down the big commit in smaller ones), but the code itself can now be expected to work. The main changes are:
Performance-wise, an |
7e0b08b
to
9d1d0bf
Compare
9d1d0bf
to
a8429fa
Compare
@marcbonnici @setrofim I've split the PR into more contained commits. The last one is pretty big but there isn't really any alternative since it's almost all new code. It should now be ready for review proper and testing so I removed the [RFC] tag on the PR name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some findings from initial testing with a chromebook.
ab3b644
to
f2d8435
Compare
3640f1b
to
c49ce1b
Compare
c49ce1b
to
4c443af
Compare
4c443af
to
b8e21ac
Compare
b8e21ac
to
84e6789
Compare
Hi @setrofim @marcbonnici, should I squash the WIP patches into the ones they are fixing up to prepare the final version of the branch ? |
Yes, please. I think we've gotten all the feedback we're going to for this; and I don't think anything more would need to be changed. |
Use the timeout parameter added in Python 3.3, which removes the need for the timer thread and avoids some weird issues in preexec_fn, as it's now documented to sometimes not work when threads are involved.
Similar to a regular property(), with the following differences: * Values are memoized and are threadlocal * The value returned by the property needs to be called (like a weakref) to get the actual value. This level of indirection is needed to allow methods to be implemented in the proxy object without clashing with the value's methods. * If the above is too annoying, a "sub property" can be created with the regular property() behavior (and therefore without the additional methods) using tls_property.basic_property .
This frees the connection to have to handle threading issues, since each thread using the Target will have its own connection. The connection will be garbage collected when the thread using it dies, avoiding connection leaks.
Update a command line to redirect standard streams as specified using the parameters. This helper allows honoring streams specified in the same way as subprocess.Popen, by doing it as much using shell redirections as possible.
* Unify the behavior of background commands in connections.BackgroundCommand(). This implements a subset of subprocess.Popen class, with a unified behavior across all connection types * Implement the SSH connection using paramiko rather than pxssh.
Check that executing the most basic command works without troubles or stderr content. If that's not the case, raise a TargetStableError.
84e6789
to
30e0ead
Compare
@setrofim the branch is updated |
Here is an crude port of SshConnection to paramiko, so pxssh can rest in peace.
Quote from a pexpect maintainer in 2014 on DFE/MONK#108:
Note: it might be a better idea to just introduce a new class rather than ruthlessly modifying SshConnection, since TelnetConnection relies on pexpect and the recent addition of
options
parameter will not allow easily moving away from an actual ssh/scp command. (paramiko seems to have an OpenSSH config emulation, maybe that would allow that to work ...)Note2: Some APIs that were not properly abstracted are also somewhat broken, like
background()
method that leaked aPopen
object, rather than just giving a handle on stdin/stdout/stderr like paramiko does.All in all, it took 2h to go from scratch to something that seem to work well enough for LISA, which is less than 10% of the time spent chasing TTY size issues (worked around but not really fixed AFAIR) and control sequences issues (#442). It also reduces by 2 the mount of code in
SshConnection
, mostly removing cruft related to interactive terminal management: