/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doCleanupMetaMembers(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.Volume, * com.emc.storageos.volumecontroller.impl.block.taskcompleter.CleanupMetaVolumeMembersCompleter) */ @Override public void doCleanupMetaMembers( StorageSystem storageSystem, Volume volume, CleanupMetaVolumeMembersCompleter cleanupCompleter) throws DeviceControllerException { // Remove meta member volumes from storage device try { log.info( String.format( "doCleanupMetaMembers Start - Array: %s, Volume: %s", storageSystem.getSerialNumber(), volume.getLabel())); // Load meta volume members from WF data String sourceStepId = cleanupCompleter.getSourceStepId(); HDSApiClient hdsApiClient = hdsApiFactory.getClient( HDSUtils.getHDSServerManagementServerInfo(storageSystem), storageSystem.getUsername(), storageSystem.getSmisPassword()); List<String> metaMembers = (ArrayList<String>) WorkflowService.getInstance().loadStepData(sourceStepId); if (metaMembers != null && !metaMembers.isEmpty()) { log.info( String.format( "doCleanupMetaMembers: Members stored for meta volume: %n %s", metaMembers)); // Check if volumes still exist in array and if it is not composite member (already // added to the meta volume) Set<String> volumeIds = new HashSet<String>(); for (String logicalUnitObjectId : metaMembers) { LogicalUnit logicalUnit = hdsApiClient.getLogicalUnitInfo( HDSUtils.getSystemObjectID(storageSystem), logicalUnitObjectId); if (logicalUnit != null) { log.debug( "doCleanupMetaMembers: Volume: " + logicalUnitObjectId + ", Usage of volume: " + logicalUnit.getComposite()); if (logicalUnit.getComposite() != HDSConstants.COMPOSITE_ELEMENT_MEMBER) { volumeIds.add(logicalUnitObjectId); } } } if (volumeIds.isEmpty()) { cleanupCompleter.setSuccess(true); log.info("doCleanupMetaMembers: No meta members to cleanup in array."); } else { log.info( String.format( "doCleanupMetaMembers: Members to cleanup in array: %n %s", volumeIds)); // Prepare parameters and call method to delete meta members from array HDSCleanupMetaVolumeMembersJob hdsJobCompleter = null; // When "cleanup" is separate workflow step, call async (for example rollback // step in volume expand) // Otherwise, call synchronously (for example when cleanup is part of meta // volume create rollback) String asyncMessageId = hdsApiClient.deleteThickLogicalUnits( HDSUtils.getSystemObjectID(storageSystem), volumeIds); if (cleanupCompleter.isWFStep()) { if (asyncMessageId != null) { ControllerServiceImpl.enqueueJob( new QueueJob( new HDSCleanupMetaVolumeMembersJob( asyncMessageId, storageSystem.getId(), volume.getId(), cleanupCompleter))); } } else { // invoke synchronously hdsJobCompleter = new HDSCleanupMetaVolumeMembersJob( asyncMessageId, storageSystem.getId(), volume.getId(), cleanupCompleter); ((HDSMetaVolumeOperations) metaVolumeOperations) .invokeMethodSynchronously(hdsApiFactory, asyncMessageId, hdsJobCompleter); } } } else { log.info( "doCleanupMetaMembers: No meta members stored for meta volume. Nothing to cleanup in array."); cleanupCompleter.setSuccess(true); } } catch (Exception e) { log.error("Problem in doCleanupMetaMembers: ", e); ServiceError error = DeviceControllerErrors.smis.methodFailed("doCleanupMetaMembers", e.getMessage()); cleanupCompleter.setError(error); cleanupCompleter.setSuccess(false); } log.info( String.format( "doCleanupMetaMembers End - Array: %s, Volume: %s", storageSystem.getSerialNumber(), volume.getLabel())); }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doDeleteVolumes(com.emc.storageos.db.client.model.StorageSystem, * java.lang.String, java.util.List, com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doDeleteVolumes( StorageSystem storageSystem, String opId, List<Volume> volumes, TaskCompleter taskCompleter) throws DeviceControllerException { try { StringBuilder logMsgBuilder = new StringBuilder( String.format("Delete Volume Start - Array:%s", storageSystem.getSerialNumber())); MultiVolumeTaskCompleter multiVolumeTaskCompleter = (MultiVolumeTaskCompleter) taskCompleter; Set<String> thickLogicalUnitIdList = new HashSet<String>(); Set<String> thinLogicalUnitIdList = new HashSet<String>(); HDSApiClient hdsApiClient = hdsApiFactory.getClient( HDSUtils.getHDSServerManagementServerInfo(storageSystem), storageSystem.getSmisUserName(), storageSystem.getSmisPassword()); String systemObjectId = HDSUtils.getSystemObjectID(storageSystem); log.info("volumes size: {}", volumes.size()); for (Volume volume : volumes) { logMsgBuilder.append(String.format("%nVolume:%s", volume.getLabel())); String logicalUnitObjectId = HDSUtils.getLogicalUnitObjectId(volume.getNativeId(), storageSystem); LogicalUnit logicalUnit = hdsApiClient.getLogicalUnitInfo(systemObjectId, logicalUnitObjectId); if (logicalUnit == null) { // related volume state (if any) has been deleted. skip // processing, if already deleted from array. log.info(String.format("Volume %s already deleted: ", volume.getNativeId())); volume.setInactive(true); dbClient.persistObject(volume); VolumeTaskCompleter deleteTaskCompleter = multiVolumeTaskCompleter.skipTaskCompleter(volume.getId()); deleteTaskCompleter.ready(dbClient); continue; } if (volume.getThinlyProvisioned()) { thinLogicalUnitIdList.add(logicalUnitObjectId); } else { thickLogicalUnitIdList.add(logicalUnitObjectId); } } log.info(logMsgBuilder.toString()); if (!multiVolumeTaskCompleter.isVolumeTaskCompletersEmpty()) { if (null != thickLogicalUnitIdList && !thickLogicalUnitIdList.isEmpty()) { String asyncThickLUsJobId = hdsApiClient.deleteThickLogicalUnits(systemObjectId, thickLogicalUnitIdList); if (null != asyncThickLUsJobId) { ControllerServiceImpl.enqueueJob( new QueueJob( new HDSDeleteVolumeJob( asyncThickLUsJobId, volumes.get(0).getStorageController(), taskCompleter))); } } if (null != thinLogicalUnitIdList && !thinLogicalUnitIdList.isEmpty()) { String asyncThinHDSJobId = hdsApiClient.deleteThinLogicalUnits(systemObjectId, thinLogicalUnitIdList); // Not sure whether this really works as tracking two jobs // in single operation. if (null != asyncThinHDSJobId) { ControllerServiceImpl.enqueueJob( new QueueJob( new HDSDeleteVolumeJob( asyncThinHDSJobId, volumes.get(0).getStorageController(), taskCompleter))); } } } else { // If we are here, there are no volumes to delete, we have // invoked ready() for the VolumeDeleteCompleter, and told // the multiVolumeTaskCompleter to skip these completers. // In this case, the multiVolumeTaskCompleter complete() // method will not be invoked and the result is that the // workflow that initiated this delete request will never // be updated. So, here we just call complete() on the // multiVolumeTaskCompleter to ensure the workflow status is // updated. multiVolumeTaskCompleter.ready(dbClient); } } catch (Exception e) { log.error("Problem in doDeleteVolume: ", e); ServiceError error = DeviceControllerErrors.hds.methodFailed("doDeleteVolume", e.getMessage()); taskCompleter.error(dbClient, error); } StringBuilder logMsgBuilder = new StringBuilder( String.format("Delete Volume End - Array: %s", storageSystem.getSerialNumber())); for (Volume volume : volumes) { logMsgBuilder.append(String.format("%nVolume:%s", volume.getLabel())); } log.info(logMsgBuilder.toString()); }