summaryrefslogtreecommitdiff
path: root/nova/virt/vmwareapi/volumeops.py
diff options
context:
space:
mode:
Diffstat (limited to 'nova/virt/vmwareapi/volumeops.py')
-rw-r--r--nova/virt/vmwareapi/volumeops.py96
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)