Skip to content

Commit cb935a3

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "compute: Avoid duplicate BDMs during reserve_block_device_name" into stable/wallaby
2 parents 0da42ad + 2bee83b commit cb935a3

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

nova/compute/manager.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6991,6 +6991,12 @@ def do_reserve():
69916991
objects.BlockDeviceMappingList.get_by_instance_uuid(
69926992
context, instance.uuid))
69936993

6994+
# Now that we have the lock check that we haven't raced another
6995+
# request and ensure there is no existing attachment
6996+
if any(b for b in bdms if b.volume_id == volume_id):
6997+
msg = _("volume %s already attached") % volume_id
6998+
raise exception.InvalidVolume(reason=msg)
6999+
69947000
# NOTE(ndipanov): We need to explicitly set all the fields on the
69957001
# object so that obj_load_attr does not fail
69967002
new_bdm = objects.BlockDeviceMapping(

nova/tests/functional/regressions/test_bug_1937375.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import time
1717

1818
from nova import context
19+
from nova import exception
1920
from nova import objects
2021
from nova.tests.functional import integrated_helpers
2122

@@ -68,7 +69,12 @@ def wrap_reserve_block_device_name(*args, **kwargs):
6869
# twice to mimic two callers racing each other after the checks on
6970
# the api.
7071
original_bdm = original_reserve_name(*args, **kwargs)
71-
original_reserve_name(*args, **kwargs)
72+
73+
# Assert that a repeat call fails as an attachment already exists
74+
self.assertRaises(
75+
exception.InvalidVolume,
76+
original_reserve_name, *args, **kwargs)
77+
7278
return original_bdm
7379

7480
with mock.patch.object(
@@ -86,10 +92,7 @@ def wrap_reserve_block_device_name(*args, **kwargs):
8692
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
8793
ctxt, server_id)
8894

89-
# FIXME(lyarwood): This is bug #1937375, we now have 3 bdms for the
90-
# instance, the original root disk and two duplicate volume bdms for
91-
# the same volume attachment.
92-
self.assertEqual(3, len(bdms))
93-
self.assertEqual(volume_id, bdms[2].volume_id)
95+
# Assert that the correct bdms are present
96+
self.assertEqual(2, len(bdms))
9497
self.assertEqual(volume_id, bdms[1].volume_id)
9598
self.assertEqual('local', bdms[0].destination_type)

nova/tests/unit/compute/test_compute_mgr.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,32 @@ def test_reserve_block_device_name_multiattach_raises(self, _):
616616
'fake_device', 'fake_volume_id', 'fake_disk_bus',
617617
'fake_device_type', tag=None, multiattach=True)
618618

619+
@mock.patch.object(compute_utils, 'add_instance_fault_from_exc',
620+
new=mock.Mock())
621+
@mock.patch.object(objects.BlockDeviceMapping, 'create', new=mock.Mock())
622+
@mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
623+
def test_reserve_block_device_name_raises_on_duplicate(self, mock_get):
624+
instance = fake_instance.fake_instance_obj(self.context)
625+
vol_bdm = objects.BlockDeviceMapping(
626+
self.context,
627+
id=1,
628+
instance_uuid=instance.uuid,
629+
volume_id="myinstanceuuid",
630+
source_type='volume',
631+
destination_type='volume',
632+
delete_on_termination=True,
633+
connection_info=None,
634+
tag='fake-tag',
635+
device_name='/dev/fake0',
636+
attachment_id=uuids.attachment_id)
637+
mock_get.return_value = objects.BlockDeviceMappingList(
638+
objects=[vol_bdm])
639+
640+
self.assertRaises(exception.InvalidVolume,
641+
self.compute.reserve_block_device_name,
642+
self.context, instance, None, "myinstanceuuid",
643+
None, None, 'foo', False)
644+
619645
@mock.patch.object(objects.Instance, 'save')
620646
@mock.patch.object(time, 'sleep')
621647
def test_allocate_network_succeeds_after_retries(

0 commit comments

Comments
 (0)