Skip to content

Commit

Permalink
VMware: fix image snapshot with attached volume
Browse files Browse the repository at this point in the history
A snapshot of a instance with an attached volume will result in
the wrong volume being uploaded to glance. The reason for this
are as follows:
1. the last image in the list of images would be exported
2. the base image would not be exported but the first found

The same happens with a VM rescue if there is a cinder volume
attached.

The solution is to search for an image that contains the instance
UUID.

Change-Id: Ic85b0ffd4f1c34f10d07b1a198eaad2030803d6f
Closes-bug: #1243193
(cherry picked from commit 9ceee09)

Conflicts:

	nova/virt/vmwareapi/vm_util.py
	nova/virt/vmwareapi/vmops.py

Change-Id: I6b9febbfe4e4e6ecf5d31a2b09a4319b07696f9c
  • Loading branch information
gkotton authored and tracyajones committed Mar 12, 2014
1 parent 1b790cc commit aa7f550
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 11 deletions.
29 changes: 27 additions & 2 deletions nova/tests/virt/vmwareapi/test_vmwareapi_vm_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,21 +285,46 @@ def test_lsilogic_controller_spec(self):
self.assertEqual("ns0:VirtualLsiLogicSASController",
config_spec.device.obj_name)

def test_get_vmdk_path_and_adapter_type(self):
def _vmdk_path_and_adapter_type_devices(self, filename, parent=None):
# Test the adapter_type returned for a lsiLogic sas controller
controller_key = 1000
filename = '[test_datastore] test_file.vmdk'
disk = fake.VirtualDisk()
disk.controllerKey = controller_key
disk_backing = fake.VirtualDiskFlatVer2BackingInfo()
disk_backing.fileName = filename
if parent:
disk_backing.parent = parent
disk.backing = disk_backing
controller = fake.VirtualLsiLogicSASController()
controller.key = controller_key
devices = [disk, controller]
return devices

def test_get_vmdk_path_and_adapter_type(self):
filename = '[test_datastore] test_file.vmdk'
devices = self._vmdk_path_and_adapter_type_devices(filename)
vmdk_info = vm_util.get_vmdk_path_and_adapter_type(devices)
adapter_type = vmdk_info[2]
self.assertEqual('lsiLogicsas', adapter_type)
self.assertEqual(vmdk_info[0], filename)

def test_get_vmdk_path_and_adapter_type_with_match(self):
n_filename = '[test_datastore] uuid/uuid.vmdk'
devices = self._vmdk_path_and_adapter_type_devices(n_filename)
vmdk_info = vm_util.get_vmdk_path_and_adapter_type(
devices, uuid='uuid')
adapter_type = vmdk_info[2]
self.assertEqual('lsiLogicsas', adapter_type)
self.assertEqual(n_filename, vmdk_info[0])

def test_get_vmdk_path_and_adapter_type_with_nomatch(self):
n_filename = '[test_datastore] diuu/diuu.vmdk'
devices = self._vmdk_path_and_adapter_type_devices(n_filename)
vmdk_info = vm_util.get_vmdk_path_and_adapter_type(
devices, uuid='uuid')
adapter_type = vmdk_info[2]
self.assertEqual('lsiLogicsas', adapter_type)
self.assertIsNone(vmdk_info[0])

def test_get_vmdk_adapter_type(self):
# Test for the adapter_type to be used in vmdk descriptor
Expand Down
16 changes: 10 additions & 6 deletions nova/virt/vmwareapi/vm_util.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,12 @@ def get_vm_extra_config_spec(client_factory, extra_opts):
return config_spec


def get_vmdk_path_and_adapter_type(hardware_devices):
def get_vmdk_path_and_adapter_type(hardware_devices, uuid=None):
"""Gets the vmdk file path and the storage adapter type."""
if hardware_devices.__class__.__name__ == "ArrayOfVirtualDevice":
hardware_devices = hardware_devices.VirtualDevice
vmdk_file_path = None
vmdk_controler_key = None
vmdk_controller_key = None
disk_type = None
unit_number = 0

Expand All @@ -307,8 +307,12 @@ def get_vmdk_path_and_adapter_type(hardware_devices):
if device.__class__.__name__ == "VirtualDisk":
if device.backing.__class__.__name__ == \
"VirtualDiskFlatVer2BackingInfo":
vmdk_file_path = device.backing.fileName
vmdk_controler_key = device.controllerKey
if uuid:
if uuid in device.backing.fileName:
vmdk_file_path = device.backing.fileName
else:
vmdk_file_path = device.backing.fileName
vmdk_controller_key = device.controllerKey
if getattr(device.backing, 'thinProvisioned', False):
disk_type = "thin"
else:
Expand All @@ -327,9 +331,9 @@ def get_vmdk_path_and_adapter_type(hardware_devices):
elif device.__class__.__name__ == "VirtualLsiLogicSASController":
adapter_type_dict[device.key] = "lsiLogicsas"

adapter_type = adapter_type_dict.get(vmdk_controler_key, "")
adapter_type = adapter_type_dict.get(vmdk_controller_key, "")

return (vmdk_file_path, vmdk_controler_key, adapter_type,
return (vmdk_file_path, vmdk_controller_key, adapter_type,
disk_type, unit_number)


Expand Down
16 changes: 13 additions & 3 deletions nova/virt/vmwareapi/vmops.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ def _get_vm_and_vmdk_attribs():
"VirtualMachine", "config.hardware.device")
(vmdk_file_path_before_snapshot, controller_key, adapter_type,
disk_type, unit_number) = vm_util.get_vmdk_path_and_adapter_type(
hardware_devices)
hardware_devices, uuid=instance['uuid'])
datastore_name = vm_util.split_datastore_path(
vmdk_file_path_before_snapshot)[0]
os_type = self._session._call_method(vim_util,
Expand Down Expand Up @@ -1049,8 +1049,10 @@ def rescue(self, context, instance, network_info, image_meta):
hardware_devices = self._session._call_method(vim_util,
"get_dynamic_property", vm_ref,
"VirtualMachine", "config.hardware.device")
vmdk_path, controller_key, adapter_type, disk_type, unit_number \
= vm_util.get_vmdk_path_and_adapter_type(hardware_devices)
(vmdk_path, controller_key, adapter_type, disk_type,
unit_number) = vm_util.get_vmdk_path_and_adapter_type(
hardware_devices, uuid=instance['uuid'])

# Figure out the correct unit number
unit_number = unit_number + 1
rescue_vm_ref = vm_util.get_vm_ref_from_uuid(self._session,
Expand All @@ -1066,6 +1068,14 @@ def rescue(self, context, instance, network_info, image_meta):

def unrescue(self, instance):
"""Unrescue the specified instance."""
# Get the original vmdk_path
vm_ref = vm_util.get_vm_ref(self._session, instance)
hardware_devices = self._session._call_method(vim_util,
"get_dynamic_property", vm_ref,
"VirtualMachine", "config.hardware.device")
(vmdk_path, controller_key, adapter_type, disk_type,
unit_number) = vm_util.get_vmdk_path_and_adapter_type(
hardware_devices, uuid=instance['uuid'])
r_instance = copy.deepcopy(instance)
r_instance['name'] = r_instance['name'] + self._rescue_suffix
r_instance['uuid'] = r_instance['uuid'] + self._rescue_suffix
Expand Down

0 comments on commit aa7f550

Please sign in to comment.