Merge "Dettaching instance_uuid for standalone TC's"
diff --git a/ironic_tempest_plugin/common/waiters.py b/ironic_tempest_plugin/common/waiters.py
index c9d87bd..2b35279 100644
--- a/ironic_tempest_plugin/common/waiters.py
+++ b/ironic_tempest_plugin/common/waiters.py
@@ -13,7 +13,6 @@
 #    under the License.
 
 from oslo_log import log
-import six
 from tempest import config
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as lib_exc
@@ -31,8 +30,8 @@
         timeout = default_timeout
     if interval is None:
         interval = default_interval
-    if (not isinstance(timeout, six.integer_types)
-            or not isinstance(interval, six.integer_types)
+    if (not isinstance(timeout, int)
+            or not isinstance(interval, int)
             or timeout < 0 or interval < 0):
         raise AssertionError(
             'timeout and interval should be >= 0 or None, current values are: '
diff --git a/ironic_tempest_plugin/config.py b/ironic_tempest_plugin/config.py
index acf2542..d5c1ebf 100644
--- a/ironic_tempest_plugin/config.py
+++ b/ironic_tempest_plugin/config.py
@@ -1,6 +1,8 @@
 # Copyright 2015 NEC Corporation
 # All Rights Reserved.
 #
+# Copyright (c) 2022 Dell Inc. or its subsidiaries.
+#
 #    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
@@ -153,6 +155,12 @@
     cfg.ListOpt('enabled_raid_interfaces',
                 default=['no-raid', 'agent'],
                 help="List of Ironic enabled RAID interfaces."),
+    cfg.ListOpt('enabled_management_interfaces',
+                default=['fake', 'ipmitool', 'noop'],
+                help="List of Ironic enabled management interfaces."),
+    cfg.ListOpt('enabled_power_interfaces',
+                default=['fake', 'ipmitool'],
+                help="List of Ironic enabled power interfaces."),
     cfg.StrOpt('default_rescue_interface',
                help="Ironic default rescue interface."),
     cfg.IntOpt('adjusted_root_disk_size_gb',
diff --git a/ironic_tempest_plugin/services/baremetal/base.py b/ironic_tempest_plugin/services/baremetal/base.py
index 3c52fcd..2acad18 100644
--- a/ironic_tempest_plugin/services/baremetal/base.py
+++ b/ironic_tempest_plugin/services/baremetal/base.py
@@ -11,10 +11,11 @@
 #    under the License.
 
 
+import functools
+from http import client as http_client
+from urllib import parse as urllib_parse
+
 from oslo_serialization import jsonutils as json
-import six
-from six.moves import http_client
-from six.moves.urllib import parse as urllib
 from tempest.lib.common import api_version_utils
 from tempest.lib.common import rest_client
 
@@ -36,7 +37,7 @@
 def handle_errors(f):
     """A decorator that allows to ignore certain types of errors."""
 
-    @six.wraps(f)
+    @functools.wraps(f)
     def wrapper(*args, **kwargs):
         param_name = 'ignore_errors'
         ignored_errors = kwargs.get(param_name, tuple())
@@ -149,7 +150,7 @@
         """
         uri = self._get_uri(resource, permanent=permanent)
         if kwargs:
-            uri += "?%s" % urllib.urlencode(kwargs)
+            uri += "?%s" % urllib_parse.urlencode(kwargs)
 
         resp, body = self.get(uri, headers=headers,
                               extra_headers=extra_headers)
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 9f001b8..26c37e0 100644
--- a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
+++ b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
@@ -10,7 +10,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from six.moves import http_client
+from http import client as http_client
 
 from ironic_tempest_plugin.services.baremetal import base
 
diff --git a/ironic_tempest_plugin/tests/api/admin/test_nodes.py b/ironic_tempest_plugin/tests/api/admin/test_nodes.py
index 85c31e0..d6b262d 100644
--- a/ironic_tempest_plugin/tests/api/admin/test_nodes.py
+++ b/ironic_tempest_plugin/tests/api/admin/test_nodes.py
@@ -11,7 +11,6 @@
 #    under the License.
 
 from oslo_utils import uuidutils
-import six
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
@@ -136,7 +135,7 @@
         body = self.client.get_node_boot_device(self.node['uuid'])
         self.assertIn('boot_device', body)
         self.assertIn('persistent', body)
-        self.assertIsInstance(body['boot_device'], six.string_types)
+        self.assertIsInstance(body['boot_device'], str)
         self.assertIsInstance(body['persistent'], bool)
 
     @decorators.idempotent_id('3622bc6f-3589-4bc2-89f3-50419c66b133')
diff --git a/ironic_tempest_plugin/tests/api/base.py b/ironic_tempest_plugin/tests/api/base.py
index d78f74a..c541dd3 100644
--- a/ironic_tempest_plugin/tests/api/base.py
+++ b/ironic_tempest_plugin/tests/api/base.py
@@ -10,7 +10,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
+import functools
+
 from tempest import config
 from tempest.lib.common import api_version_utils
 from tempest.lib.common.utils import data_utils
@@ -41,7 +42,7 @@
     """Decorator that adds resources to the appropriate cleanup list."""
 
     def decorator(f):
-        @six.wraps(f)
+        @functools.wraps(f)
         def wrapper(cls, *args, **kwargs):
             resp, body = f(cls, *args, **kwargs)
 
diff --git a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
index 32fd5c2..e4d8717 100644
--- a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
+++ b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
@@ -1,6 +1,8 @@
 #
 #    Copyright 2017 Mirantis Inc.
 #
+#    Copyright (c) 2022 Dell Inc. or its subsidiaries.
+#
 #    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
@@ -483,6 +485,18 @@
     # set via a different test).
     raid_interface = None
 
+    # The management interface to use by the HW type. The management interface
+    # of the node used in the test will be set to this value. If set to None,
+    # the node will retain its existing management_interface value (which may
+    # have been set via a different test).
+    management_interface = None
+
+    # The power interface to use by the HW type. The power interface of the
+    # node used in the test will be set to this value. If set to None, the
+    # node will retain its existing power_interface value (which may have been
+    # set via a different test).
+    power_interface = None
+
     # Boolean value specify if image is wholedisk or not.
     wholedisk_image = None
 
@@ -542,6 +556,20 @@
                 "in the list of enabled RAID interfaces %(enabled)s" % {
                     'iface': cls.raid_interface,
                     'enabled': CONF.baremetal.enabled_raid_interfaces})
+        if (cls.management_interface and cls.management_interface not in
+                CONF.baremetal.enabled_management_interfaces):
+            raise cls.skipException(
+                "Management interface %(iface)s required by test is not "
+                "in the list of enabled management interfaces %(enabled)s" % {
+                    'iface': cls.management_interface,
+                    'enabled': CONF.baremetal.enabled_management_interfaces})
+        if (cls.power_interface and cls.power_interface not in
+                CONF.baremetal.enabled_power_interfaces):
+            raise cls.skipException(
+                "Power interface %(iface)s required by test is not "
+                "in the list of enabled power interfaces %(enabled)s" % {
+                    'iface': cls.power_interface,
+                    'enabled': CONF.baremetal.enabled_power_interfaces})
         if not cls.wholedisk_image and CONF.baremetal.use_provision_network:
             raise cls.skipException(
                 'Partitioned images are not supported with multitenancy.')
@@ -580,6 +608,10 @@
             boot_kwargs['boot_interface'] = cls.boot_interface
         if cls.raid_interface:
             boot_kwargs['raid_interface'] = cls.raid_interface
+        if cls.management_interface:
+            boot_kwargs['management_interface'] = cls.management_interface
+        if cls.power_interface:
+            boot_kwargs['power_interface'] = cls.power_interface
 
         # just get an available node
         cls.node = cls.get_and_reserve_node()
diff --git a/ironic_tempest_plugin/tests/scenario/introspection_manager.py b/ironic_tempest_plugin/tests/scenario/introspection_manager.py
index 199bab1..af971d1 100644
--- a/ironic_tempest_plugin/tests/scenario/introspection_manager.py
+++ b/ironic_tempest_plugin/tests/scenario/introspection_manager.py
@@ -14,7 +14,6 @@
 import time
 
 from oslo_serialization import jsonutils as json
-import six
 import tempest
 from tempest import config
 from tempest.lib.common.api_version_utils import LATEST_MICROVERSION
@@ -173,7 +172,7 @@
         """Waits for introspection of baremetal nodes to finish.
 
         """
-        if isinstance(node_ids, six.text_type):
+        if isinstance(node_ids, str):
             node_ids = [node_ids]
         start = int(time.time())
         not_introspected = {node_id for node_id in node_ids}
diff --git a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_cleaning.py b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_cleaning.py
index 08abcfa..13fcd9b 100644
--- a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_cleaning.py
+++ b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_cleaning.py
@@ -1,6 +1,8 @@
 #
 # Copyright 2017 Mirantis Inc.
 #
+# Copyright (c) 2022 Dell Inc. or its subsidiaries.
+#
 # 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
@@ -166,3 +168,62 @@
         # and remove it before exiting the test.
         self.remove_root_device_hint()
         self.terminate_node(self.node['uuid'], force_delete=True)
+
+
+class BaremetalIdracManagementCleaning(
+        bsm.BaremetalStandaloneScenarioTest):
+
+    mandatory_attr = ['driver', 'management_interface',
+                      'power_interface']
+
+    driver = 'idrac'
+    delete_node = False
+    # Minimum version for manual cleaning is 1.15 (# v1.15: Add ability to
+    # do manual cleaning of nodes). The test cases clean up at the end by
+    # detaching the VIF. Support for VIFs was introduced by version 1.28
+    # (# v1.28: Add vifs subcontroller to node).
+    api_microversion = '1.28'
+
+    @decorators.idempotent_id('d085ff72-abef-4931-a5b0-06efd5f9a037')
+    def test_reset_idrac(self):
+        clean_steps = [
+            {
+                "interface": "management",
+                "step": "reset_idrac"
+            }
+        ]
+        self.manual_cleaning(self.node, clean_steps=clean_steps)
+
+    @decorators.idempotent_id('9252ec6f-6b5b-447e-a323-c52775b88b4e')
+    def test_clear_job_queue(self):
+        clean_steps = [
+            {
+                "interface": "management",
+                "step": "clear_job_queue"
+            }
+        ]
+        self.manual_cleaning(self.node, clean_steps=clean_steps)
+
+    @decorators.idempotent_id('7baeff52-7d6e-4dea-a48f-a85a6bfc9f62')
+    def test_known_good_state(self):
+        clean_steps = [
+            {
+                "interface": "management",
+                "step": "known_good_state"
+            }
+        ]
+        self.manual_cleaning(self.node, clean_steps=clean_steps)
+
+
+class BaremetalIdracRedfishManagementCleaning(
+        BaremetalIdracManagementCleaning):
+
+    management_interface = 'idrac-redfish'
+    power_interface = 'idrac-redfish'
+
+
+class BaremetalIdracWSManManagementCleaning(
+        BaremetalIdracManagementCleaning):
+
+    management_interface = 'idrac-wsman'
+    power_interface = 'idrac-wsman'
diff --git a/requirements.txt b/requirements.txt
index 54751e4..e012abf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,5 +8,4 @@
 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
 oslo.utils>=3.33.0 # Apache-2.0
 fixtures>=3.0.0 # Apache-2.0/BSD
-six>=1.10.0 # MIT
 tempest>=17.1.0 # Apache-2.0
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 6198ffd..7b0cc39 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -7,55 +7,54 @@
       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-victoria:
+        - ironic-standalone-wallaby:
             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-victoria:
+        - ironic-tempest-functional-python3-wallaby:
             voting: false
         - ironic-inspector-tempest
+        - ironic-inspector-tempest-yoga
         - ironic-inspector-tempest-xena
-        - ironic-inspector-tempest-wallaby
-        - ironic-inspector-tempest-victoria:
+        - ironic-inspector-tempest-wallaby:
             voting: false
         - ironic-standalone-redfish
+        - ironic-standalone-redfish-yoga:
+            voting: false
         - ironic-standalone-redfish-xena:
             voting: false
         - ironic-standalone-redfish-wallaby:
             voting: false
-        - ironic-standalone-redfish-victoria:
-            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-yoga:
+            voting: false
         - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-xena:
             voting: false
         - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-wallaby:
             voting: false
-        - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-victoria:
-            voting: false
         - ironic-inspector-tempest-discovery
+        - ironic-inspector-tempest-discovery-yoga:
+            voting: false
         - ironic-inspector-tempest-discovery-xena:
             voting: false
         - ironic-inspector-tempest-discovery-wallaby:
             voting: false
-        - ironic-inspector-tempest-discovery-victoria:
-            voting: false
     gate:
-      queue: ironic
       jobs:
         - ironic-standalone
+        - ironic-standalone-yoga
         - ironic-standalone-xena
-        - ironic-standalone-wallaby
         - ironic-tempest-functional-python3
+        - ironic-tempest-functional-python3-yoga
         - ironic-tempest-functional-python3-xena
-        - ironic-tempest-functional-python3-wallaby
         - ironic-inspector-tempest
+        - ironic-inspector-tempest-yoga
         - ironic-inspector-tempest-xena
-        - ironic-inspector-tempest-wallaby
         - ironic-standalone-redfish
         - ironic-inspector-tempest-discovery
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index 0f83c2a..42099c6 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -1,4 +1,9 @@
 - job:
+    name: ironic-standalone-yoga
+    parent: ironic-standalone
+    override-checkout: stable/yoga
+
+- job:
     name: ironic-standalone-xena
     parent: ironic-standalone
     override-checkout: stable/xena
@@ -27,6 +32,12 @@
         USE_PYTHON3: True
 
 - job:
+    name: ironic-standalone-redfish-yoga
+    parent: ironic-standalone-redfish
+    nodeset: openstack-single-node-focal
+    override-checkout: stable/yoga
+
+- job:
     name: ironic-standalone-redfish-xena
     parent: ironic-standalone-redfish
     nodeset: openstack-single-node-focal
@@ -58,6 +69,11 @@
         USE_PYTHON3: True
 
 - job:
+    name: ironic-tempest-functional-python3-yoga
+    parent: ironic-tempest-functional-python3
+    override-checkout: stable/yoga
+
+- job:
     name: ironic-tempest-functional-python3-xena
     parent: ironic-tempest-functional-python3
     override-checkout: stable/xena
@@ -83,6 +99,11 @@
     override-checkout: stable/train
 
 - job:
+    name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-yoga
+    parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
+    override-checkout: stable/yoga
+
+- job:
     name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-xena
     parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
     override-checkout: stable/xena
@@ -111,6 +132,11 @@
         USE_PYTHON3: True
 
 - job:
+    name: ironic-inspector-tempest-yoga
+    parent: ironic-inspector-tempest
+    override-checkout: stable/yoga
+
+- job:
     name: ironic-inspector-tempest-xena
     parent: ironic-inspector-tempest
     override-checkout: stable/xena
@@ -148,6 +174,11 @@
         USE_PYTHON3: True
 
 - job:
+    name: ironic-inspector-tempest-discovery-yoga
+    parent: ironic-inspector-tempest-discovery
+    override-checkout: stable/yoga
+
+- job:
     name: ironic-inspector-tempest-discovery-xena
     parent: ironic-inspector-tempest-discovery
     override-checkout: stable/xena