diff --git a/cinder/volume/drivers/netapp/remote.py b/cinder/volume/drivers/netapp/remote.py index 1e8815ea3fa..a69c1252704 100644 --- a/cinder/volume/drivers/netapp/remote.py +++ b/cinder/volume/drivers/netapp/remote.py @@ -51,6 +51,12 @@ def get_file_sizes_by_dir(self, ctxt, host, path): cctxt = self._get_cctxt(host=host) return cctxt.call(ctxt, 'get_file_sizes_by_dir', path=path) + @volume_utils.trace + def rename_file_or_dir(self, ctxt, host, old_name, new_name): + cctxt = self._get_cctxt(host=host) + return cctxt.call(ctxt, 'rename_file_or_dir', + old_name=old_name, new_name=new_name) + class SAPNetappDriverRemoteService(object): RPC_API_VERSION = SAPNetappDriverRemoteApi.RPC_API_VERSION @@ -69,3 +75,7 @@ def swap_files(self, ctxt, vol_name, original_file, new_file): def get_file_sizes_by_dir(self, ctxt, path): # Returns used bytes of a file return self._driver.zapi_client.get_file_sizes_by_dir(path) + + def rename_file_or_dir(self, ctxt, old_name, new_name): + # Renames file or directory on netapp + return self._driver.zapi_client.rename_file(old_name, new_name) diff --git a/cinder/volume/drivers/vmware/fcd.py b/cinder/volume/drivers/vmware/fcd.py index 894208b113e..1b0c8e44705 100644 --- a/cinder/volume/drivers/vmware/fcd.py +++ b/cinder/volume/drivers/vmware/fcd.py @@ -855,7 +855,7 @@ def migrate_volume(self, context, volume, host): """ false_ret = (False, None) allowed_statuses = ['available', 'reserved', 'in-use', 'maintenance', - 'extending'] + 'extending', 'retyping'] if volume['status'] not in allowed_statuses: LOG.debug('Only %s volumes can be migrated using backend ' 'assisted migration. Falling back to generic migration.', @@ -863,7 +863,16 @@ def migrate_volume(self, context, volume, host): return false_ret if 'location_info' not in host['capabilities']: - return false_ret + if 'storage_protocol' in host['capabilities']: + proto = host['capabilities']['storage_protocol'] + if "NFS" in [p.upper() for p in proto]: + if 'NFS' in volume.provider_location.upper(): + return self.migrate_to_kvm(context, volume, host) + else: + return false_ret + else: + return false_ret + info = host['capabilities']['location_info'] try: (driver_name, vcenter) = info.split(':') @@ -1078,3 +1087,39 @@ def _migrate_unattached_cross_vc_legacy(self, context, dest_host, volume, # cleanup on target volume mgr return (True, None) + + @volume_utils.trace + def migrate_to_kvm(self, context, volume, host): + # Use RPC to convert a vmware fcd to netapp raw volume + fcd_loc = vops.FcdLocation.from_provider_location( + self._provider_location_to_moref_location( + volume.provider_location + ) + ) + netapp_api = self._remote_netapp_api + netapp_fqdn = self.volumeops.get_netapp_for_ds( + fcd_loc.ds_ref()) + netapp_host = self.get_netapp_cinder_host(netapp_fqdn) + src_vmdk_path = self.volumeops.get_vmdk_path_for_fcd(fcd_loc=fcd_loc) + datastore, folder_path, src_vmdk_file = vops.split_datastore_path( + src_vmdk_path) + src_flat_file = src_vmdk_file.replace('.vmdk', '-flat.vmdk') + source_dir_path = "/vol/%s/%s" % (datastore, folder_path) + temp_path = "/vol/%s/%s" % (datastore, + folder_path.replace('/', '') + '_tmp') + netapp_api.rename_file_or_dir(context, host=netapp_host, + old_name=source_dir_path, + new_name=temp_path) + source_path = "/vol/%s/%s/%s" % (datastore, + folder_path.replace('/', '') + '_tmp', + src_flat_file) + destination_path = "/vol/%s/%s" % (datastore, volume.id) + netapp_api.rename_file_or_dir(context, host=netapp_host, + old_name=source_path, + new_name=destination_path) + provider_location = self.volumeops._get_mount_path(fcd_loc.ds_ref()) + volume.update({'provider_location': provider_location}) + volume.save() + new_host = "%s#%s" % (host['host'].split('#')[0], provider_location) + model_updates = {'host': new_host} + return (True, model_updates) diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py index 41874ba578d..c670c6ddc4e 100644 --- a/cinder/volume/manager.py +++ b/cinder/volume/manager.py @@ -2943,6 +2943,9 @@ def _can_host_migrate(volume, force_host_copy, new_type_id): if (src_storage_protocol == 'vmdk' and dest_storage_protocol == 'vstorageobject'): return True + if (src_storage_protocol == 'vstorageobject' and + "NFS" in [p.upper() for p in dest_storage_protocol]): + return True elif not force_host_copy and not new_type_id: # If no new_type_id is specified, we allow migration # to any host.