Merge "VMware: Handle missing vmdk during volume detach"

This commit is contained in:
Jenkins 2015-08-13 11:52:47 +00:00 committed by Gerrit Code Review
commit 65381d6a42
2 changed files with 74 additions and 5 deletions

View File

@ -15,6 +15,7 @@
import contextlib
import mock
from oslo_vmware import exceptions as oslo_vmw_exceptions
from nova.compute import vm_states
from nova import context
@ -322,3 +323,52 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
attach_disk_to_vm.assert_called_once_with(
volume_ref, instance, adapter_type, disk_type,
vmdk_path=new_file_name)
@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_missing_vmdk(
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
relocate_vmdk_volume.side_effect = [
oslo_vmw_exceptions.FileNotFoundException, None]
instance = mock.sentinel.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_calls = [mock.call(volume_ref, rp, datastore, host),
mock.call(volume_ref, rp, datastore, host)]
self.assertEqual(relocate_calls, relocate_vmdk_volume.call_args_list)
detach_disk_from_vm.assert_called_once_with(
volume_ref, instance, original_device)
attach_disk_to_vm.assert_called_once_with(
volume_ref, instance, adapter_type, disk_type,
vmdk_path=new_file_name)

View File

@ -19,11 +19,12 @@ Management class for Storage-related functions (attach, detach, etc).
from oslo_config import cfg
from oslo_log import log as logging
from oslo_vmware import exceptions as oslo_vmw_exceptions
from oslo_vmware import vim_util as vutil
from nova.compute import vm_states
from nova import exception
from nova.i18n import _, _LI
from nova.i18n import _, _LI, _LW
from nova.virt.vmwareapi import constants
from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
@ -459,11 +460,29 @@ class VMwareVolumeOps(object):
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, host)
detached = False
LOG.debug("Relocating volume's backing: %(backing)s to resource "
"pool: %(rp)s, datastore: %(ds)s, host: %(host)s.",
{'backing': volume_ref, 'rp': res_pool, 'ds': datastore,
'host': host})
try:
self._relocate_vmdk_volume(volume_ref, res_pool, datastore, host)
except oslo_vmw_exceptions.FileNotFoundException:
# Volume's vmdk was moved; remove the device so that we can
# relocate the volume.
LOG.warn(_LW("Virtual disk: %s of volume's backing not found."),
original_device_path, exc_info=True)
LOG.debug("Removing disk device of volume's backing and "
"reattempting relocate.")
self.detach_disk_from_vm(volume_ref, instance, original_device)
detached = True
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,
destroy_disk=True)
# Volume's backing is relocated now; detach the old vmdk if not done
# already.
if not detached:
self.detach_disk_from_vm(volume_ref, instance, original_device,
destroy_disk=True)
# Attach the current volume to the volume_ref
self.attach_disk_to_vm(volume_ref, instance,