Merge "Test case for uefi-https-boot in standalone ironic"
diff --git a/ironic_tempest_plugin/tests/api/admin/test_nodes.py b/ironic_tempest_plugin/tests/api/admin/test_nodes.py
index 2709905..e4443d9 100644
--- a/ironic_tempest_plugin/tests/api/admin/test_nodes.py
+++ b/ironic_tempest_plugin/tests/api/admin/test_nodes.py
@@ -400,16 +400,12 @@
         self.assertNotIn('tenant_vif_port_id', portgroup['internal_info'])
 
     @decorators.idempotent_id('a3d319d0-cacb-4e55-a3dc-3fa8b74880f2')
-    def test_vif_already_set_on_extra(self):
+    def test_vif_already_set(self):
         self.useFixture(
             api_microversion_fixture.APIMicroversionFixture('1.28'))
         _, self.port = self.create_port(self.node['uuid'],
                                         data_utils.rand_mac_address())
-        patch = [{'path': '/extra/vif_port_id',
-                  'op': 'add',
-                  'value': self.nport_id}]
-        self.client.update_port(self.port['uuid'], patch)
-
+        self.client.vif_attach(self.node['uuid'], self.nport_id)
         _, body = self.client.vif_list(self.node['uuid'])
         self.assertEqual({'vifs': [{'id': self.nport_id}]}, body)
 
diff --git a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
index 6b9d9e3..10a83a6 100644
--- a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
+++ b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
@@ -172,7 +172,7 @@
 
     @classmethod
     @bm.retry_on_conflict
-    def detach_all_vifs_from_node(cls, node_id):
+    def detach_all_vifs_from_node(cls, node_id, force_delete=False):
         """Detach all VIFs from a given node.
 
         :param node_id: Name or UUID of the node.
@@ -180,6 +180,11 @@
         vifs = cls.get_node_vifs(node_id)
         for vif in vifs:
             cls.baremetal_client.vif_detach(node_id, vif)
+            if force_delete:
+                try:
+                    cls.ports_client.delete_port(vif)
+                except lib_exc.NotFound:
+                    pass
 
     @classmethod
     @bm.retry_on_conflict
@@ -280,7 +285,7 @@
                                     interval=30)
 
     @classmethod
-    def terminate_node(cls, node_id):
+    def terminate_node(cls, node_id, force_delete=False):
         """Terminate active ironic node.
 
         The following actions are executed:
@@ -290,9 +295,9 @@
 
         :param node_id: Name or UUID for the node.
         """
-        cls.detach_all_vifs_from_node(node_id)
+        cls.detach_all_vifs_from_node(node_id, force_delete=force_delete)
 
-        if cls.delete_node:
+        if cls.delete_node or force_delete:
             cls.set_node_provision_state(node_id, 'deleted')
             # NOTE(vsaienko) We expect here fast switching from deleted to
             # available as automated cleaning is disabled so poll status
@@ -593,6 +598,7 @@
                 'CUSTOM_RAID', steps=steps)
             self.baremetal_client.add_node_trait(self.node['uuid'],
                                                  'CUSTOM_RAID')
+
         else:
             steps = [
                 {
@@ -612,6 +618,11 @@
                                                        config)
             self.manual_cleaning(self.node, clean_steps=steps)
 
+        # The node has been changed, anything at this point, we need to back
+        # out the raid configuration.
+        if not deploy_time:
+            self.addCleanup(self.remove_raid_configuration, self.node)
+
         # NOTE(dtantsur): this is not required, but it allows us to check that
         # the RAID device was in fact created and is used for deployment.
         patch = [{'path': '/properties/root_device',
@@ -623,14 +634,27 @@
         # NOTE(dtantsur): apparently cirros cannot boot from md devices :(
         # So we only move the node to active (verifying deployment).
         self.set_node_to_active()
+        if deploy_time:
+            self.addCleanup(self.remove_raid_configuration, self.node)
 
     def remove_root_device_hint(self):
         patch = [{'path': '/properties/root_device',
                   'op': 'remove'}]
         self.update_node(self.node['uuid'], patch=patch)
 
-    def remove_raid_configuration(self):
-        self.baremetal_client.set_node_raid_config(self.node['uuid'], {})
+    def remove_raid_configuration(self, node):
+        self.baremetal_client.set_node_raid_config(node['uuid'], {})
+        steps = [
+            {
+                "interface": "raid",
+                "step": "delete_configuration",
+            },
+            {
+                "interface": "deploy",
+                "step": "erase_devices_metadata",
+            }
+        ]
+        self.manual_cleaning(node, clean_steps=steps)
 
     def rescue_unrescue(self):
         rescue_password = uuidutils.generate_uuid()
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 47e5f63..08abcfa 100644
--- a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_cleaning.py
+++ b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_cleaning.py
@@ -90,6 +90,7 @@
     api_microversion = '1.55'
     # Software RAID is always local boot
     boot_option = 'local'
+    delete_node = False
 
     raid_config = {
         "logical_disks": [
@@ -118,11 +119,7 @@
         # remove the root device hint, so it is best for us to go ahead
         # and remove it before exiting the test.
         self.remove_root_device_hint()
-        # Removes RAID configuration
-        # TODO(TheJulia): We _should_ tear the raid configuration down
-        # however bouncing neutron ports with known DHCP reload bugs
-        # is not a super great idea for tempest tests.
-        self.remove_raid_configuration()
+        self.terminate_node(self.node['uuid'], force_delete=True)
 
 
 class SoftwareRaidDirect(bsm.BaremetalStandaloneScenarioTest):
@@ -138,6 +135,7 @@
     api_microversion = '1.55'
     # Software RAID is always local boot
     boot_option = 'local'
+    delete_node = False
 
     # TODO(dtantsur): more complex layout in this job
     raid_config = {
@@ -167,8 +165,4 @@
         # remove the root device hint, so it is best for us to go ahead
         # and remove it before exiting the test.
         self.remove_root_device_hint()
-        # Removes RAID configuration
-        # TODO(TheJulia): We _should_ tear the raid configuration down
-        # however bouncing neutron ports with known DHCP reload bugs
-        # is not a super great idea for tempest tests.
-        self.remove_raid_configuration()
+        self.terminate_node(self.node['uuid'], force_delete=True)
diff --git a/ironic_tempest_plugin/tests/scenario/test_baremetal_multitenancy.py b/ironic_tempest_plugin/tests/scenario/test_baremetal_multitenancy.py
index 33d8724..60c3ed9 100644
--- a/ironic_tempest_plugin/tests/scenario/test_baremetal_multitenancy.py
+++ b/ironic_tempest_plugin/tests/scenario/test_baremetal_multitenancy.py
@@ -78,7 +78,7 @@
         remote.validate_authentication()
 
         cmd = 'ping %s -c4 -w4 || exit 0' % destination_ip
-        success_substring = "64 bytes from %s" % destination_ip
+        success_substring = " bytes from %s" % destination_ip
         output = remote.exec_command(cmd)
         if conn_expected:
             self.assertIn(success_substring, output)
diff --git a/ironic_tempest_plugin/tests/scenario/test_baremetal_single_tenant.py b/ironic_tempest_plugin/tests/scenario/test_baremetal_single_tenant.py
index d881081..a873471 100644
--- a/ironic_tempest_plugin/tests/scenario/test_baremetal_single_tenant.py
+++ b/ironic_tempest_plugin/tests/scenario/test_baremetal_single_tenant.py
@@ -85,7 +85,7 @@
         remote.validate_authentication()
 
         cmd = 'ping %s -c4 -w4 || exit 0' % destination_ip
-        success_substring = "64 bytes from %s" % destination_ip
+        success_substring = " bytes from %s" % destination_ip
         output = remote.exec_command(cmd)
         if conn_expected:
             self.assertIn(success_substring, output)
diff --git a/test-requirements.txt b/test-requirements.txt
index 138ad35..33a724b 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -2,8 +2,5 @@
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
 
-hacking>=3.0.1,<3.1.0 # Apache-2.0
-
 stestr>=1.0.0 # Apache-2.0
 coverage!=4.4,>=4.0 # Apache-2.0
-flake8-import-order>=0.17.1 # LGPLv3
diff --git a/tox.ini b/tox.ini
index ac55994..65b5243 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-minversion = 3.2.1
+minversion = 3.9.0
 envlist = pep8
 skipsdist = True
 ignore_basepython_conflict=true
@@ -15,6 +15,10 @@
 commands = stestr run --slowest {posargs}
 
 [testenv:pep8]
+deps =
+    hacking>=3.1.0,<4.0.0 # Apache-2.0
+    flake8-import-order>=0.17.1 # LGPLv3
+    pycodestyle>=2.0.0,<2.7.0 # MIT
 commands = flake8 {posargs}
 
 [testenv:venv]
@@ -27,7 +31,7 @@
 commands =
     stestr run {posargs}
     coverage combine
-    coverage htlm -d cover
+    coverage html -d cover
     coverage xml -o cover/coverage.xml
 
 [testenv:docs]
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index b3cd832..ac8a825 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -7,55 +7,55 @@
       jobs:
         # NOTE(dtantsur): keep N-3 and older non-voting for these jobs.
         - ironic-standalone
+        - ironic-standalone-victoria
         - ironic-standalone-ussuri
-        - ironic-standalone-train
-        - ironic-standalone-stein:
+        - ironic-standalone-train:
             voting: false
         - ironic-tempest-functional-python3
+        - ironic-tempest-functional-python3-victoria
         - ironic-tempest-functional-python3-ussuri
-        - ironic-tempest-functional-python3-train
-        - ironic-tempest-functional-python3-stein:
+        - ironic-tempest-functional-python3-train:
             voting: false
         - ironic-inspector-tempest
+        - ironic-inspector-tempest-victoria
         - ironic-inspector-tempest-ussuri
-        - ironic-inspector-tempest-train
-        - ironic-inspector-tempest-stein:
+        - ironic-inspector-tempest-train:
             voting: false
         - ironic-standalone-redfish
+        - ironic-standalone-redfish-victoria:
+            voting: false
         - ironic-standalone-redfish-ussuri:
             voting: false
         - ironic-standalone-redfish-train:
             voting: false
-        - ironic-standalone-redfish-stein:
-            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-victoria:
+            voting: false
         - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-ussuri:
             voting: false
         - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-train:
             voting: false
-        - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-stein:
-            voting: false
         - ironic-inspector-tempest-discovery
+        - ironic-inspector-tempest-discovery-victoria:
+            voting: false
         - ironic-inspector-tempest-discovery-ussuri:
             voting: false
         - ironic-inspector-tempest-discovery-train:
             voting: false
-        - ironic-inspector-tempest-discovery-stein:
-            voting: false
     gate:
       queue: ironic
       jobs:
         - ironic-standalone
+        - ironic-standalone-victoria
         - ironic-standalone-ussuri
-        - ironic-standalone-train
         - ironic-tempest-functional-python3
+        - ironic-tempest-functional-python3-victoria
         - ironic-tempest-functional-python3-ussuri
-        - ironic-tempest-functional-python3-train
         - ironic-inspector-tempest
+        - ironic-inspector-tempest-victoria
         - ironic-inspector-tempest-ussuri
-        - ironic-inspector-tempest-train
         - ironic-standalone-redfish
         - ironic-inspector-tempest-discovery
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index b3824bc..ee0e524 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -1,4 +1,9 @@
 - job:
+    name: ironic-standalone-victoria
+    parent: ironic-standalone
+    override-checkout: stable/victoria
+
+- job:
     name: ironic-standalone-ussuri
     parent: ironic-standalone
     override-checkout: stable/ussuri
@@ -12,12 +17,10 @@
         USE_PYTHON3: True
 
 - job:
-    name: ironic-standalone-stein
-    parent: ironic-standalone
-    override-checkout: stable/stein
-    vars:
-      devstack_localrc:
-        USE_PYTHON3: True
+    name: ironic-standalone-redfish-victoria
+    parent: ironic-standalone-redfish
+    nodeset: openstack-single-node-focal
+    override-checkout: stable/victoria
 
 - job:
     name: ironic-standalone-redfish-ussuri
@@ -33,12 +36,9 @@
         USE_PYTHON3: True
 
 - job:
-    name: ironic-standalone-redfish-stein
-    parent: ironic-standalone-redfish
-    override-checkout: stable/stein
-    vars:
-      devstack_localrc:
-        USE_PYTHON3: True
+    name: ironic-tempest-functional-python3-victoria
+    parent: ironic-tempest-functional-python3
+    override-checkout: stable/victoria
 
 - job:
     name: ironic-tempest-functional-python3-ussuri
@@ -51,9 +51,9 @@
     override-checkout: stable/train
 
 - job:
-    name: ironic-tempest-functional-python3-stein
-    parent: ironic-tempest-functional-python3
-    override-checkout: stable/stein
+    name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-victoria
+    parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
+    override-checkout: stable/victoria
 
 - job:
     name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-ussuri
@@ -69,12 +69,13 @@
         USE_PYTHON3: True
 
 - job:
-    name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-stein
-    parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
-    override-checkout: stable/stein
+    name: ironic-inspector-tempest-victoria
+    parent: ironic-inspector-tempest
+    override-checkout: stable/victoria
     vars:
       devstack_localrc:
-        USE_PYTHON3: True
+        FIXED_NETWORK_SIZE: 4096
+        EBTABLES_RACE_FIX: True
 
 - job:
     name: ironic-inspector-tempest-ussuri
@@ -96,14 +97,9 @@
         USE_PYTHON3: True
 
 - job:
-    name: ironic-inspector-tempest-stein
-    parent: ironic-inspector-tempest
-    override-checkout: stable/stein
-    vars:
-      devstack_localrc:
-        FIXED_NETWORK_SIZE: 4096
-        EBTABLES_RACE_FIX: True
-        USE_PYTHON3: True
+    name: ironic-inspector-tempest-discovery-victoria
+    parent: ironic-inspector-tempest-discovery
+    override-checkout: stable/victoria
 
 - job:
     name: ironic-inspector-tempest-discovery-ussuri
@@ -117,11 +113,3 @@
     vars:
       devstack_localrc:
         USE_PYTHON3: True
-
-- job:
-    name: ironic-inspector-tempest-discovery-stein
-    parent: ironic-inspector-tempest-discovery
-    override-checkout: stable/stein
-    vars:
-      devstack_localrc:
-        USE_PYTHON3: True