/* * Copyright (c) 2008-2011 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.block.taskcompleter; import java.io.IOException; import java.net.URI; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.Operation; import com.emc.storageos.db.client.model.Stat; import com.emc.storageos.db.client.model.StatTimeSeries; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.db.client.util.NullColumnValueGetter; import com.emc.storageos.exceptions.DeviceControllerException; import com.emc.storageos.plugins.common.Constants; import com.emc.storageos.services.OperationTypeEnum; import com.emc.storageos.svcs.errorhandling.model.ServiceCoded; import com.emc.storageos.svcs.errorhandling.model.ServiceError; public class VolumeDeleteCompleter extends VolumeTaskCompleter { private static final Logger _log = LoggerFactory .getLogger(VolumeDeleteCompleter.class); public VolumeDeleteCompleter(URI volUri, String task) { super(Volume.class, volUri, task); } public VolumeDeleteCompleter(List<URI> volUris, String task) { super(Volume.class, volUris, task); } /** * Remove reference of deleted volume from associated source volume and associated host * * @param dbClient * @param deletedVolume */ private void removeDeletedVolumeReference(DbClient dbClient, Volume deletedVolume) { if (deletedVolume != null && !NullColumnValueGetter.isNullURI(deletedVolume.getAssociatedSourceVolume())) { Volume srcVolume = dbClient.queryObject(Volume.class, deletedVolume.getAssociatedSourceVolume()); // remove reference of deleted volume from fullCopies if (srcVolume != null) { srcVolume.getFullCopies().remove(deletedVolume.getId().toString()); dbClient.persistObject(srcVolume); } } } @Override protected void complete(DbClient dbClient, Operation.Status status, ServiceCoded coded) throws DeviceControllerException { try { List<Volume> volumes = dbClient.queryObject(Volume.class, getIds()); for (Volume volume : volumes) { switch (status) { case error: // Pattern for rollback quality: // If the step is a rollback step and we did receive an error, we want to notify the // user of the potential resource(s) that were not cleaned-up as a by-product of this // failure, so we will add such information into the incoming service code message. if (isRollingBack() && (coded instanceof ServiceError)) { ServiceError error = (ServiceError) coded; String originalMessage = error.getMessage(); String additionMessage = "Rollback encountered problems cleaning up " + volume.getNativeGuid() + " and may require manual clean up"; String updatedMessage = String.format("%s\n%s", originalMessage, additionMessage); error.setMessage(updatedMessage); } dbClient.error(Volume.class, volume.getId(), getOpId(), coded); break; default: dbClient.ready(Volume.class, volume.getId(), getOpId()); } _log.info(String.format("Done VolumeDelete - Id: %s, OpId: %s, status: %s", getId().toString(), getOpId(), status.name())); // Generate Zero Metering Record only after successful deletion if (Operation.Status.ready == status) { if (null != volume) { generateZeroStatisticsRecord(dbClient, volume); removeDeletedVolumeReference(dbClient, volume); } } recordBlockVolumeOperation(dbClient, OperationTypeEnum.DELETE_BLOCK_VOLUME, status, volume.getId().toString()); } if (status.equals(Operation.Status.ready) || (status.equals(Operation.Status.error) && isRollingBack())) { for (Volume volume : volumes) { volume.setConsistencyGroup(NullColumnValueGetter.getNullURI()); } dbClient.markForDeletion(volumes); } } catch (Exception e) { _log.error(String.format( "Failed updating status for VolumeDelete - Id: %s, OpId: %s", getIds() .toString(), getOpId()), e); } finally { super.complete(dbClient, status, coded); } } /** * Generate Zero Statistics Record for successfully deleted Volumes * * @param dbClient * @param volume * @throws IOException */ private void generateZeroStatisticsRecord(DbClient dbClient, Volume volume) { try { Stat zeroStatRecord = new Stat(); zeroStatRecord.setTimeInMillis(System.currentTimeMillis()); zeroStatRecord.setTimeCollected(System.currentTimeMillis()); zeroStatRecord.setServiceType(Constants._Block); zeroStatRecord.setAllocatedCapacity(0); zeroStatRecord.setProvisionedCapacity(0); zeroStatRecord.setBandwidthIn(0); zeroStatRecord.setBandwidthOut(0); zeroStatRecord.setTotalIOs(0); zeroStatRecord.setIdleTimeCounter(0); zeroStatRecord.setQueueLength(0); zeroStatRecord.setWriteIOs(0); zeroStatRecord.setReadIOs(0); zeroStatRecord.setKbytesTransferred(0); zeroStatRecord.setIoTimeCounter(0); zeroStatRecord.setNativeGuid(volume.getNativeGuid()); zeroStatRecord.setSnapshotCapacity(0); zeroStatRecord.setSnapshotCount(0); zeroStatRecord.setResourceId(volume.getId()); zeroStatRecord.setVirtualPool(volume.getVirtualPool()); zeroStatRecord.setProject(volume.getProject().getURI()); zeroStatRecord.setTenant(volume.getTenant().getURI()); dbClient.insertTimeSeries(StatTimeSeries.class, zeroStatRecord); } catch (Exception e) { _log.error("Zero Stat Record Creation failed for Volume : {}", volume.getId()); } } }