Merge "VMware: Fix volume relocate during detach"

This commit is contained in:
Jenkins 2015-04-15 00:12:09 +00:00 committed by Gerrit Code Review
commit e9a21ffda3
2 changed files with 86 additions and 9 deletions

View File

@ -255,3 +255,68 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
constants.ADAPTER_TYPE_LSILOGICSAS,
constants.ADAPTER_TYPE_PARAVIRTUAL):
self._test_attach_volume_iscsi(adapter_type)
@mock.patch.object(volumeops.VMwareVolumeOps,
'_get_vmdk_base_volume_device')
@mock.patch.object(volumeops.VMwareVolumeOps, '_relocate_vmdk_volume')
def test_consolidate_vmdk_volume_with_no_relocate(
self, relocate_vmdk_volume, get_vmdk_base_volume_device):
file_name = mock.sentinel.file_name
backing = mock.Mock(fileName=file_name)
original_device = mock.Mock(backing=backing)
get_vmdk_base_volume_device.return_value = original_device
device = mock.Mock(backing=backing)
volume_ref = mock.sentinel.volume_ref
vm_ref = mock.sentinel.vm_ref
self._volumeops._consolidate_vmdk_volume(self._instance, vm_ref,
device, volume_ref)
get_vmdk_base_volume_device.assert_called_once_with(volume_ref)
self.assertFalse(relocate_vmdk_volume.called)
@mock.patch.object(volumeops.VMwareVolumeOps,
'_get_vmdk_base_volume_device')
@mock.patch.object(volumeops.VMwareVolumeOps, '_relocate_vmdk_volume')
@mock.patch.object(volumeops.VMwareVolumeOps, '_get_host_of_vm')
@mock.patch.object(volumeops.VMwareVolumeOps, '_get_res_pool_of_host')
@mock.patch.object(volumeops.VMwareVolumeOps, 'detach_disk_from_vm')
@mock.patch.object(volumeops.VMwareVolumeOps, 'attach_disk_to_vm')
def test_consolidate_vmdk_volume_with_relocate(
self, attach_disk_to_vm, detach_disk_from_vm, get_res_pool_of_host,
get_host_of_vm, relocate_vmdk_volume, get_vmdk_base_volume_device):
file_name = mock.sentinel.file_name
backing = mock.Mock(fileName=file_name)
original_device = mock.Mock(backing=backing)
get_vmdk_base_volume_device.return_value = original_device
new_file_name = mock.sentinel.new_file_name
datastore = mock.sentinel.datastore
new_backing = mock.Mock(fileName=new_file_name, datastore=datastore)
device = mock.Mock(backing=new_backing)
host = mock.sentinel.host
get_host_of_vm.return_value = host
rp = mock.sentinel.rp
get_res_pool_of_host.return_value = rp
instance = self._instance
volume_ref = mock.sentinel.volume_ref
vm_ref = mock.sentinel.vm_ref
adapter_type = constants.ADAPTER_TYPE_BUSLOGIC
disk_type = constants.DISK_TYPE_EAGER_ZEROED_THICK
self._volumeops._consolidate_vmdk_volume(instance, vm_ref, device,
volume_ref, adapter_type,
disk_type)
get_vmdk_base_volume_device.assert_called_once_with(volume_ref)
relocate_vmdk_volume.assert_called_once_with(
volume_ref, rp, datastore, host)
detach_disk_from_vm.assert_called_once_with(
volume_ref, instance, original_device, destroy_disk=True)
attach_disk_to_vm.assert_called_once_with(
volume_ref, instance, adapter_type, disk_type,
vmdk_path=new_file_name)

View File

@ -374,26 +374,30 @@ class VMwareVolumeOps(object):
else:
raise exception.VolumeDriverNotFound(driver_type=driver_type)
def _relocate_vmdk_volume(self, volume_ref, res_pool, datastore):
def _relocate_vmdk_volume(self, volume_ref, res_pool, datastore,
host=None):
"""Relocate the volume.
The move type will be moveAllDiskBackingsAndAllowSharing.
"""
client_factory = self._session.vim.client.factory
spec = vm_util.relocate_vm_spec(client_factory,
datastore=datastore)
datastore=datastore,
host=host)
spec.pool = res_pool
task = self._session._call_method(self._session.vim,
"RelocateVM_Task", volume_ref,
spec=spec)
self._session._wait_for_task(task)
def _get_res_pool_of_vm(self, vm_ref):
"""Get resource pool to which the VM belongs."""
# Get the host, the VM belongs to
host = self._session._call_method(vim_util, 'get_dynamic_property',
def _get_host_of_vm(self, vm_ref):
"""Get the ESX host of given VM."""
return self._session._call_method(vim_util, 'get_dynamic_property',
vm_ref, 'VirtualMachine',
'runtime').host
def _get_res_pool_of_host(self, host):
"""Get the resource pool of given host's cluster."""
# Get the compute resource, the host belongs to
compute_res = self._session._call_method(vim_util,
'get_dynamic_property',
@ -404,6 +408,13 @@ class VMwareVolumeOps(object):
compute_res, compute_res._type,
'resourcePool')
def _get_res_pool_of_vm(self, vm_ref):
"""Get resource pool to which the VM belongs."""
# Get the host, the VM belongs to
host = self._get_host_of_vm(vm_ref)
# Get the resource pool of host's cluster.
return self._get_res_pool_of_host(host)
def _consolidate_vmdk_volume(self, instance, vm_ref, device, volume_ref,
adapter_type=None, disk_type=None):
"""Consolidate volume backing VMDK files if needed.
@ -443,11 +454,12 @@ class VMwareVolumeOps(object):
LOG.info(_LI("The volume's backing has been relocated to %s. Need to "
"consolidate backing disk file."), current_device_path)
# Pick the resource pool on which the instance resides.
# Pick the host and resource pool on which the instance resides.
# Move the volume to the datastore where the new VMDK file is present.
res_pool = self._get_res_pool_of_vm(vm_ref)
host = self._get_host_of_vm(vm_ref)
res_pool = self._get_res_pool_of_host(host)
datastore = device.backing.datastore
self._relocate_vmdk_volume(volume_ref, res_pool, datastore)
self._relocate_vmdk_volume(volume_ref, res_pool, datastore, host)
# Delete the original disk from the volume_ref
self.detach_disk_from_vm(volume_ref, instance, original_device,