Skip to content

Commit 00cba39

Browse files
author
Balazs Gibizer
committed
Avoid unbound instance_uuid var during delete
The patch I03cf285ad83e09d88cdb702a88dfed53c01610f8 fixed most of the possible cases for this to happen but missed one. An early enough exception during _delete() can cause that the instance_uuid never gets defined but then we try to use it during the finally block. This patch moves the saving of the instance_uuid to the top of the try block to avoid the issue. Change-Id: Ib3073d7f595c8927532b7c49fc7e5ffe80d508b9 Closes-Bug: #1940812 Related-Bug: #1914777 (cherry picked from commit 14e43f3)
1 parent e6c6880 commit 00cba39

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

nova/compute/api.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,6 +2281,12 @@ def _delete(self, context, instance, delete_type, cb, **instance_attrs):
22812281
# Normal delete should be attempted.
22822282
may_have_ports_or_volumes = compute_utils.may_have_ports_or_volumes(
22832283
instance)
2284+
2285+
# Save a copy of the instance UUID early, in case
2286+
# _lookup_instance returns instance = None, to pass to
2287+
# _local_delete_cleanup if needed.
2288+
instance_uuid = instance.uuid
2289+
22842290
if not instance.host and not may_have_ports_or_volumes:
22852291
try:
22862292
if self._delete_while_booting(context, instance):
@@ -2294,10 +2300,6 @@ def _delete(self, context, instance, delete_type, cb, **instance_attrs):
22942300
# full Instance or None if not found. If not found then it's
22952301
# acceptable to skip the rest of the delete processing.
22962302

2297-
# Save a copy of the instance UUID early, in case
2298-
# _lookup_instance returns instance = None, to pass to
2299-
# _local_delete_cleanup if needed.
2300-
instance_uuid = instance.uuid
23012303
cell, instance = self._lookup_instance(context, instance.uuid)
23022304
if cell and instance:
23032305
try:

nova/tests/unit/compute/test_api.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,34 @@ def test_delete_instance_from_cell0(self, destroy_mock, notify_mock):
16291629
self.compute_api.notifier, self.context, instance)
16301630
destroy_mock.assert_called_once_with()
16311631

1632+
def test_delete_instance_while_booting_host_changes_lookup_fails(self):
1633+
"""Tests the case where the instance become scheduled while being
1634+
destroyed but then the final lookup fails.
1635+
"""
1636+
instance = self._create_instance_obj({'host': None})
1637+
1638+
with test.nested(
1639+
mock.patch.object(
1640+
self.compute_api, '_delete_while_booting',
1641+
side_effect=exception.ObjectActionError(
1642+
action="delete", reason="reason")),
1643+
mock.patch.object(
1644+
self.compute_api, '_lookup_instance',
1645+
return_value=(None, None)),
1646+
mock.patch.object(self.compute_api, '_local_delete_cleanup')
1647+
) as (
1648+
_delete_while_booting, _lookup_instance, _local_delete_cleanup
1649+
):
1650+
self.compute_api._delete(
1651+
self.context, instance, 'delete', mock.NonCallableMock())
1652+
1653+
_delete_while_booting.assert_called_once_with(
1654+
self.context, instance)
1655+
_lookup_instance.assert_called_once_with(
1656+
self.context, instance.uuid)
1657+
_local_delete_cleanup.assert_called_once_with(
1658+
self.context, instance.uuid)
1659+
16321660
@mock.patch.object(context, 'target_cell')
16331661
@mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid',
16341662
side_effect=exception.InstanceMappingNotFound(

0 commit comments

Comments
 (0)