libvirt: Report the virtual size of RAW disks

If642e51a4e186833349a8e30b04224a3687f5594 started to correctly report
the actual size of preallocated file based disks but missed that this
value was later used as the virtual disk size for RAW disks.

This is an issue as nova.virt.libvirt.utils.create_image creates these
disks as sparse files with a reported actual size much smaller than the
virtual size. During block based LM this then results in disks
on the destination being created with a much smaller virtual size than
the disk should have leading to errors during the transfer.

Conflicts:
      nova/virt/libvirt/driver.py

NOTE(mriedem): The conflict is due to not having change
I9616a602ee0605f7f1dc1f47b6416f01895e025b in Ocata.

Closes-Bug: #1770640
Change-Id: I464bc2b88123a012cd12213beac4b572c3c20a56
(cherry picked from commit 016986f470)
(cherry picked from commit 2dc9795a0d)
(cherry picked from commit 938c0a7453)
This commit is contained in:
Lee Yarwood 2018-05-11 15:04:48 +01:00 committed by Matt Riedemann
parent a0bcc6bda0
commit 34f4167974
2 changed files with 32 additions and 40 deletions

View File

@ -91,7 +91,6 @@ from nova.virt import fake
from nova.virt import firewall as base_firewall
from nova.virt import hardware
from nova.virt.image import model as imgmodel
from nova.virt import images
from nova.virt.libvirt import blockinfo
from nova.virt.libvirt import config as vconfig
from nova.virt.libvirt import driver as libvirt_driver
@ -4142,7 +4141,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
[mock.call(host='127.0.0.1', port=10000),
mock.call(host='127.0.0.1', port=10001)])
@mock.patch('os.path.getsize', return_value=0) # size doesn't matter
@mock.patch('nova.virt.disk.api.get_disk_size', return_value=0)
@mock.patch('nova.virt.libvirt.storage.lvm.get_volume_size',
return_value='fake-size')
def test_detach_encrypted_volumes(self, mock_get_volume_size,
@ -7824,8 +7823,10 @@ class LibvirtConnTestCase(test.NoDBTestCase):
mock_getsize = mock.Mock()
mock_getsize.return_value = "10737418240"
mock_get_virtual_size = mock.Mock()
mock_get_virtual_size.return_value = "10737418240"
return (mock_getsize, mock_lookup)
return (mock_getsize, mock_get_virtual_size, mock_lookup)
def test_is_shared_block_storage_rbd(self):
self.flags(images_type='rbd', group='libvirt')
@ -7918,7 +7919,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
{'connection_info': 'info', 'mount_device': '/dev/vda'}]}
instance = objects.Instance(**self.test_instance)
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
(mock_getsize, mock_lookup) =\
(mock_getsize, mock_get_virtual_size, mock_lookup) =\
self._is_shared_block_storage_test_create_mocks(disks)
data = objects.LibvirtLiveMigrateData(is_volume_backed=True,
is_shared_instance_path=False)
@ -7942,7 +7943,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
{'connection_info': 'info', 'mount_device': '/dev/vda'}]}
instance = objects.Instance(**self.test_instance)
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
(mock_getsize, mock_lookup) =\
(mock_getsize, mock_get_virtual_size, mock_lookup) =\
self._is_shared_block_storage_test_create_mocks(disks)
data = objects.LibvirtLiveMigrateData(is_volume_backed=True,
is_shared_instance_path=False)
@ -7950,11 +7951,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
mock.patch.object(os.path, 'getsize', mock_getsize),
mock.patch.object(libvirt_driver.disk_api,
'get_allocated_disk_size', mock_getsize),
mock.patch.object(libvirt_driver.disk_api,
'get_disk_size', mock_get_virtual_size),
mock.patch.object(host.Host, 'get_domain', mock_lookup)):
self.assertFalse(drvr._is_shared_block_storage(
instance, data,
block_device_info = bdi))
mock_getsize.assert_called_once_with('/instance/disk.local')
mock_get_virtual_size.assert_called_once_with('/instance/disk.local')
mock_lookup.assert_called_once_with(instance)
def test_is_shared_block_storage_nfs(self):
@ -10412,27 +10416,17 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.mox.StubOutWithMock(libvirt_driver.disk_api,
'get_allocated_disk_size')
self.mox.StubOutWithMock(libvirt_driver.disk_api, 'get_disk_size')
path = '/test/disk'
size = 10737418240
libvirt_driver.disk_api.get_allocated_disk_size(path).AndReturn((size))
libvirt_driver.disk_api.get_disk_size(path).AndReturn((size))
path = '/test/disk.local'
size = 3328599655
vsize = 21474836480
libvirt_driver.disk_api.get_allocated_disk_size(path).AndReturn((size))
ret = ("image: /test/disk.local\n"
"file format: qcow2\n"
"virtual size: 20G (21474836480 bytes)\n"
"disk size: 3.1G\n"
"cluster_size: 2097152\n"
"backing file: /test/dummy (actual path: /backing/file)\n")
self.mox.StubOutWithMock(os.path, "exists")
os.path.exists('/test/disk.local').AndReturn(True)
self.mox.StubOutWithMock(utils, "execute")
utils.execute('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
'/test/disk.local', prlimit = images.QEMU_IMG_LIMITS,
).AndReturn((ret, ''))
libvirt_driver.disk_api.get_disk_size(path).AndReturn((vsize))
self.mox.ReplayAll()
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
@ -10526,27 +10520,17 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.mox.StubOutWithMock(libvirt_driver.disk_api,
'get_allocated_disk_size')
self.mox.StubOutWithMock(libvirt_driver.disk_api, 'get_disk_size')
path = '/test/disk'
size = 10737418240
libvirt_driver.disk_api.get_allocated_disk_size(path).AndReturn((size))
libvirt_driver.disk_api.get_disk_size(path).AndReturn((size))
path = '/test/disk.local'
size = 3328599655
vsize = 21474836480
libvirt_driver.disk_api.get_allocated_disk_size(path).AndReturn((size))
ret = ("image: /test/disk.local\n"
"file format: qcow2\n"
"virtual size: 20G (21474836480 bytes)\n"
"disk size: 3.1G\n"
"cluster_size: 2097152\n"
"backing file: /test/dummy (actual path: /backing/file)\n")
self.mox.StubOutWithMock(os.path, "exists")
os.path.exists('/test/disk.local').AndReturn(True)
self.mox.StubOutWithMock(utils, "execute")
utils.execute('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
'/test/disk.local', prlimit = images.QEMU_IMG_LIMITS,
).AndReturn((ret, ''))
libvirt_driver.disk_api.get_disk_size(path).AndReturn((vsize))
self.mox.ReplayAll()
conn_info = {'driver_volume_type': 'fake'}
@ -10597,9 +10581,13 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.mox.StubOutWithMock(libvirt_driver.disk_api,
"get_allocated_disk_size")
self.mox.StubOutWithMock(libvirt_driver.disk_api,
"get_disk_size")
path = '/test/disk'
size = 10737418240
libvirt_driver.disk_api.get_allocated_disk_size(path).AndReturn((size))
libvirt_driver.disk_api.get_disk_size(path).AndReturn((size))
self.mox.ReplayAll()
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
@ -18071,6 +18059,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
self.assertEqual(fields.CPUMode.HOST_MODEL, vcpu_model.mode)
self.assertEqual(vcpu_model, vcpu_model_1)
@mock.patch('nova.virt.disk.api.get_disk_size', return_value=10)
@mock.patch.object(lvm, 'get_volume_size', return_value=10)
@mock.patch.object(host.Host, "get_guest")
@mock.patch.object(dmcrypt, 'delete_volume')
@ -18079,7 +18068,8 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
@mock.patch.object(objects.Instance, 'save')
def test_cleanup_lvm_encrypted(self, mock_save, mock_undefine_domain,
mock_unfilter, mock_delete_volume,
mock_get_guest, mock_get_size):
mock_get_guest, mock_get_lvm_size,
mock_get_size):
drv = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance = objects.Instance(
uuid=uuids.instance, id=1,
@ -18109,11 +18099,12 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
block_device_info=block_device_info)
mock_delete_volume.assert_called_once_with('/dev/mapper/fake-dmcrypt')
@mock.patch('nova.virt.disk.api.get_disk_size', return_value=10)
@mock.patch.object(lvm, 'get_volume_size', return_value=10)
@mock.patch.object(host.Host, "get_guest")
@mock.patch.object(dmcrypt, 'delete_volume')
def _test_cleanup_lvm(self, mock_delete_volume, mock_get_guest, mock_size,
encrypted=False):
def _test_cleanup_lvm(self, mock_delete_volume, mock_get_guest,
mock_lvm_size, mock_get_size, encrypted=False):
drv = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance = objects.Instance(

View File

@ -7194,15 +7194,16 @@ class LibvirtDriver(driver.ComputeDriver):
{'path': path, 'target': target})
continue
# NOTE(lyarwood): Always fetch the virtual size for all disk types.
virt_size = disk_api.get_disk_size(path)
disk_type = driver_nodes[cnt].get('type')
if disk_type in ("qcow2", "ploop"):
backing_file = libvirt_utils.get_disk_backing_file(path)
virt_size = disk_api.get_disk_size(path)
over_commit_size = int(virt_size) - dk_size
else:
backing_file = ""
virt_size = dk_size
over_commit_size = 0
disk_info.append({'type': disk_type,