Add API tests for protected nodes
Depends-On: https://review.openstack.org/611662 Change-Id: I2e8f1b0b99b349be60f179a5fe7157ac327ae8d5 Story: #2003869 Task: #27611
This commit is contained in:
parent
f248d4cb07
commit
0325dbd269
|
@ -424,7 +424,12 @@ class BaremetalClient(base.BaremetalClient):
|
|||
'deploy_interface',
|
||||
'rescue_interface',
|
||||
'instance_uuid',
|
||||
'resource_class')
|
||||
'resource_class',
|
||||
'protected',
|
||||
'protected_reason',
|
||||
# TODO(dtantsur): maintenance is set differently
|
||||
# in newer API versions.
|
||||
'maintenance')
|
||||
if not patch:
|
||||
patch = self._make_patch(node_attributes, **kwargs)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ from tempest.lib import exceptions as lib_exc
|
|||
from tempest import test
|
||||
|
||||
from ironic_tempest_plugin import clients
|
||||
from ironic_tempest_plugin.common import waiters
|
||||
from ironic_tempest_plugin.tests.api.admin import api_microversion_fixture
|
||||
|
||||
CONF = config.CONF
|
||||
|
@ -104,12 +105,19 @@ class BaseBaremetalTest(api_version_utils.BaseMicroversionTest,
|
|||
cls.created_objects = {}
|
||||
for resource in RESOURCE_TYPES:
|
||||
cls.created_objects[resource] = set()
|
||||
cls.deployed_nodes = set()
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
"""Ensure that all created objects get destroyed."""
|
||||
|
||||
try:
|
||||
for node in cls.deployed_nodes:
|
||||
try:
|
||||
cls.set_node_provision_state(node, 'deleted',
|
||||
['available', None])
|
||||
except lib_exc.BadRequest:
|
||||
pass
|
||||
|
||||
for resource in RESOURCE_TYPES:
|
||||
uuids = cls.created_objects[resource]
|
||||
delete_method = getattr(cls.client, 'delete_%s' % resource)
|
||||
|
@ -183,6 +191,63 @@ class BaseBaremetalTest(api_version_utils.BaseMicroversionTest,
|
|||
|
||||
return resp, body
|
||||
|
||||
@classmethod
|
||||
def set_node_provision_state(cls, node_id, target, expected, timeout=None,
|
||||
interval=None):
|
||||
"""Sets the node's provision state.
|
||||
|
||||
:param node_id: The unique identifier of the node.
|
||||
:param target: Target provision state.
|
||||
:param expected: Expected final provision state or list of states.
|
||||
:param timeout: The timeout for reaching the expected state.
|
||||
Defaults to client.build_timeout.
|
||||
:param interval: An interval between show_node calls for status check.
|
||||
Defaults to client.build_interval.
|
||||
"""
|
||||
cls.client.set_node_provision_state(node_id, target)
|
||||
waiters.wait_for_bm_node_status(cls.client, node_id,
|
||||
'provision_state', expected,
|
||||
timeout=timeout, interval=interval)
|
||||
|
||||
@classmethod
|
||||
def provide_node(cls, node_id, cleaning_timeout=None):
|
||||
"""Make the node available.
|
||||
|
||||
:param node_id: The unique identifier of the node.
|
||||
:param cleaning_timeout: The timeout to wait for cleaning.
|
||||
Defaults to client.build_timeout.
|
||||
"""
|
||||
_, body = cls.client.show_node(node_id)
|
||||
current_state = body['provision_state']
|
||||
if current_state == 'enroll':
|
||||
cls.set_node_provision_state(node_id, 'manage', 'manageable',
|
||||
timeout=60, interval=1)
|
||||
current_state = 'manageable'
|
||||
if current_state == 'manageable':
|
||||
cls.set_node_provision_state(node_id, 'provide',
|
||||
['available', None],
|
||||
timeout=cleaning_timeout)
|
||||
current_state = 'available'
|
||||
if current_state not in ('available', None):
|
||||
raise RuntimeError("Cannot reach state 'available': node %(node)s "
|
||||
"is in unexpected state %(state)s" %
|
||||
{'node': node_id, 'state': current_state})
|
||||
|
||||
@classmethod
|
||||
def deploy_node(cls, node_id, cleaning_timeout=None, deploy_timeout=None):
|
||||
"""Deploy the node.
|
||||
|
||||
:param node_id: The unique identifier of the node.
|
||||
:param cleaning_timeout: The timeout to wait for cleaning.
|
||||
Defaults to client.build_timeout.
|
||||
:param deploy_timeout: The timeout to wait for deploy.
|
||||
Defaults to client.build_timeout.
|
||||
"""
|
||||
cls.provide_node(node_id, cleaning_timeout=cleaning_timeout)
|
||||
cls.set_node_provision_state(node_id, 'active', 'active',
|
||||
timeout=deploy_timeout)
|
||||
cls.deployed_nodes.add(node_id)
|
||||
|
||||
@classmethod
|
||||
@creates('port')
|
||||
def create_port(cls, node_id, address, extra=None, uuid=None,
|
||||
|
|
|
@ -850,3 +850,97 @@ class TestNodeFault(base.BaseBaremetalTest):
|
|||
self.assertRaises(
|
||||
lib_exc.BadRequest,
|
||||
self.client.list_nodes, fault='somefake')
|
||||
|
||||
|
||||
class TestNodeProtected(base.BaseBaremetalTest):
|
||||
"""Tests for protected baremetal nodes."""
|
||||
|
||||
min_microversion = '1.48'
|
||||
|
||||
def setUp(self):
|
||||
super(TestNodeProtected, self).setUp()
|
||||
|
||||
_, self.chassis = self.create_chassis()
|
||||
_, self.node = self.create_node(self.chassis['uuid'])
|
||||
self.provide_node(self.node['uuid'])
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
self.client.update_node(self.node['uuid'], protected=False)
|
||||
except Exception:
|
||||
pass
|
||||
super(TestNodeProtected, self).tearDown()
|
||||
|
||||
@decorators.idempotent_id('52f0cb1c-ad7b-43dc-8e22-a76438b67716')
|
||||
def test_node_protected_set_unset(self):
|
||||
self.deploy_node(self.node['uuid'])
|
||||
_, self.node = self.client.show_node(self.node['uuid'])
|
||||
self.assertFalse(self.node['protected'])
|
||||
self.assertIsNone(self.node['protected_reason'])
|
||||
|
||||
self.client.update_node(self.node['uuid'], protected=True,
|
||||
protected_reason='reason!')
|
||||
_, self.node = self.client.show_node(self.node['uuid'])
|
||||
self.assertTrue(self.node['protected'])
|
||||
self.assertEqual('reason!', self.node['protected_reason'])
|
||||
|
||||
self.client.update_node(self.node['uuid'], protected=False)
|
||||
_, self.node = self.client.show_node(self.node['uuid'])
|
||||
self.assertFalse(self.node['protected'])
|
||||
self.assertIsNone(self.node['protected_reason'])
|
||||
|
||||
@decorators.idempotent_id('8fbd101e-90e6-4843-b41a-556b34802972')
|
||||
def test_node_protected(self):
|
||||
self.deploy_node(self.node['uuid'])
|
||||
self.client.update_node(self.node['uuid'], protected=True)
|
||||
|
||||
self.assertRaises(lib_exc.Forbidden,
|
||||
self.set_node_provision_state,
|
||||
self.node['uuid'], 'deleted', 'available')
|
||||
self.assertRaises(lib_exc.Forbidden,
|
||||
self.set_node_provision_state,
|
||||
self.node['uuid'], 'rebuild', 'active')
|
||||
|
||||
@decorators.idempotent_id('04a21b51-2991-4213-8c2f-a96cfdada802')
|
||||
def test_node_protected_from_deletion(self):
|
||||
self.deploy_node(self.node['uuid'])
|
||||
self.client.update_node(self.node['uuid'], protected=True,
|
||||
maintenance=True)
|
||||
|
||||
self.assertRaises(lib_exc.Forbidden,
|
||||
self.client.delete_node,
|
||||
self.node['uuid'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('1c819f4c-6c1d-4150-ba4a-3b0dcb3c8694')
|
||||
def test_node_protected_negative(self):
|
||||
# Cannot be set for available nodes
|
||||
self.assertRaises(lib_exc.Conflict,
|
||||
self.client.update_node,
|
||||
self.node['uuid'], protected=True)
|
||||
|
||||
self.deploy_node(self.node['uuid'])
|
||||
|
||||
# Reason cannot be set for nodes that are not protected
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.client.update_node,
|
||||
self.node['uuid'], protected_reason='reason!')
|
||||
|
||||
|
||||
class TestNodesProtectedOldApi(base.BaseBaremetalTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNodesProtectedOldApi, self).setUp()
|
||||
_, self.chassis = self.create_chassis()
|
||||
_, self.node = self.create_node(self.chassis['uuid'])
|
||||
self.deploy_node(self.node['uuid'])
|
||||
_, self.node = self.client.show_node(self.node['uuid'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('08971546-27cc-40ab-851e-ba7bb52c00ab')
|
||||
def test_node_protected_old_api(self):
|
||||
exc = self.assertRaises(
|
||||
lib_exc.RestClientException,
|
||||
self.client.update_node, self.node['uuid'], protected=True)
|
||||
# 400 for old ironic, 406 for new ironic with old microversion.
|
||||
self.assertIn(exc.resp.status, (400, 406))
|
||||
|
|
Loading…
Reference in New Issue