diff --git a/ironic_tempest_plugin/config.py b/ironic_tempest_plugin/config.py index 3594b5b..c4fb185 100644 --- a/ironic_tempest_plugin/config.py +++ b/ironic_tempest_plugin/config.py @@ -129,6 +129,8 @@ BaremetalGroup = [ cfg.ListOpt('enabled_rescue_interfaces', default=['no-rescue'], help="List of Ironic enabled rescue interfaces."), + cfg.StrOpt('default_rescue_interface', + help="Ironic default rescue interface."), cfg.IntOpt('adjusted_root_disk_size_gb', min=0, help="Ironic adjusted disk size to use in the standalone tests " diff --git a/ironic_tempest_plugin/tests/scenario/baremetal_manager.py b/ironic_tempest_plugin/tests/scenario/baremetal_manager.py index c220619..6d7d55b 100644 --- a/ironic_tempest_plugin/tests/scenario/baremetal_manager.py +++ b/ironic_tempest_plugin/tests/scenario/baremetal_manager.py @@ -19,6 +19,7 @@ import time from tempest.common import waiters from tempest import config from tempest.lib.common import api_version_utils +from tempest.lib.common.utils.linux import remote_client from tempest.lib import exceptions as lib_exc from ironic_tempest_plugin import clients @@ -232,3 +233,44 @@ class BaremetalScenarioTest(manager.ScenarioTest): BaremetalProvisionStates.AVAILABLE], timeout=CONF.baremetal.unprovision_timeout, interval=30) + + def rescue_instance(self, instance, node, server_ip, + servers_client=None): + """Rescue the instance, verify we can ping and SSH.""" + if servers_client is None: + servers_client = self.servers_client + + rescuing_instance = servers_client.rescue_server(instance['id']) + rescue_password = rescuing_instance['adminPass'] + + self.wait_provisioning_state( + node['uuid'], + BaremetalProvisionStates.RESCUE, + timeout=CONF.baremetal.rescue_timeout) + waiters.wait_for_server_status(servers_client, + instance['id'], 'RESCUE') + # Ping server ip + self.assertTrue(self.ping_ip_address(server_ip)) + # Open ssh connection to server + linux_client = remote_client.RemoteClient( + server_ip, + 'rescue', + password=rescue_password, + server=self.instance, + servers_client=servers_client, + ssh_timeout=CONF.baremetal.rescue_timeout) + linux_client.validate_authentication() + + def unrescue_instance(self, instance, node, server_ip, + servers_client=None): + if servers_client is None: + servers_client = self.servers_client + self.servers_client.unrescue_server(instance['id']) + self.wait_provisioning_state( + node['uuid'], + BaremetalProvisionStates.ACTIVE, + timeout=CONF.baremetal.unrescue_timeout) + waiters.wait_for_server_status(servers_client, + instance['id'], 'ACTIVE') + # Verify server connection + self.get_remote_client(server_ip) diff --git a/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py b/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py index f78155d..61e5323 100644 --- a/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py +++ b/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py @@ -45,6 +45,26 @@ class BaremetalBasicOps(baremetal_manager.BaremetalScenarioTest): expected state transitions """ + TEST_RESCUE_MODE = False + + @classmethod + def skip_checks(cls): + super(BaremetalBasicOps, cls).skip_checks() + + # If default rescue interface is configured to test the rescue + # feature, then skips this test and let the test derived class + # to be executed. + rescue_if = CONF.baremetal.default_rescue_interface + if cls.TEST_RESCUE_MODE: + if not rescue_if or rescue_if == 'no-rescue': + msg = 'Node rescue interface is not enabled.' + raise cls.skipException(msg) + else: + if rescue_if and rescue_if != 'no-rescue': + msg = ('Node rescue interface is enabled, but %s class ' + 'cannot test rescue operations.' % cls.__name__) + raise cls.skipException(msg) + @staticmethod def _is_version_supported(version): """Return whether an API microversion is supported.""" @@ -193,7 +213,6 @@ class BaremetalBasicOps(baremetal_manager.BaremetalScenarioTest): self.validate_ports() self.validate_scheduling() ip_address = self.get_server_ip(self.instance) - self.get_remote_client(ip_address).validate_authentication() vm_client = self.get_remote_client(ip_address) # We expect the ephemeral partition to be mounted on /mnt and to have @@ -205,4 +224,15 @@ class BaremetalBasicOps(baremetal_manager.BaremetalScenarioTest): self.create_timestamp( ip_address, private_key=self.keypair['private_key']) + # Test rescue mode + if self.TEST_RESCUE_MODE: + self.rescue_instance(self.instance, self.node, ip_address) + self.unrescue_instance(self.instance, self.node, ip_address) + self.terminate_instance(self.instance) + + +class BaremetalBasicOpsAndRescue(BaremetalBasicOps): + """This test includes rescue/unrescue ops.""" + + TEST_RESCUE_MODE = True