diff options
Diffstat (limited to 'nova/virt/vmwareapi/volumeops.py')
-rw-r--r-- | nova/virt/vmwareapi/volumeops.py | 96 |
1 files changed, 90 insertions, 6 deletions
diff --git a/nova/virt/vmwareapi/volumeops.py b/nova/virt/vmwareapi/volumeops.py index 613dc671c9..e1d60cc751 100644 --- a/nova/virt/vmwareapi/volumeops.py +++ b/nova/virt/vmwareapi/volumeops.py @@ -26,12 +26,30 @@ import nova.conf from nova import exception from nova.i18n import _ from nova.virt.vmwareapi import constants +from nova.virt.vmwareapi import session from nova.virt.vmwareapi import vm_util CONF = nova.conf.CONF LOG = logging.getLogger(__name__) +class VolumeMoRefProxy(session.StableMoRefProxy): + def __init__(self, connection_info_data): + volume_ref_value = connection_info_data.get('volume') + ref = None + if volume_ref_value: + ref = vutil.get_moref(volume_ref_value, 'VirtualMachine') + super(VolumeMoRefProxy, self).__init__(ref) + self._connection_info_data = connection_info_data + + def fetch_moref(self, session): + volume_id = self._connection_info_data.get('volume_id') + if not volume_id: + volume_id = self._connection_info_data.get('name') + if volume_id: + self.moref = vm_util._get_vm_ref_from_vm_uuid(session, volume_id) + + class VMwareVolumeOps(object): """Management class for Volume-related tasks.""" @@ -300,9 +318,10 @@ class VMwareVolumeOps(object): connector['instance'] = vutil.get_moref_value(vm_ref) return connector - def _get_volume_ref(self, volume_ref_name): - """Get the volume moref from the ref name.""" - return vutil.get_moref(volume_ref_name, 'VirtualMachine') + @staticmethod + def _get_volume_ref(connection_info_data): + """Get the volume moref from the "data" field in connection_info .""" + return VolumeMoRefProxy(connection_info_data) def _get_vmdk_base_volume_device(self, volume_ref): # Get the vmdk file name that the VM is pointing to @@ -317,7 +336,7 @@ class VMwareVolumeOps(object): LOG.debug("_attach_volume_vmdk: %s", connection_info, instance=instance) data = connection_info['data'] - volume_ref = self._get_volume_ref(data['volume']) + volume_ref = self._get_volume_ref(data) # Get details required for adding disk device such as # adapter_type, disk_type @@ -367,6 +386,53 @@ class VMwareVolumeOps(object): device_name=device_name) LOG.debug("Attached ISCSI: %s", connection_info, instance=instance) + def _get_controller_key_and_unit(self, vm_ref, adapter_type): + LOG.debug("_get_controller_key_and_unit vm: %(vm_ref)s, adapter: " + "%(adapter)s.", + {'vm_ref': vm_ref, 'adapter': adapter_type}) + client_factory = self._session.vim.client.factory + devices = self._session._call_method(vutil, + "get_object_property", + vm_ref, + "config.hardware.device") + return vm_util.allocate_controller_key_and_unit_number( + client_factory, devices, adapter_type) + + def _attach_fcd(self, vm_ref, adapter_type, fcd_id, ds_ref_val): + (controller_key, unit_number, + controller_spec) = self._get_controller_key_and_unit( + vm_ref, adapter_type) + + if controller_spec: + # No controller available to attach, create one first. + config_spec = self._session.vim.client.factory.create( + 'ns0:VirtualMachineConfigSpec') + config_spec.deviceChange = [controller_spec] + vm_util.reconfigure_vm(self._session, vm_ref, config_spec) + (controller_key, unit_number, + controller_spec) = self._get_controller_key_and_unit( + vm_ref, adapter_type) + + vm_util.attach_fcd( + self._session, vm_ref, fcd_id, ds_ref_val, controller_key, + unit_number) + + def _attach_volume_fcd(self, connection_info, instance): + """Attach fcd volume storage to VM instance.""" + LOG.debug("_attach_volume_fcd: %s", connection_info, instance=instance) + vm_ref = vm_util.get_vm_ref(self._session, instance) + data = connection_info['data'] + adapter_type = data['adapter_type'] + + if adapter_type == constants.ADAPTER_TYPE_IDE: + state = vm_util.get_vm_state(self._session, instance) + if state != power_state.SHUTDOWN: + raise exception.Invalid(_('%s does not support disk ' + 'hotplug.') % adapter_type) + + self._attach_fcd(vm_ref, adapter_type, data['id'], data['ds_ref_val']) + LOG.debug("Attached fcd: %s", connection_info, instance=instance) + def attach_volume(self, connection_info, instance, adapter_type=None): """Attach volume storage to VM instance.""" driver_type = connection_info['driver_volume_type'] @@ -376,6 +442,8 @@ class VMwareVolumeOps(object): self._attach_volume_vmdk(connection_info, instance, adapter_type) elif driver_type == constants.DISK_FORMAT_ISCSI: self._attach_volume_iscsi(connection_info, instance, adapter_type) + elif driver_type == constants.DISK_FORMAT_FCD: + self._attach_volume_fcd(connection_info, instance) else: raise exception.VolumeDriverNotFound(driver_type=driver_type) @@ -503,7 +571,7 @@ class VMwareVolumeOps(object): LOG.debug("_detach_volume_vmdk: %s", connection_info, instance=instance) data = connection_info['data'] - volume_ref = self._get_volume_ref(data['volume']) + volume_ref = self._get_volume_ref(data) device = self._get_vmdk_backed_disk_device(vm_ref, data) @@ -558,6 +626,20 @@ class VMwareVolumeOps(object): self.detach_disk_from_vm(vm_ref, instance, device, destroy_disk=True) LOG.debug("Detached ISCSI: %s", connection_info, instance=instance) + def _detach_volume_fcd(self, connection_info, instance): + """Detach fcd volume storage to VM instance.""" + vm_ref = vm_util.get_vm_ref(self._session, instance) + data = connection_info['data'] + adapter_type = data['adapter_type'] + + if adapter_type == constants.ADAPTER_TYPE_IDE: + state = vm_util.get_vm_state(self._session, instance) + if state != power_state.SHUTDOWN: + raise exception.Invalid(_('%s does not support disk ' + 'hotplug.') % adapter_type) + + vm_util.detach_fcd(self._session, vm_ref, data['id']) + def detach_volume(self, connection_info, instance): """Detach volume storage to VM instance.""" driver_type = connection_info['driver_volume_type'] @@ -567,6 +649,8 @@ class VMwareVolumeOps(object): self._detach_volume_vmdk(connection_info, instance) elif driver_type == constants.DISK_FORMAT_ISCSI: self._detach_volume_iscsi(connection_info, instance) + elif driver_type == constants.DISK_FORMAT_FCD: + self._detach_volume_fcd(connection_info, instance) else: raise exception.VolumeDriverNotFound(driver_type=driver_type) @@ -580,7 +664,7 @@ class VMwareVolumeOps(object): vm_ref = vm_util.get_vm_ref(self._session, instance) data = connection_info['data'] # Get the volume ref - volume_ref = self._get_volume_ref(data['volume']) + volume_ref = self._get_volume_ref(data) # Pick the resource pool on which the instance resides. Move the # volume to the datastore of the instance. res_pool = self._get_res_pool_of_vm(vm_ref) |