Allign DC tests for sanity

- align DC sanity tests.
- add function to get controllers.
- update IPMI keywords to select controllers by BMC IP.
- fix central controller selection bug in ipmi and power keyword.
- update DcManagerSubcloudManagerKeywords to use IPMI for subcloud power off.

Change-Id: I2679f04510823d4f9949c3cdac206cbc7fd4f2bb
Signed-off-by: Abhishek jaiswal <abhishek.jaiswal@windriver.com>
This commit is contained in:
Abhishek jaiswal
2025-04-11 13:14:25 -04:00
parent 20c8586a9f
commit d20ab276fd
5 changed files with 132 additions and 97 deletions

View File

@@ -459,3 +459,14 @@ class LabConfig:
log_strings.append(f" {log_string}") log_strings.append(f" {log_string}")
return log_strings return log_strings
def get_controllers(self) -> List[Node]:
"""
Getter for controller nodes.
Returns:
List[Node]: List of controller nodes
"""
nodes = self.get_nodes()
controllers = [node for node in nodes if node.node_type == "controller"]
return controllers

View File

@@ -13,23 +13,39 @@ class IPMIToolChassisPowerKeywords(BaseKeyword):
lab_config = ConfigurationManager.get_lab_config() lab_config = ConfigurationManager.get_lab_config()
self.bm_password = lab_config.get_bm_password() self.bm_password = lab_config.get_bm_password()
if host_name:
node = lab_config.get_node(host_name)
self.bm_ip = node.get_bm_ip()
self.bm_username = node.get_bm_username()
node = lab_config.get_node(host_name) def _power_off(self, bm_ip: str, bm_username: str, bm_password: str):
self.bm_ip = node.get_bm_ip() """Powers off the host using IPMI tool
self.bm_username = node.get_bm_username()
Args:
bm_ip (str): IP address of the BMC
bm_username (str): Username for BMC
bm_password (str): Password for BMC
"""
self.ssh_connection.send(f"ipmitool -I lanplus -H {bm_ip} -U {bm_username} -P {bm_password} chassis power off")
def power_on(self): def power_on(self):
""" """Powers on the host"""
Powers on the host
Returns:
"""
self.ssh_connection.send(f"ipmitool -I lanplus -H {self.bm_ip} -U {self.bm_username} -P {self.bm_password} chassis power on") self.ssh_connection.send(f"ipmitool -I lanplus -H {self.bm_ip} -U {self.bm_username} -P {self.bm_password} chassis power on")
def power_off(self): def power_off(self):
""" """Powers off the host"""
Powers off the host self._power_off(self.bm_ip, self.bm_username, self.bm_password)
Returns:
def power_off_subcloud(self, subcloud_name: str):
"""Powers off the host
Args:
subcloud_name (str): name of the subcloud to be powered off
""" """
self.ssh_connection.send(f"ipmitool -I lanplus -H {self.bm_ip} -U {self.bm_username} -P {self.bm_password} chassis power off") sc_config = ConfigurationManager.get_lab_config().get_subcloud(subcloud_name)
controllers = sc_config.get_controllers()
bm_password = sc_config.get_bm_password()
for controller in controllers:
self._power_off(controller.get_bm_ip(), controller.get_bm_username(), bm_password)
self.bm_ip = controller.get_bm_ip()

View File

@@ -3,29 +3,27 @@ import time
from framework.logging.automation_logger import get_logger from framework.logging.automation_logger import get_logger
from framework.ssh.ssh_connection import SSHConnection from framework.ssh.ssh_connection import SSHConnection
from keywords.base_keyword import BaseKeyword from keywords.base_keyword import BaseKeyword
from keywords.bmc.ipmitool.chassis.power.ipmitool_chassis_power_keywords import IPMIToolChassisPowerKeywords
from keywords.cloud_platform.command_wrappers import source_openrc from keywords.cloud_platform.command_wrappers import source_openrc
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_list_keywords import DcManagerSubcloudListKeywords from keywords.cloud_platform.dcmanager.dcmanager_subcloud_list_keywords import DcManagerSubcloudListKeywords
from keywords.cloud_platform.dcmanager.objects.dcmanager_subcloud_list_object_filter import DcManagerSubcloudListObjectFilter from keywords.cloud_platform.dcmanager.objects.dcmanager_subcloud_list_object_filter import DcManagerSubcloudListObjectFilter
from keywords.cloud_platform.dcmanager.objects.dcmanager_subcloud_manage_output import DcManagerSubcloudManageOutput from keywords.cloud_platform.dcmanager.objects.dcmanager_subcloud_manage_output import DcManagerSubcloudManageOutput
from keywords.cloud_platform.ssh.lab_connection_keywords import LabConnectionKeywords
class DcManagerSubcloudManagerKeywords(BaseKeyword): class DcManagerSubcloudManagerKeywords(BaseKeyword):
""" """This class contains all the keywords related to the 'dcmanager subcloud <manage/unmanage> <subcloud name>' and command."""
This class contains all the keywords related to the 'dcmanager subcloud <manage/unmanage> <subcloud name>' and
command.
"""
def __init__(self, ssh_connection: SSHConnection): def __init__(self, ssh_connection: SSHConnection):
""" """Constructor
Constructor
Args: Args:
ssh_connection (SSHConnection): The SSH connection to the central subcloud. ssh_connection (SSHConnection): The SSH connection to the central subcloud.
""" """
self.ssh_connection = ssh_connection self.ssh_connection = ssh_connection
def get_dcmanager_subcloud_manage(self, subcloud_name: str, timeout: int) -> DcManagerSubcloudManageOutput: def get_dcmanager_subcloud_manage(self, subcloud_name: str, timeout: int) -> DcManagerSubcloudManageOutput:
""" """Dcmanager subcloud manage
Gets the output of 'dcmanager subcloud manage <subcloud_name>' as an instance of DcManagerSubcloudManageOutput Gets the output of 'dcmanager subcloud manage <subcloud_name>' as an instance of DcManagerSubcloudManageOutput
if the subcloud is successfully set to 'managed' (its 'management' attribute updated to 'managed') within the if the subcloud is successfully set to 'managed' (its 'management' attribute updated to 'managed') within the
specified 'timeout' period. Otherwise, this method returns None. specified 'timeout' period. Otherwise, this method returns None.
@@ -42,7 +40,8 @@ class DcManagerSubcloudManagerKeywords(BaseKeyword):
return self._get_dcmanager_subcloud_operation(subcloud_name, timeout, "manage") return self._get_dcmanager_subcloud_operation(subcloud_name, timeout, "manage")
def get_dcmanager_subcloud_unmanage(self, subcloud_name: str, timeout: int) -> DcManagerSubcloudManageOutput: def get_dcmanager_subcloud_unmanage(self, subcloud_name: str, timeout: int) -> DcManagerSubcloudManageOutput:
""" """Dcmanager subcloud unmanage
Gets the output of 'dcmanager subcloud unmanage <subcloud_name>' as an instance of DcManagerSubcloudManageOutput Gets the output of 'dcmanager subcloud unmanage <subcloud_name>' as an instance of DcManagerSubcloudManageOutput
if the subcloud is successfully set to 'unmanaged' (its 'management' attribute updated to 'unmanaged') within if the subcloud is successfully set to 'unmanaged' (its 'management' attribute updated to 'unmanaged') within
the specified 'timeout' period. Otherwise, this method returns None. the specified 'timeout' period. Otherwise, this method returns None.
@@ -59,7 +58,8 @@ class DcManagerSubcloudManagerKeywords(BaseKeyword):
return self._get_dcmanager_subcloud_operation(subcloud_name, timeout, "unmanage") return self._get_dcmanager_subcloud_operation(subcloud_name, timeout, "unmanage")
def _get_dcmanager_subcloud_operation(self, subcloud_name: str, end_time: int, operation: str) -> DcManagerSubcloudManageOutput: def _get_dcmanager_subcloud_operation(self, subcloud_name: str, end_time: int, operation: str) -> DcManagerSubcloudManageOutput:
""" """Dcmanager subcloud manage/unmanage
Gets the output of 'dcmanager subcloud <operation> <subcloud_name>' as an instance of DcManagerSubcloudManageOutput Gets the output of 'dcmanager subcloud <operation> <subcloud_name>' as an instance of DcManagerSubcloudManageOutput
if the subcloud is successfully set to 'managed' or 'unmanaged' (its 'management' attribute updated to 'managed' if the subcloud is successfully set to 'managed' or 'unmanaged' (its 'management' attribute updated to 'managed'
or to 'unmanaged', depending on 'operation') within the specified 'timeout' period. Otherwise, this method or to 'unmanaged', depending on 'operation') within the specified 'timeout' period. Otherwise, this method
@@ -68,11 +68,15 @@ class DcManagerSubcloudManagerKeywords(BaseKeyword):
Args: Args:
subcloud_name (str): The name of the subcloud that must be set to the 'managed' state. subcloud_name (str): The name of the subcloud that must be set to the 'managed' state.
end_time (int): The maximum time, in seconds, to wait for the subcloud to enter the 'managed' state. end_time (int): The maximum time, in seconds, to wait for the subcloud to enter the 'managed' state.
operation (str): The operation to be performed on the subcloud ('manage' or 'unmanage').
Returns: Returns:
DcManagerSubcloudManageOutput: An instance representing the output of the command DcManagerSubcloudManageOutput: An instance representing the output of the command
'dcmanager subcloud <operation> <subcloud_name>' if successful, or None otherwise. 'dcmanager subcloud <operation> <subcloud_name>' if successful, or None otherwise.
Raises:
TimeoutError: If the subcloud does not enter the 'managed' or 'unmanaged' state within the specified timeout.
""" """
target_state = "managed" target_state = "managed"
if operation == "unmanage": if operation == "unmanage":
@@ -112,24 +116,17 @@ class DcManagerSubcloudManagerKeywords(BaseKeyword):
Raises: TimeoutError Raises: TimeoutError
""" """
# get SSH connection to subcloud # get SSH connection to subcloud
subcloud_ssh = LabConnectionKeywords().get_subcloud_ssh(subcloud_name) # power off all the controllers in the subcloud
# power off the subcloud IPMIToolChassisPowerKeywords(self.ssh_connection, None).power_off_subcloud(subcloud_name)
# TODO find a better way to do it. as DC libvirt has no IPMI , To make work for both
# labs and virtual labs we need to find a way to power off the subcloud
subcloud_ssh.send_as_sudo("shutdown -h now")
self.validate_success_return_code(subcloud_ssh)
# This section is responsible for verifying whether the state has changed within a defined timeout. # This section is responsible for verifying whether the state has changed within a defined timeout.
target_state = "offline" target_state = "offline"
end_time = time.time() + timeout end_time = time.time() + timeout
while time.time() < end_time: while time.time() < end_time:
dcm_sc_list_kw = DcManagerSubcloudListKeywords(self.ssh_connection) dcm_sc_list_kw = DcManagerSubcloudListKeywords(self.ssh_connection)
subclouds_list = dcm_sc_list_kw.get_dcmanager_subcloud_list() subcloud = dcm_sc_list_kw.get_dcmanager_subcloud_list().get_subcloud_by_name(subcloud_name)
subclouds = subclouds_list.get_dcmanager_subcloud_list_objects() if subcloud.get_availability() == target_state:
for sc in subclouds: return True
if sc.get_name() == subcloud_name and sc.get_availability() == target_state: # If the subcloud is not 'offline', wait and check again
return True
# If the subcloud is not in the list or its availability is not 'offline', wait and check again
time.sleep(5) time.sleep(5)
error_message = f"Failed to change the state of subcloud '{subcloud_name}' to '{target_state}'." error_message = f"Failed to change the state of subcloud '{subcloud_name}' to '{target_state}'."
get_logger().log_error(error_message) get_logger().log_error(error_message)

View File

@@ -6,6 +6,8 @@ from config.configuration_manager import ConfigurationManager
from framework.logging.automation_logger import get_logger from framework.logging.automation_logger import get_logger
from framework.validation.validation import validate_equals from framework.validation.validation import validate_equals
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_add_keywords import DcManagerSubcloudAddKeywords from keywords.cloud_platform.dcmanager.dcmanager_subcloud_add_keywords import DcManagerSubcloudAddKeywords
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_delete_keywords import DcManagerSubcloudDeleteKeywords
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_manager_keywords import DcManagerSubcloudManagerKeywords
from keywords.cloud_platform.ssh.lab_connection_keywords import LabConnectionKeywords from keywords.cloud_platform.ssh.lab_connection_keywords import LabConnectionKeywords
from keywords.cloud_platform.system.host.system_host_list_keywords import SystemHostListKeywords from keywords.cloud_platform.system.host.system_host_list_keywords import SystemHostListKeywords
@@ -58,6 +60,41 @@ def subcloud_add(subcloud_name: str):
get_logger().log_info(f"The management state of the subcloud {subcloud_name} {manage_status}") get_logger().log_info(f"The management state of the subcloud {subcloud_name} {manage_status}")
def subcloud_delete(subcloud_name: str):
"""Delete a subcloud from the system.
Args:
subcloud_name (str): name of the subcloud to be deleted
"""
# Gets the SSH connection to the active controller of the central cloud.
ssh_connection = LabConnectionKeywords().get_active_controller_ssh()
dcm_sc_list_kw = DcManagerSubcloudListKeywords(ssh_connection)
subcloud = dcm_sc_list_kw.get_dcmanager_subcloud_list().get_subcloud_by_name(subcloud_name)
sc_name = subcloud.get_name()
msg = (f"Subcloud selected for deletion ID={subcloud.get_id()} ", f" Name={sc_name}, ", f" Management state={subcloud.get_management()} ")
get_logger().log_info(msg)
dcm_sc_manager_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
# poweroff the subcloud.
get_logger().log_test_case_step(f"Poweroff subcloud={sc_name}.")
dcm_sc_manager_kw.set_subcloud_poweroff(sc_name)
# Unmanage the subcloud.
if subcloud.get_management() == "managed":
dcm_sc_manager_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
get_logger().log_test_case_step(f"Unmanage subcloud={sc_name}.")
dcm_sc_manage_output = dcm_sc_manager_kw.get_dcmanager_subcloud_unmanage(sc_name, timeout=10)
get_logger().log_info(f"The management state of the subcloud {sc_name} was changed to {dcm_sc_manage_output.get_dcmanager_subcloud_manage_object().get_management()}.")
# delete the subcloud
get_logger().log_test_case_step(f"Delete subcloud={sc_name}.")
dcm_sc_del_kw = DcManagerSubcloudDeleteKeywords(ssh_connection)
dcm_sc_del_kw.dcmanager_subcloud_delete(sc_name)
# validate that the subcloud is deleted
subclouds_list = dcm_sc_list_kw.get_dcmanager_subcloud_list()
get_logger().log_test_case_step(f"Validate that subcloud={sc_name} is deleted.")
validate_equals(subclouds_list.is_subcloud_in_output(sc_name), False, f"{sc_name} is no longer in the subcloud list.")
@mark.p0 @mark.p0
@mark.lab_has_min_2_subclouds @mark.lab_has_min_2_subclouds
def test_dc_subcloud_add_simplex(): def test_dc_subcloud_add_simplex():
@@ -116,3 +153,39 @@ def test_dc_subcloud_add_duplex():
# read the config file for subcloud # read the config file for subcloud
subcloud_name = "subcloud2" subcloud_name = "subcloud2"
subcloud_add(subcloud_name) subcloud_add(subcloud_name)
@mark.p0
@mark.lab_has_min_2_subclouds
def test_dc_subcloud_delete_simplex():
"""
Verify subcloud deletion works as expected
Test Steps:
- log onto system controller
- list all subclouds and get the lowest id subcloud
- unmanage the subcloud
- power off the subcloud
- delete the subcloud
- validate that the subcloud is deleted
"""
subcloud_name = "subcloud1"
subcloud_delete(subcloud_name)
@mark.p0
@mark.lab_has_min_2_subclouds
def test_dc_subcloud_delete_duplex():
"""
Verify subcloud deletion works as expected
Test Steps:
- log onto system controller
- list all subclouds and get the lowest id subcloud
- unmanage the subcloud
- power off the subcloud
- delete the subcloud
- validate that the subcloud is deleted
"""
subcloud_name = "subcloud2"
subcloud_delete(subcloud_name)

View File

@@ -14,7 +14,6 @@ from framework.ssh.ssh_connection import SSHConnection
from framework.validation.validation import validate_equals, validate_equals_with_retry from framework.validation.validation import validate_equals, validate_equals_with_retry
from framework.web.webdriver_core import WebDriverCore from framework.web.webdriver_core import WebDriverCore
from keywords.cloud_platform.dcmanager.dcmanager_alarm_summary_keywords import DcManagerAlarmSummaryKeywords from keywords.cloud_platform.dcmanager.dcmanager_alarm_summary_keywords import DcManagerAlarmSummaryKeywords
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_delete_keywords import DcManagerSubcloudDeleteKeywords
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_list_keywords import DcManagerSubcloudListKeywords 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_manager_keywords import DcManagerSubcloudManagerKeywords
from keywords.cloud_platform.dcmanager.dcmanager_subcloud_show_keywords import DcManagerSubcloudShowKeywords from keywords.cloud_platform.dcmanager.dcmanager_subcloud_show_keywords import DcManagerSubcloudShowKeywords
@@ -1400,64 +1399,3 @@ def deploy_images_to_local_registry(ssh_connection: SSHConnection):
docker_load_image_keywords.load_docker_image_to_host("node-hello-alpine.tar") docker_load_image_keywords.load_docker_image_to_host("node-hello-alpine.tar")
docker_load_image_keywords.tag_docker_image_for_registry("node-hello:alpine", "node-hello", local_registry) docker_load_image_keywords.tag_docker_image_for_registry("node-hello:alpine", "node-hello", local_registry)
docker_load_image_keywords.push_docker_image_to_registry("node-hello", local_registry) docker_load_image_keywords.push_docker_image_to_registry("node-hello", local_registry)
@mark.p0
@mark.lab_has_min_2_subclouds
def test_dc_subcloud_delete(request):
"""
Verify subcloud deletion works as expected
Test Steps:
- log onto system controller
- list all subclouds and get the lowest id subcloud
- unmanage the subcloud
- power off the subcloud
- delete the subcloud
- validate that the subcloud is deleted
"""
get_logger().log_info("Starting 'test_dc_subcloud_delete' test case.")
# Gets the SSH connection to the active controller of the central cloud.
ssh_connection = LabConnectionKeywords().get_active_controller_ssh()
# check if subclouds has added in config
subclouds = ConfigurationManager.get_lab_config().get_subclouds()
if not subclouds:
raise ValueError("Failed. No subclouds were found in lab config")
# List all subclouds and get the lowest id subcloud.
dcm_sc_list_kw = DcManagerSubcloudListKeywords(ssh_connection)
subclouds_list = dcm_sc_list_kw.get_dcmanager_subcloud_list()
# Retrieves subclouds before deletion.
orig_subclouds = subclouds_list.get_dcmanager_subcloud_list_objects()
total_subclouds = len(orig_subclouds)
lowest_subcloud = subclouds_list.get_healthy_subcloud_with_lowest_id()
sc_name = lowest_subcloud.get_name()
get_logger().log_info(f"Total subclouds Before deletion: {total_subclouds}")
msg = (f"Subcloud selected for deletion ID={lowest_subcloud.get_id()} ", f" Name={sc_name}, ", f" Management state={lowest_subcloud.get_management()} ")
get_logger().log_info(msg)
dcm_sc_manager_kw = DcManagerSubcloudManagerKeywords(ssh_connection)
# Unmanage the subcloud.
get_logger().log_test_case_step(f"Unmanage subcloud={sc_name}.")
dcm_sc_manage_output = dcm_sc_manager_kw.get_dcmanager_subcloud_unmanage(sc_name, timeout=10)
get_logger().log_info(f"The management state of the subcloud {sc_name} was changed to {dcm_sc_manage_output.get_dcmanager_subcloud_manage_object().get_management()}.")
# poweroff the subcloud.
get_logger().log_test_case_step(f"Poweroff subcloud={sc_name}.")
dcm_sc_manager_kw.set_subcloud_poweroff(sc_name)
# delete the subcloud
get_logger().log_test_case_step(f"Delete subcloud={sc_name}.")
dcm_sc_del_kw = DcManagerSubcloudDeleteKeywords(ssh_connection)
dcm_sc_del_kw.dcmanager_subcloud_delete(sc_name)
# Retrieves subclouds after deletion.
subclouds_list = dcm_sc_list_kw.get_dcmanager_subcloud_list()
subclouds_after_deletion = subclouds_list.get_dcmanager_subcloud_list_objects()
# assert len(subclouds_after_deletion) == total_subclouds - 1, "Subcloud was not deleted successfully"
validate_equals(len(subclouds_after_deletion), total_subclouds - 1, "Subcloud deleted successfully")
validate_equals(subclouds_list.is_subcloud_in_output(sc_name), False, f"{sc_name} is no longer in the subcloud list.")