Merge "Clarify checksum for wholedisk images."
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 26c37e0..db06a9e 100644
--- a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
+++ b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
@@ -602,6 +602,19 @@
target)
@base.handle_errors
+ def set_node_state(self, node_uuid, state, target):
+ """Set state for the specified node.
+
+ :param node_uuid: The unique identifier of the node.
+ :param state: The desired state to set.
+ :param target: The target state
+
+ """
+ target = {'target': target}
+ return self._put_request('nodes/%s/states/%s' % (node_uuid, state),
+ target)
+
+ @base.handle_errors
def set_node_provision_state(self, node_uuid, state, configdrive=None,
clean_steps=None, rescue_password=None):
"""Set provision state of the specified node.
@@ -681,6 +694,38 @@
return body
@base.handle_errors
+ def set_node_indicator_state(self, node_uuid, component, ind_ident, state):
+ """Get the current indicator state
+
+ :param node_uuid: The unique identifier of the node.
+ :param component: The Bare Metal node component.
+ :param ind_ident: The indicator of a Bare Metal component.
+ :param state: The state of an indicator of the component of the node.
+ Possible values are: OFF, ON, BLINKING or UNKNOWN.
+
+ """
+ resp, body = self._put_request(
+ 'nodes/%s/management/indicators/%s@%s'
+ % (node_uuid, ind_ident, component), {'state': state})
+ self.expected_success(http_client.OK, resp.status)
+ return resp, body
+
+ @base.handle_errors
+ def get_node_indicator_state(self, node_uuid, component, ind_ident):
+ """Get the current indicator state
+
+ :param node_uuid: The unique identifier of the node.
+ :param component: The Bare Metal node component.
+ :param ind_ident: The indicator of a Bare Metal component.
+
+ """
+ path = 'nodes/%s/management/indicators/%s@%s' % (node_uuid, ind_ident,
+ component)
+ resp, body = self._list_request(path)
+ self.expected_success(http_client.OK, resp.status)
+ return resp, body
+
+ @base.handle_errors
def get_node_supported_boot_devices(self, node_uuid):
"""Get the supported boot devices of the specified node.
@@ -864,3 +909,39 @@
"""
return self._delete_request('allocations', allocation_ident)
+
+ @base.handle_errors
+ def list_node_history(self, node_uuid):
+ """List history entries for a node.
+
+ :param node_uuid: The unique identifier of the node.
+ """
+ return self._list_request('/nodes/%s/history' % node_uuid)
+
+ @base.handle_errors
+ def list_vendor_passthru_methods(self, node_uuid):
+ """List vendor-specific extensions (passthru) methods for a node
+
+ :param node_uuid: The unique identifier of the node.
+ """
+ return self._list_request('/nodes/%s/vendor_passthru/methods'
+ % node_uuid)
+
+ @base.handle_errors
+ def ipa_heartbeat(self, node_uuid, callback_url, agent_token,
+ agent_version):
+ """Create a IPA heartbeat from the given body.
+
+ :param node_uuid: The unique identifier of the node.
+ :param callback_url: The URL of an active ironic-python-agent ramdisk
+ :param agent_token: The token of the ironic-python-agent ramdisk
+ :param agent_version: The version of the ironic-python-agent ramdisk
+ """
+ kwargs = {
+ 'node_ident': node_uuid,
+ 'callback_url': callback_url,
+ 'agent_version': agent_version,
+ 'agent_token': agent_token,
+ }
+
+ return self._create_request_no_response_body('heartbeat', kwargs)
diff --git a/ironic_tempest_plugin/tests/api/base.py b/ironic_tempest_plugin/tests/api/base.py
index 5469579..6ebb162 100644
--- a/ironic_tempest_plugin/tests/api/base.py
+++ b/ironic_tempest_plugin/tests/api/base.py
@@ -482,3 +482,16 @@
"""
resp, body = cls.client.create_allocation(resource_class, **kwargs)
return resp, body
+
+
+class BaseBaremetalRBACTest(BaseBaremetalTest):
+
+ # Unless otherwise superceeded by a version, RBAC tests generally start at
+ # version 1.70 as that is when System scope and the delineation occured.
+ min_microversion = '1.70'
+
+ @classmethod
+ def skip_checks(cls):
+ super(BaseBaremetalRBACTest, cls).skip_checks()
+ if not CONF.enforce_scope.ironic:
+ raise cls.skipException('RBAC tests for Ironic are not enabled.')
diff --git a/ironic_tempest_plugin/tests/api/rbac_defaults/__init__.py b/ironic_tempest_plugin/tests/api/rbac_defaults/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ironic_tempest_plugin/tests/api/rbac_defaults/__init__.py
diff --git a/ironic_tempest_plugin/tests/api/rbac_defaults/test_nodes.py b/ironic_tempest_plugin/tests/api/rbac_defaults/test_nodes.py
new file mode 100644
index 0000000..2625ac3
--- /dev/null
+++ b/ironic_tempest_plugin/tests/api/rbac_defaults/test_nodes.py
@@ -0,0 +1,1285 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest import config
+# from tempest.lib.common import rest_client
+# from tempest.lib.common.utils import data_utils
+# from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from ironic_tempest_plugin.common import waiters
+from ironic_tempest_plugin.tests.api import base
+
+CONF = config.CONF
+
+
+class TestNodeProjectReader(base.BaseBaremetalRBACTest):
+ """Tests for baremetal nodes with a tempest project reader."""
+
+ credentials = ['system_admin', 'project_reader']
+
+ def setUp(self):
+ super(TestNodeProjectReader, self).setUp()
+
+ self.client = self.os_system_admin.baremetal.BaremetalClient()
+ self.reader_client = self.os_project_reader.baremetal.BaremetalClient()
+ _, self.chassis = self.create_chassis()
+ # Bare node, no inherent permissions by default for project readers.
+ _, self.node = self.create_node(self.chassis['uuid'])
+
+ # Default policy is:
+ # ('role:reader and '
+ # '(project_id:%(node.owner)s or project_id:%(node.lessee)s)')
+
+ def test_reader_cannot_create_node(self):
+ try:
+ resp, body = self.reader_client.create_node(self.chassis['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_get_node(self):
+ """Reader cannot get node
+
+ baremetal:node:list
+ """
+ try:
+ resp, body = self.reader_client.show_node(self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_list_is_empty(self):
+ """Expected default for no lessee or owner rights is an empty list.
+
+ baremetal:node:list and baremetal:node:list_all
+ """
+ resp, body = self.reader_client.list_nodes()
+ self.assertEqual(0, len(body['nodes']))
+
+ def test_reader_cannot_update_node(self):
+ """Reader cannot update node
+
+ baremetal:node:update
+ """
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_driver_info(self):
+ """Reader cannot update node driver_info
+
+ baremetal:node:update:driver_info
+ """
+ patch = [{'path': '/driver_info/ipmi_username', 'op': 'replace',
+ 'value': 'foo_user'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_properties(self):
+ """Reader cannot update node properties
+
+ baremetal:node:update:properties
+ """
+ new_p = {'cpu_arch': 'arm64', 'cpus': '1', 'local_gb': '10000',
+ 'memory_mb': '12300'}
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ properties=new_p)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_chassis_uuid(self):
+ """Reader cannot update node chassis uuid
+
+ baremetal:node:update:chassis_uuid
+ """
+ patch = [{'path': '/chassis_uuid', 'op': 'replace',
+ 'value': 'new_chassis_uuid'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_instance_uuid(self):
+ """Reader cannot update node instance uuid
+
+ baremetal:node:update:instance_uuid
+ """
+ patch = [{'path': '/instance_uuid', 'op': 'replace',
+ 'value': 'new_instance_uuid'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_lessee(self):
+ """Reader cannot update node lessee
+
+ baremetal:node:update:lessee
+ """
+ patch = [{'path': '/lessee', 'op': 'replace',
+ 'value': 'new_lessee'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_owner(self):
+ """Reader cannot update node owner
+
+ baremetal:node:update:owner
+ """
+ patch = [{'path': '/owner', 'op': 'replace',
+ 'value': 'new_owner'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_driver_interfaces(self):
+ """Reader cannot update node driver interfaces
+
+ baremetal:node:update:driver_interfaces
+ """
+ patch = [{'path': '/driver', 'op': 'replace', 'value': 'ipmi'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_network_data(self):
+ """Reader cannot update node network data
+
+ baremetal:node:update:network_data
+ """
+ new_net_data = {'networks': [], 'services': [], 'links': []}
+ patch = [{'path': '/network_data', 'op': 'replace',
+ 'value': new_net_data}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_conductor_group(self):
+ """Reader cannot update node conductor group
+
+ baremetal:node:update:conductor_group
+ """
+ patch = [{'path': '/conductor_group', 'op': 'replace',
+ 'value': 'new_group'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_name(self):
+ """Reader cannot update node name
+
+ baremetal:node:update:name
+ """
+ patch = [{'path': '/name', 'op': 'replace', 'value': 'new_name'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_retired(self):
+ """Reader cannot update node retired
+
+ baremetal:node:update:retired
+ """
+ patch = [{'path': '/retired', 'op': 'replace', 'value': True}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_node_extra(self):
+ """Reader cannot update node extra
+
+ baremetal:node:update:extra
+ """
+ patch = [{'path': '/extra', 'op': 'replace',
+ 'value': {'extra': 'extra'}}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_instance_info(self):
+ """Reader cannot update node instance info
+
+ baremetal:node:update:instance_info
+ """
+ patch = [{'path': '/instance_info', 'op': 'replace',
+ 'value': {'display_name': 'new_display_name'}}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_update_owner_provisioned(self):
+ """Reader cannot update node owner provisioned
+
+ baremetal:node:update_owner_provisioned
+ """
+ provision_states_list = ['manage', 'provide', 'active']
+ target_states_list = ['manageable', 'available', 'active']
+ for (provision_state, target_state) in zip(provision_states_list,
+ target_states_list):
+ self.client.set_node_provision_state(self.node['uuid'],
+ provision_state)
+ waiters.wait_for_bm_node_status(self.client, self.node['uuid'],
+ attr='provision_state',
+ status=target_state, timeout=10)
+
+ patch = [{'path': '/owner', 'op': 'replace',
+ 'value': {'display_name': 'new_owner'}}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+ finally:
+ self.client.set_node_provision_state(self.node['uuid'],
+ 'deleted')
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_delete_node(self):
+ """Reader cannot delete node
+
+ baremetal:node:delete
+ """
+ try:
+ resp, body = self.reader_client.delete_node(self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_validate_node(self):
+ """Reader cannot validate node
+
+ baremetal:node:validate
+ """
+ try:
+ resp, body = self.reader_client.validate_driver_interface(
+ self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_maintenance(self):
+ """Reader cannot set maintenance mode
+
+ baremetal:node:set_maintenance
+ """
+ patch = [{'path': '/maintenance', 'op': 'replace', 'value': True}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_unset_maintenance(self):
+ """Reader cannot unset maintenance mode
+
+ baremetal:node:clear_maintenance
+ """
+ patch = [{'path': '/maintenance', 'op': 'replace', 'value': False}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_get_boot_device(self):
+ """Reader cannot get boot device
+
+ baremetal:node:get_boot_device
+ """
+ try:
+ resp, body = self.reader_client.get_node_boot_device(
+ self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_boot_device(self):
+ """Reader cannot set boot device
+
+ baremetal:node:set_boot_device
+ """
+ try:
+ resp, body = self.reader_client.set_node_boot_device(
+ self.node['uuid'], 'pxe')
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_get_indicator_state(self):
+ """Reader cannot get indicator state
+
+ baremetal:node:get_indicator_state
+ """
+ try:
+ resp, body = self.reader_client.get_node_indicator_state(
+ self.node['uuid'], 'system', 'led')
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_indicator_state(self):
+ """Reader cannot set indicator state
+
+ baremetal:node:set_indicator_state
+ """
+ try:
+ resp, body = self.reader_client.set_node_indicator_state(
+ self.node['uuid'], 'system', 'led', 'BLINKING')
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_inject_nmi(self):
+ """Reader cannot inject NMI
+
+ baremetal:node:inject_nmi
+ """
+ try:
+ resp, body = self.reader_client._put_request(
+ '/v1/nodes/%s/management/inject_nmi' % self.node['uuid'], {})
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_get_states(self):
+ """Reader cannot list the states of the node
+
+ baremetal:node:get_states
+ """
+ try:
+ resp, body = self.reader_client.list_nodestates(self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_power_state(self):
+ """Reader cannot set power state
+
+ baremetal:node:set_power_state
+ """
+ try:
+ resp, body = self.reader_client.set_node_power_state(
+ self.node['uuid'], 'off')
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_boot_mode(self):
+ """Reader cannot set boot mode
+
+ baremetal:node:set_boot_mode
+ """
+ try:
+ resp, body = self.reader_client.set_node_state(
+ self.node['uuid'], 'boot_mode', 'uefi')
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_secure_boot(self):
+ """Reader cannot set secure boot
+
+ baremetal:node:set_secure_boot
+ """
+ try:
+ resp, body = self.reader_client.set_node_state(
+ self.node['uuid'], 'secure_boot', True)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_provision_state(self):
+ """Reader cannot set provision state
+
+ baremetal:node:set_provision_state
+ """
+ try:
+ resp, body = self.reader_client.set_node_provision_state(
+ self.node['uuid'], 'manage')
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_raid_state(self):
+ """Reader cannot set raid state
+
+ baremetal:node:set_raid_state
+ """
+ try:
+ resp, body = self.reader_client.set_node_state(
+ self.node['uuid'], 'target_raid_config', {'raid': 'config'})
+ except lib_exc.UnexpectedResponseCode as e:
+ resp = e.resp
+
+ self.assertEqual(405, resp.status)
+
+ def test_reader_cannot_get_console(self):
+ """Reader cannot get console
+
+ baremetal:node:get_console
+ """
+ try:
+ resp, body = self.reader_client.get_console(self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_set_console_state(self):
+ """Reader cannot set console state
+
+ baremetal:node:set_console_state
+ """
+ try:
+ resp, body = self.reader_client.set_console_mode(
+ self.node['uuid'], enabled=True)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_vif_list(self):
+ """Reader cannot list vifs
+
+ baremetal:node:vif:list
+ """
+ try:
+ resp, body = self.reader_client.vif_list(self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_vif_attach(self):
+ """Reader cannot attach vif
+
+ baremetal:node:vif:attach
+ """
+ try:
+ resp, body = self.reader_client.vif_attach(
+ self.node['uuid'], 'vifid')
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_vif_detach(self):
+ """Reader cannot detach vif
+
+ baremetal:node:vif:detach
+ """
+ try:
+ resp, body = self.reader_client.vif_detach(
+ self.node['uuid'], 'vifid')
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_traits_list(self):
+ """Reader cannot list traits
+
+ baremetal:node:traits:list
+ """
+ try:
+ resp, body = self.reader_client.list_node_traits(self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_traits_set(self):
+ """Reader cannot set traits
+
+ baremetal:node:traits:set
+ """
+ try:
+ resp, body = self.reader_client.set_node_traits(
+ self.node['uuid'], ['CUSTOM_TRAIT_A', 'CUSTOM_TRAIT_B'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_traits_delete(self):
+ """Reader cannot delete traits
+
+ baremetal:node:traits:delete
+ """
+ try:
+ resp, body = self.reader_client.remove_node_traits(
+ self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_bios_get(self):
+ """Reader cannot get bios settings
+
+ baremetal:node:bios:get
+ """
+ try:
+ resp, body = self.reader_client.list_node_bios_settings(
+ self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_disable_cleaning(self):
+ """Reader cannot disable automated node cleaning
+
+ baremetal:node:disable_cleaning
+ """
+ patch = [{'path': '/automated_clean', 'op': 'replace', 'value': False}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_history_get(self):
+ """Reader cannot list history entries for a node
+
+ baremetal:node:history:get
+ """
+ try:
+ resp, body = self.reader_client.list_node_history(
+ self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_vendor_passthru(self):
+ """Reader cannot list vendor-specific extensions
+
+ baremetal:node:vendor_passthru
+ """
+ try:
+ resp, body = self.reader_client.list_vendor_passthru_methods(
+ self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_ipa_heartbeat(self):
+ """Reader cannot heartbeat
+
+ baremetal:node:ipa_heartbeat
+ """
+ # TODO(hjensas)
+ # try:
+ # resp, body = self.reader_client.ipa_heartbeat(
+ # self.node['uuid'], callback_url='http://foo/',
+ # agent_token=uuidutils.generate_uuid(), agent_version='1')
+ # except lib_exc.BadRequest as e:
+ # resp = e.resp
+ #
+ # self.assertEqual(400, resp.status)
+ pass
+
+
+class TestNodeSystemReader(base.BaseBaremetalRBACTest):
+ """Tests for baremetal nodes with a tempest system reader.
+
+ All tests here must always expect *multiple* nodes visible, since
+ this is a global reader role.
+
+ https://opendev.org/openstack/ironic/src/branch/master/ironic/common/policy.py#L60 # noqa
+ """
+
+ credentials = ['system_admin', 'system_reader']
+
+ def setUp(self):
+ super(TestNodeSystemReader, self).setUp()
+
+ self.client = self.os_system_admin.baremetal.BaremetalClient()
+ self.reader_client = self.os_system_reader.baremetal.BaremetalClient()
+ _, self.chassis = self.create_chassis()
+ _, self.node = self.create_node(self.chassis['uuid'])
+
+ def test_reader_cannot_create_node(self):
+ """Reader cannot create node
+
+ baremetal:node:create
+ """
+ try:
+ resp, body = self.reader_client.create_node(self.chassis['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_can_get_node(self):
+ """Reader can get node
+
+ baremetal:node:??get??list??
+ """
+ resp, body = self.reader_client.show_node(self.node['uuid'])
+ self.assertEqual(200, resp.status)
+
+ def test_reader_list_is_not_empty(self):
+ """List nodes return all nodes
+
+ baremetal:node:list and baremetal:node:list_all
+ """
+ resp, body = self.reader_client.list_nodes()
+ self.assertGreater(len(body['nodes']), 0)
+
+ def test_reader_cannot_update_node(self):
+ """Reader cannot update node
+
+ baremetal:node:update
+ """
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_driver_info(self):
+ """Reader cannot update node driver_info
+
+ baremetal:node:update:driver_info
+ """
+ patch = [{'path': '/driver_info/ipmi_username', 'op': 'replace',
+ 'value': 'foo_user'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_properties(self):
+ """Reader cannot update node properties
+
+ baremetal:node:update:properties
+ """
+ new_p = {'cpu_arch': 'arm64', 'cpus': '1', 'local_gb': '10000',
+ 'memory_mb': '12300'}
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ properties=new_p)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_chassis_uuid(self):
+ """Reader cannot update node chassis uuid
+
+ baremetal:node:update:chassis_uuid
+ """
+ patch = [{'path': '/chassis_uuid', 'op': 'replace',
+ 'value': 'new_chassis_uuid'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_instance_uuid(self):
+ """Reader cannot update node instance uuid
+
+ baremetal:node:update:instance_uuid
+ """
+ patch = [{'path': '/instance_uuid', 'op': 'replace',
+ 'value': 'new_instance_uuid'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_lessee(self):
+ """Reader cannot update node lessee
+
+ baremetal:node:update:lessee
+ """
+ patch = [{'path': '/lessee', 'op': 'replace',
+ 'value': 'new_lessee'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_owner(self):
+ """Reader cannot update node owner
+
+ baremetal:node:update:owner
+ """
+ patch = [{'path': '/owner', 'op': 'replace',
+ 'value': 'new_owner'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_driver_interfaces(self):
+ """Reader cannot update node driver interfaces
+
+ baremetal:node:update:driver_interfaces
+ """
+ patch = [{'path': '/driver', 'op': 'replace', 'value': 'ipmi'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_network_data(self):
+ """Reader cannot update node network data
+
+ baremetal:node:update:network_data
+ """
+ new_net_data = {'networks': [], 'services': [], 'links': []}
+ patch = [{'path': '/network_data', 'op': 'replace',
+ 'value': new_net_data}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_conductor_group(self):
+ """Reader cannot update node conductor group
+
+ baremetal:node:update:conductor_group
+ """
+ patch = [{'path': '/conductor_group', 'op': 'replace',
+ 'value': 'new_group'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_name(self):
+ """Reader cannot update node name
+
+ baremetal:node:update:name
+ """
+ patch = [{'path': '/name', 'op': 'replace', 'value': 'new_name'}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_retired(self):
+ """Reader cannot update node retired
+
+ baremetal:node:update:retired
+ """
+ patch = [{'path': '/retired', 'op': 'replace', 'value': True}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_node_extra(self):
+ """Reader cannot update node extra
+
+ baremetal:node:update:extra
+ """
+ patch = [{'path': '/extra', 'op': 'replace',
+ 'value': {'extra': 'extra'}}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_instance_info(self):
+ """Reader cannot update node instance info
+
+ baremetal:node:update:instance_info
+ """
+ patch = [{'path': '/instance_info', 'op': 'replace',
+ 'value': {'display_name': 'new_display_name'}}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_update_owner_provisioned(self):
+ """Reader cannot update node owner provisioned
+
+ baremetal:node:update_owner_provisioned
+ """
+ provision_states_list = ['manage', 'provide', 'active']
+ target_states_list = ['manageable', 'available', 'active']
+ for (provision_state, target_state) in zip(provision_states_list,
+ target_states_list):
+ self.client.set_node_provision_state(self.node['uuid'],
+ provision_state)
+ waiters.wait_for_bm_node_status(self.client, self.node['uuid'],
+ attr='provision_state',
+ status=target_state, timeout=10)
+
+ patch = [{'path': '/owner', 'op': 'replace',
+ 'value': {'display_name': 'new_owner'}}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+ finally:
+ self.client.set_node_provision_state(self.node['uuid'],
+ 'deleted')
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_delete_node(self):
+ """Reader cannot delete node
+
+ baremetal:node:delete
+ """
+ try:
+ resp, body = self.reader_client.delete_node(self.node['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_validate_node(self):
+ """Reader cannot validate node
+
+ baremetal:node:validate
+ """
+ try:
+ resp, body = self.reader_client.validate_driver_interface(
+ self.node['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_set_maintenance(self):
+ """Reader cannot set maintenance mode
+
+ baremetal:node:set_maintenance
+ """
+ patch = [{'path': '/maintenance', 'op': 'replace', 'value': True}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_unset_maintenance(self):
+ """Reader cannot unset maintenance mode
+
+ baremetal:node:clear_maintenance
+ """
+ patch = [{'path': '/maintenance', 'op': 'replace', 'value': False}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_get_boot_device(self):
+ """Reader cannot get boot device
+
+ baremetal:node:get_boot_device
+ """
+ try:
+ resp, body = self.reader_client.get_node_boot_device(
+ self.node['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_set_boot_device(self):
+ """Reader cannot set boot device
+
+ baremetal:node:set_boot_device
+ """
+ try:
+ resp, body = self.reader_client.set_node_boot_device(
+ self.node['uuid'], 'pxe')
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_can_get_indicator_state(self):
+ """Reader can get indicator state
+
+ baremetal:node:get_indicator_state
+ """
+ resp, body = self.reader_client.get_node_indicator_state(
+ self.node['uuid'], 'system', 'led')
+ self.assertEqual(200, resp.status)
+
+ def test_reader_cannot_set_indicator_state(self):
+ """Reader cannot set indicator state
+
+ baremetal:node:set_indicator_state
+ """
+ try:
+ resp, body = self.reader_client.set_node_indicator_state(
+ self.node['uuid'], 'system', 'led', 'BLINKING')
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_inject_nmi(self):
+ """Reader cannot inject NMI
+
+ baremetal:node:inject_nmi
+ """
+ try:
+ resp, body = self.reader_client._put_request(
+ '/v1/nodes/%s/management/inject_nmi' % self.node['uuid'], {})
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_can_get_states(self):
+ """Reader can list the states of the node
+
+ baremetal:node:get_states
+ """
+ resp, body = self.reader_client.list_nodestates(self.node['uuid'])
+ self.assertEqual(200, resp.status)
+
+ def test_reader_cannot_set_power_state(self):
+ """Reader cannot set power state
+
+ baremetal:node:set_power_state
+ """
+ try:
+ resp, body = self.reader_client.set_node_power_state(
+ self.node['uuid'], 'off')
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_set_boot_mode(self):
+ """Reader cannot set boot mode
+
+ baremetal:node:set_boot_mode
+ """
+ try:
+ resp, body = self.reader_client.set_node_state(
+ self.node['uuid'], 'boot_mode', 'uefi')
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_set_secure_boot(self):
+ """Reader cannot set secure boot
+
+ baremetal:node:set_secure_boot
+ """
+ try:
+ resp, body = self.reader_client.set_node_state(
+ self.node['uuid'], 'secure_boot', True)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_set_provision_state(self):
+ """Reader cannot set provision state
+
+ baremetal:node:set_provision_state
+ """
+ try:
+ resp, body = self.reader_client.set_node_provision_state(
+ self.node['uuid'], 'manage')
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_set_raid_state(self):
+ """Reader cannot set raid state
+
+ baremetal:node:set_raid_state
+ """
+ try:
+ resp, body = self.reader_client.set_node_state(
+ self.node['uuid'], 'target_raid_config', {'raid': 'config'})
+ except lib_exc.UnexpectedResponseCode as e:
+ resp = e.resp
+
+ self.assertEqual(405, resp.status)
+
+ def test_reader_cannot_get_console(self):
+ """Reader cannot get console
+
+ baremetal:node:get_console
+ """
+ try:
+ resp, body = self.reader_client.get_console(self.node['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_set_console_state(self):
+ """Reader cannot set console state
+
+ baremetal:node:set_console_state
+ """
+ try:
+ resp, body = self.reader_client.set_console_mode(
+ self.node['uuid'], enabled=True)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_can_vif_list(self):
+ """Reader can list vifs
+
+ baremetal:node:vif:list
+ """
+ resp, body = self.reader_client.vif_list(self.node['uuid'])
+ self.assertEqual(200, resp.status)
+
+ def test_reader_cannot_vif_attach(self):
+ """Reader cannot attach vif
+
+ baremetal:node:vif:attach
+ """
+ try:
+ resp, body = self.reader_client.vif_attach(
+ self.node['uuid'], 'vifid')
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_vif_detach(self):
+ """Reader cannot detach vif
+
+ baremetal:node:vif:detach
+ """
+ try:
+ resp, body = self.reader_client.vif_detach(
+ self.node['uuid'], 'vifid')
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_can_traits_list(self):
+ """Reader can list traits
+
+ baremetal:node:traits:list
+ """
+ resp, body = self.reader_client.list_node_traits(self.node['uuid'])
+ self.assertEqual(200, resp.status)
+
+ def test_reader_cannot_traits_set(self):
+ """Reader cannot set traits
+
+ baremetal:node:traits:set
+ """
+ try:
+ resp, body = self.reader_client.set_node_traits(
+ self.node['uuid'], ['CUSTOM_TRAIT_A', 'CUSTOM_TRAIT_B'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_traits_delete(self):
+ """Reader cannot delete traits
+
+ baremetal:node:traits:delete
+ """
+ try:
+ resp, body = self.reader_client.remove_node_traits(
+ self.node['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_can_bios_get(self):
+ """Reader can get bios settings
+
+ baremetal:node:bios:get
+ """
+ resp, body = self.reader_client.list_node_bios_settings(
+ self.node['uuid'])
+ self.assertEqual(200, resp.status)
+
+ def test_reader_cannot_disable_cleaning(self):
+ """Reader cannot disable automated node cleaning
+
+ baremetal:node:disable_cleaning
+ """
+ patch = [{'path': '/automated_clean', 'op': 'replace', 'value': False}]
+ try:
+ resp, body = self.reader_client.update_node(self.node['uuid'],
+ patch=patch)
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_history_get(self):
+ """Reader cannot list history entries for a node
+
+ baremetal:node:history:get
+ """
+ try:
+ resp, body = self.reader_client.list_node_history(
+ self.node['uuid'])
+ except lib_exc.NotFound as e:
+ resp = e.resp
+
+ self.assertEqual(404, resp.status)
+
+ def test_reader_cannot_vendor_passthru(self):
+ """Reader cannot list vendor-specific extensions
+
+ baremetal:node:vendor_passthru
+ """
+ try:
+ resp, body = self.reader_client.list_vendor_passthru_methods(
+ self.node['uuid'])
+ except lib_exc.Forbidden as e:
+ resp = e.resp
+
+ self.assertEqual(403, resp.status)
+
+ def test_reader_cannot_ipa_heartbeat(self):
+ """Reader cannot heartbeat
+
+ baremetal:node:ipa_heartbeat
+ """
+ # TODO(hjensas)
+ pass
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 9bde6c3..ab38566 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -7,55 +7,65 @@
jobs:
# NOTE(dtantsur): keep N-3 and older non-voting for these jobs.
- ironic-standalone
- - ironic-standalone-yoga
- - ironic-standalone-xena
- - ironic-standalone-wallaby:
+ - ironic-standalone-2023.1
+ - ironic-standalone-zed
+ - ironic-standalone-yoga:
+ voting: false
+ - ironic-standalone-xena:
voting: false
- ironic-tempest-functional-python3
- - ironic-tempest-functional-python3-yoga
- - ironic-tempest-functional-python3-xena
- - ironic-tempest-functional-python3-wallaby:
+ - ironic-tempest-functional-python3-2023.1
+ - ironic-tempest-functional-python3-zed
+ - ironic-tempest-functional-python3-yoga:
+ voting: false
+ - ironic-tempest-functional-python3-xena:
voting: false
- ironic-inspector-tempest
- - ironic-inspector-tempest-yoga
- - ironic-inspector-tempest-xena
- - ironic-inspector-tempest-wallaby:
+ - ironic-inspector-tempest-2023.1
+ - ironic-inspector-tempest-zed
+ - ironic-inspector-tempest-yoga:
+ voting: false
+ - ironic-inspector-tempest-xena:
voting: false
- ironic-standalone-anaconda
+ - ironic-standalone-anaconda-2023.1
- ironic-standalone-redfish
+ - ironic-standalone-redfish-2023.1
+ - ironic-standalone-redfish-zed
- ironic-standalone-redfish-yoga:
voting: false
- ironic-standalone-redfish-xena:
voting: false
- - ironic-standalone-redfish-wallaby:
- voting: false
# NOTE(dtantsur): these jobs cover rarely changed tests and are quite
# unstable, so keep them non-voting.
- ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode:
voting: false
+ - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-2023.1:
+ voting: false
+ - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-zed:
+ voting: false
- ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-yoga:
voting: false
- ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-xena:
voting: false
- - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-wallaby:
- voting: false
- ironic-inspector-tempest-discovery
+ - ironic-inspector-tempest-discovery-2023.1
+ - ironic-inspector-tempest-discovery-zed
- ironic-inspector-tempest-discovery-yoga:
voting: false
- ironic-inspector-tempest-discovery-xena:
voting: false
- - ironic-inspector-tempest-discovery-wallaby:
- voting: false
gate:
jobs:
- ironic-standalone
- - ironic-standalone-yoga
- - ironic-standalone-xena
+ - ironic-standalone-2023.1
+ - ironic-standalone-zed
- ironic-tempest-functional-python3
- - ironic-tempest-functional-python3-yoga
- - ironic-tempest-functional-python3-xena
+ - ironic-tempest-functional-python3-2023.1
+ - ironic-tempest-functional-python3-zed
- ironic-inspector-tempest
- - ironic-inspector-tempest-yoga
- - ironic-inspector-tempest-xena
+ - ironic-inspector-tempest-2023.1
+ - ironic-inspector-tempest-zed
- ironic-standalone-redfish
+ - ironic-standalone-redfish-2023.1
- ironic-inspector-tempest-discovery
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index 42099c6..570b262 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -1,4 +1,14 @@
- job:
+ name: ironic-standalone-2023.1
+ parent: ironic-standalone
+ override-checkout: stable/2023.1
+
+- job:
+ name: ironic-standalone-zed
+ parent: ironic-standalone
+ override-checkout: stable/zed
+
+- job:
name: ironic-standalone-yoga
parent: ironic-standalone
override-checkout: stable/yoga
@@ -32,6 +42,16 @@
USE_PYTHON3: True
- job:
+ name: ironic-standalone-redfish-2023.1
+ parent: ironic-standalone
+ override-checkout: stable/2023.1
+
+- job:
+ name: ironic-standalone-redfish-zed
+ parent: ironic-standalone
+ override-checkout: stable/zed
+
+- job:
name: ironic-standalone-redfish-yoga
parent: ironic-standalone-redfish
nodeset: openstack-single-node-focal
@@ -69,6 +89,21 @@
USE_PYTHON3: True
- job:
+ name: ironic-standalone-anaconda-2023.1
+ parent: ironic-standalone-anaconda
+ override-checkout: stable/2023.1
+
+- job:
+ name: ironic-tempest-functional-python3-2023.1
+ parent: ironic-tempest-functional-python3
+ override-checkout: stable/2023.1
+
+- job:
+ name: ironic-tempest-functional-python3-zed
+ parent: ironic-tempest-functional-python3
+ override-checkout: stable/zed
+
+- job:
name: ironic-tempest-functional-python3-yoga
parent: ironic-tempest-functional-python3
override-checkout: stable/yoga
@@ -99,6 +134,16 @@
override-checkout: stable/train
- job:
+ name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-zed
+ parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
+ override-checkout: stable/zed
+
+- job:
+ name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-2023.1
+ parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
+ override-checkout: stable/2023.1
+
+- job:
name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-yoga
parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
override-checkout: stable/yoga
@@ -132,6 +177,16 @@
USE_PYTHON3: True
- job:
+ name: ironic-inspector-tempest-2023.1
+ parent: ironic-inspector-tempest
+ override-checkout: stable/2023.1
+
+- job:
+ name: ironic-inspector-tempest-zed
+ parent: ironic-inspector-tempest
+ override-checkout: stable/zed
+
+- job:
name: ironic-inspector-tempest-yoga
parent: ironic-inspector-tempest
override-checkout: stable/yoga
@@ -174,6 +229,16 @@
USE_PYTHON3: True
- job:
+ name: ironic-inspector-tempest-discovery-2023.1
+ parent: ironic-inspector-tempest-discovery
+ override-checkout: stable/2023.1
+
+- job:
+ name: ironic-inspector-tempest-discovery-zed
+ parent: ironic-inspector-tempest-discovery
+ override-checkout: stable/zed
+
+- job:
name: ironic-inspector-tempest-discovery-yoga
parent: ironic-inspector-tempest-discovery
override-checkout: stable/yoga