Merge "Replace deprecated assertItemsEqual"
diff --git a/ironic_tempest_plugin/config.py b/ironic_tempest_plugin/config.py
index 47bcb55..38a67eb 100644
--- a/ironic_tempest_plugin/config.py
+++ b/ironic_tempest_plugin/config.py
@@ -20,6 +20,10 @@
 from tempest import config  # noqa
 
 
+_INSPECTOR_REASON = ('ironic-inspector was retired in favor of the built-in'
+                     'agent inspect interface.')
+
+
 # NOTE(TheJulia): The following options are loaded into a tempest
 # plugin configuration option via plugin.py.
 ironic_service_option = cfg.BoolOpt('ironic',
@@ -29,6 +33,8 @@
 
 inspector_service_option = cfg.BoolOpt("ironic_inspector",
                                        default=False,
+                                       deprecated_for_removal=True,
+                                       deprecated_reason=_INSPECTOR_REASON,
                                        help="Whether or not ironic-inspector "
                                        "is expected to be available")
 
@@ -40,6 +46,8 @@
 
 inspector_scope_enforcement = cfg.BoolOpt('ironic_inspector',
                                           default=True,
+                                          deprecated_for_removal=True,
+                                          deprecated_reason=_INSPECTOR_REASON,
                                           help='Whether or not '
                                                'ironic-inspector is expected '
                                                'to enforce auth scope.')
@@ -288,28 +296,42 @@
 BaremetalIntrospectionGroup = [
     cfg.StrOpt('catalog_type',
                default='baremetal-introspection',
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="Catalog type of the baremetal provisioning service"),
     cfg.StrOpt('endpoint_type',
                default='publicURL',
                choices=['public', 'admin', 'internal',
                         'publicURL', 'adminURL', 'internalURL'],
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="The endpoint type to use for the baremetal introspection"
                     " service"),
     cfg.IntOpt('introspection_sleep',
                default=30,
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="Introspection sleep before check status"),
     cfg.IntOpt('introspection_timeout',
                default=600,
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="Introspection time out"),
     cfg.IntOpt('introspection_start_timeout',
                default=90,
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="Timeout to start introspection"),
     cfg.IntOpt('hypervisor_update_sleep',
                default=60,
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="Time to wait until nova becomes aware of "
                     "bare metal instances"),
     cfg.IntOpt('hypervisor_update_timeout',
                default=300,
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="Time out for wait until nova becomes aware of "
                     "bare metal instances"),
     # NOTE(aarefiev): status_check_period default is 60s, but checking
@@ -317,14 +339,20 @@
     # 80s would be enough to make one more check.
     cfg.IntOpt('ironic_sync_timeout',
                default=80,
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="Time it might take for Ironic--Inspector "
                     "sync to happen"),
     cfg.IntOpt('discovery_timeout',
                default=300,
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="Time to wait until new node would enrolled in "
                     "ironic"),
     cfg.BoolOpt('auto_discovery_feature',
                 default=False,
+                deprecated_for_removal=True,
+                deprecated_reason=_INSPECTOR_REASON,
                 help="Is the auto-discovery feature enabled. Enroll hook "
                      "should be specified in node_not_found_hook - processing "
                      "section of inspector.conf"),
@@ -332,11 +360,17 @@
                # TODO(dtantsur): change to fake-hardware when Queens is no
                # longer supported.
                default='fake',
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="The driver expected to be set on newly discovered nodes. "
                     "Only has effect with auto_discovery_feature is True."),
     cfg.StrOpt('auto_discovery_target_driver',
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="The driver to set on the newly discovered nodes. "
                     "Only has effect with auto_discovery_feature is True."),
     cfg.StrOpt('data_store',
+               deprecated_for_removal=True,
+               deprecated_reason=_INSPECTOR_REASON,
                help="The storage backend for storing introspection data."),
 ]
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 2c0d713..2cc2f5c 100644
--- a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
+++ b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
@@ -326,7 +326,6 @@
         :param description: The description of the chassis.
             Default: test-chassis
         :return: A tuple with the server response and the created chassis.
-
         """
         chassis = {'description': kwargs.get('description', 'test-chassis')}
 
@@ -1055,3 +1054,38 @@
     def list_portgroups_details_by_node(self, node_ident):
         """List detailed portgroups filtered by node."""
         return self._list_request(f'nodes/{node_ident}/portgroups/detail')
+
+    @base.handle_errors
+    def create_inspection_rule(self, payload):
+        """Create Inspection rule.
+
+        :param payload: Inspection rule JSON
+        """
+        return self._create_request('inspection_rules', payload)
+
+    @base.handle_errors
+    def show_inspection_rule(self, rule_uuid):
+        """Show Inspection rule."""
+        return self._show_request('inspection_rules', rule_uuid)
+
+    @base.handle_errors
+    def list_inspection_rule(self, **kwargs):
+        """List all Inspection rules."""
+        return self._list_request('inspection_rules', **kwargs)
+
+    @base.handle_errors
+    def update_inspection_rule(self, rule_uuid, patch):
+        """Update the specified Inspection rule.
+
+        :param rule_uuid: The unique identifier of the inspection rule.
+        :param patch: List of dicts representing json patches.
+        """
+        return self._patch_request('inspection_rules', rule_uuid, patch)
+
+    @base.handle_errors
+    def delete_inspection_rule(self, rule_uuid):
+        """Delete Inspection rule.
+
+        :param rule_uuid: uuid of the inspection rule.
+        """
+        return self._delete_request('inspection_rules', rule_uuid)
diff --git a/ironic_tempest_plugin/tests/api/admin/test_inspection_rules.py b/ironic_tempest_plugin/tests/api/admin/test_inspection_rules.py
new file mode 100644
index 0000000..3d00ce3
--- /dev/null
+++ b/ironic_tempest_plugin/tests/api/admin/test_inspection_rules.py
@@ -0,0 +1,172 @@
+# 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.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+from ironic_tempest_plugin.tests.api.admin import api_microversion_fixture
+from ironic_tempest_plugin.tests.api import base
+
+
+class TestInspectionRules(base.BaseBaremetalTest):
+    """API tests for Inspection Rules endpoints"""
+
+    # Inspection rules API was introduced in microversion 1.96
+    # We will be skipping this test for the older version.
+    min_microversion = '1.96'
+
+    def setUp(self):
+        super(TestInspectionRules, self).setUp()
+
+        _, self.node = self.create_node(None)
+
+        self.useFixture(
+            api_microversion_fixture.APIMicroversionFixture('1.96'))
+
+    def _create_inspection_rule_payload(self, **kwargs):
+        """Create a Inspection rule payload."""
+        payload = {
+            "description": "Inspection rule to log node UUID",
+            "conditions": [],
+            "actions": [
+                {
+                    "op": "log",
+                    "args": {
+                        "msg": "Node with UUID {node.uuid} is being inspected"
+                    }
+                }
+            ],
+            "phase": "main",
+            "priority": 0,
+            "sensitive": False
+        }
+
+        payload.update(kwargs)
+
+        return payload
+
+    @decorators.idempotent_id('7fb771cd-b011-409e-a255-3c71cf7251e8')
+    def test_create_rule_sensitive_true(self):
+        """Test creating rule with sensitive=True."""
+        rule_uuid = data_utils.rand_uuid()
+        payload = self._create_inspection_rule_payload(sensitive=True)
+
+        self.create_inspection_rule(rule_uuid, payload)
+
+        _, fetched_rule = self.client.show_inspection_rule(rule_uuid)
+
+        self.assertTrue(fetched_rule.get('sensitive'))
+        self.assertIsNone(fetched_rule.get('conditions'))
+        self.assertIsNone(fetched_rule.get('actions'))
+
+    @decorators.idempotent_id('e60b4513-7c3d-4b2c-b485-17443bf6485f')
+    def test_create_rule_complex_logging_conditions_actions(self):
+        """Test creating rule with loop conditions and actions"""
+        complex_log_conditions = [
+            {
+                "op": "eq",
+                "args": [
+                    "{inventory.system.product_name}",
+                    "{item}"
+                ],
+                "loop": [
+                    "product_name_1",
+                    "product_name_2",
+                    "product_name_3"
+                ],
+                "multiple": "any"
+            }
+        ]
+
+        complex_log_actions = [
+            {
+                "op": "set-attribute",
+                "args": [
+                    "{item[path]}",
+                    "{item[value]}"
+                ],
+                "loop": [
+                    {
+                        "path": "/driver_info/ipmi_username",
+                        "value": "admin"
+                    },
+                    {
+                        "path": "/driver_info/ipmi_password",
+                        "value": "password"
+                    },
+                    {
+                        "path": "/driver_info/ipmi_address",
+                        "value": "{inventory[bmc_address]}"
+                    }
+                ]
+            }
+        ]
+
+        payload = self._create_inspection_rule_payload(
+            conditions=complex_log_conditions,
+            actions=complex_log_actions,
+        )
+
+        _, created_rule = self.create_inspection_rule(None, payload)
+
+        self.assertEqual(complex_log_conditions,
+                         created_rule.get('conditions'))
+        self.assertEqual(complex_log_actions,
+                         created_rule.get('actions'))
+
+    @decorators.idempotent_id('a786a4ec-1e43-4fb9-8fc3-c53aa4e1f52f')
+    def test_patch_conditions_actions_priority(self):
+        """Test Updating rule'si priority, condition and actions"""
+        payload = self._create_inspection_rule_payload()
+
+        patch = [
+            {
+                "op": "replace",
+                "path": "/priority",
+                "value": 200
+            },
+            {
+                "op": "replace",
+                "path": "/conditions",
+                "value": [
+                    {
+                        "op": "eq",
+                        "args": ["{{ inventory.cpu.count }}", 8]
+                    }
+                ]
+            },
+            {
+                "op": "replace",
+                "path": "/actions",
+                "value": [
+                    {
+                        "op": "set-attribute",
+                        "args": ["{{ /properties/cpu_model }}", "cpu_xyz"]
+                    },
+                    {
+                        "op": "log",
+                        "args": ["CPU model updated via rule."]
+                    }
+                ]
+            }
+        ]
+
+        _, created_rule = self.create_inspection_rule(None, payload)
+        _, fetched_rule = self.client.update_inspection_rule(
+            created_rule.get('uuid'), patch)
+
+        self.assertEqual(fetched_rule.get('priority'),
+                         patch[0]['value'])
+        self.assertEqual(fetched_rule.get('conditions'),
+                         patch[1]['value'])
+        self.assertEqual(fetched_rule.get('actions'),
+                         patch[2]['value'])
diff --git a/ironic_tempest_plugin/tests/api/admin/test_inspection_rules_negatives.py b/ironic_tempest_plugin/tests/api/admin/test_inspection_rules_negatives.py
new file mode 100644
index 0000000..a92728b
--- /dev/null
+++ b/ironic_tempest_plugin/tests/api/admin/test_inspection_rules_negatives.py
@@ -0,0 +1,79 @@
+#    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.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from ironic_tempest_plugin.tests.api.admin import api_microversion_fixture
+from ironic_tempest_plugin.tests.api import base
+
+
+class TestInspectionRulesNegative(base.BaseBaremetalTest):
+    """Negative Inspection Rules test"""
+
+    # Inspection rules API was introduced in microversion 1.96
+    # We will be skipping this test for the older version.
+    min_microversion = '1.96'
+
+    def setUp(self):
+        super(TestInspectionRulesNegative, self).setUp()
+
+        _, self.node = self.create_node(None)
+
+        self.useFixture(
+            api_microversion_fixture.APIMicroversionFixture('1.96'))
+
+    def _create_inspection_rule_payload(self, **kwargs):
+        """Create a Inspection rule payload."""
+        payload = {
+            "description": "Inspection rule to log node UUID",
+            "conditions": [],
+            "actions": [
+                {
+                    "op": "log",
+                    "args": {
+                        "msg": "Node with UUID {node.uuid} is being inspected"
+                    }
+                }
+            ],
+            "phase": "main",
+            "priority": 0,
+            "sensitive": False
+        }
+
+        payload.update(kwargs)
+
+        return payload
+
+    @decorators.idempotent_id('55403d94-53ce-41ab-989a-da3399314c9d')
+    @decorators.attr(type=['negative'])
+    def test_create_invalid_priority_fails(self):
+        """Test to create Inspection rule with invalid priorities"""
+        invalid_priorities = [-1, 10000, 5000.50]
+
+        for priority_val in invalid_priorities:
+            payload = self._create_inspection_rule_payload(
+                priority=priority_val)
+
+            self.assertRaises(lib_exc.BadRequest,
+                              self.create_inspection_rule,
+                              rule_uuid=None, payload=payload)
+
+    @decorators.idempotent_id('cf9615b3-904e-4456-b00a-622d39892b88')
+    @decorators.attr(type=['negative'])
+    def test_delete_by_wrong_uiid(self):
+        """Test to delete Inspection Rule with wrong uuid"""
+        rule_uuid = data_utils.rand_uuid()
+        self.assertRaises(lib_exc.NotFound,
+                          self.delete_inspection_rule,
+                          rule_uuid=rule_uuid)
diff --git a/ironic_tempest_plugin/tests/api/admin/test_portgroups.py b/ironic_tempest_plugin/tests/api/admin/test_portgroups.py
index 332c791..80724fe 100644
--- a/ironic_tempest_plugin/tests/api/admin/test_portgroups.py
+++ b/ironic_tempest_plugin/tests/api/admin/test_portgroups.py
@@ -21,7 +21,7 @@
 class TestPortGroups(base.BaseBaremetalTest):
     """Basic positive test cases for port groups."""
 
-    min_microversion = '1.23'
+    min_microversion = '1.26'  # portgroup mode and properties introduced
 
     def setUp(self):
         super(TestPortGroups, self).setUp()
diff --git a/ironic_tempest_plugin/tests/api/base.py b/ironic_tempest_plugin/tests/api/base.py
index c07137b..7744aee 100644
--- a/ironic_tempest_plugin/tests/api/base.py
+++ b/ironic_tempest_plugin/tests/api/base.py
@@ -38,7 +38,8 @@
 # NOTE(jroll): resources must be deleted in a specific order, this list
 # defines the resource types to clean up, and the correct order.
 RESOURCE_TYPES = ['port', 'portgroup', 'node', 'volume_connector',
-                  'volume_target', 'chassis', 'deploy_template', 'runbook']
+                  'volume_target', 'chassis', 'deploy_template',
+                  'runbook', 'inspection_rule']
 
 
 def creates(resource):
@@ -520,6 +521,32 @@
         resp, body = cls.client.create_allocation(resource_class, **kwargs)
         return resp, body
 
+    @classmethod
+    @creates('inspection_rule')
+    def create_inspection_rule(cls, rule_uuid, payload):
+        """Wrapper utility for creating Inspection rule.
+
+        :param rule_uuid: UUID of the Inspection rule.
+        :param payload: Inspection rule other fields.
+        :return: Server response.
+        """
+        if rule_uuid is not None:
+            payload['uuid'] = rule_uuid
+
+        resp, body = cls.client.create_inspection_rule(payload)
+
+        return resp, body
+
+    @classmethod
+    def delete_inspection_rule(cls, rule_uuid):
+        """Delete a inspection rules having the specified UUID.
+
+        :param rule_uuid: UUID of the Inspection rule.
+        """
+        resp, body = cls.client.delete_inspection_rule(rule_uuid)
+
+        return resp
+
 
 class BaseBaremetalRBACTest(BaseBaremetalTest):
 
diff --git a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_advanced_ops.py b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_advanced_ops.py
index 0a7116a..b66309b 100644
--- a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_advanced_ops.py
+++ b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_advanced_ops.py
@@ -27,6 +27,7 @@
     driver = 'redfish'
     deploy_interface = 'direct'
     boot_interface = 'redfish-virtual-media'
+    # To force interface retoggling.
     image_ref = CONF.baremetal.whole_disk_image_ref
     image_checksum = CONF.baremetal.whole_disk_image_checksum
     wholedisk_image = True
@@ -95,7 +96,23 @@
 
         # Get the latest state for the node.
         self.node = self.get_node(self.node['uuid'])
+        # This test, as far as I'm remembering after the fact, was developed
+        # in an environment where neutron was the default network interface.
+        # so we must try to set it to properly ensure dhcp-less operation.
         prior_prov_net = self.node['driver_info'].get('provisioning_network')
+        try:
+            self.client.update_node(self.node['uuid'],
+                                    [{'path': '/network_interface',
+                                      'op': 'replace',
+                                      'value': 'neutron'}])
+            self.addCleanup(self.update_node,
+                            self.node['uuid'],
+                            [{'op': 'replace',
+                              'path': '/network_interface',
+                              'value': 'flat'}])
+        except Exception:
+            raise self.skipException(
+                "Ironic configuration incorrect to exercise this test.")
 
         ip_version = CONF.validation.ip_version_for_ssh
         tenant_cidr = '10.0.6.0/24'
diff --git a/releasenotes/notes/deprecate-inspector-0de255090cd2cb82.yaml b/releasenotes/notes/deprecate-inspector-0de255090cd2cb82.yaml
new file mode 100644
index 0000000..0607071
--- /dev/null
+++ b/releasenotes/notes/deprecate-inspector-0de255090cd2cb82.yaml
@@ -0,0 +1,10 @@
+---
+deprecations:
+  - |
+    Support for ironic-inspector has been deprecated, because ironic-inspector
+    was already retired. Due to this deprecation, the following options are
+    also deprecated.
+
+    - ``[service_available] ironic_inspector``
+    - ``[enforce_scope] ironic_inspector``
+    - All options in the ``[baremetal_introspection]`` section.
diff --git a/test-requirements.txt b/test-requirements.txt
index 0ce003e..a080de9 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,2 +1 @@
 stestr>=1.0.0 # Apache-2.0
-coverage>=4.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index bf8061c..79892f5 100644
--- a/tox.ini
+++ b/tox.ini
@@ -21,16 +21,6 @@
 [testenv:venv]
 commands = {posargs}
 
-[testenv:cover]
-setenv =
-    {[testenv]setenv}
-    PYTHON=coverage run --source ironic_tempest_plugin --parallel-mode
-commands =
-    stestr run {posargs}
-    coverage combine
-    coverage html -d cover
-    coverage xml -o cover/coverage.xml
-
 [testenv:docs]
 deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
        -r{toxinidir}/doc/requirements.txt
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 8ba9c3a..c89b63e 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -7,34 +7,29 @@
       jobs:
         # NOTE(dtantsur): keep N-3 and older non-voting for these jobs.
         - ironic-tempest-functional-python3
+        - ironic-tempest-functional-python3-2025.2
         - ironic-tempest-functional-python3-2025.1
-        - ironic-tempest-functional-python3-2024.2
+        # NOTE(TheJulia): Consensus in the 2026.1 PTG is that we don't need
+        # to run the anaconda job as heavily as we need to run the normal
+        # tempest jobs.
         - ironic-standalone-anaconda
-        - ironic-standalone-anaconda-2025.1
-        - ironic-standalone-anaconda-2024.2
         - ironic-standalone-redfish
+        - ironic-standalone-redfish-2025.2
         - ironic-standalone-redfish-2025.1
-        - ironic-standalone-redfish-2024.2
-        # NOTE(dtantsur): inspector is deprecated and rarely sees any changes,
-        # no point in running many jobs
-        - ironic-inspector-tempest
         # 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-2025.1:
+        - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-2025.2:
             voting: false
         - ironic-inspector-tempest-discovery:
             voting: false
     gate:
       jobs:
         - ironic-tempest-functional-python3
+        - ironic-tempest-functional-python3-2025.2
         - ironic-tempest-functional-python3-2025.1
-        - ironic-tempest-functional-python3-2024.2
         - ironic-standalone-anaconda
-        - ironic-standalone-anaconda-2025.1
-        - ironic-standalone-anaconda-2024.2
         - ironic-standalone-redfish
+        - ironic-standalone-redfish-2025.2
         - ironic-standalone-redfish-2025.1
-        - ironic-standalone-redfish-2024.2
-        - ironic-inspector-tempest
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index d573737..f67694b 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -1,12 +1,7 @@
 - job:
-    name: ironic-standalone-2024.2
-    parent: ironic-standalone
-    override-checkout: stable/2024.2
-
-- job:
-    name: ironic-standalone-2024.1
-    parent: ironic-standalone
-    override-checkout: stable/2024.1
+    name: ironic-standalone-redfish-2025.2
+    parent: ironic-standalone-redfish
+    override-checkout: stable/2025.2
 
 - job:
     name: ironic-standalone-redfish-2025.1
@@ -14,14 +9,9 @@
     override-checkout: stable/2025.1
 
 - job:
-    name: ironic-standalone-redfish-2024.2
-    parent: ironic-standalone-redfish
-    override-checkout: stable/2024.2
-
-- job:
-    name: ironic-standalone-redfish-2024.1
-    parent: ironic-standalone-redfish
-    override-checkout: stable/2024.1
+    name: ironic-standalone-anaconda-2025.2
+    parent: ironic-standalone-anaconda
+    override-checkout: stable/2025.2
 
 - job:
     name: ironic-standalone-anaconda-2025.1
@@ -29,14 +19,9 @@
     override-checkout: stable/2025.1
 
 - job:
-    name: ironic-standalone-anaconda-2024.2
-    parent: ironic-standalone-anaconda
-    override-checkout: stable/2024.2
-
-- job:
-    name: ironic-standalone-anaconda-2024.1
-    parent: ironic-standalone-anaconda
-    override-checkout: stable/2024.1
+    name: ironic-tempest-functional-python3-2025.2
+    parent: ironic-tempest-functional-python3
+    override-checkout: stable/2025.2
 
 - job:
     name: ironic-tempest-functional-python3-2025.1
@@ -44,46 +29,11 @@
     override-checkout: stable/2025.1
 
 - job:
-    name: ironic-tempest-functional-python3-2024.2
-    parent: ironic-tempest-functional-python3
-    override-checkout: stable/2024.2
-
-- job:
-    name: ironic-tempest-functional-python3-2024.1
-    parent: ironic-tempest-functional-python3
-    override-checkout: stable/2024.1
-
-- job:
-    name: ironic-tempest-functional-rbac-scope-enforced-2024.2
-    parent: ironic-tempest-functional-rbac-scope-enforced
-    override-checkout: stable/2024.2
-
-- job:
-    name: ironic-tempest-functional-rbac-scope-enforced-2024.1
-    parent: ironic-tempest-functional-rbac-scope-enforced
-    override-checkout: stable/2024.1
+    name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-2025.2
+    parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
+    override-checkout: stable/2025.2
 
 - job:
     name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-2025.1
     parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
     override-checkout: stable/2025.1
-
-- job:
-    name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-2024.2
-    parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
-    override-checkout: stable/2024.2
-
-- job:
-    name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-2024.1
-    parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
-    override-checkout: stable/2024.1
-
-- job:
-    name: ironic-inspector-tempest-2024.2
-    parent: ironic-inspector-tempest
-    override-checkout: stable/2024.2
-
-- job:
-    name: ironic-inspector-tempest-2024.1
-    parent: ironic-inspector-tempest
-    override-checkout: stable/2024.1