Merge "Single tenant tests: BM to BM and BM to VM"
diff --git a/.gitreview b/.gitreview
index 5977701..5226891 100644
--- a/.gitreview
+++ b/.gitreview
@@ -1,4 +1,4 @@
[gerrit]
-host=review.openstack.org
+host=review.opendev.org
port=29418
project=openstack/ironic-tempest-plugin.git
diff --git a/README.rst b/README.rst
index 0f7ec06..e4e5a10 100644
--- a/README.rst
+++ b/README.rst
@@ -7,7 +7,7 @@
* Free software: Apache license
* Documentation: https://docs.openstack.org/ironic-tempest-plugin
-* Source: https://git.openstack.org/cgit/openstack/ironic-tempest-plugin
+* Source: https://opendev.org/openstack/ironic-tempest-plugin
* Bugs: https://storyboard.openstack.org/#!/project/951
.. _Tempest: https://docs.openstack.org/tempest/latest/
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 2156eb7..114d4b0 100755
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -22,10 +22,13 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
- #'sphinx.ext.intersphinx',
- 'oslosphinx'
+ 'openstackdocstheme'
]
+# openstackdocstheme options
+repository_name = 'openstack/ironic-tempest-plugin'
+use_storyboard = True
+
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
@@ -55,8 +58,8 @@
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
-# html_theme = '_theme'
# html_static_path = ['static']
+html_theme = 'openstackdocs'
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
diff --git a/ironic_tempest_plugin/config.py b/ironic_tempest_plugin/config.py
index a3b5019..79b6d18 100644
--- a/ironic_tempest_plugin/config.py
+++ b/ironic_tempest_plugin/config.py
@@ -198,4 +198,6 @@
cfg.StrOpt('auto_discovery_target_driver',
help="The driver to set on the newly discovered nodes. "
"Only has effect with auto_discovery_feature is True."),
+ cfg.StrOpt('data_store',
+ 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 08e15cd..b326e0d 100644
--- a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
+++ b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
@@ -846,7 +846,8 @@
:return: A tuple with the server response and the created allocation.
"""
- kwargs['resource_class'] = resource_class
+ if resource_class:
+ kwargs['resource_class'] = resource_class
return self._create_request('allocations', kwargs)
@base.handle_errors
diff --git a/ironic_tempest_plugin/tests/api/admin/base.py b/ironic_tempest_plugin/tests/api/admin/base.py
index 746eea6..8cc8aec 100644
--- a/ironic_tempest_plugin/tests/api/admin/base.py
+++ b/ironic_tempest_plugin/tests/api/admin/base.py
@@ -104,7 +104,7 @@
cls.power_timeout = CONF.baremetal.power_timeout
cls.unprovision_timeout = CONF.baremetal.unprovision_timeout
cls.created_objects = {}
- for resource in RESOURCE_TYPES:
+ for resource in RESOURCE_TYPES + ['allocation']:
cls.created_objects[resource] = set()
cls.deployed_nodes = set()
@@ -122,6 +122,14 @@
except lib_exc.BadRequest:
pass
+ # Delete allocations explicitly after unprovisioning instances, but
+ # before deleting nodes.
+ for allocation in cls.created_objects['allocation']:
+ try:
+ cls.client.delete_allocation(allocation)
+ except lib_exc.NotFound:
+ pass
+
for node in cls.created_objects['node']:
try:
cls.client.update_node(node, instance_uuid=None)
@@ -452,3 +460,15 @@
res=resource,
uuid=uuid)
self.assertEqual(expected_link, link)
+
+ @classmethod
+ @creates('allocation')
+ def create_allocation(cls, resource_class, **kwargs):
+ """Wrapper utility for creating test allocations.
+
+ :param resource_class: Resource class to request.
+ :param kwargs: Other fields to pass.
+ :return: A tuple with the server response and the created allocation.
+ """
+ resp, body = cls.client.create_allocation(resource_class, **kwargs)
+ return resp, body
diff --git a/ironic_tempest_plugin/tests/api/admin/test_allocations.py b/ironic_tempest_plugin/tests/api/admin/test_allocations.py
index a6e8e9c..972d864 100644
--- a/ironic_tempest_plugin/tests/api/admin/test_allocations.py
+++ b/ironic_tempest_plugin/tests/api/admin/test_allocations.py
@@ -21,18 +21,15 @@
CONF = config.CONF
-class TestAllocations(base.BaseBaremetalTest):
- """Tests for baremetal allocations."""
-
- min_microversion = '1.52'
-
- def provide_node(self, node_id, cleaning_timeout=None):
- super(TestAllocations, self).provide_node(node_id, cleaning_timeout)
+class Base(base.BaseBaremetalTest):
+ @classmethod
+ def provide_and_power_off_node(cls, node_id, cleaning_timeout=None):
+ cls.provide_node(node_id, cleaning_timeout)
# Force non-empty power state, otherwise allocation API won't pick it
- self.client.set_node_power_state(node_id, 'power off')
+ cls.client.set_node_power_state(node_id, 'power off')
def setUp(self):
- super(TestAllocations, self).setUp()
+ super(Base, self).setUp()
# Generate a resource class to prevent parallel tests from clashing
# with each other.
@@ -41,12 +38,18 @@
_, self.chassis = self.create_chassis()
_, self.node = self.create_node(self.chassis['uuid'],
resource_class=self.resource_class)
- self.provide_node(self.node['uuid'])
+ self.provide_and_power_off_node(self.node['uuid'])
+
+
+class TestAllocations(Base):
+ """Tests for baremetal allocations."""
+
+ min_microversion = '1.52'
@decorators.idempotent_id('9203ea28-3c61-4108-8498-22247b654ff6')
def test_create_show_allocation(self):
self.assertIsNone(self.node['allocation_uuid'])
- _, body = self.client.create_allocation(self.resource_class)
+ _, body = self.create_allocation(self.resource_class)
uuid = body['uuid']
self.assertTrue(uuid)
@@ -72,10 +75,10 @@
_, node2 = self.create_node(self.chassis['uuid'],
resource_class=self.resource_class)
self.client.set_node_traits(node2['uuid'], ['CUSTOM_MEOW'])
- self.provide_node(node2['uuid'])
+ self.provide_and_power_off_node(node2['uuid'])
- _, body = self.client.create_allocation(self.resource_class,
- traits=['CUSTOM_MEOW'])
+ _, body = self.create_allocation(self.resource_class,
+ traits=['CUSTOM_MEOW'])
uuid = body['uuid']
self.assertTrue(uuid)
@@ -95,10 +98,10 @@
_, node2 = self.create_node(self.chassis['uuid'],
resource_class=self.resource_class,
name=node_name)
- self.provide_node(node2['uuid'])
+ self.provide_and_power_off_node(node2['uuid'])
- _, body = self.client.create_allocation(self.resource_class,
- candidate_nodes=[node_name])
+ _, body = self.create_allocation(self.resource_class,
+ candidate_nodes=[node_name])
uuid = body['uuid']
self.assertTrue(uuid)
@@ -114,23 +117,21 @@
@decorators.idempotent_id('84eb3c21-4e16-4f33-9551-dce0f8689462')
def test_delete_allocation(self):
- _, body = self.client.create_allocation(self.resource_class)
+ _, body = self.create_allocation(self.resource_class)
self.client.delete_allocation(body['uuid'])
self.assertRaises(lib_exc.NotFound, self.client.show_allocation,
body['uuid'])
@decorators.idempotent_id('5e30452d-ee92-4342-82c1-5eea5e55c937')
def test_delete_allocation_by_name(self):
- _, body = self.client.create_allocation(self.resource_class,
- name='banana')
+ _, body = self.create_allocation(self.resource_class, name='banana')
self.client.delete_allocation('banana')
self.assertRaises(lib_exc.NotFound, self.client.show_allocation,
'banana')
@decorators.idempotent_id('fbbc13bc-86da-438b-af01-d1bc1bab57d6')
def test_show_by_name(self):
- _, body = self.client.create_allocation(self.resource_class,
- name='banana')
+ _, body = self.create_allocation(self.resource_class, name='banana')
_, loaded_body = self.client.show_allocation('banana')
# The allocation will likely have been processed by this time, so do
# not compare the whole body.
@@ -139,7 +140,7 @@
@decorators.idempotent_id('4ca123c4-160d-4d8d-a3f7-15feda812263')
def test_list_allocations(self):
- _, body = self.client.create_allocation(self.resource_class)
+ _, body = self.create_allocation(self.resource_class)
_, listing = self.client.list_allocations()
self.assertIn(body['uuid'],
@@ -152,8 +153,8 @@
@decorators.idempotent_id('092b7148-9ff0-4107-be57-2cfcd21eb5d7')
def test_list_allocations_by_state(self):
- _, body = self.client.create_allocation(self.resource_class)
- _, body2 = self.client.create_allocation(self.resource_class + 'foo2')
+ _, body = self.create_allocation(self.resource_class)
+ _, body2 = self.create_allocation(self.resource_class + 'foo2')
waiters.wait_for_allocation(self.client, body['uuid'])
waiters.wait_for_allocation(self.client, body2['uuid'],
@@ -177,7 +178,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('bf7e1375-019a-466a-a294-9c1052827ada')
def test_create_allocation_resource_class_mismatch(self):
- _, body = self.client.create_allocation(self.resource_class + 'foo')
+ _, body = self.create_allocation(self.resource_class + 'foo')
_, body = waiters.wait_for_allocation(self.client, body['uuid'],
expect_error=True)
@@ -187,7 +188,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('b4eeddee-ca34-44f9-908b-490b78b18486')
def test_create_allocation_traits_mismatch(self):
- _, body = self.client.create_allocation(
+ _, body = self.create_allocation(
self.resource_class, traits=['CUSTOM_DOES_NOT_EXIST'])
_, body = waiters.wait_for_allocation(self.client, body['uuid'],
@@ -201,10 +202,56 @@
_, node2 = self.create_node(self.chassis['uuid'],
resource_class=self.resource_class + 'alt')
# Mismatch between the resource class and the candidate node
- _, body = self.client.create_allocation(
+ _, body = self.create_allocation(
self.resource_class, candidate_nodes=[node2['uuid']])
_, body = waiters.wait_for_allocation(self.client, body['uuid'],
expect_error=True)
self.assertEqual('error', body['state'])
self.assertTrue(body['last_error'])
+
+
+class TestBackfill(Base):
+ """Tests for backfilling baremetal allocations."""
+
+ min_microversion = '1.58'
+
+ @decorators.idempotent_id('10774c1d-6b79-453a-8e26-9bf04ab580a4')
+ def test_backfill_allocation(self):
+ self.deploy_node(self.node['uuid'])
+
+ _, body = self.client.create_allocation(self.resource_class,
+ node=self.node['uuid'])
+ uuid = body['uuid']
+ self.assertEqual(self.node['uuid'], body['node_uuid'])
+ self.assertEqual('active', body['state'])
+ self.assertIsNone(body['last_error'])
+
+ _, body2 = self.client.show_node_allocation(body['node_uuid'])
+ self.assertEqual(self.node['uuid'], body2['node_uuid'])
+ self.assertEqual('active', body2['state'])
+ self.assertIsNone(body2['last_error'])
+
+ _, node = self.client.show_node(self.node['uuid'])
+ self.assertEqual(uuid, node['allocation_uuid'])
+
+ @decorators.idempotent_id('c33d4b65-1232-4a3f-9aad-942e32f6f7b0')
+ def test_backfill_without_resource_class(self):
+ self.deploy_node(self.node['uuid'])
+
+ _, body = self.client.create_allocation(None, node=self.node['uuid'])
+ uuid = body['uuid']
+ self.assertEqual(self.node['uuid'], body['node_uuid'])
+ self.assertEqual('active', body['state'])
+ self.assertIsNone(body['last_error'])
+ # Resource class is copied from node
+ self.assertEqual(self.node['resource_class'], body['resource_class'])
+
+ _, body2 = self.client.show_node_allocation(body['node_uuid'])
+ self.assertEqual(self.node['uuid'], body2['node_uuid'])
+ self.assertEqual('active', body2['state'])
+ self.assertIsNone(body2['last_error'])
+ self.assertEqual(self.node['resource_class'], body2['resource_class'])
+
+ _, node = self.client.show_node(self.node['uuid'])
+ self.assertEqual(uuid, node['allocation_uuid'])
diff --git a/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py b/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py
index 61e5323..4fa73ee 100644
--- a/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py
+++ b/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py
@@ -101,13 +101,13 @@
LOG.info("Looking for partition %s mounted on %s", label, mount)
# Validate we have a device with the given partition label
- cmd = "/sbin/blkid | grep '%s' | cut -d':' -f1" % label
+ cmd = "/sbin/blkid -c /dev/null -l -o device -t LABEL=%s" % label
device = client.exec_command(cmd).rstrip('\n')
LOG.debug("Partition device is %s", device)
self.assertNotEqual('', device)
# Validate the mount point for the device
- cmd = "mount | grep '%s' | cut -d' ' -f3" % device
+ cmd = "mount | grep -w '%s' | cut -d' ' -f3" % device
actual_mount = client.exec_command(cmd).rstrip('\n')
LOG.debug("Partition mount point is %s", actual_mount)
self.assertEqual(actual_mount, mount)
diff --git a/ironic_tempest_plugin/tests/scenario/test_introspection_basic.py b/ironic_tempest_plugin/tests/scenario/test_introspection_basic.py
index f97316d..9823a88 100644
--- a/ironic_tempest_plugin/tests/scenario/test_introspection_basic.py
+++ b/ironic_tempest_plugin/tests/scenario/test_introspection_basic.py
@@ -94,7 +94,12 @@
for node_id in self.node_ids:
node = self.node_show(node_id)
self.assertEqual('yes', node['extra']['rule_success'])
- if CONF.service_available.swift:
+ data_store = CONF.baremetal_introspection.data_store
+ if data_store is None:
+ # Backward compatibility, the option is not set.
+ data_store = ('swift' if CONF.service_available.swift
+ else 'none')
+ if data_store != 'none':
self.verify_node_introspection_data(node)
self.verify_node_flavor(node)
diff --git a/ironic_tempest_plugin/tests/scenario/test_introspection_discovery.py b/ironic_tempest_plugin/tests/scenario/test_introspection_discovery.py
index c44844f..6f92d43 100644
--- a/ironic_tempest_plugin/tests/scenario/test_introspection_discovery.py
+++ b/ironic_tempest_plugin/tests/scenario/test_introspection_discovery.py
@@ -156,7 +156,12 @@
inspected_node = self.node_show(self.node_info['name'])
self.verify_node_flavor(inspected_node)
- if CONF.service_available.swift:
+ data_store = CONF.baremetal_introspection.data_store
+ if data_store is None:
+ # Backward compatibility, the option is not set.
+ data_store = ('swift' if CONF.service_available.swift
+ else 'none')
+ if data_store != 'none':
self.verify_node_introspection_data(inspected_node)
self.assertEqual(ProvisionStates.ENROLL,
inspected_node['provision_state'])
diff --git a/test-requirements.txt b/test-requirements.txt
index 1b68194..b5667d2 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -4,8 +4,8 @@
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
-sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD
-oslosphinx>=4.7.0 # Apache-2.0
+sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD
+sphinx!=1.6.6,!=1.6.7,>=1.6.2;python_version>='3.4' # BSD
+openstackdocstheme>=1.18.1 # Apache-2.0
-# releasenotes
reno>=2.5.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index 6b0e1ae..0cc29c7 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,11 +5,12 @@
[testenv]
usedevelop = True
-install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
+install_command = pip install {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
PYTHONWARNINGS=default::DeprecationWarning
-deps = -r{toxinidir}/test-requirements.txt
+deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/test-requirements.txt
commands = python setup.py test --slowest --testr-args='{posargs}'
[testenv:pep8]
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 2c6dce8..bcedbc3 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -7,48 +7,46 @@
jobs:
# NOTE(dtantsur): keep N-3 and older non-voting for these jobs.
- ironic-standalone
+ - ironic-standalone-stein
- ironic-dsvm-standalone-rocky
- # NOTE(iurygregory): we want to make voting again
- ironic-dsvm-standalone-queens:
voting: false
- - ironic-dsvm-standalone-pike:
- voting: false
- ironic-tempest-functional-python3
+ - ironic-tempest-functional-python3-stein
- ironic-tempest-dsvm-functional-python3-rocky
- ironic-inspector-tempest
+ - ironic-inspector-tempest-stein
- ironic-tempest-dsvm-ironic-inspector-rocky
- - ironic-tempest-dsvm-ironic-inspector-queens
- - ironic-tempest-dsvm-ironic-inspector-pike:
+ - ironic-tempest-dsvm-ironic-inspector-queens:
voting: false
# NOTE(dtantsur): these jobs cover rarely changed tests and are quite
# unstable, so keep them non-voting on stable branches.
- # NOTE(iurygregory): debug rocky and queens
- # since before was working, pike was broken before
+ # NOTE(iurygregory): debug rocky and queens since they used to pass
- ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
+ - ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-stein:
+ voting: false
- ironic-tempest-dsvm-ipa-wholedisk-agent_ipmitool-tinyipa-multinode-rocky:
voting: false
- ironic-tempest-dsvm-ipa-wholedisk-agent_ipmitool-tinyipa-multinode-queens:
voting: false
- - ironic-tempest-dsvm-ipa-wholedisk-agent_ipmitool-tinyipa-multinode-pike:
- voting: false
- ironic-inspector-tempest-discovery
+ - ironic-inspector-tempest-discovery-stein:
+ voting: false
- ironic-inspector-tempest-dsvm-discovery-rocky:
voting: false
- ironic-inspector-tempest-dsvm-discovery-queens:
voting: false
- # NOTE(iurygregory): we may want to debug why its failling since before was green
- - ironic-inspector-tempest-dsvm-discovery-pike:
- voting: false
gate:
queue: ironic
jobs:
- # NOTE(iurygregory): re add ironic-dsvm-standalone-queens when is green again
- ironic-standalone
+ - ironic-standalone-stein
- ironic-dsvm-standalone-rocky
- ironic-tempest-functional-python3
+ - ironic-tempest-functional-python3-stein
- ironic-tempest-dsvm-functional-python3-rocky
- ironic-inspector-tempest
+ - ironic-inspector-tempest-stein
- ironic-tempest-dsvm-ironic-inspector-rocky
- - ironic-tempest-dsvm-ironic-inspector-queens
- ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
- ironic-inspector-tempest-discovery
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index e4cf069..f553787 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -1,4 +1,9 @@
- job:
+ name: ironic-standalone-stein
+ parent: ironic-standalone
+ override-branch: stable/stein
+
+- job:
name: ironic-dsvm-standalone-rocky
parent: ironic-standalone
override-branch: stable/rocky
@@ -15,12 +20,10 @@
EBTABLES_RACE_FIX: True
IRONIC_USE_MOD_WSGI: True
-
- job:
- name: ironic-dsvm-standalone-pike
- parent: ironic-standalone
- override-branch: stable/pike
- nodeset: openstack-single-node-xenial
+ name: ironic-tempest-functional-python3-stein
+ parent: ironic-tempest-functional-python3
+ override-branch: stable/stein
- job:
name: ironic-tempest-dsvm-functional-python3-rocky
@@ -34,6 +37,11 @@
rabbit: True
- job:
+ name: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode-stein
+ parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
+ override-branch: stable/stein
+
+- job:
name: ironic-tempest-dsvm-ipa-wholedisk-agent_ipmitool-tinyipa-multinode-rocky
parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
override-branch: stable/rocky
@@ -70,22 +78,13 @@
OVS_BRIDGE_MAPPINGS: 'mynetwork:sub1brbm,public:br_ironic_vxlan'
- job:
- name: ironic-tempest-dsvm-ipa-wholedisk-agent_ipmitool-tinyipa-multinode-pike
- parent: ironic-tempest-ipa-wholedisk-direct-tinyipa-multinode
- override-branch: stable/pike
- nodeset: openstack-two-node-xenial
+ name: ironic-inspector-tempest-stein
+ parent: ironic-inspector-tempest
+ override-branch: stable/stein
vars:
devstack_localrc:
- IRONIC_DEFAULT_BOOT_OPTION: netboot
FIXED_NETWORK_SIZE: 4096
- IRONIC_DEFAULT_RESCUE_INTERFACE: agent
EBTABLES_RACE_FIX: True
- PUBLIC_BRIDGE: br_ironic_vxlan
- OVS_BRIDGE_MAPPINGS: 'mynetwork:brbm,public:br_ironic_vxlan'
- group-vars:
- subnode:
- devstack_localrc:
- OVS_BRIDGE_MAPPINGS: 'mynetwork:sub1brbm,public:br_ironic_vxlan'
- job:
name: ironic-tempest-dsvm-ironic-inspector-rocky
@@ -108,14 +107,9 @@
EBTABLES_RACE_FIX: True
- job:
- name: ironic-tempest-dsvm-ironic-inspector-pike
- parent: ironic-inspector-tempest
- override-branch: stable/pike
- nodeset: openstack-single-node-xenial
- vars:
- devstack_localrc:
- FIXED_NETWORK_SIZE: 4096
- EBTABLES_RACE_FIX: True
+ name: ironic-inspector-tempest-discovery-stein
+ parent: ironic-inspector-tempest-discovery
+ override-branch: stable/stein
- job:
name: ironic-inspector-tempest-dsvm-discovery-rocky
@@ -128,9 +122,3 @@
parent: ironic-inspector-tempest-discovery
override-branch: stable/queens
nodeset: openstack-single-node-xenial
-
-- job:
- name: ironic-inspector-tempest-dsvm-discovery-pike
- parent: ironic-inspector-tempest-discovery
- override-branch: stable/pike
- nodeset: openstack-single-node-xenial