diff --git a/nova/tests/unit/virt/vmwareapi/test_images.py b/nova/tests/unit/virt/vmwareapi/test_images.py index 9e3a5b1b2bc1..4a5424e7dd08 100644 --- a/nova/tests/unit/virt/vmwareapi/test_images.py +++ b/nova/tests/unit/virt/vmwareapi/test_images.py @@ -28,6 +28,7 @@ from nova import test import nova.tests.unit.image.fake from nova.virt.vmwareapi import constants from nova.virt.vmwareapi import images +from nova.virt.vmwareapi import vm_util class VMwareImagesTestCase(test.NoDBTestCase): @@ -118,12 +119,14 @@ class VMwareImagesTestCase(test.NoDBTestCase): mock.patch.object(images.IMAGE_API, 'download'), mock.patch.object(images, 'start_transfer'), mock.patch.object(images, '_build_shadow_vm_config_spec'), - mock.patch.object(session, '_call_method') + mock.patch.object(session, '_call_method'), + mock.patch.object(vm_util, 'get_vmdk_info') ) as (mock_image_api_get, mock_image_api_download, mock_start_transfer, mock_build_shadow_vm_config_spec, - mock_call_method): + mock_call_method, + mock_get_vmdk_info): image_data = {'id': 'fake-id', 'disk_format': 'vmdk', 'size': 512} @@ -169,7 +172,8 @@ class VMwareImagesTestCase(test.NoDBTestCase): fileobj=mock_read_handle) mock_start_transfer.assert_called_once_with(context, mock_read_handle, 512, write_file_handle=mock_write_handle) - + mock_get_vmdk_info.assert_called_once_with( + session, mock.sentinel.vm_ref, 'fake-vm') mock_call_method.assert_called_once_with( session.vim, "UnregisterVM", mock.sentinel.vm_ref) @@ -186,12 +190,14 @@ class VMwareImagesTestCase(test.NoDBTestCase): mock.patch.object(images.IMAGE_API, 'download'), mock.patch.object(images, 'start_transfer'), mock.patch.object(images, '_build_shadow_vm_config_spec'), - mock.patch.object(session, '_call_method') + mock.patch.object(session, '_call_method'), + mock.patch.object(vm_util, 'get_vmdk_info') ) as (mock_image_api_get, mock_image_api_download, mock_start_transfer, mock_build_shadow_vm_config_spec, - mock_call_method): + mock_call_method, + mock_get_vmdk_info): image_data = {'id': 'fake-id', 'disk_format': 'vmdk', 'size': 512} @@ -219,6 +225,8 @@ class VMwareImagesTestCase(test.NoDBTestCase): mock_call_method.assert_called_once_with( session.vim, "UnregisterVM", mock.sentinel.vm_ref) + mock_get_vmdk_info.assert_called_once_with( + session, mock.sentinel.vm_ref, 'fake-vm') def test_from_image_with_image_ref(self): raw_disk_size_in_gb = 83 diff --git a/nova/tests/unit/virt/vmwareapi/test_vmops.py b/nova/tests/unit/virt/vmwareapi/test_vmops.py index 1ec50049302b..228dad8c0cb3 100644 --- a/nova/tests/unit/virt/vmwareapi/test_vmops.py +++ b/nova/tests/unit/virt/vmwareapi/test_vmops.py @@ -2110,7 +2110,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): image_ds_loc.rel_path, cookies='Fake-CookieJar') - @mock.patch.object(images, 'fetch_image_stream_optimized') + @mock.patch.object(images, 'fetch_image_stream_optimized', + return_value=123) def test_fetch_image_as_vapp(self, mock_fetch_image): vi = self._make_vm_config_info() image_ds_loc = mock.Mock() @@ -2124,6 +2125,23 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): self._ds.name, vi.dc_info.vmFolder, self._vmops._root_resource_pool) + self.assertEqual(vi.ii.file_size, 123) + + @mock.patch.object(images, 'fetch_image_ova', return_value=123) + def test_fetch_image_as_ova(self, mock_fetch_image): + vi = self._make_vm_config_info() + image_ds_loc = mock.Mock() + image_ds_loc.parent.basename = 'fake-name' + self._vmops._fetch_image_as_ova(self._context, vi, image_ds_loc) + mock_fetch_image.assert_called_once_with( + self._context, + vi.instance, + self._session, + 'fake-name', + self._ds.name, + vi.dc_info.vmFolder, + self._vmops._root_resource_pool) + self.assertEqual(vi.ii.file_size, 123) @mock.patch.object(uuidutils, 'generate_uuid', return_value='tmp-uuid') def test_prepare_iso_image(self, mock_generate_uuid): diff --git a/nova/virt/vmwareapi/images.py b/nova/virt/vmwareapi/images.py index 524b1787dcfe..81e4609d2f47 100644 --- a/nova/virt/vmwareapi/images.py +++ b/nova/virt/vmwareapi/images.py @@ -34,6 +34,7 @@ from nova import image from nova.objects import fields from nova.virt.vmwareapi import constants from nova.virt.vmwareapi import io_util +from nova.virt.vmwareapi import vm_util # NOTE(mdbooth): We use use_linked_clone below, but don't have to import it # because nova.virt.vmwareapi.driver is imported first. In fact, it is not @@ -379,8 +380,10 @@ def fetch_image_stream_optimized(context, instance, session, vm_name, LOG.info(_LI("Downloaded image file data %(image_ref)s"), {'image_ref': instance.image_ref}, instance=instance) + vmdk = vm_util.get_vmdk_info(session, imported_vm_ref, vm_name) session._call_method(session.vim, "UnregisterVM", imported_vm_ref) LOG.info(_LI("The imported VM was unregistered"), instance=instance) + return vmdk.capacity_in_bytes def get_vmdk_name_from_ovf(xmlstr): @@ -444,11 +447,14 @@ def fetch_image_ova(context, instance, session, vm_name, ds_name, LOG.info(_LI("Downloaded OVA image file %(image_ref)s"), {'image_ref': instance.image_ref}, instance=instance) imported_vm_ref = write_handle.get_imported_vm() + vmdk = vm_util.get_vmdk_info(session, + imported_vm_ref, + vm_name) session._call_method(session.vim, "UnregisterVM", imported_vm_ref) LOG.info(_LI("The imported VM was unregistered"), instance=instance) - return + return vmdk.capacity_in_bytes raise exception.ImageUnacceptable( reason=_("Extracting vmdk from OVA failed."), image_id=image_ref) diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index 82ef0500de8e..f6620bb68147 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -419,7 +419,7 @@ class VMwareVMOps(object): 'datastore_name': vi.datastore.name}, instance=vi.instance) - images.fetch_image_stream_optimized( + image_size = images.fetch_image_stream_optimized( context, vi.instance, self._session, @@ -427,6 +427,10 @@ class VMwareVMOps(object): vi.datastore.name, vi.dc_info.vmFolder, self._root_resource_pool) + # The size of the image is different from the size of the virtual disk. + # We want to use the latter. On vSAN this is the only way to get this + # size because there is no VMDK descriptor. + vi.ii.file_size = image_size def _fetch_image_as_ova(self, context, vi, image_ds_loc): """Download root disk of an OVA image as streamOptimized.""" @@ -435,13 +439,17 @@ class VMwareVMOps(object): # of the VM use to import it with. vm_name = image_ds_loc.parent.basename - images.fetch_image_ova(context, + image_size = images.fetch_image_ova(context, vi.instance, self._session, vm_name, vi.datastore.name, vi.dc_info.vmFolder, self._root_resource_pool) + # The size of the image is different from the size of the virtual disk. + # We want to use the latter. On vSAN this is the only way to get this + # size because there is no VMDK descriptor. + vi.ii.file_size = image_size def _prepare_sparse_image(self, vi): tmp_dir_loc = vi.datastore.build_path(