Make Nova better at keeping track of volume sizes in BDM

Up until now we would really only care about the size of ephemeral and
swap BDM entries'volume_size' being set properly, while we would rely on
Cinder to be the canonical source of truth for the size information of
snapshots and volumes.

There is some overhead in querying Cinder every time this basic
information is needed, and we do have a volume_size field in all BDM
entries already, so let's keep it up to date.

Change-Id: I9ffbb6cf40c1012f774a382cf1dcceba64637e6d
Related-bug: #1370177
This commit is contained in:
Nikola Dipanov 2015-06-05 20:44:04 +01:00
parent 817946b90f
commit d13012da9d
4 changed files with 30 additions and 7 deletions

View File

@ -1247,6 +1247,7 @@ class API(base.Base):
self.volume_api.check_attach(context,
volume,
instance=instance)
bdm.volume_size = volume.get('size')
except (exception.CinderConnectionFailed,
exception.InvalidVolume):
raise
@ -1254,7 +1255,8 @@ class API(base.Base):
raise exception.InvalidBDMVolume(id=volume_id)
elif snapshot_id is not None:
try:
self.volume_api.get_snapshot(context, snapshot_id)
snap = self.volume_api.get_snapshot(context, snapshot_id)
bdm.volume_size = bdm.volume_size or snap.get('size')
except exception.CinderConnectionFailed:
raise
except Exception:

View File

@ -365,7 +365,7 @@ class ComputeVolumeTestCase(BaseTestCase):
self.context, objects.Instance(),
fake_instance.fake_db_instance())
self.stubs.Set(self.compute.volume_api, 'get', lambda *a, **kw:
{'id': self.volume_id,
{'id': self.volume_id, 'size': 4,
'attach_status': 'detached'})
self.stubs.Set(self.compute.driver, 'get_volume_connector',
lambda *a, **kw: None)
@ -530,6 +530,7 @@ class ComputeVolumeTestCase(BaseTestCase):
'snapshot_id': None,
'volume_id': self.volume_id,
'device_name': '/dev/vdb',
'volume_size': 55,
'delete_on_termination': False,
})]
prepped_bdm = self.compute._prep_block_device(
@ -736,6 +737,7 @@ class ComputeVolumeTestCase(BaseTestCase):
no_device=False,
disk_bus='foo',
device_type='disk',
volume_size=1,
volume_id=1)
host_volume_bdms = {'id': 1, 'device_name': '/dev/vdb',
'connection_info': '{}', 'instance_uuid': instance['uuid'],
@ -867,7 +869,7 @@ class ComputeVolumeTestCase(BaseTestCase):
def test_validate_bdm(self):
def fake_get(self, context, res_id):
return {'id': res_id}
return {'id': res_id, 'size': 4}
def fake_check_attach(*args, **kwargs):
pass
@ -901,7 +903,6 @@ class ComputeVolumeTestCase(BaseTestCase):
'volume_id': volume_id,
'guest_format': None,
'boot_index': 1,
'volume_size': 6
}, anon=True),
fake_block_device.FakeDbBlockDeviceDict({
'device_name': '/dev/sda2',
@ -910,8 +911,8 @@ class ComputeVolumeTestCase(BaseTestCase):
'snapshot_id': snapshot_id,
'device_type': 'disk',
'guest_format': None,
'volume_size': 6,
'boot_index': 0,
'volume_size': 4
}, anon=True),
fake_block_device.FakeDbBlockDeviceDict({
'device_name': '/dev/sda3',
@ -929,6 +930,8 @@ class ComputeVolumeTestCase(BaseTestCase):
# Make sure it passes at first
self.compute_api._validate_bdm(self.context, instance,
instance_type, mappings)
self.assertEqual(4, mappings[1].volume_size)
self.assertEqual(6, mappings[2].volume_size)
# Boot sequence
mappings[2].boot_index = 2
@ -950,7 +953,6 @@ class ComputeVolumeTestCase(BaseTestCase):
'source_type': 'blank',
'destination_type': 'local',
'device_type': 'disk',
'volume_id': volume_id,
'guest_format': None,
'boot_index': -1,
'volume_size': 1
@ -960,7 +962,6 @@ class ComputeVolumeTestCase(BaseTestCase):
'source_type': 'blank',
'destination_type': 'local',
'device_type': 'disk',
'volume_id': volume_id,
'guest_format': None,
'boot_index': -1,
'volume_size': 1
@ -4496,6 +4497,7 @@ class ComputeTestCase(BaseTestCase):
volume = {'instance_uuid': None,
'device_name': None,
'id': volume_id,
'size': 200,
'attach_status': 'detached'}
bdm = objects.BlockDeviceMapping(
**{'context': self.context,

View File

@ -465,6 +465,23 @@ class TestDriverBlockDevice(test.NoDBTestCase):
self.assertThat(test_bdm['connection_info'],
matchers.DictMatches(expected_conn_info))
def test_volume_attach_update_size(self):
test_bdm = self.driver_classes['volume'](self.volume_bdm)
test_bdm.volume_size = None
volume = {'id': 'fake-volume-id-1',
'attach_status': 'detached',
'size': 42}
instance, expected_conn_info = self._test_volume_attach(
test_bdm, self.volume_bdm, volume)
self.mox.ReplayAll()
test_bdm.attach(self.context, instance,
self.volume_api, self.virt_driver)
self.assertEqual(expected_conn_info, test_bdm['connection_info'])
self.assertEqual(42, test_bdm.volume_size)
def test_volume_attach_check_attach_fails(self):
test_bdm = self.driver_classes['volume'](
self.volume_bdm)

View File

@ -264,6 +264,8 @@ class DriverVolumeBlockDevice(DriverBlockDevice):
volume_api.terminate_connection(context, volume_id,
connector)
self['connection_info'] = connection_info
if self.volume_size is None:
self.volume_size = volume.get('size')
mode = 'rw'
if 'data' in connection_info: