Skip to content
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

SSHExecutor respects MaxSessions #218

Merged
merged 19 commits into from
Nov 19, 2021
Merged

SSHExecutor respects MaxSessions #218

merged 19 commits into from
Nov 19, 2021

Conversation

maxfischer2781
Copy link
Member

@maxfischer2781 maxfischer2781 commented Nov 13, 2021

This PR changes SSHExecutor to use at most MaxSessions at once.

  • Detect remote sshd MaxSessions via probing
  • Limit concurrent sessions

This is a rather straightforward implementation of step 1 in #217. After opening a new connection, it is probed until ChannelOpenError to deduce the remote MaxSessions. This limit is then enforced using a Semaphore on accessing the connection, queueing additional requests.
The large diff of run_command is because the Semaphore logic works best with a context manager.

@codecov-commenter
Copy link

codecov-commenter commented Nov 14, 2021

Codecov Report

Merging #218 (2d31c69) into master (2afcbd4) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #218   +/-   ##
=======================================
  Coverage   99.55%   99.55%           
=======================================
  Files          41       41           
  Lines        1789     1810   +21     
=======================================
+ Hits         1781     1802   +21     
  Misses          8        8           
Impacted Files Coverage Δ
tardis/utilities/executors/sshexecutor.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2afcbd4...2d31c69. Read the comment docs.

@maxfischer2781 maxfischer2781 requested review from a team, mschnepf, RHofsaess and giffels and removed request for a team November 15, 2021 08:10
@maxfischer2781 maxfischer2781 marked this pull request as ready for review November 15, 2021 08:10
mschnepf
mschnepf previously approved these changes Nov 17, 2021
Copy link
Member

@mschnepf mschnepf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 👍
Thanks for the improvement

RHofsaess
RHofsaess previously approved these changes Nov 17, 2021
Copy link

@RHofsaess RHofsaess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like the probing but after a little research I also did not find another way to get the max sessions.
So I think the changes are fine!
Thanks.

Copy link
Member

@giffels giffels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for improving the ssh connection handling. I have a few questions concerning the implementation and a request to further improve unittesting before the approval. Could you take this into account, please?

tardis/utilities/executors/sshexecutor.py Outdated Show resolved Hide resolved
tardis/utilities/executors/sshexecutor.py Show resolved Hide resolved
tardis/utilities/executors/sshexecutor.py Outdated Show resolved Hide resolved
@giffels giffels added this to the 0.7.0 - Release milestone Nov 18, 2021
Copy link
Member

@giffels giffels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for your contribution and applying the suggested changes. Everything looks good now.

Copy link
Member

@mschnepf mschnepf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. 👍
You also get bonus points from me

def test_max_sessions(self):
with self.subTest(sessions="default"):
self.assertEqual(
DEFAULT_MAX_SESSIONS, run_async(probe_max_session, MockConnection())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is idea behind this test?
Isn't it automatically successful?
Or am I misunderstanding something here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a sanity test that the Mock/probe behaves as expected. Other tests rely on the default as well, so if they fail this test reveals whether the issue is with the default or the other tests.

Copy link
Member

@giffels giffels Nov 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It tests the functionality of the probe_max_session function defined in

async def probe_max_session(connection: asyncssh.SSHClientConnection):
"""
Probe the sshd `MaxSessions`, i.e. the multiplexing limit per connection
"""
sessions = 0
# It does not actually matter what kind of session we open here, but:
# - it should stay open without a separate task to manage it
# - it should reliably and promptly clean up when done probing
# `create_process` is a bit heavy but does all that.
async with AsyncExitStack() as aes:
try:
while True:
await aes.enter_context(await connection.create_process())
sessions += 1
except asyncssh.ChannelOpenError:
pass
return sessions
. In case someone changes the code so, that the functionality is not obtained anymore. The test will fail. For example someone removes .

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay thanks. That makes perfectly sense!

Copy link

@RHofsaess RHofsaess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@giffels giffels merged commit c532a19 into master Nov 19, 2021
@giffels giffels deleted the ssh-maxsessions branch November 19, 2021 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants