From d55c1f84598f87cd37b4767a09fa7243f12b396a Mon Sep 17 00:00:00 2001 From: croy Date: Thu, 1 May 2025 16:08:34 -0400 Subject: [PATCH] Streamlining RSync usage Added rsync_to_remote_server as a mirror of rsync_from_remote_server and replaced the call that was using execute_rsync. The execute_rsync call was failing on HostKeyChecking issues. Change-Id: I2ad221b2ef837d5455a754ad651adec2a39b1e06 Signed-off-by: croy --- keywords/files/file_keywords.py | 56 ++++++++++++++----- .../cloud_platform/sanity/test_dc_sanity.py | 10 ++-- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/keywords/files/file_keywords.py b/keywords/files/file_keywords.py index c42cb5d0..1042a2ff 100644 --- a/keywords/files/file_keywords.py +++ b/keywords/files/file_keywords.py @@ -1,6 +1,5 @@ import time -from config.configuration_manager import ConfigurationManager from framework.exceptions.keyword_exception import KeywordException from framework.logging.automation_logger import get_logger from framework.ssh.ssh_connection import SSHConnection @@ -215,19 +214,6 @@ class FileKeywords(BaseKeyword): self.ssh_connection.send_as_sudo(f"rm -r -f {folder_path}") return self.validate_file_exists_with_sudo(folder_path) - def execute_rsync(self, source_path: str, remote_path: str): - """Execute rsync command to copy files from source (active controller) to destination - - Args: - source_path (str): The source path in active controller - remote_path (str): The destination path - """ - pasw = ConfigurationManager.get_lab_config().get_admin_credentials().get_password() - - # active_controller_ssh.send(f"sshpass -p '{pasw}' rsync -avz {source} {user}@{destination}") - self.ssh_connection.send(f"sshpass -p '{pasw}' rsync -avz {source_path} {remote_path}") - self.validate_success_return_code(self.ssh_connection) - def rename_file(self, old_file_name: str, new_file_name: str): """ Renames the file. @@ -238,6 +224,48 @@ class FileKeywords(BaseKeyword): """ self.ssh_connection.send_as_sudo(f"mv {old_file_name} {new_file_name}") + def rsync_to_remote_server(self, local_dest_path: str, remote_server: str, remote_user: str, remote_password: str, remote_path: str, recursive: bool = False, rsync_options: str = "") -> None: + """ + Rsync a file or directory to a remote server from the target host. + + This method runs rsync on the host associated with the current SSHConnection + (self.ssh_connection). It initiates an outbound connection to the remote server + using sshpass for authentication, allowing flexible copying of files or directories + to external sources from the target host. + + Default rsync options are '-avz' (archive mode, verbose, compression). Additional options + can be appended if needed to support scenarios like progress display, bandwidth throttling, or cleanup. + + Args: + local_dest_path (str): Absolute path on the target host where the file or directory should be copied. + remote_server (str): Remote server IP address or hostname. + remote_user (str): Username to authenticate with the remote server. + remote_password (str): Password to authenticate with the remote server. + remote_path (str): Absolute path to the file or directory on the remote server. + recursive (bool, optional): Whether to copy directories recursively by adding 'r' to options. Defaults to False. + rsync_options (str, optional): Additional rsync command-line options (e.g., "--progress", "--bwlimit=10000"). Defaults to "". + + Raises: + KeywordException: If the rsync operation fails due to SSH, rsync, or connection issues. + """ + opts = "-avz" + if recursive: + opts += "r" + + if rsync_options: + opts += f" {rsync_options}" + + cmd = f"sshpass -p '{remote_password}' rsync {opts} -e 'ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10' {local_dest_path} {remote_user}@{remote_server}:{remote_path}" + + get_logger().log_info(f"Executing rsync command: {cmd}") + + try: + self.ssh_connection.send(cmd) + self.validate_success_return_code(self.ssh_connection) + except Exception as e: + get_logger().log_error(f"Failed to rsync file from {local_dest_path} to {remote_user}@{remote_server}:{remote_path}: {e}") + raise KeywordException(f"Failed to rsync file from {local_dest_path} to {remote_user}@{remote_server}:{remote_path}: {e}") from e + def rsync_from_remote_server(self, remote_server: str, remote_user: str, remote_password: str, remote_path: str, local_dest_path: str, recursive: bool = False, rsync_options: str = "") -> None: """ Rsync a file or directory from a remote server to the target host. diff --git a/testcases/cloud_platform/sanity/test_dc_sanity.py b/testcases/cloud_platform/sanity/test_dc_sanity.py index 6af7d20d..d3329e23 100644 --- a/testcases/cloud_platform/sanity/test_dc_sanity.py +++ b/testcases/cloud_platform/sanity/test_dc_sanity.py @@ -35,11 +35,13 @@ def sanity_pre_requisite(): for sc_assets in deployment_assets_config.subclouds_deployment_assets.values(): # get base path of the file for file in [sc_assets.get_deployment_config_file(), sc_assets.get_install_file(), sc_assets.get_bootstrap_file()]: + # get the base path of the file - base_file_path = os.path.join(os.path.dirname(file), "") - # prepare remote path - remote_path = f"{user}@{standby_host_name}:{base_file_path}" - file_kw.execute_rsync(file, remote_path) + base_file_path = f"{os.path.dirname(file)}/" + + # RSync the files over to the standby controller + password = ConfigurationManager.get_lab_config().get_admin_credentials().get_password() + file_kw.rsync_to_remote_server(file, standby_host_name, user, password, base_file_path) def subcloud_add(subcloud_name: str):