@Override public StorageOperationResponse<DeleteVolumesResponse> deleteVolumes( DeleteVolumesRequest request) { logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "deleteVolumes: request:" + request, null); List<StorageLogMessage> logMessages = new ArrayList<StorageLogMessage>(); for (StorageVolume volume : request.storageVolumes) { try { Share share = openstackClient.getShare(volume.storageVolumeId); Status shareStatus = share.getStatus(); // snapshotState.equals(Status.AVAILABLE) if (!shareStatus.equals(Status.AVAILABLE)) { logger.log( IJavaEeLog.SEVERITY_WARNING, this.getClass().getName(), "Volume :" + share.getId() + " is in unexpected state: " + share.getStatus() + ".Operation may fail.", null); } openstackClient.deleteShare(volume.storageVolumeId); } catch (Exception e) { logger.traceThrowable( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "deleteVolumes:" + e.getMessage(), null, e); logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), e.getMessage())); } } if (logMessages.isEmpty()) { DeleteVolumesResponse payload = new DeleteVolumesResponse(); StorageOperationResponse<DeleteVolumesResponse> response = new StorageOperationResponse<DeleteVolumesResponse>(payload); response.setPercentCompleted(100); response.setStatus(StorageOperationStatus.COMPLETED); return response; } else { return StorageAdapterImplHelper.createFailedResponse( logMessages, DeleteVolumesResponse.class); } }
private String createTargetShare( OpenstackFileCloneVolumesContext context, OpenstackFileCloneVolumeStatus status, boolean source) throws CloudClientException { String snapshotId; if (source) { // snapshotId = status.volumeToBeCloned.sourceVolumeId; TODO: why does AWS do it this way? // wrong value is passed here snapshotId = status.sourceSnapshotId; } else { snapshotId = status.volumeToBeCloned.targetVolumeId; } ShareSnapshot snapshot = openstackClient.getSnapshot(snapshotId); String shareType = null; if (status.volumeToBeCloned.isSourceVolumeSnapshot) { shareType = "standard"; } else { String volumeId = status.volumeToBeCloned.sourceVolumeId; Share sourceVolume = openstackClient.getShare(volumeId); shareType = sourceVolume.getShareType(); } String shareName = status.volumeToBeCloned.targetVolumeName; Share share = openstackClient.createShareFromSnapshot(shareName, snapshot, shareType); status.targetVolumeId = share.getId(); logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + context.operationId + " creating volume: " + share.getId(), null); return share.getId(); }
/** * @param operationId * @param context * @return * @throws InfrastructAdapterException */ public StorageOperationResponse<PostProcessCloneVolumesResponse> getOperationStatus( StorageOperationId operationId, OpenstackFileCloneVolumesContext context) throws InfrastructAdapterException { logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " context: " + context, null); List<StorageLogMessage> logMessages = new ArrayList<StorageLogMessage>(); Status snapshotState = null; Share share = null; Status shareState = null; String snapshotId = null; String sourceVolumeId = null; String targetVolumeId = null; int progress = 0; int operationProgress = 0; boolean pending = false; boolean failed = false; boolean snapshotsReady = true; List<OpenstackFileCloneVolumeStatus> volumeStatus = context.volumeStatus; // STEP 1 : Check sourceSnapshot State for (OpenstackFileCloneVolumeStatus status : volumeStatus) { try { sourceVolumeId = status.volumeToBeCloned.sourceVolumeId; snapshotId = status.sourceSnapshotId; // String sourceSnapshotId = status.sourceSnapshotId; logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), " //STEP 1 : Check sourceSnapshot State " + snapshotId, null); if (status.sourceSnapshotComplete) continue; // snapshot already completed // snapshot = openstackClient.getSnapshot(snapshotId); snapshotState = openstackClient.getSnapshotStatus(snapshotId); logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " checking snapshot: " + snapshotId + " state: " + snapshotState, null); if (snapshotState.equals(Status.CREATING)) { // logger.log(IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: // operationId: " + operationId + "checking snapshot:" + snapshotId + " progress:" + // snapshot.getProgress(), null); String percent = "0"; // snapshot.getProgress(); //progress not tracked in Openstack // if (percent.isEmpty()) { // percent = "0"; // } else { // percent = percent.substring(0,percent.length() -2); // } progress = Integer.parseInt(percent); if (progress < operationProgress) operationProgress = progress; pending = true; snapshotsReady = false; continue; } else if (snapshotState.equals(Status.AVAILABLE)) { status.sourceSnapshotComplete = true; logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " completed source snapshot: " + snapshotId, null); // if (isRemoteClone(status.volumeToBeCloned)) { // createTargetSnapshot(snapshotId, status, operationId.toString()); // } else { createTargetShare(context, status, true); // } } else if (snapshotState.equals(Status.ERROR)) { logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " failed: " + snapshotId, null); logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), "Failed to Clone volume " + status.volumeToBeCloned.sourceVolumeId + ". Snapshot process terminated with ERROR")); failed = true; break; } else { throw new IllegalStateException( "Failed to Clone volume " + status.volumeToBeCloned.sourceVolumeId + ". Snapshot process returned unexpected status: " + snapshotState); } } catch (Exception e) { failed = true; logger.traceThrowable( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus:" + e.getMessage(), null, e); logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), "getOperationStatus:" + e.getMessage())); } } // STEP 2: Check Target Snapshot state (for cross-region only) //TODO for (OpenstackFileCloneVolumeStatus status : context.volumeStatus) { if (isRemoteClone(status.volumeToBeCloned)) { if (status.targetSnapshotId != null && !status.targetSnapshotComplete) { try { snapshotId = status.targetSnapshotId; // snapshot = openstackClient.getSnapshot(snapshotId); snapshotState = openstackClient.getSnapshotStatus(snapshotId); logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " checking snapshot: " + snapshotId + " state: " + snapshotState, null); if (snapshotState.equals(Status.CREATING)) { // logger.log(IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), // "getOperationStatus: operationId: " + operationId + "checking snapshot:" + // snapshotId + " progress:" + snapshot.getProgress(), null); // TODO: openstack doesnt have percent complete I think so map percentages based on // state 0, 50,100 String percent = "0"; // snapshot.getStatus() if (percent.isEmpty()) { percent = "0"; } else { percent = percent.substring(0, percent.length() - 2); } progress = Integer.parseInt(percent); if (progress < operationProgress) operationProgress = progress; pending = true; snapshotsReady = false; continue; } else if (snapshotState.equals(Status.AVAILABLE)) { status.targetSnapshotComplete = true; logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " completed target snapshot: " + snapshotId, null); createTargetShare(context, status, true); } else if (snapshotState.equals(Status.ERROR)) { logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " failed: " + snapshotId, null); logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), "Failed to Clone volume " + status.volumeToBeCloned.sourceVolumeId + ". Snapshot process terminated with ERROR")); failed = true; break; } else { throw new IllegalStateException( "Failed to Clone volume " + status.volumeToBeCloned.sourceVolumeId + ". Snapshot process returned unexpected status: " + snapshotState); } } catch (CloudClientException e) { failed = true; logger.traceThrowable( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus:" + e.getMessage(), null, e); logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), e.getMessage())); break; } } } } // STEP 3: Check Target Volume state for (OpenstackFileCloneVolumeStatus status : context.volumeStatus) { if (status.targetVolumeId == null) continue; try { share = openstackClient.getShare(status.targetVolumeId); if (share == null) { failed = true; logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), "Volume " + status.targetVolumeId + " not found")); break; } // } catch (CloudClientException e) { } catch (Exception e) { failed = true; logger.traceThrowable( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus:" + e.getMessage(), null, e); logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), e.getMessage())); break; } shareState = share.getStatus(); logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " checking volume: " + share.getId() + " state: " + shareState, null); if ((shareState.equals(Status.CREATING))) { pending = true; logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " in progress: " + share.getId(), null); } else if (shareState.equals(Status.ERROR)) { logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " create volume failed: " + share.getId(), null); logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), "Failed to Clone volume " + share.getId() + ". Process terminated with ERROR")); failed = true; break; } else if (shareState.equals(Status.AVAILABLE)) { logger.log( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus: operationId: " + operationId + " completed volume: " + share.getId(), null); status.targetVolumeComplete = true; // once volume is ready we can delete the temporary snapshot as it is no longer needed. if (status.targetSnapshotComplete) { snapshotId = status.targetSnapshotId; } else { snapshotId = status.sourceSnapshotId; } try { boolean forDelete = false; if (forDelete) { openstackClient.deleteSnapshot(snapshotId); } } catch (Exception e) { logger.traceThrowable( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "getOperationStatus:" + e.getMessage(), null, e); // here we just log warning as failing to delete the temporary snapshot does not fail the // clone operation logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_WARNING, "OSFile", System.currentTimeMillis(), "Failed delete temorary snapshot " + share.getSnapshotId() + ". " + e.getMessage())); } } else { logMessages.add( new StorageLogMessage( IJavaEeLog.SEVERITY_ERROR, "OSFile", System.currentTimeMillis(), "Unexpected volume state: " + shareState.name())); failed = true; break; } } if (failed) { // cleanup cancelVolumes(operationId, context); return StorageAdapterImplHelper.createFailedResponse( logMessages, PostProcessCloneVolumesResponse.class); } else if (pending) { PostProcessCloneVolumesResponse payload = new PostProcessCloneVolumesResponse(); StorageOperationResponse<PostProcessCloneVolumesResponse> response = new StorageOperationResponse<PostProcessCloneVolumesResponse>(payload); response.setPercentCompleted(progress); response.setId(operationId); response.setContext(context); response.setStatus(StorageOperationStatus.EXECUTING); response.setLogMessages(logMessages); return response; } else { // operation completed successfully PostProcessCloneVolumesResponse payload = new PostProcessCloneVolumesResponse(); payload.mountConfiguration = new ArrayList<MountData>(); for (OpenstackFileCloneVolumeStatus state : context.volumeStatus) { state.volumeToBeCloned.targetVolumeId = state.targetVolumeId; sourceVolumeId = state.volumeToBeCloned.sourceVolumeId; targetVolumeId = state.volumeToBeCloned.targetVolumeId; Share sourceShare = openstackClient.getShare(sourceVolumeId); String sourceExport = sourceShare.getExport(); Share targetShare = openstackClient.getShare(targetVolumeId); String targetExport = targetShare.getExport(); List<MountData> sourceMnts = state.volumeToBeCloned.sourceMountConfiguration; if (sourceMnts != null && !sourceMnts.isEmpty()) { for (int i = 0; i < sourceMnts.size(); i++) { MountData srcMD = sourceMnts.get(i); String sourceExportPath = srcMD.exportPath; if (!sourceExportPath.contains(sourceExport)) continue; MountData targetMD = state.volumeToBeCloned.targetMountConfiguration.get(i); String targetExportPath = sourceExportPath.replace(sourceExport, targetExport); targetMD.exportPath = targetExportPath; payload.mountConfiguration.add(targetMD); } } try { List<? extends ShareAccessMapping> listAccess = openstackClient.listAccess(sourceVolumeId); for (ShareAccessMapping shareAccessMapping : listAccess) { String accessTo = shareAccessMapping.getAccessTo(); Boolean active = openstackClient.allowAccess(targetVolumeId, accessTo); } } catch (Exception e) { logger.traceThrowable( IJavaEeLog.SEVERITY_DEBUG, this.getClass().getName(), "cloneVolumes:" + e.getMessage(), null, e); // ArrayList<StorageLogMessage> logMessages = cancel(snapshots); // logMessages.add(0, new StorageLogMessage(IJavaEeLog.SEVERITY_ERROR, // "OSFile", System.currentTimeMillis(), e.getMessage())); return StorageAdapterImplHelper.createFailedResponse( logMessages, PostProcessCloneVolumesResponse.class); } } StorageOperationResponse<PostProcessCloneVolumesResponse> response = new StorageOperationResponse<PostProcessCloneVolumesResponse>(payload); response.setId(operationId); response.setPercentCompleted(100); response.setLogMessages(logMessages); response.setStatus(StorageOperationStatus.COMPLETED); return response; } }