summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBalazs Gibizer <balazs.gibizer@est.tech>2020-02-10 15:23:02 +0100
committerBalazs Gibizer <balazs.gibizer@est.tech>2020-07-13 13:39:47 +0200
commit618dd9bdc24b3a1de6a5581d4e7201efdf1f86bd (patch)
tree5c6adbe87f67b34aaac3507ebb6b1b927008e4a4
parent33d5b585f24f66c2533a65e026904d1c919ee7bb (diff)
downloadnova-618dd9bdc24b3a1de6a5581d4e7201efdf1f86bd.tar.gz
Reproduce bug 1862633
If port update fails during unshelve of an offloaded server then placement allocation on the target host is leaked. Changes in test_bug_1862633.py due to: * the NeutronFixture improvement done in Id8d2c48c9c864554a917596e377d30515465fec1 is missing from stable/pike therefore the fault injection mock needed to be moved to a higher level function. * the Ie4676eed0039c927b35af7573f0b57fd762adbaa refactor is also missing and causing the name change of wait_for_versioned_notification Change-Id: I7be32e4fc2e69f805535e0a437931516f491e5cb Related-Bug: #1862633 (cherry picked from commit c33ebdafbd633578a0a4b6f1b118c756510acea6) (cherry picked from commit bd1bfc13d7e2c418afc409871ab56da454a1334d) (cherry picked from commit f960d1751d752d559ea18604bfd1fcaf1a3283cd) (cherry picked from commit 5e452f8eb743c226af4f4998835ece8dd142a011) (cherry picked from commit eb4f0a5aa93feb2dc7730987207f052a04bc33db)
-rw-r--r--nova/tests/functional/regressions/test_bug_1862633.py100
1 files changed, 100 insertions, 0 deletions
diff --git a/nova/tests/functional/regressions/test_bug_1862633.py b/nova/tests/functional/regressions/test_bug_1862633.py
new file mode 100644
index 0000000000..e35e391417
--- /dev/null
+++ b/nova/tests/functional/regressions/test_bug_1862633.py
@@ -0,0 +1,100 @@
+# 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.
+import mock
+from neutronclient.common import exceptions as neutron_exception
+
+from nova import test
+from nova.tests import fixtures as nova_fixtures
+from nova.tests.functional import integrated_helpers
+from nova.tests.unit import fake_notifier
+from nova.tests.unit.image import fake as fake_image
+from nova.virt import fake
+
+
+class UnshelveNeutronErrorTest(
+ test.TestCase, integrated_helpers.InstanceHelperMixin):
+ def setUp(self):
+ super(UnshelveNeutronErrorTest, self).setUp()
+ # Start standard fixtures.
+ placement = nova_fixtures.PlacementFixture()
+ self.useFixture(placement)
+ self.placement_api = placement.api
+ self.neutron = nova_fixtures.NeutronFixture(self)
+ self.useFixture(self.neutron)
+ fake_image.stub_out_image_service(self)
+ self.addCleanup(fake_image.FakeImageService_reset)
+ # Start nova services.
+ self.api = self.useFixture(nova_fixtures.OSAPIFixture(
+ api_version='v2.1')).admin_api
+ self.api.microversion = 'latest'
+ fake_notifier.stub_notifier(self)
+ self.addCleanup(fake_notifier.reset)
+
+ self.start_service('conductor')
+ self.start_service('scheduler')
+ self.addCleanup(fake.restore_nodes)
+ fake.set_nodes(['host1'])
+ self.start_service('compute', host='host1')
+ fake.set_nodes(['host2'])
+ self.start_service('compute', host='host2')
+
+ def test_unshelve_offloaded_fails_due_to_neutron(self):
+ server_req = self._build_minimal_create_server_request(
+ self.api, name='unshelve-error-vm',
+ image_uuid='155d900f-4e14-4e4c-a73d-069cbf4541e6',
+ networks=[{'port': self.neutron.port_1['id']}], az='nova:host1')
+ created_server = self.api.post_server({'server': server_req})
+ server = self._wait_for_state_change(
+ self.api, created_server, 'ACTIVE')
+
+ # with default config shelve means immediate offload as well
+ req = {
+ 'shelve': {}
+ }
+ self.api.post_server_action(server['id'], req)
+ self._wait_for_server_parameter(
+ self.api, server, {'status': 'SHELVED_OFFLOADED'})
+ allocations = self.placement_api.get(
+ '/allocations/%s' % server['id']).body['allocations']
+ self.assertEqual(0, len(allocations))
+
+ # disable the original host of the instance to force a port update
+ # during unshelve
+ source_service_id = self.api.get_services(
+ host='host1', binary='nova-compute')[0]['id']
+ self.api.put_service(source_service_id, {"status": "disabled"})
+
+ # Simulate that port update fails during unshelve due to neutron is
+ # unavailable
+ with mock.patch(
+ 'nova.network.neutronv2.api.API.'
+ 'setup_instance_network_on_host',
+ side_effect=neutron_exception.ConnectionFailed(reason='test')):
+ req = {'unshelve': None}
+ self.api.post_server_action(server['id'], req)
+ fake_notifier.wait_for_versioned_notification(
+ 'instance.unshelve.start')
+ self._wait_for_server_parameter(
+ self.api,
+ server,
+ {'status': 'SHELVED_OFFLOADED',
+ 'OS-EXT-STS:task_state': None})
+
+ # As the instance went back to offloaded state we expect no allocation
+ # allocations = self.placement_api.get(
+ # '/allocations/%s' % server['id']).body['allocations']
+ # self.assertEqual(0, len(allocations))
+ #
+ # but the allocation is leaked this is bug 1862633
+ allocations = self.placement_api.get(
+ '/allocations/%s' % server['id']).body['allocations']
+ self.assertEqual(1, len(allocations))