Merge "VMware: manage_existing for VMDK driver"

This commit is contained in:
Jenkins 2016-02-29 22:44:16 +00:00 committed by Gerrit Code Review
commit f674bd602b
5 changed files with 193 additions and 0 deletions

@ -2413,6 +2413,53 @@ class VMwareVcVmdkDriverTestCase(test.TestCase):
existing_ref))
get_existing.assert_called_once_with(existing_ref)
@mock.patch.object(VMDK_DRIVER, '_get_existing')
@mock.patch.object(VMDK_DRIVER, '_create_backing')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
@mock.patch.object(VMDK_DRIVER, '_get_ds_name_folder_path')
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'_get_disk_type')
def test_manage_existing(
self, get_disk_type, get_ds_name_folder_path, vops,
create_backing, get_existing):
vm = mock.sentinel.vm
src_path = mock.sentinel.src_path
disk_backing = mock.Mock(fileName=src_path)
disk_device = mock.Mock(backing=disk_backing, capacityInKB=1048576)
get_existing.return_value = (vm, disk_device)
backing = mock.sentinel.backing
create_backing.return_value = backing
src_dc = mock.sentinel.src_dc
dest_dc = mock.sentinel.dest_dc
vops.get_dc.side_effect = [src_dc, dest_dc]
volume = self._create_volume_dict()
ds_name = "ds1"
folder_path = "%s/" % volume['name']
get_ds_name_folder_path.return_value = (ds_name, folder_path)
disk_type = mock.sentinel.disk_type
get_disk_type.return_value = disk_type
existing_ref = mock.sentinel.existing_ref
self._driver.manage_existing(volume, existing_ref)
get_existing.assert_called_once_with(existing_ref)
create_backing.assert_called_once_with(
volume, create_params={vmdk.CREATE_PARAM_DISK_LESS: True})
vops.detach_disk_from_backing.assert_called_once_with(vm, disk_device)
dest_path = "[%s] %s%s.vmdk" % (ds_name, folder_path, volume['name'])
vops.move_vmdk_file.assert_called_once_with(
src_dc, src_path, dest_path, dest_dc_ref=dest_dc)
vops.attach_disk_to_backing.assert_called_once_with(
backing, disk_device.capacityInKB, disk_type, 'lsiLogic',
dest_path)
vops.update_backing_disk_uuid.assert_called_once_with(backing,
volume['id'])
@mock.patch('oslo_vmware.api.VMwareAPISession')
def test_session(self, apiSession):
self._session = None

@ -1326,6 +1326,39 @@ class VolumeOpsTestCase(test.TestCase):
spec=reconfig_spec)
self.session.wait_for_task.assert_called_once_with(task)
def test_create_spec_for_disk_remove(self):
disk_spec = mock.Mock()
self.session.vim.client.factory.create.return_value = disk_spec
disk_device = mock.sentinel.disk_device
self.vops._create_spec_for_disk_remove(disk_device)
self.session.vim.client.factory.create.assert_called_once_with(
'ns0:VirtualDeviceConfigSpec')
self.assertEqual('remove', disk_spec.operation)
self.assertEqual(disk_device, disk_spec.device)
@mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.'
'_create_spec_for_disk_remove')
@mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.'
'_reconfigure_backing')
def test_detach_disk_from_backing(self, reconfigure_backing, create_spec):
disk_spec = mock.sentinel.disk_spec
create_spec.return_value = disk_spec
reconfig_spec = mock.Mock()
self.session.vim.client.factory.create.return_value = reconfig_spec
backing = mock.sentinel.backing
disk_device = mock.sentinel.disk_device
self.vops.detach_disk_from_backing(backing, disk_device)
create_spec.assert_called_once_with(disk_device)
self.session.vim.client.factory.create.assert_called_once_with(
'ns0:VirtualMachineConfigSpec')
self.assertEqual([disk_spec], reconfig_spec.deviceChange)
reconfigure_backing.assert_called_once_with(backing, reconfig_spec)
def test_rename_backing(self):
task = mock.sentinel.task
self.session.invoke_api.return_value = task
@ -1653,6 +1686,31 @@ class VolumeOpsTestCase(test.TestCase):
force=True)
self.session.wait_for_task.assert_called_once_with(task)
def test_move_vmdk_file(self):
task = mock.sentinel.task
invoke_api = self.session.invoke_api
invoke_api.return_value = task
disk_mgr = self.session.vim.service_content.virtualDiskManager
src_dc_ref = mock.sentinel.src_dc_ref
src_vmdk_file_path = mock.sentinel.src_vmdk_file_path
dest_dc_ref = mock.sentinel.dest_dc_ref
dest_vmdk_file_path = mock.sentinel.dest_vmdk_file_path
self.vops.move_vmdk_file(src_dc_ref,
src_vmdk_file_path,
dest_vmdk_file_path,
dest_dc_ref=dest_dc_ref)
invoke_api.assert_called_once_with(self.session.vim,
'MoveVirtualDisk_Task',
disk_mgr,
sourceName=src_vmdk_file_path,
sourceDatacenter=src_dc_ref,
destName=dest_vmdk_file_path,
destDatacenter=dest_dc_ref,
force=True)
self.session.wait_for_task.assert_called_once_with(task)
def test_delete_vmdk_file(self):
task = mock.sentinel.task
invoke_api = self.session.invoke_api

@ -1694,6 +1694,45 @@ class VMwareVcVmdkDriver(driver.VolumeDriver):
(_vm, disk) = self._get_existing(existing_ref)
return int(math.ceil(disk.capacityInKB * units.Ki / float(units.Gi)))
def manage_existing(self, volume, existing_ref):
"""Brings an existing virtual disk under Cinder management.
Detaches the virtual disk identified by existing_ref and attaches
it to a volume backing.
:param volume: Cinder volume to manage
:param existing_ref: Driver-specific information used to identify a
volume
"""
(vm, disk) = self._get_existing(existing_ref)
# Create a backing for the volume.
create_params = {CREATE_PARAM_DISK_LESS: True}
backing = self._create_backing(volume, create_params=create_params)
# Detach the disk to be managed from the source VM.
self.volumeops.detach_disk_from_backing(vm, disk)
# Move the disk to the datastore folder of volume backing.
src_dc = self.volumeops.get_dc(vm)
dest_dc = self.volumeops.get_dc(backing)
(ds_name, folder_path) = self._get_ds_name_folder_path(backing)
dest_path = volumeops.VirtualDiskPath(
ds_name, folder_path, volume['name'])
self.volumeops.move_vmdk_file(src_dc,
disk.backing.fileName,
dest_path.get_descriptor_ds_file_path(),
dest_dc_ref=dest_dc)
# Attach the disk to be managed to volume backing.
self.volumeops.attach_disk_to_backing(
backing,
disk.capacityInKB,
VMwareVcVmdkDriver._get_disk_type(volume),
'lsiLogic',
dest_path.get_descriptor_ds_file_path())
self.volumeops.update_backing_disk_uuid(backing, volume['id'])
@property
def session(self):
if not self._session:

@ -1228,6 +1228,26 @@ class VMwareVolumeOps(object):
self._reconfigure_backing(backing, reconfig_spec)
LOG.debug("Backing VM: %s reconfigured with new disk.", backing)
def _create_spec_for_disk_remove(self, disk_device):
cf = self._session.vim.client.factory
disk_spec = cf.create('ns0:VirtualDeviceConfigSpec')
disk_spec.operation = 'remove'
disk_spec.device = disk_device
return disk_spec
def detach_disk_from_backing(self, backing, disk_device):
"""Detach the given disk from backing."""
LOG.debug("Reconfiguring backing VM: %(backing)s to remove disk: "
"%(disk_device)s.",
{'backing': backing, 'disk_device': disk_device})
cf = self._session.vim.client.factory
reconfig_spec = cf.create('ns0:VirtualMachineConfigSpec')
spec = self._create_spec_for_disk_remove(disk_device)
reconfig_spec.deviceChange = [spec]
self._reconfigure_backing(backing, reconfig_spec)
def rename_backing(self, backing, new_name):
"""Rename backing VM.
@ -1495,6 +1515,32 @@ class VMwareVolumeOps(object):
LOG.info(_LI("Successfully copied disk at: %(src)s to: %(dest)s."),
{'src': src_vmdk_file_path, 'dest': dest_vmdk_file_path})
def move_vmdk_file(self, src_dc_ref, src_vmdk_file_path,
dest_vmdk_file_path, dest_dc_ref=None):
"""Move the given vmdk file to another datastore location.
:param src_dc_ref: Reference to datacenter containing src datastore
:param src_vmdk_file_path: Source vmdk file path
:param dest_vmdk_file_path: Destination vmdk file path
:param dest_dc_ref: Reference to datacenter of dest datastore.
If unspecified, source datacenter is used.
"""
LOG.debug('Moving disk: %(src)s to %(dest)s.',
{'src': src_vmdk_file_path, 'dest': dest_vmdk_file_path})
dest_dc_ref = dest_dc_ref or src_dc_ref
diskMgr = self._session.vim.service_content.virtualDiskManager
task = self._session.invoke_api(self._session.vim,
'MoveVirtualDisk_Task',
diskMgr,
sourceName=src_vmdk_file_path,
sourceDatacenter=src_dc_ref,
destName=dest_vmdk_file_path,
destDatacenter=dest_dc_ref,
force=True)
self._session.wait_for_task(task)
def delete_vmdk_file(self, vmdk_file_path, dc_ref):
"""Delete given vmdk files.

@ -0,0 +1,3 @@
---
features:
- Added support for manage volume in the VMware VMDK driver.