Save bdm.connection_info before calling volume_api.attach_volume
There is a race in attach/detach of a volume where the volume status
goes to 'in-use' before the bdm.connection_info data is stored in the
database. Since attach is a cast, the caller can see the volume go to
'in-use' and immediately try to detach the volume and blow up in the
compute manager because bdm.connection_info isn't set stored in the
database.
This fixes the issue by saving the connection_info immediately before
calling volume_api.attach_volume (which sets the volume status to
'in-use').
Closes-Bug: #1327218
Conflicts:
nova/tests/unit/compute/test_compute.py
nova/tests/unit/virt/test_block_device.py
nova/virt/block_device.py
NOTE(mriedem): The block_device conflicts are due to using dot
notation when accessing object fields and in kilo the context is
no longer passed to bdm.save(). The test conflicts are due to moving
the test modules in kilo and passing the context on save().
Change-Id: Ib95c8f7b66aca0c4ac7b92d140cbeb5e85c2717f
(cherry picked from commit 6fb2ef96d6
)
This commit is contained in:
parent
a19a1e52f1
commit
bbf6348997
|
@ -573,7 +573,7 @@ class ComputeVolumeTestCase(BaseTestCase):
|
|||
})]
|
||||
prepped_bdm = self.compute._prep_block_device(
|
||||
self.context, self.instance, block_device_mapping)
|
||||
mock_save.assert_called_once_with(self.context)
|
||||
self.assertEqual(2, mock_save.call_count)
|
||||
volume_driver_bdm = prepped_bdm['block_device_mapping'][0]
|
||||
self.assertEqual(volume_driver_bdm['connection_info']['serial'],
|
||||
self.volume_id)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import contextlib
|
||||
|
||||
import mock
|
||||
import mox
|
||||
|
||||
from nova import block_device
|
||||
from nova import context
|
||||
|
@ -381,7 +382,11 @@ class TestDriverBlockDevice(test.NoDBTestCase):
|
|||
self.volume_api.attach(elevated_context, fake_volume['id'],
|
||||
'fake_uuid', bdm_dict['device_name'],
|
||||
mode=access_mode).AndReturn(None)
|
||||
driver_bdm._bdm_obj.save(self.context).AndReturn(None)
|
||||
# NOTE(mriedem): save() is called with the elevated context within
|
||||
# attach() and with the original context from the update_db decorator
|
||||
# so we ignore which arg it is in test.
|
||||
driver_bdm._bdm_obj.save(
|
||||
mox.IgnoreArg()).MultipleTimes().AndReturn(None)
|
||||
return instance, expected_conn_info
|
||||
|
||||
def test_volume_attach(self):
|
||||
|
|
|
@ -265,6 +265,11 @@ class DriverVolumeBlockDevice(DriverBlockDevice):
|
|||
if 'data' in connection_info:
|
||||
mode = connection_info['data'].get('access_mode', 'rw')
|
||||
if volume['attach_status'] == "detached":
|
||||
# NOTE(mriedem): save our current state so connection_info is in
|
||||
# the database before the volume status goes to 'in-use' because
|
||||
# after that we can detach and connection_info is required for
|
||||
# detach.
|
||||
self.save(context)
|
||||
volume_api.attach(context, volume_id, instance['uuid'],
|
||||
self['mount_device'], mode=mode)
|
||||
|
||||
|
|
Loading…
Reference in New Issue