Skip to content

Conversation

@perseoGI
Copy link
Contributor

@perseoGI perseoGI commented Jul 7, 2025

Changelog: omit
Docs: omit

Adapt changes from #17357

Partially migrated plain sfpt direct usages and copy the full conan config (without the cache packages) to the remote machine instead of just copying the build/host profiles.

@perseoGI perseoGI added this to the 2.19.0 milestone Jul 7, 2025
self.client.load_system_host_keys()
self.client.connect(hostname)
self.runner_output = RunnerOutput(hostname)
self.remote_conn = RemoteConnection(self.client, self.runner_output)
Copy link
Member

Choose a reason for hiding this comment

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

This is confusing to have both a self.client that is a SSHClient, and to have another self.remote_conn, that is an object that contains another SSHClient

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I understand your concern and agree with you.
self.client will be removed in a future PR. I'm trying to split changes from #17357 and to do the migration in an incremental way, some duplications have to coexist.

Copy link
Member

Choose a reason for hiding this comment

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

I am fine with it, maybe just add a couple of comments:

# this self.client manages the main ssh connection
self.client = SSHClient()

# This client manages just the sftp transfers
# TODO: Integrate both client calls in one
self.remote_conn = RemoteConnection

Copy link
Contributor

Choose a reason for hiding this comment

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

I understand your concern and agree with you.
self.client will be removed in a future PR. I'm trying to split changes from #17357 and to do the migration in an incremental way, some duplications have to coexist.

I'm not entirely sure it's justified to have a whole class just to wrap simple calls - however, I would argue that these are not duplicates, just have very confusing names.

self.client = SSHClient() this is very clear

self.remote_conn = RemoteConnection this not so much - this is only wrapping around paramiko's SFTPClient - which is a different class because it's a different connection. Arguably, the RemoteConnection class does not need to get a new one for each operation.

Could be two attributes, self.ssh_client and self.sftp_client - persist the latter throughout the entire execution, rather than open a new connection for each operation (see my comments elsewhere)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okey, I've updated the code renaming the class properties

def _sync_conan_config(self):
# Transfer conan config to remote
self.remote_conn.put_dir(
self.conan_api.config.home(),
Copy link
Contributor

Choose a reason for hiding this comment

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

What folder is this sending, exactly? I would probably have something more explicit rather than anything by exclusion -
We could stand simple and just sync the profiles folder (maybe the remotes and maybe global.conf)

we should probably think ahead - there's a chance we'll have to be more selective (any configs that have paths that are relevant to the "local" machine will not work on the remote runner!)

Copy link
Contributor Author

@perseoGI perseoGI Jul 23, 2025

Choose a reason for hiding this comment

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

That is a good approach. I've updated the method to only copy:

  • profiles folder
  • settings.yml
  • settings_user.yml
  • global.conf
  • remotes.json

I've added a TODO note to check for local path references on each file before copying. If you agree, I can implement a basic version of that functionality in this PR, or I can leave it for a future (and isolated) PR.

continue
if item.is_file():
self.runner_output.verbose(f"Copying file {item.as_posix()} to {dest_item}")
self.put(item.as_posix(), dest_item)
Copy link
Contributor

Choose a reason for hiding this comment

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

we are opening a new sftp connection for each file, which doesn't feel right, i would open/close a new connection for every single file operation.
I would rename this class sftpClient or something to that effect, keep the paramiko object as an attribute (passed to the constructor), and persist it instead of calling open_sftp() from this class

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is a good improve in performance, thank you!

try:
sftp.mkdir(folder)
except IOError:
if ignore_existing:
Copy link
Contributor

Choose a reason for hiding this comment

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

is it possible for the IOError exception to be raised by something else other than the directory existing??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not in the context of mkdir

Copy link
Contributor

Choose a reason for hiding this comment

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

Is the error type different if you don't have permission to create the folder? The question is if you can hide a permissions error if you have ignore_existing=True.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated the code with a more exhaustive exception check, thanks!

@czoido czoido modified the milestones: 2.19.0, 2.20 Jul 23, 2025
self.conan_api.cache.restore(local_cache_tgz)


class RemoteConnection:
Copy link
Contributor

Choose a reason for hiding this comment

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

do we want to allow Python annotations in this class?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I cannot answer this to you, IMHO I prefer annotations

@memsharded memsharded modified the milestones: 2.20, 2.21 Aug 28, 2025
@memsharded memsharded modified the milestones: 2.21.0, 2.22.0 Sep 26, 2025
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