summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2021-01-27 17:27:03 +0000
committerGerrit Code Review <review@openstack.org>2021-01-27 17:27:03 +0000
commite71a6fa4a1a18dbbb01a90df1b73934b00564547 (patch)
tree4c0baf4fe09bc08c4e888f98681f1c8add459336
parenteebf94b6540fcd16826067fac544b5a3238842a3 (diff)
parent95fc16133406da6bb07f9f8ffc21e99f1e4695f4 (diff)
downloadnova-e71a6fa4a1a18dbbb01a90df1b73934b00564547.tar.gz
Merge "Add regression test for bug #1899649" into stable/victoria
-rw-r--r--nova/tests/functional/regressions/test_bug_1899649.py110
1 files changed, 110 insertions, 0 deletions
diff --git a/nova/tests/functional/regressions/test_bug_1899649.py b/nova/tests/functional/regressions/test_bug_1899649.py
new file mode 100644
index 0000000000..3029046587
--- /dev/null
+++ b/nova/tests/functional/regressions/test_bug_1899649.py
@@ -0,0 +1,110 @@
+# Copyright 2020, Red Hat, Inc. All Rights Reserved.
+#
+# 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 nova.tests import fixtures as nova_fixtures
+from nova.tests.functional.libvirt import base
+from nova.tests.unit.virt.libvirt import fakelibvirt
+
+
+class TestVolAttachmentsAfterFailureToScheduleOrBuild(base.ServersTestBase):
+ """Regression test for bug .
+
+ This regression test aims to ensure a volume attachment remains in place
+ after a failure to either schedule a server or when building a server
+ directly on a compute after skipping the scheduler.
+
+ A volume attachment is required to remain after such failures to ensure the
+ volume itself remains marked as reserved.
+
+ To ensure this is as accurate as possible the tests use the libvirt
+ functional base class to mimic a real world example with NUMA nodes being
+ requested via flavor extra specs. The underlying compute being unable to
+ meet this request ensuring a failure.
+ """
+
+ microversion = 'latest'
+
+ def setUp(self):
+ super().setUp()
+
+ # Launch a single libvirt based compute service with a single NUMA node
+ host_info = fakelibvirt.HostInfo(
+ cpu_nodes=1, cpu_sockets=1, cpu_cores=2, kB_mem=15740000)
+ self.start_compute(host_info=host_info, hostname='compute1')
+
+ # Use a flavor requesting 2 NUMA nodes that we know will always fail
+ self.flavor_id = self._create_flavor(extra_spec={'hw:numa_nodes': '2'})
+
+ # Craft a common bfv server request for use within each test
+ self.volume_id = nova_fixtures.CinderFixture.IMAGE_BACKED_VOL
+ self.server = {
+ 'name': 'test',
+ 'flavorRef': self.flavor_id,
+ 'imageRef': '',
+ 'networks': 'none',
+ 'block_device_mapping_v2': [{
+ 'source_type': 'volume',
+ 'destination_type': 'volume',
+ 'boot_index': 0,
+ 'uuid': self.volume_id}]
+ }
+
+ def _assert_failure_and_volume_attachments(self, server):
+ # Assert that the server is in an ERROR state
+ self._wait_for_state_change(server, 'ERROR')
+
+ # Assert that the volume is in a reserved state. As this isn't modelled
+ # by the CinderFixture we just assert that a single volume attachment
+ # remains after the failure and that it is referenced by the server.
+ attachments = self.cinder.volume_to_attachment.get(self.volume_id)
+ self.assertEqual(1, len(attachments))
+ self.assertIn(
+ self.volume_id, self.cinder.volume_ids_for_instance(server['id']))
+
+ def test_failure_to_schedule(self):
+ # Assert that a volume attachment remains after a failure to schedule
+ server = self.api.post_server({'server': self.server})
+ self._assert_failure_and_volume_attachments(server)
+
+ def test_failure_to_schedule_with_az(self):
+ # Assert that a volume attachment remains after a failure to schedule
+ # with the addition of an availability_zone in the request
+ self.server['availability_zone'] = 'nova'
+ server = self.api.post_server({'server': self.server})
+ self._assert_failure_and_volume_attachments(server)
+
+ def test_failure_to_schedule_with_host(self):
+ # Assert that a volume attachment remains after a failure to schedule
+ # using the optional host parameter introduced in microversion 2.74
+ self.server['host'] = 'compute1'
+ server = self.admin_api.post_server({'server': self.server})
+ self._assert_failure_and_volume_attachments(server)
+
+ def test_failure_to_build_with_az_and_host(self):
+ # Assert that a volume attachments does not remain after a failure to
+ # build and reschedule by providing an availability_zone *and* host,
+ # skipping the scheduler. This is bug #1899649.
+ self.server['availability_zone'] = 'nova:compute1'
+ server = self.admin_api.post_server({'server': self.server})
+
+ # Assert the server ends up in an ERROR state
+ self._wait_for_state_change(server, 'ERROR')
+
+ # FIXME(lyarwood): A single volume attachment should be present for the
+ # instance at this stage as the volume *can* otherwise be marked as
+ # available within Cinder if it isn't multi-attached.
+ attachments = self.cinder.volume_to_attachment.get(self.volume_id)
+ self.assertEqual(0, len(attachments))
+ self.assertNotIn(
+ self.volume_id, self.cinder.volume_ids_for_instance(server['id']))