/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.cinder.job; import java.net.URI; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.cinder.CinderConstants; import com.emc.storageos.cinder.CinderEndPointInfo; import com.emc.storageos.cinder.api.CinderApi; import com.emc.storageos.cinder.errorhandling.CinderException; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.StoragePool; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.volumecontroller.JobContext; import com.emc.storageos.volumecontroller.TaskCompleter; import com.emc.storageos.volumecontroller.impl.cinder.CinderUtils; public class CinderDeleteVolumeJob extends CinderJob { private static final Logger logger = LoggerFactory.getLogger(CinderDeleteVolumeJob.class); private static final long serialVersionUID = -1477978360849416445L; private String volumeDeleteStatus = CinderConstants.ComponentStatus.DELETING.getStatus(); /** * @param jobId * @param jobName * @param storageSystem * @param componentType * @param ep * @param taskCompleter */ public CinderDeleteVolumeJob(String jobId, String jobName, URI storageSystem, String componentType, CinderEndPointInfo ep, TaskCompleter taskCompleter) { super(jobId, "DeleteVolume:VolumeName:" + jobName, storageSystem, componentType, ep, taskCompleter); } /** * Called to update the job status when the volume delete job completes. * * * @param jobContext The job context. */ public void updateStatus(JobContext jobContext) throws Exception { DbClient dbClient = jobContext.getDbClient(); try { if (status == JobStatus.IN_PROGRESS) { return; } StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, getStorageSystemURI()); CinderApi cinderApi = jobContext.getCinderApiFactory().getApi(storageSystem.getActiveProviderURI(), getEndPointInfo()); // Get list of volumes; get set of storage pool ids to which they belong. List<Volume> volumes = new ArrayList<Volume>(); Set<URI> poolURIs = new HashSet<URI>(); long deletedVolumesTotCapacity = 0L; for (URI id : getTaskCompleter().getIds()) { Volume volume = dbClient.queryObject(Volume.class, id); volumes.add(volume); poolURIs.add(volume.getPool()); deletedVolumesTotCapacity += volume.getCapacity(); } // If terminal state update storage pool capacity if (status == JobStatus.SUCCESS) { // Update capacity of storage pools. for (URI poolURI : poolURIs) { StoragePool storagePool = dbClient.queryObject(StoragePool.class, poolURI); CinderUtils.updateStoragePoolCapacity(dbClient, cinderApi, storagePool, String.valueOf(deletedVolumesTotCapacity / CinderConstants.BYTES_TO_GB), true); } } StringBuilder logMsgBuilder = new StringBuilder(); if (status == JobStatus.SUCCESS) { for (Volume volume : volumes) { volume.setInactive(true); dbClient.persistObject(volume); dbClient.ready(Volume.class, volume.getId(), getTaskCompleter().getOpId()); if (logMsgBuilder.length() != 0) { logMsgBuilder.append("\n"); } logMsgBuilder.append(String.format("Successfully deleted volume %s", volume.getId())); } } else if (status == JobStatus.FAILED) { for (URI id : getTaskCompleter().getIds()) { if (logMsgBuilder.length() != 0) { logMsgBuilder.append("\n"); } logMsgBuilder.append(String.format("Failed to delete volume: %s", id)); } } if (logMsgBuilder.length() > 0) { logger.info(logMsgBuilder.toString()); } } catch (Exception e) { setErrorStatus("Encountered an internal error during delete volume job status processing: " + e.getMessage()); logger.error("Caught exception while handling updateStatus for delete volume job.", e); } finally { super.updateStatus(jobContext); } } @Override protected boolean isJobSucceeded(String currentStatus) { return (CinderConstants.ComponentStatus.DELETED.getStatus().equalsIgnoreCase(currentStatus)); } @Override protected boolean isJobFailed(String currentStatus) { return (CinderConstants.ComponentStatus.ERROR.getStatus().equalsIgnoreCase(currentStatus) || CinderConstants.ComponentStatus.ERROR_DELETING.getStatus().equalsIgnoreCase(currentStatus)); } /** * Gets the current status of volume deletion */ protected String getCurrentStatus(CinderApi cinderApi) throws Exception { logger.info("Start getCurrentStatus()"); try { // As long as the status remains "Deleting", this will go through volumeDeleteStatus = cinderApi.getTaskStatus(getJobId(), CinderConstants.ComponentType.volume.name()); } catch (CinderException ce) { // Here means, the volume got deleted // check if the earlier status was "deleting", to be sure // that the delete volume was attempted if (CinderConstants.ComponentStatus.DELETING.getStatus().equalsIgnoreCase(volumeDeleteStatus)) { volumeDeleteStatus = CinderConstants.ComponentStatus.DELETED.getStatus(); } } logger.info("End getCurrentStatus() Status is:" + volumeDeleteStatus); return volumeDeleteStatus; } }