Add negative testcases and update positive testcase for subcloud rename
Negative testcases were added to validate subcloud rename failures with invalid inputs (same name, existing name, invalid name). The positive testcase was also modified to simplify the helper function and return the original subcloud name for consistent teardown handling. Test Plan: PASS: Verify valid subcloud rename succeeds and restores original name PASS: Verify renaming to the same subcloud name fails with correct error PASS: Verify renaming to an existing subcloud name fails with correct error PASS: Verify renaming with invalid subcloud name fails with correct error Change-Id: Iba755883f10b9726d814dc69d1f145466a2e133a Signed-off-by: aabhinav <ayyapasetti.abhinav@windriver.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from framework.ssh.ssh_connection import SSHConnection
|
||||
from keywords.base_keyword import BaseKeyword
|
||||
from keywords.cloud_platform.command_wrappers import source_openrc
|
||||
from keywords.cloud_platform.dcmanager.objects.dcmanager_subcloud_show_output import DcManagerSubcloudShowOutput
|
||||
@@ -8,11 +9,12 @@ class DcManagerSubcloudUpdateKeywords(BaseKeyword):
|
||||
This class contains all the keywords related to the 'dcmanager subcloud update' commands.
|
||||
"""
|
||||
|
||||
def __init__(self, ssh_connection):
|
||||
def __init__(self, ssh_connection: SSHConnection):
|
||||
"""
|
||||
Constructor
|
||||
|
||||
Args:
|
||||
ssh_connection:
|
||||
ssh_connection(SSHConnection): An active SSH connection to the controller.
|
||||
|
||||
"""
|
||||
self.ssh_connection = ssh_connection
|
||||
@@ -20,11 +22,14 @@ class DcManagerSubcloudUpdateKeywords(BaseKeyword):
|
||||
def dcmanager_subcloud_update(self, subcloud_name: str, update_attr: str, update_value: str) -> DcManagerSubcloudShowOutput:
|
||||
"""
|
||||
Updates the subcloud attr using'dcmanager subcloud update <subcloud name> --<update_attr> <update_value>' output.
|
||||
Args: subcloud_name (str): a str representing a subcloud's name.
|
||||
update_attr (str): the attribute to update (ex. description)
|
||||
update_value (str): the value to update the attribute to (ex. this is a new description)
|
||||
|
||||
Returns: DcManagerSubcloudShowOutput
|
||||
Args:
|
||||
subcloud_name (str): a str representing a subcloud's name.
|
||||
update_attr (str): the attribute to update (ex. description)
|
||||
update_value (str): the value to update the attribute to (ex. this is a new description)
|
||||
|
||||
Returns:
|
||||
DcManagerSubcloudShowOutput: Object representation of the command output.
|
||||
|
||||
"""
|
||||
output = self.ssh_connection.send(source_openrc(f"dcmanager subcloud update {subcloud_name} --{update_attr} '{update_value}'"))
|
||||
@@ -32,3 +37,21 @@ class DcManagerSubcloudUpdateKeywords(BaseKeyword):
|
||||
dcmanager_subcloud_show_output = DcManagerSubcloudShowOutput(output)
|
||||
|
||||
return dcmanager_subcloud_show_output
|
||||
|
||||
def dcmanager_subcloud_update_with_error(self, subcloud_name: str, update_attr: str, update_value: str) -> str:
|
||||
"""
|
||||
Updates the subcloud attr using'dcmanager subcloud update <subcloud name> --<update_attr> <update_value>' output(error handling version).
|
||||
|
||||
Args:
|
||||
subcloud_name (str): a str representing a subcloud's name.
|
||||
update_attr (str): the attribute to update (ex. description)
|
||||
update_value (str): the value to update the attribute to (ex. this is a new description)
|
||||
|
||||
Returns:
|
||||
str: Raw command output (for error validation).
|
||||
|
||||
"""
|
||||
output = self.ssh_connection.send(source_openrc(f"dcmanager subcloud update {subcloud_name} --{update_attr} '{update_value}'"))
|
||||
if isinstance(output, list) and len(output) > 0:
|
||||
return "\n".join(line.strip() for line in output)
|
||||
return output.strip() if isinstance(output, str) else str(output)
|
||||
|
||||
@@ -149,6 +149,30 @@ class DcManagerSubcloudListOutput:
|
||||
lowest_subcloud = min(subclouds, key=lambda subcloud: int(subcloud.get_id()))
|
||||
return lowest_subcloud
|
||||
|
||||
def get_different_healthy_subcloud(self, exclude_subcloud_name: str) -> DcManagerSubcloudListObject:
|
||||
"""
|
||||
Gets a healthy subcloud whose name is different from the argument 'exclude_subcloud_name'.
|
||||
|
||||
Args:
|
||||
exclude_subcloud_name (str): The name of the subcloud to exclude.
|
||||
|
||||
Returns:
|
||||
DcManagerSubcloudListObject: An instance of DcManagerSubcloudListObject representing a healthy subcloud
|
||||
(Managed, Online, Deploy completed, Synchronized) whose name is different from 'exclude_subcloud_name'.
|
||||
|
||||
Raises:
|
||||
ValueError: If no eligible healthy subcloud is found excluding 'exclude_subcloud_name'.
|
||||
"""
|
||||
dcmanager_subcloud_list_object_filter = DcManagerSubcloudListObjectFilter.get_healthy_subcloud_filter()
|
||||
subclouds = self.get_dcmanager_subcloud_list_objects_filtered(dcmanager_subcloud_list_object_filter)
|
||||
eligible_subclouds = [sc for sc in subclouds if sc.get_name() != exclude_subcloud_name]
|
||||
|
||||
if not eligible_subclouds:
|
||||
error_message = f"No healthy subcloud found excluding '{exclude_subcloud_name}'."
|
||||
raise ValueError(error_message)
|
||||
|
||||
return min(eligible_subclouds, key=lambda sc: int(sc.get_id()))
|
||||
|
||||
def get_subcloud_by_name(self, subcloud_name: str) -> DcManagerSubcloudListObject:
|
||||
"""
|
||||
Gets an instance of DcManagerSubcloudListObject whose name attribute is equal to the argument 'subcloud_name'.
|
||||
|
||||
@@ -1,65 +1,218 @@
|
||||
import time
|
||||
from typing import Tuple
|
||||
|
||||
from pytest import mark
|
||||
|
||||
from framework.kpi.time_kpi import TimeKPI
|
||||
from framework.logging.automation_logger import get_logger
|
||||
from framework.validation.validation import validate_equals
|
||||
from framework.ssh.ssh_connection import SSHConnection
|
||||
from framework.validation.validation import validate_equals, validate_str_contains
|
||||
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_list_keywords import DcManagerSubcloudListKeywords
|
||||
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_manager_keywords import DcManagerSubcloudManagerKeywords
|
||||
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_update_keywords import DcManagerSubcloudUpdateKeywords
|
||||
from keywords.cloud_platform.health.health_keywords import HealthKeywords
|
||||
from keywords.cloud_platform.ssh.lab_connection_keywords import LabConnectionKeywords
|
||||
|
||||
|
||||
def get_subcloud_name(ssh_connection: SSHConnection) -> str:
|
||||
"""
|
||||
Retrieve the name of the healthy subcloud with the lowest ID.
|
||||
|
||||
Args:
|
||||
ssh_connection (SSHConnection): Active SSH connection to the controller.
|
||||
|
||||
Returns:
|
||||
str: The original subcloud name.
|
||||
"""
|
||||
dcm_sc_list_kw = DcManagerSubcloudListKeywords(ssh_connection)
|
||||
lowest_subcloud = dcm_sc_list_kw.get_dcmanager_subcloud_list().get_healthy_subcloud_with_lowest_id()
|
||||
sc_name_original = lowest_subcloud.get_name()
|
||||
return sc_name_original
|
||||
|
||||
|
||||
def dcmanager_subcloud_rename(ssh_connection: SSHConnection, sc_name_new: str) -> str:
|
||||
"""
|
||||
Perform a successful subcloud rename.
|
||||
|
||||
This function:
|
||||
- Retrieves the original subcloud name.
|
||||
- Unmanages the subcloud.
|
||||
- Renames it using dcmanager.
|
||||
- Returns the original subcloud name for teardown.
|
||||
|
||||
Args:
|
||||
ssh_connection (SSHConnection): Active SSH connection to the controller.
|
||||
sc_name_new (str): The new name for the subcloud.
|
||||
|
||||
Returns:
|
||||
str: The original subcloud name.
|
||||
"""
|
||||
sc_name_original = get_subcloud_name(ssh_connection)
|
||||
dcm_sc_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
|
||||
|
||||
dcm_sc_kw.get_dcmanager_subcloud_unmanage(sc_name_original, 30)
|
||||
get_logger().log_info(f"Subcloud selected for rename: {sc_name_original}")
|
||||
|
||||
DcManagerSubcloudUpdateKeywords(ssh_connection).dcmanager_subcloud_update(sc_name_original, "name", sc_name_new)
|
||||
get_logger().log_info(f"Subcloud {sc_name_original} renamed to {sc_name_new}")
|
||||
|
||||
return sc_name_original
|
||||
|
||||
|
||||
def dcmanager_subcloud_rename_negative(ssh_connection: SSHConnection, sc_name_new: str) -> Tuple[str, str]:
|
||||
"""
|
||||
Attempt a subcloud rename expected to fail.
|
||||
|
||||
This function:
|
||||
- Retrieves the original subcloud name.
|
||||
- Unmanages the subcloud.
|
||||
- Attempts rename with invalid/new name.
|
||||
- Returns error message and original subcloud name.
|
||||
|
||||
Args:
|
||||
ssh_connection (SSHConnection): Active SSH connection to the controller.
|
||||
sc_name_new (str): The new (invalid or conflicting) name for the subcloud.
|
||||
|
||||
Returns:
|
||||
Tuple[str, str]: (error_message, original subcloud name)
|
||||
"""
|
||||
sc_name_original = get_subcloud_name(ssh_connection)
|
||||
dcm_sc_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
|
||||
|
||||
dcm_sc_kw.get_dcmanager_subcloud_unmanage(sc_name_original, 30)
|
||||
get_logger().log_info(f"Subcloud selected for rename: {sc_name_original}")
|
||||
|
||||
error_message = DcManagerSubcloudUpdateKeywords(ssh_connection).dcmanager_subcloud_update_with_error(sc_name_original, "name", sc_name_new)
|
||||
return error_message, sc_name_original
|
||||
|
||||
|
||||
@mark.p0
|
||||
@mark.lab_has_subcloud
|
||||
def test_dc_subcloud_rename(request):
|
||||
def test_subcloud_rename(request):
|
||||
"""
|
||||
Verify subcloud rename
|
||||
|
||||
Test Steps:
|
||||
- log onto active controller
|
||||
- Get original name
|
||||
- Run dcmanager subcloud update <subcloud_name> --name <new_name>
|
||||
- validate that subcloud has new name
|
||||
- log the time kpi takes from out-of-sync to in-sync
|
||||
- Reset name back to old name
|
||||
- Log onto the active controller
|
||||
- Get the original subcloud name
|
||||
- Rename subcloud
|
||||
- Manage the renamed subcloud
|
||||
- Validate that the subcloud has the new name
|
||||
- Validate that the subcloud returns to "in-sync" state
|
||||
- Reset subcloud name back to original
|
||||
"""
|
||||
ssh_connection = LabConnectionKeywords().get_active_controller_ssh()
|
||||
# new name used for renaming
|
||||
sc_name_new = "testsubcloudrename"
|
||||
# Get the lowest subcloud (the subcloud with the lowest id).
|
||||
dcm_sc_list_kw = DcManagerSubcloudListKeywords(ssh_connection)
|
||||
lowest_subcloud = dcm_sc_list_kw.get_dcmanager_subcloud_list().get_healthy_subcloud_with_lowest_id()
|
||||
sc_name_original = lowest_subcloud.get_name()
|
||||
get_logger().log_info(f"Subcloud selected for rename: {sc_name_original}")
|
||||
|
||||
# unmange before rename
|
||||
dcm_sc_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
|
||||
dcm_sc_manage_out = dcm_sc_kw.get_dcmanager_subcloud_unmanage(sc_name_original, 300)
|
||||
get_logger().log_info(f"The management state of the subcloud {sc_name_original} was changed to {dcm_sc_manage_out.get_dcmanager_subcloud_manage_object().get_management()}.")
|
||||
|
||||
time_kpi = TimeKPI(time.time())
|
||||
subcloud_update_output = DcManagerSubcloudUpdateKeywords(ssh_connection).dcmanager_subcloud_update(sc_name_original, "name", sc_name_new)
|
||||
get_logger().log_info(f"sc rename: {subcloud_update_output.get_dcmanager_subcloud_show_object().__dict__}")
|
||||
dcm_sc_manage_out = dcm_sc_kw.get_dcmanager_subcloud_manage(sc_name_new, 300)
|
||||
sc_name_new = "testsubcloudrenames"
|
||||
sc_name_original = dcmanager_subcloud_rename(ssh_connection, sc_name_new)
|
||||
|
||||
def teardown():
|
||||
dcm_sc_kw.get_dcmanager_subcloud_unmanage(sc_name_new, 300)
|
||||
DcManagerSubcloudUpdateKeywords(ssh_connection).dcmanager_subcloud_update(sc_name_new, "name", sc_name_original)
|
||||
# manage the cloud back
|
||||
dcm_sc_kw.get_dcmanager_subcloud_manage(sc_name_original, 300)
|
||||
|
||||
# Register the teardown function to be called after the test
|
||||
request.addfinalizer(teardown)
|
||||
# Manage renamed subcloud
|
||||
dcm_sc_kw.get_dcmanager_subcloud_manage(sc_name_new, 30)
|
||||
|
||||
# Validate rename
|
||||
obj_subcloud = dcm_sc_list_kw.get_dcmanager_subcloud_list().get_subcloud_by_name(sc_name_new)
|
||||
validate_equals(obj_subcloud.get_name(), sc_name_new, "Validate that the name has been changed")
|
||||
# Validate that subcloud is in Insync Status
|
||||
|
||||
# Validate in-sync
|
||||
dcm_sc_list_kw.validate_subcloud_sync_status(sc_name_new, "in-sync")
|
||||
time_kpi.log_elapsed_time(time.time(), "time taken for subcloud In-Sync")
|
||||
# validate Healthy status
|
||||
# since the lab_config does not have the renamed subcloud name, using the original name to ssh
|
||||
subcloud_ssh = LabConnectionKeywords().get_subcloud_ssh(sc_name_original)
|
||||
HealthKeywords(subcloud_ssh).validate_healty_cluster()
|
||||
|
||||
# Teardown to reset subcloud name
|
||||
def teardown():
|
||||
dcmanager_subcloud_rename(ssh_connection, sc_name_original)
|
||||
dcm_sc_kw.get_dcmanager_subcloud_manage(sc_name_original, 300)
|
||||
dcm_sc_list_kw.validate_subcloud_sync_status(sc_name_original, "in-sync")
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
|
||||
@mark.p0
|
||||
@mark.lab_has_subcloud
|
||||
def test_subcloud_rename_negative_same_subcloud_name(request) -> None:
|
||||
"""
|
||||
Verify that renaming a subcloud to its existing name fails with the correct error.
|
||||
|
||||
Test Steps:
|
||||
- Log onto the active controller
|
||||
- Get the current subcloud name
|
||||
- Attempt to rename the subcloud with the same name
|
||||
- Validate that the error message indicates renaming to the same name is not allowed
|
||||
- Ensure subcloud is managed again after the test
|
||||
"""
|
||||
ssh_connection = LabConnectionKeywords().get_active_controller_ssh()
|
||||
dcm_sc_list_kw = DcManagerSubcloudListKeywords(ssh_connection)
|
||||
sc_name_new = get_subcloud_name(ssh_connection)
|
||||
|
||||
# Attempt invalid rename (same name)
|
||||
error_message, sc_name_original = dcmanager_subcloud_rename_negative(ssh_connection, sc_name_new)
|
||||
|
||||
# Validate error message
|
||||
validate_str_contains(error_message, "same as the current subcloud", f"Subcloud rename should not allow a name that is the same as the current name {sc_name_new}")
|
||||
|
||||
def teardown():
|
||||
dcm_sc_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
|
||||
dcm_sc_kw.get_dcmanager_subcloud_manage(sc_name_original, timeout=60)
|
||||
dcm_sc_list_kw.validate_subcloud_sync_status(sc_name_original, "in-sync")
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
|
||||
@mark.p0
|
||||
@mark.lab_has_min_2_subclouds
|
||||
def test_dcmanager_subcloud_rename_negative_existing_subcloud_name(request) -> None:
|
||||
"""
|
||||
Verify that attempting to rename a subcloud to the name of another existing subcloud fails.
|
||||
|
||||
Test Steps:
|
||||
- Log into the active controller.
|
||||
- Retrieve the name of the subcloud to be renamed.
|
||||
- Identify a different healthy subcloud to use its name for the rename attempt.
|
||||
- Attempt to rename the original subcloud using the existing name of another subcloud.
|
||||
- Validate that the error message indicates that the name is already in use.
|
||||
- Ensure the original subcloud is managed and in-sync after the test.
|
||||
"""
|
||||
ssh_connection = LabConnectionKeywords().get_active_controller_ssh()
|
||||
dcm_sc_list_kw = DcManagerSubcloudListKeywords(ssh_connection)
|
||||
sc_name = get_subcloud_name(ssh_connection)
|
||||
sc_name_new = dcm_sc_list_kw.get_dcmanager_subcloud_list().get_different_healthy_subcloud(sc_name).get_name()
|
||||
|
||||
# Attempt invalid rename (existing subcloud name)
|
||||
error_message, sc_name_original = dcmanager_subcloud_rename_negative(ssh_connection, sc_name_new)
|
||||
|
||||
# Validate error message
|
||||
validate_str_contains(error_message, "already exist", f"Subcloud name should not be the same as another existing subcloud {sc_name_new}")
|
||||
|
||||
def teardown():
|
||||
dcm_sc_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
|
||||
dcm_sc_kw.get_dcmanager_subcloud_manage(sc_name_original, timeout=60)
|
||||
dcm_sc_list_kw.validate_subcloud_sync_status(sc_name_original, "in-sync")
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
|
||||
@mark.p0
|
||||
@mark.lab_has_subcloud
|
||||
def test_dcmanager_subcloud_rename_negative_invalid_name(request) -> None:
|
||||
"""
|
||||
Verify that renaming a subcloud with an invalid name fails.
|
||||
|
||||
Test Steps:
|
||||
- Log onto the active controller
|
||||
- Attempt to rename a subcloud with an invalid name
|
||||
- Validate that the error message indicates the name is invalid
|
||||
- Ensure subcloud is managed again after the test
|
||||
"""
|
||||
ssh_connection = LabConnectionKeywords().get_active_controller_ssh()
|
||||
sc_name_new = "Subcloud" # Invalid name because subcloud names should not consist of uppercase letters
|
||||
|
||||
# Attempt invalid rename
|
||||
error_message, sc_name_original = dcmanager_subcloud_rename_negative(ssh_connection, sc_name_new)
|
||||
|
||||
# Validate expected error message
|
||||
validate_str_contains(error_message, "must contain alphabetic characters", f"Error message for invalid subcloud name: {sc_name_new}")
|
||||
|
||||
def teardown():
|
||||
dcm_sc_list_kw = DcManagerSubcloudListKeywords(ssh_connection)
|
||||
dcm_sc_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
|
||||
dcm_sc_kw.get_dcmanager_subcloud_manage(sc_name_original, timeout=60)
|
||||
dcm_sc_list_kw.validate_subcloud_sync_status(sc_name_original, "in-sync")
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
Reference in New Issue
Block a user