/** * Detaches volumes from initiators. * * @param storage the storage * @param volumes the volumes * @param initiators the initiators * @throws Exception the exception */ private void detachVolumesFromInitiators( StorageSystem storage, List<Volume> volumes, List<Initiator> initiators) throws Exception { CinderEndPointInfo ep = CinderUtils.getCinderEndPoint(storage.getActiveProviderURI(), dbClient); log.debug("Getting the cinder APi for the provider with id {}", storage.getActiveProviderURI()); CinderApi cinderApi = cinderApiFactory.getApi(storage.getActiveProviderURI(), ep); List<Initiator> iSCSIInitiators = new ArrayList<Initiator>(); List<Initiator> fcInitiators = new ArrayList<Initiator>(); splitInitiatorsByProtocol(initiators, iSCSIInitiators, fcInitiators); String host = getHostNameFromInitiators(initiators); Map<String, String[]> mapSettingVsValues = getFCInitiatorsArray(fcInitiators); String[] fcInitiatorsWwpns = mapSettingVsValues.get(WWPNS); String[] fcInitiatorsWwnns = mapSettingVsValues.get(WWNNS); for (Volume volume : volumes) { // cinder generated volume ID String volumeId = volume.getNativeId(); // for iSCSI for (Initiator initiator : iSCSIInitiators) { String initiatorPort = initiator.getInitiatorPort(); log.debug( String.format( "Detaching volume %s ( %s ) from initiator %s on Openstack cinder node", volumeId, volume.getId(), initiatorPort)); cinderApi.detachVolume(volumeId, initiatorPort, null, null, host); // TODO : Do not use Job to poll status till we figure out how // to get detach status. /* * CinderJob detachJob = new CinderDetachVolumeJob(volumeId, * volume.getLabel(), storage.getId(), * CinderConstants.ComponentType.volume.name(), ep, * taskCompleter); ControllerServiceImpl.enqueueJob(new * QueueJob(detachJob)); */ } // for FC if (fcInitiatorsWwpns.length > 0) { log.debug( String.format( "Detaching volume %s ( %s ) from initiator %s on Openstack cinder node", volumeId, volume.getId(), fcInitiatorsWwpns)); cinderApi.detachVolume(volumeId, null, fcInitiatorsWwpns, fcInitiatorsWwnns, host); } // If ITLs are added, remove them removeITLsFromVolume(volume); } }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.CloneOperations#createSingleClone( * com.emc.storageos.db.client.model.StorageSystem, java.net.URI, java.net.URI, * java.lang.Boolean, * com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void createSingleClone( StorageSystem storageSystem, URI sourceObject, URI cloneVolume, Boolean createInactive, TaskCompleter taskCompleter) { log.info("START createSingleClone operation"); boolean isVolumeClone = true; try { BlockObject sourceObj = BlockObject.fetch(dbClient, sourceObject); URI tenantUri = null; if (sourceObj instanceof BlockSnapshot) { // In case of snapshot, get the tenant from its parent volume NamedURI parentVolUri = ((BlockSnapshot) sourceObj).getParent(); Volume parentVolume = dbClient.queryObject(Volume.class, parentVolUri); tenantUri = parentVolume.getTenant().getURI(); isVolumeClone = false; } else { // This is a default flow tenantUri = ((Volume) sourceObj).getTenant().getURI(); isVolumeClone = true; } Volume cloneObj = dbClient.queryObject(Volume.class, cloneVolume); StoragePool targetPool = dbClient.queryObject(StoragePool.class, cloneObj.getPool()); TenantOrg tenantOrg = dbClient.queryObject(TenantOrg.class, tenantUri); // String cloneLabel = generateLabel(tenantOrg, cloneObj); CinderEndPointInfo ep = CinderUtils.getCinderEndPoint(storageSystem.getActiveProviderURI(), dbClient); log.info( "Getting the cinder APi for the provider with id " + storageSystem.getActiveProviderURI()); CinderApi cinderApi = cinderApiFactory.getApi(storageSystem.getActiveProviderURI(), ep); String volumeId = ""; if (isVolumeClone) { volumeId = cinderApi.cloneVolume( cloneObj.getLabel(), (cloneObj.getCapacity() / (1024 * 1024 * 1024)), targetPool.getNativeId(), sourceObj.getNativeId()); } else { volumeId = cinderApi.createVolumeFromSnapshot( cloneObj.getLabel(), (cloneObj.getCapacity() / (1024 * 1024 * 1024)), targetPool.getNativeId(), sourceObj.getNativeId()); } log.debug("Creating volume with the id " + volumeId + " on Openstack cinder node"); if (volumeId != null) { Map<String, URI> volumeIds = new HashMap<String, URI>(); volumeIds.put(volumeId, cloneObj.getId()); ControllerServiceImpl.enqueueJob( new QueueJob( new CinderSingleVolumeCreateJob( volumeId, cloneObj.getLabel(), storageSystem.getId(), CinderConstants.ComponentType.volume.name(), ep, taskCompleter, targetPool.getId(), volumeIds))); } } catch (InternalException e) { String errorMsg = String.format(CREATE_ERROR_MSG_FORMAT, sourceObject, cloneVolume); log.error(errorMsg, e); taskCompleter.error(dbClient, e); } catch (Exception e) { String errorMsg = String.format(CREATE_ERROR_MSG_FORMAT, sourceObject, cloneVolume); log.error(errorMsg, e); ServiceError serviceError = DeviceControllerErrors.cinder.operationFailed("createSingleClone", e.getMessage()); taskCompleter.error(dbClient, serviceError); } }
/** * Attaches volumes to initiators. * * @param storage the storage * @param volumes the volumes * @param initiators the initiators * @param volumeToTargetLunMap the volume to target lun map * @throws Exception the exception */ private void attachVolumesToInitiators( StorageSystem storage, List<Volume> volumes, List<Initiator> initiators, Map<URI, Integer> volumeToTargetLunMap, Map<Volume, Map<String, List<String>>> volumeToInitiatorTargetMap, ExportMask exportMask) throws Exception { CinderEndPointInfo ep = CinderUtils.getCinderEndPoint(storage.getActiveProviderURI(), dbClient); log.debug( "Getting the cinder APi for the provider with id {}", storage.getActiveProviderURI()); CinderApi cinderApi = cinderApiFactory.getApi(storage.getActiveProviderURI(), ep); List<Initiator> iSCSIInitiators = new ArrayList<Initiator>(); List<Initiator> fcInitiators = new ArrayList<Initiator>(); splitInitiatorsByProtocol(initiators, iSCSIInitiators, fcInitiators); String host = getHostNameFromInitiators(initiators); Map<String, String[]> mapSettingVsValues = getFCInitiatorsArray(fcInitiators); String[] fcInitiatorsWwpns = mapSettingVsValues.get(WWPNS); String[] fcInitiatorsWwnns = mapSettingVsValues.get(WWNNS); for (Volume volume : volumes) { // cinder generated volume ID String volumeId = volume.getNativeId(); int targetLunId = -1; VolumeAttachResponse attachResponse = null; // for iSCSI for (Initiator initiator : iSCSIInitiators) { String initiatorPort = initiator.getInitiatorPort(); log.debug( String.format( "Attaching volume %s ( %s ) to initiator %s on Openstack cinder node", volumeId, volume.getId(), initiatorPort)); attachResponse = cinderApi.attachVolume(volumeId, initiatorPort, null, null, host); log.info("Got response : {}", attachResponse.connection_info.toString()); targetLunId = attachResponse.connection_info.data.target_lun; } // for FC if (fcInitiatorsWwpns.length > 0) { log.debug( String.format( "Attaching volume %s ( %s ) to initiators %s on Openstack cinder node", volumeId, volume.getId(), fcInitiatorsWwpns)); attachResponse = cinderApi.attachVolume(volumeId, null, fcInitiatorsWwpns, fcInitiatorsWwnns, host); log.info("Got response : {}", attachResponse.connection_info.toString()); targetLunId = attachResponse.connection_info.data.target_lun; Map<String, List<String>> initTargetMap = attachResponse.connection_info.data.initiator_target_map; if (null != initTargetMap && !initTargetMap.isEmpty()) { volumeToInitiatorTargetMap.put( volume, attachResponse.connection_info.data.initiator_target_map); } } volumeToTargetLunMap.put(volume.getId(), targetLunId); // After the successful export, create or modify the storage ports CinderStoragePortOperations storagePortOperationsInstance = CinderStoragePortOperations.getInstance(storage, dbClient); storagePortOperationsInstance.invoke(attachResponse); } // Add ITLs to volume objects storeITLMappingInVolume(volumeToTargetLunMap, exportMask); }