Merge "import zuul job settings from project-config"
diff --git a/HACKING.rst b/HACKING.rst
index ca7b5cd..eac83a4 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -1,4 +1,4 @@
 ironic-tempest-plugin Style Commandments
 ===============================================
 
-Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/
+Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/
diff --git a/doc/source/config/with-nova.rst b/doc/source/config/with-nova.rst
index 3537588..67dcc62 100644
--- a/doc/source/config/with-nova.rst
+++ b/doc/source/config/with-nova.rst
@@ -46,6 +46,8 @@
     # Minimum and maximum API versions to test against.
     min_microversion = <min API version as X.Y>
     max_microversion = <max API version as X.Y>
+    # Driver to use for API tests for Queens and newer:
+    driver = fake-hardware
 
     [compute]
     # Configure the bare metal flavor so that the Compute services provisions
diff --git a/doc/source/usage.rst b/doc/source/usage.rst
index 3e3c56e..27b5ebe 100644
--- a/doc/source/usage.rst
+++ b/doc/source/usage.rst
@@ -38,11 +38,20 @@
 
 ``ironic``
     all bare metal tests
+``ironic_tempest_plugin.tests.api``
+    only API tests using fake hardware, without other OpenStack services (these
+    tests are run by jobs starting with ``tempest-dsvm-ironic-functional``)
+``ironic_tempest_plugin.tests.scenario``
+    all integration tests, excluding the API tests with fake hardware (these
+    tests are run by most of the jobs)
 ``ironic_standalone``
     standalone bare metal tests that do not use the Compute service
+    (these tests are run by the job ``ironic-dsvm-standalone``)
 ``InspectorBasicTest``
-    basic introspection tests
+    basic introspection tests (these tests are run by most of the jobs with
+    ``ironic-inspector`` in their name)
 ``InspectorDiscoveryTest``
-    introspection auto-discovery tests
+    introspection auto-discovery tests (these tests are run by the job
+    ``ironic-inspector-tempest-dsvm-discovery`` and require additional set up)
 
 .. _Tempest documentation: https://docs.openstack.org/tempest/latest/run.html
diff --git a/ironic_tempest_plugin/config.py b/ironic_tempest_plugin/config.py
index c4fb185..7cabf69 100644
--- a/ironic_tempest_plugin/config.py
+++ b/ironic_tempest_plugin/config.py
@@ -129,6 +129,9 @@
     cfg.ListOpt('enabled_rescue_interfaces',
                 default=['no-rescue'],
                 help="List of Ironic enabled rescue interfaces."),
+    cfg.ListOpt('enabled_boot_interfaces',
+                default=['fake', 'pxe'],
+                help="List of Ironic enabled boot interfaces."),
     cfg.StrOpt('default_rescue_interface',
                help="Ironic default rescue interface."),
     cfg.IntOpt('adjusted_root_disk_size_gb',
diff --git a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
index c7d6b50..94780a8 100644
--- a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
+++ b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
@@ -418,6 +418,12 @@
     # been set via a different test).
     rescue_interface = None
 
+    # The boot interface to use by the HW type. The boot interface of the
+    # node used in the test will be set to this value. If set to None, the
+    # node will retain its existing boot_interface value (which may have been
+    # set via a different test).
+    boot_interface = None
+
     # Boolean value specify if image is wholedisk or not.
     wholedisk_image = None
 
@@ -463,6 +469,13 @@
                 "in the list of enabled rescue interfaces %(enabled)s" % {
                     'iface': cls.rescue_interface,
                     'enabled': CONF.baremetal.enabled_rescue_interfaces})
+        if (cls.boot_interface and cls.boot_interface not in
+                CONF.baremetal.enabled_boot_interfaces):
+            raise cls.skipException(
+                "Boot interface %(iface)s required by test is not "
+                "in the list of enabled boot interfaces %(enabled)s" % {
+                    'iface': cls.boot_interface,
+                    'enabled': CONF.baremetal.enabled_boot_interfaces})
         if not cls.wholedisk_image and CONF.baremetal.use_provision_network:
             raise cls.skipException(
                 'Partitioned images are not supported with multitenancy.')
@@ -497,6 +510,8 @@
             boot_kwargs['deploy_interface'] = cls.deploy_interface
         if cls.rescue_interface:
             boot_kwargs['rescue_interface'] = cls.rescue_interface
+        if cls.boot_interface:
+            boot_kwargs['boot_interface'] = cls.boot_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 eb31327..21b9911 100644
--- a/ironic_tempest_plugin/tests/scenario/introspection_manager.py
+++ b/ironic_tempest_plugin/tests/scenario/introspection_manager.py
@@ -201,8 +201,7 @@
         while True:
             time.sleep(CONF.baremetal_introspection.hypervisor_update_sleep)
             stats = self.hypervisor_stats()
-            expected_cpus = self.baremetal_flavor()['vcpus']
-            if int(stats['hypervisor_statistics']['vcpus']) >= expected_cpus:
+            if int(stats['hypervisor_statistics']['count']):
                 break
 
             timeout = CONF.baremetal_introspection.hypervisor_update_timeout
diff --git a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_basic_ops.py b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_basic_ops.py
index 5aa7543..45b5271 100644
--- a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_basic_ops.py
+++ b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_basic_ops.py
@@ -237,3 +237,99 @@
         self.unrescue_node(self.node['uuid'])
         self.assertTrue(self.ping_ip_address(self.node_ip,
                                              should_succeed=True))
+
+
+class BaremetalIloDirectWholediskHttpLink(
+        bsm.BaremetalStandaloneScenarioTest):
+
+    api_microversion = '1.31'  # to set the deploy_interface
+    driver = 'ilo'
+    deploy_interface = 'direct'
+    boot_interface = 'ilo-virtual-media'
+    image_ref = CONF.baremetal.whole_disk_image_url
+    image_checksum = CONF.baremetal.whole_disk_image_checksum
+    wholedisk_image = True
+
+    @decorators.idempotent_id('c2db24e7-b9bb-44df-6765-e60134346fd0')
+    @utils.services('network')
+    def test_ip_access_to_server(self):
+        self.boot_and_verify_node()
+
+
+class BaremetalIloDirectPartitioned(bsm.BaremetalStandaloneScenarioTest):
+
+    api_microversion = '1.31'  # to set the deploy_interface
+    driver = 'ilo'
+    deploy_interface = 'direct'
+    boot_interface = 'ilo-virtual-media'
+    image_ref = CONF.baremetal.partition_image_ref
+    wholedisk_image = False
+
+    @decorators.idempotent_id('ea85e19c-d8dc-4577-4d05-fbbbe4ce3f8c')
+    @utils.services('image', 'network')
+    def test_ip_access_to_server(self):
+        self.boot_and_verify_node()
+
+
+class BaremetalIloIscsiWholediskHttpLink(
+        bsm.BaremetalStandaloneScenarioTest):
+
+    api_microversion = '1.31'  # to set the deploy_interface
+    driver = 'ilo'
+    deploy_interface = 'iscsi'
+    boot_interface = 'ilo-virtual-media'
+    image_ref = CONF.baremetal.whole_disk_image_url
+    image_checksum = CONF.baremetal.whole_disk_image_checksum
+    wholedisk_image = True
+
+    @decorators.idempotent_id('71ccf06f-45db-8f93-afd0-d4efae2bfd4e')
+    @utils.services('network')
+    def test_ip_access_to_server(self):
+        self.boot_and_verify_node()
+
+
+class BaremetalIloIscsiPartitioned(bsm.BaremetalStandaloneScenarioTest):
+
+    api_microversion = '1.31'  # to set the deploy_interface
+    driver = 'ilo'
+    deploy_interface = 'iscsi'
+    boot_interface = 'ilo-virtual-media'
+    image_ref = CONF.baremetal.partition_image_ref
+    wholedisk_image = False
+
+    @decorators.idempotent_id('d926c683-4d05-8252-b9bb-35babbed6e86')
+    @utils.services('image', 'network')
+    def test_ip_access_to_server(self):
+        self.boot_and_verify_node()
+
+
+class BaremetalIloPxeWholediskHttpLink(
+        bsm.BaremetalStandaloneScenarioTest):
+
+    api_microversion = '1.31'  # to set the deploy_interface
+    driver = 'ilo'
+    deploy_interface = 'direct'
+    boot_interface = 'ilo-pxe'
+    image_ref = CONF.baremetal.whole_disk_image_url
+    image_checksum = CONF.baremetal.whole_disk_image_checksum
+    wholedisk_image = True
+
+    @decorators.idempotent_id('d926c683-1a32-edbc-07dc-95cd74eefecb')
+    @utils.services('network')
+    def test_ip_access_to_server(self):
+        self.boot_and_verify_node()
+
+
+class BaremetalIloPxePartitioned(bsm.BaremetalStandaloneScenarioTest):
+
+    api_microversion = '1.31'  # to set the deploy_interface
+    driver = 'ilo'
+    deploy_interface = 'direct'
+    boot_interface = 'ilo-pxe'
+    image_ref = CONF.baremetal.partition_image_ref
+    wholedisk_image = False
+
+    @decorators.idempotent_id('71ccf06f-07dc-4577-6869-1b1bfa423b9b')
+    @utils.services('image', 'network')
+    def test_ip_access_to_server(self):
+        self.boot_and_verify_node()