Skip to content

Commit b38add9

Browse files
committed
[vmware] Cache images as VM templates
Upon user request, the driver can cache the image as a VM Template and reuse that to create the volume(s). This feature is useful when creating many volumes in parallel from the same image. Users can request the image cache feature when creating the volume, by passing the use_image_cache='true' as a property (metadata). The feature must be enabled per backend, for example: ``` [vmware] enable_image_cache = true ``` This will enable the image cache feature for the vmware backend. The image templates will then be stored in a folder similar to the volumes folder: OpensStack/Project (vmware_image_cache)/Volumes, where {backend}_image_cache is used as a project name. The driver will periodically delete the cached images that are expired. The expiry time can be controlled via the property `image_cache_age_seconds` set on the backend configuration. Only images smaller than the configured `image_cache_max_size_gb` will be cached. Change-Id: I6f5e481f6997a180a455b47abe525b93bcf9aa4e
1 parent d45b475 commit b38add9

File tree

2 files changed

+296
-28
lines changed

2 files changed

+296
-28
lines changed

cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ def setUp(self):
123123
vmware_random_datastore_range=None,
124124
vmware_datastores_as_pools=False,
125125
allow_pulling_images_from_url=False,
126+
enable_image_cache=False,
127+
image_cache_max_size_gb=0,
126128
)
127129

128130
self._db = mock.Mock()
@@ -287,6 +289,7 @@ def _create_volume_dict(self,
287289
'size': size,
288290
'volume_attachment': attachment,
289291
'project_id': project_id,
292+
'metadata': {},
290293
}
291294

292295
def _create_volume_obj(self,
@@ -838,6 +841,68 @@ def test_copy_image_to_volume_with_extend_backing(self, vmware_disk_type):
838841
def test_copy_image_to_volume_with_ova_container(self):
839842
self._test_copy_image_to_volume(container_format='ova')
840843

844+
@ddt.data(
845+
({'enable_image_cache': False},
846+
False),
847+
({'enable_image_cache': True, 'use_image_cache': 'N/A'},
848+
False),
849+
({'enable_image_cache': True, 'use_image_cache': 'true',
850+
'image_cache_max_size_gb': 1, 'image_size': 2 * units.Gi},
851+
False),
852+
({'enable_image_cache': True, 'use_image_cache': 'true',
853+
'image_cache_max_size_gb': 2, 'image_size': 2 * units.Gi},
854+
True)
855+
)
856+
@ddt.unpack
857+
@mock.patch.object(VMDK_DRIVER, '_do_copy_image_to_volume')
858+
@mock.patch.object(VMDK_DRIVER, 'volumeops')
859+
@mock.patch.object(VMDK_DRIVER, '_extend_backing')
860+
@mock.patch.object(VMDK_DRIVER, '_create_volume_from_cached_image')
861+
@mock.patch.object(VMDK_DRIVER, '_get_cached_image_backing')
862+
def test_copy_image_to_volume_cached(self, params, expected,
863+
mock_get_cached_backing,
864+
mock_create_from_cached,
865+
mock_extend_backing,
866+
mock_volumeops,
867+
mock_do_copy_image):
868+
self._config.enable_image_cache = (
869+
params.get('enable_image_cache', False))
870+
self._config.image_cache_max_size_gb = (
871+
params.get('image_cache_max_size_gb', 0))
872+
873+
volume = self._create_volume_dict()
874+
875+
use_image_cache = params.get('use_image_cache')
876+
if use_image_cache:
877+
volume['metadata']['use_image_cache'] = use_image_cache
878+
879+
backing = mock.sentinel.backing
880+
mock_volumeops.get_backing.return_value = backing
881+
mock_volumeops.get_disk_size.return_value = self.VOL_SIZE * units.Gi
882+
883+
mock_get_cached_backing.return_value = mock.sentinel.backing
884+
885+
image_service = mock.Mock()
886+
image_meta = self._create_image_meta(
887+
size=params.get('image_size', 1 * units.Gi))
888+
image_service.show.return_value = image_meta
889+
890+
self._driver.copy_image_to_volume(
891+
mock.sentinel.context, volume, image_service, self.IMAGE_ID)
892+
893+
if expected:
894+
mock_do_copy_image.assert_not_called()
895+
mock_get_cached_backing.assert_called_once_with(
896+
mock.sentinel.context, volume,
897+
image_service, self.IMAGE_ID, image_meta)
898+
mock_create_from_cached.assert_called_once_with(
899+
volume, backing)
900+
else:
901+
mock_get_cached_backing.assert_not_called()
902+
mock_do_copy_image.assert_called_once_with(
903+
mock.sentinel.context, volume,
904+
image_service, self.IMAGE_ID, image_meta)
905+
841906
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
842907
'_get_disk_type')
843908
@mock.patch.object(VMDK_DRIVER, '_check_disk_conversion')

0 commit comments

Comments
 (0)