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

ssh transport : adapt for subclassing #4363

Merged
merged 13 commits into from
Sep 23, 2020
Merged

Conversation

adegomme
Copy link
Contributor

@adegomme adegomme commented Sep 9, 2020

follow up of #4199 ( and #4235)

To be able to release aiida-sshonly as a plugin without duplicating code, I had to make some tiny changes to ssh.py, easing its subclassing to better isolate the file transfer parts and keep sftp references wrapped.

  • this adds some simple wrappers around some sftp calls, that can be overriden in another class. Most methods don't need changing, as it has to be overriden fully, mainly utilities are changed (stat, lstat, symlink)
  • new method to initialize file transport separately. Also adds error checking for SFTP initialization, with an explicit message if it fails to launch, and a possible solution.
  • also limit the output of a log message to 1000 characters, as whole files can be printed in it when using a transport sending large ssh commands.

Merging this would would allow (even better if #3787 is also merged) the plugin to use ssh.py from aiida instead of a copy, which leads to incompatibilities and duplications.

- try to minimize intrusivity and changes in ssh.py (no new class/subclass)
- initialization of the file transport is moved to another method
- some calls are untouched, as they have to be overriden entirely
- some calls had to be split (by adding a wrapper around the self.sftp call), so that only this wrapper is overriden.
When sending files with ssonly plugin, they get pasted entirely in the log otherwise.
@codecov
Copy link

codecov bot commented Sep 9, 2020

Codecov Report

Merging #4363 into develop will decrease coverage by 0.03%.
The diff coverage is 80.77%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #4363      +/-   ##
===========================================
- Coverage    79.23%   79.20%   -0.02%     
===========================================
  Files          476      473       -3     
  Lines        34827    34800      -27     
===========================================
- Hits         27591    27560      -31     
- Misses        7236     7240       +4     
Flag Coverage Δ
#django 73.09% <80.77%> (+0.05%) ⬆️
#sqlalchemy 72.29% <80.77%> (-<0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
aiida/transports/plugins/ssh.py 77.78% <80.77%> (+0.03%) ⬆️
aiida/engine/daemon/runner.py 79.32% <0.00%> (-3.44%) ⬇️
aiida/engine/daemon/client.py 72.42% <0.00%> (-1.14%) ⬇️
aiida/orm/entities.py 97.62% <0.00%> (-0.59%) ⬇️
aiida/transports/plugins/local.py 81.29% <0.00%> (-0.25%) ⬇️
aiida/backends/sqlalchemy/models/group.py 92.86% <0.00%> (-0.24%) ⬇️
aiida/backends/djsite/db/models.py 81.18% <0.00%> (-0.11%) ⬇️
aiida/orm/nodes/data/remote.py 58.52% <0.00%> (ø)
aiida/backends/djsite/db/migrations/__init__.py 68.84% <0.00%> (ø)
...migrations/versions/0edcdd5a30f0_dbgroup_extras.py
... and 2 more

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 26f14ae...41cd80b. Read the comment docs.

@ltalirz
Copy link
Member

ltalirz commented Sep 15, 2020

thanks a lot, @adegomme !
@giovannipizzi would you be available for reviewing this?

Copy link
Member

@ramirezfranciscof ramirezfranciscof left a comment

Choose a reason for hiding this comment

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

Hi @adegomme , and thanks for this re-structuring! This all looks really good, I just had one modification request for the error message and maybe some discussion regarding the 1000 char cap on the logging.

aiida/transports/plugins/ssh.py Outdated Show resolved Hide resolved
@@ -1228,7 +1256,7 @@ def _exec_command_internal(self, command, combine_stderr=False, bufsize=-1): #
else:
command_to_execute = command

self.logger.debug('Command to be executed: {}'.format(command_to_execute))
self.logger.debug('Command to be executed: {}'.format(command_to_execute[:1000]))
Copy link
Member

Choose a reason for hiding this comment

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

So the rest of the re-organization and wrapping of methods seems ok to me, but this is the only modification that I am unsure about. Can't you be loosing important log info like this? I would also maybe ask for the input of @giovannipizzi and/or @sphuber in this, since they probably know better what to expect inside that command and why is being logged.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also interested to know why @adegomme thinks this should be cropped.

Copy link
Contributor Author

@adegomme adegomme Sep 17, 2020

Choose a reason for hiding this comment

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

To send a file with the sshonly plugin, the resulting command is equivalent to ssh remote "echo '$(cat localfile)' | cat > remotefile" , with the '$(cat localfile)' being a python read instead, as I never managed to have the cat version behave correctly.
This logger call means that the whole content of the file is printed in the log :
example when making a 'verdi computer test'
09/17/2020 10:17:12 AM <1120861> aiida.transport.SshOnlyTransport: [DEBUG] Command to be executed: cd '/path/aiida' && echo 'Test from '"'"'verdi computer test'"'"' on 2020-09-17T10:17:05.830707' | cat > /path/aiida/tmpbtteknws

So this adds the whole file content to the log output when debug is activated, which is not great. Every input file, structure file, pseudopotential file gets printed in the stdout or the log when debug is on, and when several MB get dumped on you, this can be troublesome.
Cropping is meant to avoid ruining the log and the terminal. 1000 char is a bit arbitrary (but seemed to be large enough to not affect other messages in my tests), and maybe we could add a comment when it's cropped ( simply "...", or "cropped to 1000 chars to maintain readability") to avoid confusion.
Another idea would be to have an optional parameter on _exec_command_internal to disable this log message, but you would not see any file upload log in this case.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. Thanks for the explanation. In any case, even if we keep this, we should definitely comment this, because it is not obvious at all, especially given that the actual use case comes from a subclass that lives in another plugin package. @giovannipizzi do you see a way around this? If we make the cropping size an optional argument to the function, at least SshOnly can override the copy file method to call _exec_command_internal to pass max_log_size=1000 or something to that effect.

Copy link
Member

Choose a reason for hiding this comment

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

After discussing with @sphuber I think a good solution is to have a class attribute, e.g. _MAX_EXEC_COMMAND_LOG_SIZE=None in this base class.
Here the logic would not crop if self._MAX_EXEC_COMMAND_LOG_SIZE is None, otherwise it would crop to this length (command_to_execute[:self._MAX_EXEC_COMMAND_LOG_SIZE]).

In this way the current behaviour is unchanged, and in your subclass @adegomme you can just set _MAX_EXEC_COMMAND_LOG_SIZE to the value you want.

@adegomme what do you think? Are you OK to do this small change? After, it's ready to merge for me

Copy link
Contributor

@sphuber sphuber 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 @adegomme in addition to @ramirezfranciscof comments, I have some other small comments, but other than that this looks good and almost ready to go.

aiida/transports/plugins/ssh.py Outdated Show resolved Hide resolved
aiida/transports/plugins/ssh.py Outdated Show resolved Hide resolved
aiida/transports/plugins/ssh.py Outdated Show resolved Hide resolved
aiida/transports/plugins/ssh.py Outdated Show resolved Hide resolved
@sphuber
Copy link
Contributor

sphuber commented Sep 17, 2020

Thanks for all the changes @adegomme . I am happy with the current state, except I would like to think a bit more about the cropping of the logging in the _exec_internal_command. Once we have the input of @giovannipizzi I think this should be ready to go.

@@ -1228,7 +1256,7 @@ def _exec_command_internal(self, command, combine_stderr=False, bufsize=-1): #
else:
command_to_execute = command

self.logger.debug('Command to be executed: {}'.format(command_to_execute))
self.logger.debug('Command to be executed: {}'.format(command_to_execute[:1000]))
Copy link
Member

Choose a reason for hiding this comment

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

After discussing with @sphuber I think a good solution is to have a class attribute, e.g. _MAX_EXEC_COMMAND_LOG_SIZE=None in this base class.
Here the logic would not crop if self._MAX_EXEC_COMMAND_LOG_SIZE is None, otherwise it would crop to this length (command_to_execute[:self._MAX_EXEC_COMMAND_LOG_SIZE]).

In this way the current behaviour is unchanged, and in your subclass @adegomme you can just set _MAX_EXEC_COMMAND_LOG_SIZE to the value you want.

@adegomme what do you think? Are you OK to do this small change? After, it's ready to merge for me

@adegomme
Copy link
Contributor Author

The _MAX_EXEC_COMMAND_LOG_SIZE seems to be a great solution, I will do this immediately.

@sphuber sphuber dismissed stale reviews from giovannipizzi and ramirezfranciscof September 23, 2020 11:29

Changes addressed

@sphuber sphuber merged commit f2f6e2f into aiidateam:develop Sep 23, 2020
@sphuber
Copy link
Contributor

sphuber commented Sep 23, 2020

Thanks a lot @adegomme !

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