diff --git a/config/lab/objects/lab_config.py b/config/lab/objects/lab_config.py index e566c3c..2670f8c 100644 --- a/config/lab/objects/lab_config.py +++ b/config/lab/objects/lab_config.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Optional import json5 from config.host.objects.host_configuration import HostConfiguration @@ -205,6 +205,34 @@ class LabConfig: return node return None + def get_computes(self) -> [Node]: + """ + Returns the list of nodes whose type is 'compute'. + Returns: + list[Node]: The list of nodes whose type is 'compute'. + + """ + nodes = self.get_nodes() + computes = [node for node in nodes if node.node_type == 'Compute'] + return computes + + def get_compute(self, compute_name) -> Optional[Node]: + """ + Retrieve an instance of Node whose type is 'Compute' and name is specified by the argument 'compute_name'. + Args: + compute_name (str): the name of the 'Compute' node. + + Returns: + Node: An instance of Node whose type field is 'Compute'. + + """ + computes = self.get_computes() + compute = [compute_node for compute_node in computes if compute_node.get_name() == compute_name] + if len(compute) > 0: + return compute[0] + else: + return None + def is_ipv6(self): """ Return True is lab is ipv6, False otherwise diff --git a/keywords/cloud_platform/ssh/lab_connection_keywords.py b/keywords/cloud_platform/ssh/lab_connection_keywords.py index d6822f1..91372b8 100644 --- a/keywords/cloud_platform/ssh/lab_connection_keywords.py +++ b/keywords/cloud_platform/ssh/lab_connection_keywords.py @@ -1,4 +1,5 @@ from config.configuration_manager import ConfigurationManager +from config.lab.objects.node import Node from framework.exceptions.keyword_exception import KeywordException from framework.ssh.ssh_connection import SSHConnection from framework.ssh.ssh_connection_manager import SSHConnectionManager @@ -89,3 +90,32 @@ class LabConnectionKeywords(BaseKeyword): ) return connection + + def get_compute_ssh(self, compute_name: str) -> SSHConnection: + """ + Gets an SSH connection to the 'Compute' node whose name is specified by the argument 'compute_name'. + Args: + compute_name (string): The name of the 'Compute' node. + + Returns: the SSH connection to the 'Compute' node whose name is specified by the argument 'compute_name'. + + """ + lab_config = ConfigurationManager.get_lab_config() + compute_node: Node = lab_config.get_compute(compute_name) + + if not compute_node: + raise ValueError(f"There is no 'Compute' node named {compute_name} defined in your config file.") + + jump_host_config = None + if lab_config.is_use_jump_server(): + jump_host_config = lab_config.get_jump_host_configuration() + + connection = SSHConnectionManager.create_ssh_connection( + compute_node.get_ip(), + lab_config.get_admin_credentials().get_user_name(), + lab_config.get_admin_credentials().get_password(), + ssh_port=lab_config.get_ssh_port(), + jump_host=jump_host_config, + ) + + return connection \ No newline at end of file diff --git a/testcases/cloud_platform/sanity/test_sanity.py b/testcases/cloud_platform/sanity/test_sanity.py index 01f7770..24ce2c2 100644 --- a/testcases/cloud_platform/sanity/test_sanity.py +++ b/testcases/cloud_platform/sanity/test_sanity.py @@ -2,6 +2,7 @@ import time import pytest from config.configuration_manager import ConfigurationManager +from config.lab.objects.node import Node from framework.logging.automation_logger import get_logger from framework.resources.resource_finder import get_stx_resource_path from framework.ssh.secure_transfer_file.secure_transfer_file import SecureTransferFile @@ -968,6 +969,7 @@ def test_dc_unmanage_manage_subclouds(request): @mark.p0 +@mark.lab_has_subcloud def test_dc_central_lock_unlock_host(request): """ Verify lock/unlock of hosts (standby and compute hosts). @@ -976,9 +978,6 @@ def test_dc_central_lock_unlock_host(request): - Retrieve the standby controller. - Lock standby controller and ensure it is successfully locked. - Unlock standby controller and ensure it is successfully unlocked. - - Retrieve a compute host. - - Lock the compute host and ensure it is successfully locked. - - Unlock the compute host and ensure it is successfully unlocked. """ # Gets the SSH connection to the active controller. ssh_connection = LabConnectionKeywords().get_active_controller_ssh() @@ -999,7 +998,7 @@ def test_dc_central_lock_unlock_host(request): # Unlocks the standby host if it was locked in this test but not unlocked. if system_host_lock_keywords.is_host_locked(standby_host_name): system_host_lock_keywords.unlock_host(standby_host_name) - get_logger().log_error(f"Teardown: It was not possible to unlock the host {standby_host_name}.") + get_logger().log_error(f"Teardown: The host {standby_host_name} was successfully unlocked.") else: get_logger().log_info(f"Teardown: It was not necessary to unlock the host {standby_host_name}.") @@ -1017,4 +1016,52 @@ def test_dc_central_lock_unlock_host(request): assert system_host_lock_keywords.is_host_unlocked(standby_host_name), f"It was not possible to unlock the host {standby_host_name}." get_logger().log_info(f"The host {standby_host_name} was successfully set to 'unlocked' state.") - # TODO test a compute host \ No newline at end of file + +@mark.p0 +@mark.lab_has_compute +def test_dc_central_compute_lock_unlock(request): + """ + Verify lock/unlock of 'Compute' type node in the Central controller. + + Test Steps: + - Retrieves 'Compute' type node instance. + - Locks the node and ensure it is successfully locked. + - Unlocks the node and ensure it is successfully unlocked. + """ + # Gets the SSH connection to the active controller. + ssh_connection = LabConnectionKeywords().get_active_controller_ssh() + get_logger().log_info(f"SSH connection to active controller: {ssh_connection}.") + + # Gets the object responsible for lock/unlock the hosts under test. + system_host_lock_keywords = SystemHostLockKeywords(ssh_connection) + + # Gets the first 'Compute' node. + lab_config = ConfigurationManager.get_lab_config() + computes = lab_config.get_computes() + assert len(computes) > 0, "This Central Controller has no nodes of type 'Compute'." + compute: Node = computes[0] + compute_name = compute.get_name() + + def teardown(): + # Unlocks the 'Compute' Node if it was locked in this test but not unlocked. + if system_host_lock_keywords.is_host_locked(compute_name): + system_host_lock_keywords.unlock_host(compute_name) + get_logger().log_error(f"Teardown: The 'Compute' node {compute_name} was successfully unlocked.") + else: + get_logger().log_info(f"Teardown: It was not necessary to unlock the 'Compute' node {compute_name}.") + + request.addfinalizer(teardown) + + # Tries to lock the 'Compute' node. + get_logger().log_info(f"The 'Compute' node {compute_name} will be set to the 'locked' state.") + system_host_lock_keywords.lock_host(compute_name) + assert system_host_lock_keywords.is_host_locked( + compute_name), f"It was not possible to lock the 'Compute' node {compute_name}." + get_logger().log_info(f"The 'Compute' node {compute_name} was successfully set to 'locked' state.") + + # Tries to unlock the 'Compute' node. + get_logger().log_info(f"The 'Compute' node {compute_name} will be set to 'unlocked' state.") + system_host_lock_keywords.unlock_host(compute_name) + assert system_host_lock_keywords.is_host_unlocked( + compute_name), f"It was not possible to unlock the 'Compute' node {compute_name}." + get_logger().log_info(f"The 'Compute' node {compute_name} was successfully set to 'unlocked' state.") \ No newline at end of file diff --git a/testcases/pytest.ini b/testcases/pytest.ini index 8b442b7..f0d35c6 100644 --- a/testcases/pytest.ini +++ b/testcases/pytest.ini @@ -29,6 +29,8 @@ markers= lab_has_bond_interface: mark tests where the host must have a bond interface lab_has_storage_6_osd: mark tests that use specific labs with 6 or more OSDs lab_has_subcloud: mark tests that require at least one subcloud + lab_has_compute: mark tests that require at least one compute node + subcloud_lab_has_compute: mark tests that require at least one subcloud containing at least one compute node #TODO: add 'lab_has_bmc_ipmi', 'lab_has_bmc_redfish', 'lab_has_bmc_dynamic', and 'lab_bmc_sensor'