diff --git a/keywords/cloud_platform/dcmanager/dcmanager_subcloud_list_keywords.py b/keywords/cloud_platform/dcmanager/dcmanager_subcloud_list_keywords.py index 1d738ed5..5f885dca 100644 --- a/keywords/cloud_platform/dcmanager/dcmanager_subcloud_list_keywords.py +++ b/keywords/cloud_platform/dcmanager/dcmanager_subcloud_list_keywords.py @@ -2,6 +2,7 @@ import time from framework.logging.automation_logger import get_logger from framework.ssh.ssh_connection import SSHConnection +from framework.validation.validation import validate_equals_with_retry from keywords.base_keyword import BaseKeyword from keywords.cloud_platform.command_wrappers import source_openrc from keywords.cloud_platform.dcmanager.objects.dcmanager_subcloud_list_output import DcManagerSubcloudListOutput @@ -68,3 +69,27 @@ class DcManagerSubcloudListKeywords(BaseKeyword): time.sleep(polling_sleep_time) get_logger().log_error(msg) raise TimeoutError(msg) + + def validate_subcloud_availability_status(self, subcloud_name: str) -> bool: + """Validates the availability status of the specified subcloud until reaches online state. + + Args: + subcloud_name (str): a str name for the subcloud. + + Returns: + bool: True if the subcloud reaches the desired status. + + Raises: + Exception: if the subcloud is offline. + + """ + + def get_availability(): + sc_list_out = self.get_dcmanager_subcloud_list().get_subcloud_by_name(subcloud_name) + sc_availability = sc_list_out.get_availability() + msg = f"Subcloud {subcloud_name} is in {sc_availability} state" + get_logger().log_info(msg) + + return sc_availability + + validate_equals_with_retry(get_availability, "online", "Validate if subcloud is in online state.") diff --git a/keywords/cloud_platform/deployment_assets/host_profile_yaml_keywords.py b/keywords/cloud_platform/deployment_assets/host_profile_yaml_keywords.py new file mode 100644 index 00000000..7395d368 --- /dev/null +++ b/keywords/cloud_platform/deployment_assets/host_profile_yaml_keywords.py @@ -0,0 +1,79 @@ +import os + +import yaml + +from framework.ssh.ssh_connection import SSHConnection +from keywords.files.file_keywords import FileKeywords + + +class HostProfileYamlKeywords: + """ + This class is responsible for processing the host profile YAML files. + """ + + def __init__(self, ssh_connection: SSHConnection): + """Constructor + + Args: + ssh_connection (SSHConnection): ssh object + + """ + self.ssh_connection = ssh_connection + + def edit_yaml_spec_storage(self, searched_metadata: str, fs: str, size: int, remote_filename: str): + """Edit storage specs for the desired filesystem. + + Args: + searched_metadata (str): Metadata to be searched. + fs (str): Desired filesystem to be modified. + size (int): Desired size to be set. + remote_filename (str): Name of the output file. + """ + local_filename = self.download_file(remote_filename) + with open(local_filename) as stream: + list_doc = list(yaml.safe_load_all(stream)) + + for document in list_doc: + metadata_name = document["metadata"]["name"] + if metadata_name == searched_metadata: + for item in document["spec"]["storage"]["filesystems"]: + if item["name"] == fs: + item["size"] = size + + self.write_yaml(list(list_doc), local_filename) + self.upload_file(local_filename, remote_filename) + + def write_yaml(self, yaml_data: list, output_filename: str): + """Writes the received data to a yaml file. + + Args: + yaml_data (list): Output data received after being modified. + output_filename (str): Name of the file to be saved. + + """ + with open(output_filename, "w") as f: + yaml.safe_dump_all(yaml_data, f) + + def download_file(self, file: str) -> str: + """Downloads the desired file from remote. + + Args: + file (str): Path to file to be downloaded. + + Returns: + str: Local path to downloaded file. + + """ + filename = file.split("/")[-1] + FileKeywords(ssh_connection=self.ssh_connection).download_file(file, f"{filename}") + return filename + + def upload_file(self, local_file: str, remote_file: str): + """Uploads the modified file to remote and removes the local copy. + + Args: + local_file (str): Local file to be uploaded. + remote_file (str): Remote file name. + """ + FileKeywords(self.ssh_connection).upload_file(local_file, remote_file) + os.remove(local_file) diff --git a/testcases/cloud_platform/regression/dc/reconfig/test_subcloud_reconfig.py b/testcases/cloud_platform/regression/dc/reconfig/test_subcloud_reconfig.py new file mode 100644 index 00000000..3b5d93fd --- /dev/null +++ b/testcases/cloud_platform/regression/dc/reconfig/test_subcloud_reconfig.py @@ -0,0 +1,49 @@ +from pytest import mark + +from config.configuration_manager import ConfigurationManager +from framework.validation.validation import validate_equals +from keywords.cloud_platform.dcmanager.dcmanager_subcloud_deploy_keywords import DCManagerSubcloudDeployKeywords +from keywords.cloud_platform.dcmanager.dcmanager_subcloud_list_keywords import DcManagerSubcloudListKeywords +from keywords.cloud_platform.dcmanager.objects.dcmanager_subcloud_deploy_object import DcManagerSubcloudDeployObject +from keywords.cloud_platform.deployment_assets.host_profile_yaml_keywords import HostProfileYamlKeywords +from keywords.cloud_platform.ssh.lab_connection_keywords import LabConnectionKeywords +from keywords.cloud_platform.system.host.system_host_fs_keywords import SystemHostFSKeywords +from keywords.cloud_platform.system.host.system_host_list_keywords import SystemHostListKeywords + + +@mark.p2 +@mark.lab_has_subcloud +def test_reconfig_one_subcloud(request): + """ + Execute a subcloud reconfiguration + + Test Steps: + - Modify docker size from 30 to 32. + - Run dcmanager subcloud deploy config command. + - Verify that the docker storage size increased from 30 to 32. + """ + + deployment_assets_config = ConfigurationManager.get_deployment_assets_config() + system_controller_ssh = LabConnectionKeywords().get_active_controller_ssh() + + # Gets the lowest subcloud (the subcloud with the lowest id). + dcmanager_subcloud_list_keywords = DcManagerSubcloudListKeywords(system_controller_ssh) + lowest_subcloud = dcmanager_subcloud_list_keywords.get_dcmanager_subcloud_list().get_healthy_subcloud_with_lowest_id() + subcloud_name = lowest_subcloud.get_name() + + subcloud_ssh = LabConnectionKeywords().get_subcloud_ssh(subcloud_name) + + deployment_file = deployment_assets_config.get_subcloud_deployment_assets(subcloud_name).get_deployment_config_file() + hostname = SystemHostListKeywords(system_controller_ssh).get_active_controller().get_host_name() + + HostProfileYamlKeywords(system_controller_ssh).edit_yaml_spec_storage(searched_metadata=f"{hostname}-profile", fs="docker", size=32, remote_filename=deployment_file) + old_fs_size = SystemHostFSKeywords(subcloud_ssh).get_system_host_fs_list(host_name=hostname).get_system_host_fs("docker").get_size() + sysadmin_password = ConfigurationManager.get_lab_config().get_admin_credentials().get_password() + + deploy_params = DcManagerSubcloudDeployObject(subcloud=subcloud_name, deploy_config=deployment_file, bmc_password=sysadmin_password) + DCManagerSubcloudDeployKeywords(system_controller_ssh).deploy_config_subcloud(deploy_params=deploy_params) + + new_fs_size = SystemHostFSKeywords(subcloud_ssh).get_system_host_fs_list(host_name=hostname).get_system_host_fs("docker").get_size() + + dcmanager_subcloud_list_keywords.validate_subcloud_availability_status(subcloud_name) + validate_equals(old_fs_size, new_fs_size, "Validate that filesystem size for docker changed.")