VMware: Take the volume size from the user input

When we create a volume from an image or a snapshot, we need to
take the size of the volume from the user input and validate whether
the size is appropriate instead of taking the image size as the
volume size directly.

Change-Id: If09933d8ffa989c4dacc0860c19ea332bc21092a
Closes-Bug: #1237557
This commit is contained in:
Vincent Hou 2013-12-04 03:51:20 -05:00
parent 7c2d6fed70
commit 015555acb7
4 changed files with 589 additions and 239 deletions

View File

@ -140,6 +140,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
TASK_POLL_INTERVAL = 5.0
IMG_TX_TIMEOUT = 10
MAX_OBJECTS = 100
VMDK_DRIVER = vmdk.VMwareEsxVmdkDriver
def setUp(self):
super(VMwareEsxVmdkDriverTestCase, self).setUp()
@ -682,34 +683,6 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
driver._verify_volume_creation.assert_called_once_with(volume)
mock_vops.get_backing.assert_called_once_with('src_snapshot_name')
def test_clone_backing_by_copying(self):
"""Test _clone_backing_by_copying."""
m = self.mox
m.StubOutWithMock(self._driver.__class__, 'volumeops')
self._driver.volumeops = self._volumeops
volume = FakeObject()
src_vmdk_path = "[datastore] src_vm/src_vm.vmdk"
new_vmdk_path = "[datastore] dest_vm/dest_vm.vmdk"
backing = FakeMor('VirtualMachine', 'my_back')
m.StubOutWithMock(self._driver, '_create_backing_in_inventory')
mux = self._driver._create_backing_in_inventory(volume)
mux.AndReturn(backing)
m.StubOutWithMock(self._volumeops, 'get_vmdk_path')
self._volumeops.get_vmdk_path(backing).AndReturn(new_vmdk_path)
m.StubOutWithMock(self._volumeops, 'get_dc')
datacenter = FakeMor('Datacenter', 'my_dc')
self._volumeops.get_dc(backing).AndReturn(datacenter)
m.StubOutWithMock(self._volumeops, 'delete_vmdk_file')
self._volumeops.delete_vmdk_file(new_vmdk_path, datacenter)
m.StubOutWithMock(self._volumeops, 'copy_vmdk_file')
self._volumeops.copy_vmdk_file(datacenter, src_vmdk_path,
new_vmdk_path)
m.ReplayAll()
self._driver._clone_backing_by_copying(volume, src_vmdk_path)
m.UnsetStubs()
m.VerifyAll()
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareEsxVmdkDriver.'
'volumeops', new_callable=mock.PropertyMock)
def test_create_cloned_volume_with_backing(self, mock_vops):
@ -717,13 +690,14 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
mock_vops = mock_vops.return_value
driver = self._driver
volume = mock.sentinel.volume
src_vref = {'name': 'src_snapshot_name'}
fake_size = 1
src_vref = {'name': 'src_snapshot_name', 'size': fake_size}
backing = mock.sentinel.backing
driver._verify_volume_creation = mock.MagicMock()
mock_vops.get_backing.return_value = backing
src_vmdk_path = "[datastore] src_vm/src_vm.vmdk"
mock_vops.get_vmdk_path.return_value = src_vmdk_path
driver._clone_backing_by_copying = mock.MagicMock()
src_vmdk = "[datastore] src_vm/src_vm.vmdk"
mock_vops.get_vmdk_path.return_value = src_vmdk
driver._create_backing_by_copying = mock.MagicMock()
# invoke the create_volume_from_snapshot api
driver.create_cloned_volume(volume, src_vref)
@ -732,8 +706,57 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
driver._verify_volume_creation.assert_called_once_with(volume)
mock_vops.get_backing.assert_called_once_with('src_snapshot_name')
mock_vops.get_vmdk_path.assert_called_once_with(backing)
driver._clone_backing_by_copying.assert_called_once_with(volume,
src_vmdk_path)
driver._create_backing_by_copying.assert_called_once_with(volume,
src_vmdk,
fake_size)
@mock.patch.object(VMDK_DRIVER, '_extend_volumeops_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_create_backing_in_inventory')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_create_backing_by_copying(self, volumeops, create_backing,
_extend_virtual_disk):
self._test_create_backing_by_copying(volumeops, create_backing,
_extend_virtual_disk)
def _test_create_backing_by_copying(self, volumeops, create_backing,
_extend_virtual_disk):
"""Test _create_backing_by_copying."""
fake_volume = {'size': 2, 'name': 'fake_volume-0000000000001'}
fake_size = 1
fake_src_vmdk_path = "[datastore] src_vm/src_vm.vmdk"
fake_backing = mock.sentinel.backing
fake_vmdk_path = mock.sentinel.path
#"[datastore] dest_vm/dest_vm.vmdk"
fake_dc = mock.sentinel.datacenter
create_backing.return_value = fake_backing
volumeops.get_vmdk_path.return_value = fake_vmdk_path
volumeops.get_dc.return_value = fake_dc
# Test with fake_volume['size'] greater than fake_size
self._driver._create_backing_by_copying(fake_volume,
fake_src_vmdk_path,
fake_size)
create_backing.assert_called_once_with(fake_volume)
volumeops.get_vmdk_path.assert_called_once_with(fake_backing)
volumeops.get_dc.assert_called_once_with(fake_backing)
volumeops.delete_vmdk_file.assert_called_once_with(fake_vmdk_path,
fake_dc)
volumeops.copy_vmdk_file.assert_called_once_with(fake_dc,
fake_src_vmdk_path,
fake_vmdk_path)
_extend_virtual_disk.assert_called_once_with(fake_volume['size'],
fake_vmdk_path,
fake_dc)
# Reset all the mocks and test with fake_volume['size']
# not greater than fake_size
_extend_virtual_disk.reset_mock()
fake_size = 2
self._driver._create_backing_by_copying(fake_volume,
fake_src_vmdk_path,
fake_size)
self.assertFalse(_extend_virtual_disk.called)
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareEsxVmdkDriver.'
'volumeops', new_callable=mock.PropertyMock)
@ -782,15 +805,17 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
mock_vops = mock_vops.return_value
driver = self._driver
volume = {'volume_type_id': None, 'name': 'mock_vol'}
snapshot = {'volume_name': 'mock_vol', 'name': 'mock_snap'}
snapshot = {'volume_name': 'mock_vol', 'name': 'mock_snap',
'volume_size': 1}
fake_size = snapshot['volume_size']
backing = mock.sentinel.backing
snap_moref = mock.sentinel.snap_moref
driver._verify_volume_creation = mock.MagicMock()
mock_vops.get_backing.return_value = backing
mock_vops.get_snapshot.return_value = snap_moref
src_vmdk_path = "[datastore] src_vm/src_vm-001.vmdk"
mock_vops.get_vmdk_path.return_value = src_vmdk_path
driver._clone_backing_by_copying = mock.MagicMock()
src_vmdk = "[datastore] src_vm/src_vm-001.vmdk"
mock_vops.get_vmdk_path.return_value = src_vmdk
driver._create_backing_by_copying = mock.MagicMock()
# invoke the create_volume_from_snapshot api
driver.create_volume_from_snapshot(volume, snapshot)
@ -801,161 +826,228 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
mock_vops.get_snapshot.assert_called_once_with(backing,
'mock_snap')
mock_vops.get_vmdk_path.assert_called_once_with(snap_moref)
driver._clone_backing_by_copying.assert_called_once_with(volume,
src_vmdk_path)
driver._create_backing_by_copying.assert_called_once_with(volume,
src_vmdk,
fake_size)
def test_copy_image_to_volume_non_vmdk(self):
"""Test copy_image_to_volume for a non-vmdk disk format."""
m = self.mox
image_id = 'image-123456789'
image_meta = FakeObject()
image_meta['disk_format'] = 'novmdk'
image_service = m.CreateMock(glance.GlanceImageService)
image_service.show(mox.IgnoreArg(), image_id).AndReturn(image_meta)
m.ReplayAll()
fake_context = mock.sentinel.context
fake_image_id = 'image-123456789'
fake_image_meta = {'disk_format': 'novmdk'}
image_service = mock.Mock()
image_service.show.return_value = fake_image_meta
fake_volume = {'name': 'fake_name', 'size': 1}
self.assertRaises(exception.ImageUnacceptable,
self._driver.copy_image_to_volume,
mox.IgnoreArg(), mox.IgnoreArg(),
image_service, image_id)
m.UnsetStubs()
m.VerifyAll()
fake_context, fake_volume,
image_service, fake_image_id)
def test_copy_image_to_volume_vmdk(self):
@mock.patch.object(vmware_images, 'fetch_flat_image')
@mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_get_ds_name_flat_vmdk_path')
@mock.patch.object(VMDK_DRIVER, '_create_backing_in_inventory')
@mock.patch.object(VMDK_DRIVER, 'session')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_copy_image_to_volume_vmdk(self, volume_ops, session,
_create_backing_in_inventory,
_get_ds_name_flat_vmdk_path,
_extend_vmdk_virtual_disk,
fetch_flat_image):
"""Test copy_image_to_volume with an acceptable vmdk disk format."""
m = self.mox
m.StubOutWithMock(self._driver.__class__, 'session')
self._driver.session = self._session
m.StubOutWithMock(api.VMwareAPISession, 'vim')
self._session.vim = self._vim
m.StubOutWithMock(self._driver.__class__, 'volumeops')
self._driver.volumeops = self._volumeops
self._test_copy_image_to_volume_vmdk(volume_ops, session,
_create_backing_in_inventory,
_get_ds_name_flat_vmdk_path,
_extend_vmdk_virtual_disk,
fetch_flat_image)
image_id = 'image-id'
image_meta = FakeObject()
image_meta['disk_format'] = 'vmdk'
image_meta['size'] = 1 * units.MiB
image_meta['properties'] = {'vmware_disktype': 'preallocated'}
image_service = m.CreateMock(glance.GlanceImageService)
image_service.show(mox.IgnoreArg(), image_id).AndReturn(image_meta)
volume = FakeObject()
vol_name = 'volume name'
volume['name'] = vol_name
backing = FakeMor('VirtualMachine', 'my_vm')
m.StubOutWithMock(self._driver, '_create_backing_in_inventory')
self._driver._create_backing_in_inventory(volume).AndReturn(backing)
datastore_name = 'datastore1'
def _test_copy_image_to_volume_vmdk(self, volume_ops, session,
_create_backing_in_inventory,
_get_ds_name_flat_vmdk_path,
_extend_vmdk_virtual_disk,
fetch_flat_image):
cookies = session.vim.client.options.transport.cookiejar
fake_context = mock.sentinel.context
fake_image_id = 'image-id'
fake_image_meta = {'disk_format': 'vmdk',
'size': 2 * units.GiB,
'properties': {'vmware_disktype': 'preallocated'}}
image_service = mock.Mock(glance.GlanceImageService)
fake_size = 3
fake_volume = {'name': 'volume_name', 'size': fake_size}
fake_backing = mock.sentinel.backing
fake_datastore_name = 'datastore1'
flat_vmdk_path = 'myvolumes/myvm-flat.vmdk'
m.StubOutWithMock(self._driver, '_get_ds_name_flat_vmdk_path')
moxed = self._driver._get_ds_name_flat_vmdk_path(mox.IgnoreArg(),
vol_name)
moxed.AndReturn((datastore_name, flat_vmdk_path))
host = FakeMor('Host', 'my_host')
m.StubOutWithMock(self._volumeops, 'get_host')
self._volumeops.get_host(backing).AndReturn(host)
datacenter = FakeMor('Datacenter', 'my_datacenter')
m.StubOutWithMock(self._volumeops, 'get_dc')
self._volumeops.get_dc(host).AndReturn(datacenter)
datacenter_name = 'my-datacenter'
m.StubOutWithMock(self._volumeops, 'get_entity_name')
self._volumeops.get_entity_name(datacenter).AndReturn(datacenter_name)
flat_path = '[%s] %s' % (datastore_name, flat_vmdk_path)
m.StubOutWithMock(self._volumeops, 'delete_file')
self._volumeops.delete_file(flat_path, datacenter)
client = FakeObject()
client.options = FakeObject()
client.options.transport = FakeObject()
cookies = FakeObject()
client.options.transport.cookiejar = cookies
m.StubOutWithMock(self._vim.__class__, 'client')
self._vim.client = client
m.StubOutWithMock(vmware_images, 'fetch_flat_image')
fake_host = mock.sentinel.host
fake_datacenter = mock.sentinel.datacenter
fake_datacenter_name = mock.sentinel.datacenter_name
timeout = self._config.vmware_image_transfer_timeout_secs
vmware_images.fetch_flat_image(mox.IgnoreArg(), timeout, image_service,
image_id, image_size=image_meta['size'],
host=self.IP,
data_center_name=datacenter_name,
datastore_name=datastore_name,
cookies=cookies,
file_path=flat_vmdk_path)
m.ReplayAll()
self._driver.copy_image_to_volume(mox.IgnoreArg(), volume,
image_service, image_id)
m.UnsetStubs()
m.VerifyAll()
image_service.show.return_value = fake_image_meta
_create_backing_in_inventory.return_value = fake_backing
_get_ds_name_flat_vmdk_path.return_value = (fake_datastore_name,
flat_vmdk_path)
volume_ops.get_host.return_value = fake_host
volume_ops.get_dc.return_value = fake_datacenter
volume_ops.get_entity_name.return_value = fake_datacenter_name
def test_copy_image_to_volume_stream_optimized(self):
# If the volume size is greater than the image size,
# _extend_vmdk_virtual_disk will be called.
self._driver.copy_image_to_volume(fake_context, fake_volume,
image_service, fake_image_id)
image_service.show.assert_called_with(fake_context, fake_image_id)
_create_backing_in_inventory.assert_called_with(fake_volume)
_get_ds_name_flat_vmdk_path.assert_called_with(fake_backing,
fake_volume['name'])
volume_ops.get_host.assert_called_with(fake_backing)
volume_ops.get_dc.assert_called_with(fake_host)
volume_ops.get_entity_name.assert_called_with(fake_datacenter)
fetch_flat_image.assert_called_with(fake_context, timeout,
image_service,
fake_image_id,
image_size=fake_image_meta['size'],
host=self.IP,
data_center_name=
fake_datacenter_name,
datastore_name=fake_datastore_name,
cookies=cookies,
file_path=flat_vmdk_path)
_extend_vmdk_virtual_disk.assert_called_with(fake_volume['name'],
fake_size)
self.assertFalse(volume_ops.delete_backing.called)
# If the volume size is not greater then than the image size,
# _extend_vmdk_virtual_disk will not be called.
_extend_vmdk_virtual_disk.reset_mock()
fake_size = 2
fake_volume['size'] = fake_size
self._driver.copy_image_to_volume(fake_context, fake_volume,
image_service, fake_image_id)
self.assertFalse(_extend_vmdk_virtual_disk.called)
self.assertFalse(volume_ops.delete_backing.called)
# If fetch_flat_image raises an Exception, delete_backing
# will be called.
fetch_flat_image.side_effect = exception.CinderException
self.assertRaises(exception.CinderException,
self._driver.copy_image_to_volume,
fake_context, fake_volume,
image_service, fake_image_id)
volume_ops.delete_backing.assert_called_with(fake_backing)
@mock.patch.object(vmware_images, 'fetch_stream_optimized_image')
@mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume')
@mock.patch.object(VMDK_DRIVER, 'session')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_copy_image_to_volume_stream_optimized(self, volumeops,
session,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image):
"""Test copy_image_to_volume.
Test with an acceptable vmdk disk format and streamOptimized disk type.
"""
m = self.mox
m.StubOutWithMock(self._driver.__class__, 'session')
self._driver.session = self._session
m.StubOutWithMock(api.VMwareAPISession, 'vim')
self._session.vim = self._vim
m.StubOutWithMock(self._driver.__class__, 'volumeops')
self._driver.volumeops = self._volumeops
self._test_copy_image_to_volume_stream_optimized(volumeops,
session,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image)
image_id = 'image-id'
def _test_copy_image_to_volume_stream_optimized(self, volumeops,
session,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image):
fake_context = mock.Mock()
fake_backing = mock.sentinel.backing
fake_image_id = 'image-id'
size = 5 * units.GiB
size_kb = float(size) / units.KiB
size_gb = float(size) / units.GiB
# image_service.show call
image_meta = FakeObject()
image_meta['disk_format'] = 'vmdk'
image_meta['size'] = size
image_meta['properties'] = {'vmware_disktype': 'streamOptimized'}
image_service = m.CreateMock(glance.GlanceImageService)
image_service.show(mox.IgnoreArg(), image_id).AndReturn(image_meta)
# _select_ds_for_volume call
(host, rp, folder, summary) = (FakeObject(), FakeObject(),
FakeObject(), FakeObject())
summary.name = "datastore-1"
vol_name = 'volume name'
volume = FakeObject()
volume['name'] = vol_name
volume['size'] = size_gb
volume['volume_type_id'] = None # _get_disk_type will return 'thin'
disk_type = 'thin'
m.StubOutWithMock(self._driver, '_select_ds_for_volume')
self._driver._select_ds_for_volume(volume).AndReturn((host, rp,
folder,
summary))
# _get_create_spec call
m.StubOutWithMock(self._volumeops, '_get_create_spec')
self._volumeops._get_create_spec(vol_name, 0, disk_type,
summary.name)
# vim.client.factory.create call
class FakeFactory(object):
def create(self, name):
return mox.MockAnything()
client = FakeObject()
client.factory = FakeFactory()
m.StubOutWithMock(self._vim.__class__, 'client')
self._vim.client = client
# fetch_stream_optimized_image call
fake_volume_size = 1 + size_gb
fake_image_meta = {'disk_format': 'vmdk', 'size': size,
'properties': {'vmware_disktype':
'streamOptimized'}}
image_service = mock.Mock(glance.GlanceImageService)
fake_host = mock.sentinel.host
fake_rp = mock.sentinel.rp
fake_folder = mock.sentinel.folder
fake_summary = mock.sentinel.summary
fake_summary.name = "datastore-1"
fake_vm_create_spec = mock.sentinel.spec
fake_disk_type = 'thin'
vol_name = 'fake_volume name'
fake_volume = {'name': vol_name, 'size': fake_volume_size,
'volume_type_id': None}
cf = session.vim.client.factory
vm_import_spec = cf.create('ns0:VirtualMachineImportSpec')
vm_import_spec.configSpec = fake_vm_create_spec
timeout = self._config.vmware_image_transfer_timeout_secs
m.StubOutWithMock(vmware_images, 'fetch_stream_optimized_image')
vmware_images.fetch_stream_optimized_image(mox.IgnoreArg(), timeout,
image_service, image_id,
session=self._session,
host=self.IP,
resource_pool=rp,
vm_folder=folder,
vm_create_spec=
mox.IgnoreArg(),
image_size=size)
m.ReplayAll()
self._driver.copy_image_to_volume(mox.IgnoreArg(), volume,
image_service, image_id)
m.UnsetStubs()
m.VerifyAll()
image_service.show.return_value = fake_image_meta
volumeops._get_create_spec.return_value = fake_vm_create_spec
volumeops.get_backing.return_value = fake_backing
# If _select_ds_for_volume raises an exception, _get_create_spec
# will not be called.
_select_ds_for_volume.side_effect = error_util.VimException('Error')
self.assertRaises(error_util.VimException,
self._driver.copy_image_to_volume,
fake_context, fake_volume,
image_service, fake_image_id)
self.assertFalse(volumeops._get_create_spec.called)
# If the volume size is greater then than the image size,
# _extend_vmdk_virtual_disk will be called.
_select_ds_for_volume.side_effect = None
_select_ds_for_volume.return_value = (fake_host, fake_rp,
fake_folder, fake_summary)
self._driver.copy_image_to_volume(fake_context, fake_volume,
image_service, fake_image_id)
image_service.show.assert_called_with(fake_context, fake_image_id)
_select_ds_for_volume.assert_called_with(fake_volume)
volumeops._get_create_spec.assert_called_with(fake_volume['name'],
0,
fake_disk_type,
fake_summary.name)
self.assertTrue(fetch_optimized_image.called)
fetch_optimized_image.assert_called_with(fake_context, timeout,
image_service,
fake_image_id,
session=session,
host=self.IP,
resource_pool=fake_rp,
vm_folder=fake_folder,
vm_create_spec=
vm_import_spec,
image_size=size)
_extend_virtual_disk.assert_called_with(fake_volume['name'],
fake_volume_size)
self.assertFalse(volumeops.get_backing.called)
self.assertFalse(volumeops.delete_backing.called)
# If the volume size is not greater then than the image size,
# _extend_vmdk_virtual_disk will not be called.
fake_volume_size = size_gb
fake_volume['size'] = fake_volume_size
_extend_virtual_disk.reset_mock()
self._driver.copy_image_to_volume(fake_context, fake_volume,
image_service, fake_image_id)
self.assertFalse(_extend_virtual_disk.called)
self.assertFalse(volumeops.get_backing.called)
self.assertFalse(volumeops.delete_backing.called)
# If fetch_stream_optimized_image raises an exception,
# get_backing and delete_backing will be called.
fetch_optimized_image.side_effect = exception.CinderException
self.assertRaises(exception.CinderException,
self._driver.copy_image_to_volume,
fake_context, fake_volume,
image_service, fake_image_id)
volumeops.get_backing.assert_called_with(fake_volume['name'])
volumeops.delete_backing.assert_called_with(fake_backing)
def test_copy_volume_to_image_non_vmdk(self):
"""Test copy_volume_to_image for a non-vmdk disk format."""
@ -1075,9 +1167,51 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
m.UnsetStubs()
m.VerifyAll()
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_extend_vmdk_virtual_disk(self, volume_ops):
"""Test vmdk._extend_vmdk_virtual_disk."""
self._test_extend_vmdk_virtual_disk(volume_ops)
def _test_extend_vmdk_virtual_disk(self, volume_ops):
fake_backing = mock.sentinel.backing
fake_vmdk_path = "[datastore] dest_vm/dest_vm.vmdk"
fake_dc = mock.sentinel.datacenter
fake_name = 'fake_name'
fake_size = 7
# If the backing is None, get_vmdk_path and get_dc
# will not be called
volume_ops.get_backing.return_value = None
volume_ops.get_vmdk_path.return_value = fake_vmdk_path
volume_ops.get_dc.return_value = fake_dc
self._driver._extend_vmdk_virtual_disk(fake_name, fake_size)
volume_ops.get_backing.assert_called_once_with(fake_name)
self.assertFalse(volume_ops.get_vmdk_path.called)
self.assertFalse(volume_ops.get_dc.called)
self.assertFalse(volume_ops.extend_virtual_disk.called)
# Reset the mock and set the backing with a fake,
# all the mocks should be called.
volume_ops.get_backing.reset_mock()
volume_ops.get_backing.return_value = fake_backing
self._driver._extend_vmdk_virtual_disk(fake_name, fake_size)
volume_ops.get_vmdk_path.assert_called_once_with(fake_backing)
volume_ops.get_dc.assert_called_once_with(fake_backing)
volume_ops.extend_virtual_disk.assert_called_once_with(fake_size,
fake_vmdk_path,
fake_dc)
# Test the exceptional case for extend_virtual_disk
volume_ops.extend_virtual_disk.side_effect = error_util.VimException(
'VimException raised.')
self.assertRaises(error_util.VimException,
self._driver._extend_vmdk_virtual_disk,
fake_name, fake_size)
class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
"""Test class for VMwareVcVmdkDriver."""
VMDK_DRIVER = vmdk.VMwareVcVmdkDriver
DEFAULT_PROFILE = 'fakeProfile'
DEFAULT_VC_VERSION = '5.5'
@ -1162,6 +1296,14 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
self.assertFalse(self._driver._storage_policy_enabled)
self.assertFalse(vol_ops.retrieve_profile_id.called)
@mock.patch.object(VMDK_DRIVER, '_extend_volumeops_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_create_backing_in_inventory')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_create_backing_by_copying(self, volumeops, create_backing,
extend_virtual_disk):
self._test_create_backing_by_copying(volumeops, create_backing,
extend_virtual_disk)
def test_init_conn_with_instance_and_backing(self):
"""Test initialize_connection with instance and backing."""
m = self.mox
@ -1256,50 +1398,85 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
m.UnsetStubs()
m.VerifyAll()
def test_clone_backing_linked(self):
@mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_clone_backing_linked(self, volume_ops, _extend_vmdk_virtual_disk):
"""Test _clone_backing with clone type - linked."""
m = self.mox
m.StubOutWithMock(self._driver.__class__, 'volumeops')
self._driver.volumeops = self._volumeops
m.StubOutWithMock(self._volumeops, 'clone_backing')
volume = FakeObject()
volume['name'] = 'volume_name'
self._volumeops.clone_backing(volume['name'], mox.IgnoreArg(),
mox.IgnoreArg(),
volumeops.LINKED_CLONE_TYPE,
mox.IgnoreArg())
fake_size = 3
fake_volume = {'volume_type_id': None, 'name': 'fake_name',
'size': fake_size}
fake_snapshot = {'volume_name': 'volume_name',
'name': 'snapshot_name',
'volume_size': 2}
fake_type = volumeops.LINKED_CLONE_TYPE
fake_backing = mock.sentinel.backing
self._driver._clone_backing(fake_volume, fake_backing, fake_snapshot,
volumeops.LINKED_CLONE_TYPE,
fake_snapshot['volume_size'])
volume_ops.clone_backing.assert_called_with(fake_volume['name'],
fake_backing,
fake_snapshot,
fake_type,
None)
# If the volume size is greater than the original snapshot size,
# _extend_vmdk_virtual_disk will be called.
_extend_vmdk_virtual_disk.assert_called_with(fake_volume['name'],
fake_volume['size'])
m.ReplayAll()
self._driver._clone_backing(volume, mox.IgnoreArg(), mox.IgnoreArg(),
volumeops.LINKED_CLONE_TYPE)
m.UnsetStubs()
m.VerifyAll()
# If the volume size is not greater than the original snapshot size,
# _extend_vmdk_virtual_disk will not be called.
fake_size = 2
fake_volume['size'] = fake_size
_extend_vmdk_virtual_disk.reset_mock()
self._driver._clone_backing(fake_volume, fake_backing, fake_snapshot,
volumeops.LINKED_CLONE_TYPE,
fake_snapshot['volume_size'])
self.assertFalse(_extend_vmdk_virtual_disk.called)
def test_clone_backing_full(self):
@mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_clone_backing_full(self, volume_ops, _select_ds_for_volume,
_extend_vmdk_virtual_disk):
"""Test _clone_backing with clone type - full."""
m = self.mox
m.StubOutWithMock(self._driver.__class__, 'volumeops')
self._driver.volumeops = self._volumeops
backing = FakeMor('VirtualMachine', 'my_vm')
datastore = FakeMor('Datastore', 'my_ds')
m.StubOutWithMock(self._driver, '_select_ds_for_volume')
volume = FakeObject()
volume['name'] = 'volume_name'
volume['size'] = 1
summary = FakeDatastoreSummary(1, 1, datastore=datastore)
self._driver._select_ds_for_volume(volume).AndReturn((_, _, _,
summary))
m.StubOutWithMock(self._volumeops, 'clone_backing')
self._volumeops.clone_backing(volume['name'], backing,
mox.IgnoreArg(),
volumeops.FULL_CLONE_TYPE,
datastore)
fake_host = mock.sentinel.host
fake_backing = mock.sentinel.backing
fake_folder = mock.sentinel.folder
fake_datastore = mock.sentinel.datastore
fake_resource_pool = mock.sentinel.resourcePool
fake_summary = mock.Mock(spec=object)
fake_summary.datastore = fake_datastore
fake_size = 3
fake_volume = {'volume_type_id': None, 'name': 'fake_name',
'size': fake_size}
fake_snapshot = {'volume_name': 'volume_name', 'name': 'snapshot_name',
'volume_size': 2}
_select_ds_for_volume.return_value = (fake_host,
fake_resource_pool,
fake_folder, fake_summary)
self._driver._clone_backing(fake_volume, fake_backing, fake_snapshot,
volumeops.FULL_CLONE_TYPE,
fake_snapshot['volume_size'])
_select_ds_for_volume.assert_called_with(fake_volume)
volume_ops.clone_backing.assert_called_with(fake_volume['name'],
fake_backing,
fake_snapshot,
volumeops.FULL_CLONE_TYPE,
fake_datastore)
# If the volume size is greater than the original snapshot size,
# _extend_vmdk_virtual_disk will be called.
_extend_vmdk_virtual_disk.assert_called_with(fake_volume['name'],
fake_volume['size'])
m.ReplayAll()
self._driver._clone_backing(volume, backing, mox.IgnoreArg(),
volumeops.FULL_CLONE_TYPE)
m.UnsetStubs()
m.VerifyAll()
# If the volume size is not greater than the original snapshot size,
# _extend_vmdk_virtual_disk will not be called.
fake_size = 2
fake_volume['size'] = fake_size
_extend_vmdk_virtual_disk.reset_mock()
self._driver._clone_backing(fake_volume, fake_backing, fake_snapshot,
volumeops.FULL_CLONE_TYPE,
fake_snapshot['volume_size'])
self.assertFalse(_extend_vmdk_virtual_disk.called)
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'volumeops', new_callable=mock.PropertyMock)
@ -1348,7 +1525,8 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
mock_vops = mock_vops.return_value
driver = self._driver
volume = {'volume_type_id': None, 'name': 'mock_vol'}
snapshot = {'volume_name': 'mock_vol', 'name': 'mock_snap'}
snapshot = {'volume_name': 'mock_vol', 'name': 'mock_snap',
'volume_size': 2}
backing = mock.sentinel.backing
snap_moref = mock.sentinel.snap_moref
driver._verify_volume_creation = mock.MagicMock()
@ -1368,7 +1546,8 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
driver._clone_backing.assert_called_once_with(volume,
backing,
snap_moref,
default_clone_type)
default_clone_type,
snapshot['volume_size'])
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'volumeops', new_callable=mock.PropertyMock)
@ -1391,7 +1570,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
mock_vops = mock_vops.return_value
driver = self._driver
volume = {'volume_type_id': None, 'name': 'mock_vol'}
src_vref = {'name': 'src_snapshot_name'}
src_vref = {'name': 'src_snapshot_name', 'size': 1}
backing = mock.sentinel.backing
driver._verify_volume_creation = mock.MagicMock()
mock_vops.get_backing.return_value = backing
@ -1407,7 +1586,8 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
driver._clone_backing.assert_called_once_with(volume,
backing,
None,
default_clone_type)
default_clone_type,
src_vref['size'])
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'volumeops', new_callable=mock.PropertyMock)
@ -1419,7 +1599,8 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
mock_vops = mock_vops.return_value
driver = self._driver
volume = {'volume_type_id': None, 'name': 'mock_vol', 'id': 'mock_id'}
src_vref = {'name': 'src_snapshot_name', 'status': 'available'}
src_vref = {'name': 'src_snapshot_name', 'status': 'available',
'size': 1}
backing = mock.sentinel.backing
driver._verify_volume_creation = mock.MagicMock()
mock_vops.get_backing.return_value = backing
@ -1441,7 +1622,8 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
driver._clone_backing.assert_called_once_with(volume,
backing,
mock.sentinel.snapshot,
linked_clone)
linked_clone,
src_vref['size'])
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'volumeops', new_callable=mock.PropertyMock)
@ -1474,7 +1656,6 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
@mock.patch('cinder.volume.volume_types.get_volume_type_extra_specs')
def test_get_storage_profile(self, get_volume_type_extra_specs):
"""Test vmdk _get_storage_profile."""
# volume with no type id returns None
volume = FakeObject()
volume['volume_type_id'] = None
@ -1586,3 +1767,46 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
size = volume['size'] * units.GiB
driver._select_datastore_summary.assert_called_once_with(size,
filtered_dss)
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_extend_vmdk_virtual_disk(self, volume_ops):
"""Test vmdk._extend_vmdk_virtual_disk."""
self._test_extend_vmdk_virtual_disk(volume_ops)
@mock.patch.object(vmware_images, 'fetch_flat_image')
@mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_get_ds_name_flat_vmdk_path')
@mock.patch.object(VMDK_DRIVER, '_create_backing_in_inventory')
@mock.patch.object(VMDK_DRIVER, 'session')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_copy_image_to_volume_vmdk(self, volume_ops, session,
_create_backing_in_inventory,
_get_ds_name_flat_vmdk_path,
_extend_vmdk_virtual_disk,
fetch_flat_image):
"""Test copy_image_to_volume with an acceptable vmdk disk format."""
self._test_copy_image_to_volume_vmdk(volume_ops, session,
_create_backing_in_inventory,
_get_ds_name_flat_vmdk_path,
_extend_vmdk_virtual_disk,
fetch_flat_image)
@mock.patch.object(vmware_images, 'fetch_stream_optimized_image')
@mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume')
@mock.patch.object(VMDK_DRIVER, 'session')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_copy_image_to_volume_stream_optimized(self, volumeops,
session,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image):
"""Test copy_image_to_volume.
Test with an acceptable vmdk disk format and streamOptimized disk type.
"""
self._test_copy_image_to_volume_stream_optimized(volumeops,
session,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image)

View File

@ -20,6 +20,7 @@ Test suite for VMware VMDK driver volumeops module.
import mock
from cinder import test
from cinder import units
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim_util
from cinder.volume.drivers.vmware import volumeops
@ -791,3 +792,24 @@ class VolumeOpsTestCase(test.TestCase):
name=vmdk_file_path,
datacenter=dc_ref)
self.session.wait_for_task.assert_called_once_with(task)
def test_extend_virtual_disk(self):
"""Test volumeops.extend_virtual_disk."""
task = mock.sentinel.task
invoke_api = self.session.invoke_api
invoke_api.return_value = task
disk_mgr = self.session.vim.service_content.virtualDiskManager
fake_size = 5
fake_size_in_kb = fake_size * units.MiB
fake_name = 'fake_volume_0000000001'
fake_dc = mock.sentinel.datacenter
self.vops.extend_virtual_disk(fake_size,
fake_name, fake_dc)
invoke_api.assert_called_once_with(self.session.vim,
"ExtendVirtualDisk_Task",
disk_mgr,
name=fake_name,
datacenter=fake_dc,
newCapacityKb=fake_size_in_kb,
eagerZero=False)
self.session.wait_for_task.assert_called_once_with(task)

View File

@ -676,24 +676,37 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
"""
self._delete_snapshot(snapshot)
def _clone_backing_by_copying(self, volume, src_vmdk_path):
"""Clones volume backing.
def _create_backing_by_copying(self, volume, src_vmdk_path,
src_size_in_gb):
"""Create volume backing.
Creates a backing for the input volume and replaces its VMDK file
with the input VMDK file copy.
:param volume: New Volume object
:param src_vmdk_path: VMDK file path of the source volume backing
:param src_size_in_gb: The size of the original volume to be cloned
in GB. The size of the target volume is saved in volume['size'].
This parameter is used to check if the size specified by the user is
greater than the original size. If so, the target volume should extend
its size.
"""
# Create a backing
backing = self._create_backing_in_inventory(volume)
new_vmdk_path = self.volumeops.get_vmdk_path(backing)
dest_vmdk_path = self.volumeops.get_vmdk_path(backing)
datacenter = self.volumeops.get_dc(backing)
# Deleting the current VMDK file
self.volumeops.delete_vmdk_file(new_vmdk_path, datacenter)
self.volumeops.delete_vmdk_file(dest_vmdk_path, datacenter)
# Copying the source VMDK file
self.volumeops.copy_vmdk_file(datacenter, src_vmdk_path, new_vmdk_path)
self.volumeops.copy_vmdk_file(datacenter, src_vmdk_path,
dest_vmdk_path)
# If the target volume has a larger size than the source
# volume/snapshot, we need to resize/extend the size of the
# vmdk virtual disk to the value specified by the user.
if volume['size'] > src_size_in_gb:
self._extend_volumeops_virtual_disk(volume['size'], dest_vmdk_path,
datacenter)
LOG.info(_("Successfully cloned new backing: %(back)s from "
"source VMDK file: %(vmdk)s.") %
{'back': backing, 'vmdk': src_vmdk_path})
@ -718,7 +731,8 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
'vol': volume['name']})
return
src_vmdk_path = self.volumeops.get_vmdk_path(backing)
self._clone_backing_by_copying(volume, src_vmdk_path)
self._create_backing_by_copying(volume, src_vmdk_path,
src_vref['size'])
def create_cloned_volume(self, volume, src_vref):
"""Creates volume clone.
@ -750,13 +764,14 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
snapshot_moref = self.volumeops.get_snapshot(backing,
snapshot['name'])
if not snapshot_moref:
LOG.info(_("There is no snapshot point for the snapshoted volume: "
"%(snap)s. Not creating any backing for the "
"volume: %(vol)s.") %
LOG.info(_("There is no snapshot point for the snapshotted "
"volume: %(snap)s. Not creating any backing for "
"the volume: %(vol)s.") %
{'snap': snapshot['name'], 'vol': volume['name']})
return
src_vmdk_path = self.volumeops.get_vmdk_path(snapshot_moref)
self._clone_backing_by_copying(volume, src_vmdk_path)
self._create_backing_by_copying(volume, src_vmdk_path,
snapshot['volume_size'])
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot.
@ -903,6 +918,40 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
LOG.info(_("Done copying image: %(id)s to volume: %(vol)s.") %
{'id': image_id, 'vol': volume['name']})
def _extend_vmdk_virtual_disk(self, name, new_size_in_gb):
"""Extend the size of the vmdk virtual disk to the new size.
:param name: the name of the volume
:param new_size_in_gb: the new size the vmdk virtual disk extends to
"""
backing = self.volumeops.get_backing(name)
if not backing:
LOG.info(_("The backing is not found, so there is no need "
"to extend the vmdk virtual disk for the volume "
"%s."), name)
else:
root_vmdk_path = self.volumeops.get_vmdk_path(backing)
datacenter = self.volumeops.get_dc(backing)
self._extend_volumeops_virtual_disk(new_size_in_gb, root_vmdk_path,
datacenter)
def _extend_volumeops_virtual_disk(self, new_size_in_gb, root_vmdk_path,
datacenter):
"""Call the ExtendVirtualDisk_Task.
:param new_size_in_gb: the new size the vmdk virtual disk extends to
:param root_vmdk_path: the path for the vmdk file
:param datacenter: reference to the datacenter
"""
try:
self.volumeops.extend_virtual_disk(new_size_in_gb,
root_vmdk_path, datacenter)
except error_util.VimException:
with excutils.save_and_reraise_exception():
LOG.exception(_("Unable to extend the size of the "
"vmdk virtual disk at the path %s."),
root_vmdk_path)
def copy_image_to_volume(self, context, volume, image_service, image_id):
"""Creates volume from image.
@ -917,23 +966,36 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
:param image_id: Glance image id
"""
LOG.debug(_("Copy glance image: %s to create new volume.") % image_id)
# Record the volume size specified by the user, if the size is input
# from the API.
volume_size_in_gb = volume['size']
# Verify glance image is vmdk disk format
metadata = image_service.show(context, image_id)
VMwareEsxVmdkDriver._validate_disk_format(metadata['disk_format'])
# Get disk_type for vmdk disk
disk_type = None
image_size_in_bytes = metadata['size']
properties = metadata['properties']
if properties and 'vmware_disktype' in properties:
disk_type = properties['vmware_disktype']
if disk_type == 'streamOptimized':
self._fetch_stream_optimized_image(context, volume, image_service,
image_id, metadata['size'])
image_id, image_size_in_bytes)
else:
self._fetch_flat_image(context, volume, image_service, image_id,
metadata['size'])
image_size_in_bytes)
# image_size_in_bytes is the capacity of the image in Bytes and
# volume_size_in_gb is the size specified by the user, if the
# size is input from the API.
#
# Convert the volume_size_in_gb into bytes and compare with the
# image size. If the volume_size_in_gb is greater, meaning the
# user specifies a larger volume, we need to extend/resize the vmdk
# virtual disk to the capacity specified by the user.
if volume_size_in_gb * units.GiB > image_size_in_bytes:
self._extend_vmdk_virtual_disk(volume['name'], volume_size_in_gb)
def copy_volume_to_image(self, context, volume, image_service, image_meta):
"""Creates glance image from volume.
@ -1159,13 +1221,14 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
volumeops.LINKED_CLONE_TYPE),
volumeops.FULL_CLONE_TYPE)
def _clone_backing(self, volume, backing, snapshot, clone_type):
def _clone_backing(self, volume, backing, snapshot, clone_type, src_vsize):
"""Clone the backing.
:param volume: New Volume object
:param backing: Reference to the backing entity
:param snapshot: Reference to snapshot entity
:param snapshot: Reference to the snapshot entity
:param clone_type: type of the clone
:param src_vsize: the size of the source volume
"""
datastore = None
if not clone_type == volumeops.LINKED_CLONE_TYPE:
@ -1174,6 +1237,15 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
datastore = summary.datastore
clone = self.volumeops.clone_backing(volume['name'], backing,
snapshot, clone_type, datastore)
# If the volume size specified by the user is greater than
# the size of the source volume, the newly created volume will
# allocate the capacity to the size of the source volume in the backend
# VMDK datastore, though the volume information indicates it has a
# capacity of the volume size. If the volume size is greater,
# we need to extend/resize the capacity of the vmdk virtual disk from
# the size of the source volume to the volume size.
if volume['size'] > src_vsize:
self._extend_vmdk_virtual_disk(volume['name'], volume['size'])
LOG.info(_("Successfully created clone: %s.") % clone)
def _create_volume_from_snapshot(self, volume, snapshot):
@ -1188,7 +1260,7 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
self._verify_volume_creation(volume)
backing = self.volumeops.get_backing(snapshot['volume_name'])
if not backing:
LOG.info(_("There is no backing for the snapshoted volume: "
LOG.info(_("There is no backing for the snapshotted volume: "
"%(snap)s. Not creating any backing for the "
"volume: %(vol)s.") %
{'snap': snapshot['name'], 'vol': volume['name']})
@ -1196,13 +1268,14 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
snapshot_moref = self.volumeops.get_snapshot(backing,
snapshot['name'])
if not snapshot_moref:
LOG.info(_("There is no snapshot point for the snapshoted volume: "
"%(snap)s. Not creating any backing for the "
"volume: %(vol)s.") %
LOG.info(_("There is no snapshot point for the snapshotted "
"volume: %(snap)s. Not creating any backing for "
"the volume: %(vol)s.") %
{'snap': snapshot['name'], 'vol': volume['name']})
return
clone_type = VMwareVcVmdkDriver._get_clone_type(volume)
self._clone_backing(volume, backing, snapshot_moref, clone_type)
self._clone_backing(volume, backing, snapshot_moref, clone_type,
snapshot['volume_size'])
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot.
@ -1240,7 +1313,8 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
# then create the linked clone out of this snapshot point.
name = 'snapshot-%s' % volume['id']
snapshot = self.volumeops.create_snapshot(backing, name, None)
self._clone_backing(volume, backing, snapshot, clone_type)
self._clone_backing(volume, backing, snapshot, clone_type,
src_vref['size'])
def create_cloned_volume(self, volume, src_vref):
"""Creates volume clone.

View File

@ -18,6 +18,7 @@ Implements operations on volumes residing on VMware datastores.
"""
from cinder.openstack.common import log as logging
from cinder import units
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim_util
@ -318,6 +319,35 @@ class VMwareVolumeOps(object):
LOG.debug(_("Created child folder: %s.") % child_folder)
return child_folder
def extend_virtual_disk(self, requested_size_in_gb, name, dc_ref,
eager_zero=False):
"""Extend the virtual disk to the requested size.
:param requested_size_in_gb: Size of the volume in GB
:param name: Name of the backing
:param dc_ref: Reference datacenter
:param eager_zero: Boolean determining if the free space
is zeroed out
"""
LOG.debug(_("Extending the volume %(name)s to %(size)s GB."),
{'name': name, 'size': requested_size_in_gb})
diskMgr = self._session.vim.service_content.virtualDiskManager
# VMWare API needs the capacity unit to be in KB, so convert the
# capacity unit from GB to KB.
size_in_kb = requested_size_in_gb * units.MiB
task = self._session.invoke_api(self._session.vim,
"ExtendVirtualDisk_Task",
diskMgr,
name=name,
datacenter=dc_ref,
newCapacityKb=size_in_kb,
eagerZero=eager_zero)
self._session.wait_for_task(task)
LOG.info(_("Successfully extended the volume %(name)s to "
"%(size)s GB."),
{'name': name, 'size': requested_size_in_gb})
def _get_create_spec(self, name, size_kb, disk_type, ds_name,
profileId=None):
"""Return spec for creating volume backing.