Merge "Correct the usage on listing neutron ports"
diff --git a/ironic_tempest_plugin/services/baremetal/base.py b/ironic_tempest_plugin/services/baremetal/base.py
index e1c1d71..46c0a2f 100644
--- a/ironic_tempest_plugin/services/baremetal/base.py
+++ b/ironic_tempest_plugin/services/baremetal/base.py
@@ -85,7 +85,8 @@
return json.loads(object_str)
- def _get_uri(self, resource_name, uuid=None, permanent=False):
+ def _get_uri(self, resource_name, uuid=None, permanent=False,
+ params=None):
"""Get URI for a specific resource or object.
:param resource_name: The name of the REST resource, e.g., 'nodes'.
@@ -94,10 +95,15 @@
"""
prefix = self.uri_prefix if not permanent else ''
+ if params:
+ params = '?' + '&'.join('%s=%s' % tpl for tpl in params.items())
+ else:
+ params = ''
- return '{pref}/{res}{uuid}'.format(pref=prefix,
- res=resource_name,
- uuid='/%s' % uuid if uuid else '')
+ return '{pref}/{res}{uuid}{params}'.format(
+ pref=prefix, res=resource_name,
+ uuid='/%s' % uuid if uuid else '',
+ params=params)
def _make_patch(self, allowed_attributes, **kwargs):
"""Create a JSON patch according to RFC 6902.
@@ -229,16 +235,17 @@
self.expected_success(expected_status, resp.status)
return resp, body
- def _patch_request(self, resource, uuid, patch_object):
+ def _patch_request(self, resource, uuid, patch_object, params=None):
"""Update specified object with JSON-patch.
:param resource: The name of the REST resource, e.g., 'nodes'.
:param uuid: The unique identifier of an object in UUID format.
+ :param params: query parameters to pass.
:returns: A tuple with the server response and the serialized patched
object.
"""
- uri = self._get_uri(resource, uuid)
+ uri = self._get_uri(resource, uuid, params=params)
patch_body = json.dumps(patch_object)
resp, body = self.patch(uri, body=patch_body)
diff --git a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
index 25420bc..b31b433 100644
--- a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
+++ b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
@@ -410,6 +410,11 @@
:return: A tuple with the server response and the updated node.
"""
+ if 'reset_interfaces' in kwargs:
+ params = {'reset_interfaces': str(kwargs.pop('reset_interfaces'))}
+ else:
+ params = {}
+
node_attributes = ('properties/cpu_arch',
'properties/cpus',
'properties/local_gb',
@@ -423,7 +428,7 @@
if not patch:
patch = self._make_patch(node_attributes, **kwargs)
- return self._patch_request('nodes', uuid, patch)
+ return self._patch_request('nodes', uuid, patch, params=params)
@base.handle_errors
def update_chassis(self, uuid, **kwargs):
diff --git a/ironic_tempest_plugin/tests/api/admin/test_nodes.py b/ironic_tempest_plugin/tests/api/admin/test_nodes.py
index 8d97a8f..8c1343f 100644
--- a/ironic_tempest_plugin/tests/api/admin/test_nodes.py
+++ b/ironic_tempest_plugin/tests/api/admin/test_nodes.py
@@ -409,6 +409,96 @@
self.client.vif_detach(self.node['uuid'], self.nport_id)
+class TestHardwareInterfaces(base.BaseBaremetalTest):
+
+ min_microversion = '1.31'
+ # Subclasses can override this with more interfaces available in later API
+ # versions.
+ hardware_interfaces = [
+ 'boot',
+ 'console',
+ 'deploy',
+ 'inspect',
+ 'management',
+ 'power',
+ 'raid',
+ 'vendor',
+ ]
+
+ @classmethod
+ def skip_checks(cls):
+ super(TestHardwareInterfaces, cls).skip_checks()
+ if CONF.baremetal.driver != 'fake-hardware':
+ raise cls.skipException('These tests rely on fake-hardware')
+
+ @property
+ def optional_interfaces(self):
+ return set(self.hardware_interfaces) - {'boot', 'deploy',
+ 'management', 'power'}
+
+ def setUp(self):
+ super(TestHardwareInterfaces, self).setUp()
+
+ _, self.chassis = self.create_chassis()
+ _, self.node = self.create_node(self.chassis['uuid'])
+
+ # Reset optional interfaces to non-default values
+ for iface in self.optional_interfaces:
+ self.client.update_node(self.node['uuid'],
+ [{'path': '/%s_interface' % iface,
+ 'op': 'add',
+ 'value': 'no-%s' % iface}])
+
+ def test_set_interfaces(self):
+ for iface in self.hardware_interfaces:
+ field = '%s_interface' % iface
+ self.client.update_node(self.node['uuid'],
+ [{'path': '/%s' % field,
+ 'op': 'add',
+ 'value': 'fake'}])
+ _, node = self.client.show_node(self.node['uuid'])
+ self.assertEqual('fake', node[field])
+
+ def test_reset_interfaces(self):
+ for iface in self.hardware_interfaces:
+ field = '%s_interface' % iface
+ self.client.update_node(self.node['uuid'],
+ [{'path': '/%s' % field,
+ 'op': 'remove'}])
+ _, node = self.client.show_node(self.node['uuid'])
+ self.assertEqual('fake', node[field])
+
+
+class TestResetInterfaces(TestHardwareInterfaces):
+
+ min_microversion = '1.45'
+
+ @classmethod
+ def skip_checks(cls):
+ super(TestResetInterfaces, cls).skip_checks()
+ if 'ipmi' not in CONF.baremetal.enabled_hardware_types:
+ raise cls.skipException('These tests rely on ipmi enabled')
+
+ def test_no_reset_by_default(self):
+ self.assertRaises(
+ lib_exc.BadRequest,
+ self.client.update_node,
+ self.node['uuid'],
+ [{'path': '/driver', 'value': 'ipmi', 'op': 'replace'}])
+ _, node = self.client.show_node(self.node['uuid'])
+ self.assertEqual('fake-hardware', node['driver'])
+
+ def test_reset_all_interfaces(self):
+ self.client.update_node(self.node['uuid'],
+ [{'path': '/driver',
+ 'value': 'ipmi',
+ 'op': 'replace'}],
+ reset_interfaces=True)
+ _, node = self.client.show_node(self.node['uuid'])
+ for iface in self.hardware_interfaces:
+ self.assertNotEqual('fake', node['%s_interface' % iface])
+
+
class TestNodesTraits(base.BaseBaremetalTest):
min_microversion = '1.37'
diff --git a/setup.cfg b/setup.cfg
index 64770b6..99f34dc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,7 +5,7 @@
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
-home-page = https://docs.openstack.org/ironic-tempest-plugin
+home-page = https://docs.openstack.org/ironic-tempest-plugin/latest/
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology