/* * Copyright (c) 2012 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.smis.job; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.volumecontroller.JobContext; import com.emc.storageos.volumecontroller.impl.block.taskcompleter.MetaVolumeTaskCompleter; import com.emc.storageos.volumecontroller.impl.smis.CIMConnectionFactory; import com.emc.storageos.volumecontroller.impl.smis.SmisConstants; import com.emc.storageos.workflow.WorkflowService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.cim.CIMObjectPath; import javax.cim.CIMProperty; import javax.wbem.CloseableIterator; import javax.wbem.client.WBEMClient; import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class SmisCreateMetaVolumeMembersJob extends SmisJob { private static final Logger _log = LoggerFactory.getLogger(SmisCreateMetaVolumeMembersJob.class); private int _count; private Volume _metaHead; private List<String> _metaMembers = new ArrayList<String>(); private MetaVolumeTaskCompleter _metaVolumeTaskCompleter; public SmisCreateMetaVolumeMembersJob(CIMObjectPath cimJob, URI storageSystem, Volume metaHead, int count, MetaVolumeTaskCompleter metaVolumeTaskCompleter) { super(cimJob, storageSystem, metaVolumeTaskCompleter.getVolumeTaskCompleter(), "CreateMetaVolumeMembers"); _metaVolumeTaskCompleter = metaVolumeTaskCompleter; _count = count; _metaHead = metaHead; } public List<String> getMetaMembers() { return _metaMembers; } /** * Called to update the job status when the create meta members job completes. * * @param jobContext The job context. */ public void updateStatus(JobContext jobContext) throws Exception { CloseableIterator<CIMObjectPath> iterator = null; DbClient dbClient = jobContext.getDbClient(); JobStatus jobStatus = getJobStatus(); try { if (jobStatus == JobStatus.IN_PROGRESS) { return; } String opId = getTaskCompleter().getOpId(); StringBuilder logMsgBuilder = new StringBuilder(String.format("Updating status of job %s to %s, task: %s", this.getJobName(), jobStatus.name(), opId)); CIMConnectionFactory cimConnectionFactory = jobContext.getCimConnectionFactory(); WBEMClient client = getWBEMClient(dbClient, cimConnectionFactory); iterator = client.associatorNames(getCimJob(), null, SmisConstants.CIM_STORAGE_VOLUME, null, null); if (jobStatus == JobStatus.SUCCESS) { // verify that all meta members have been created List<CIMObjectPath> volumePaths = new ArrayList<CIMObjectPath>(); while (iterator.hasNext()) { volumePaths.add(iterator.next()); } if (volumePaths.size() != _count) { logMsgBuilder.append("\n"); logMsgBuilder.append(String.format( " Failed to create required number %s of meta members for meta head %s caused by %s: , task: %s.", _count, _metaHead.getLabel(), _errorDescription, opId)); _log.error(logMsgBuilder.toString()); setFailedStatus(logMsgBuilder.toString()); } else { // Process meta members logMsgBuilder.append("\n"); logMsgBuilder.append(String.format(" Created required number %s of meta members for meta head %s, task: %s .", _count, _metaHead.getLabel(), opId)); Iterator<CIMObjectPath> volumePathsIterator = volumePaths.iterator(); while (volumePathsIterator.hasNext()) { CIMObjectPath volumePath = volumePathsIterator.next(); CIMProperty<String> deviceID = (CIMProperty<String>) volumePath.getKey(SmisConstants.CP_DEVICE_ID); String nativeID = deviceID.getValue(); _metaMembers.add(nativeID); logMsgBuilder.append(String.format("%n Meta member device ID: %s", nativeID)); } _log.info(logMsgBuilder.toString()); } } else if (jobStatus == JobStatus.FAILED || jobStatus == JobStatus.FATAL_ERROR) { logMsgBuilder.append("\n"); logMsgBuilder.append(String.format( "Task %s failed to create meta members for meta head volume: %s caused by: %s", opId, _metaHead.getLabel(), _errorDescription)); _log.error(logMsgBuilder.toString()); setFailedStatus(logMsgBuilder.toString()); } } catch (Exception e) { _log.error("Caught an exception while trying to updateStatus for " + this.getJobName(), e); setPostProcessingErrorStatus("Encountered an internal error during " + this.getJobName() + " job status processing : " + e.getMessage()); } finally { if (iterator != null) { iterator.close(); } _metaVolumeTaskCompleter.setLastStepStatus(jobStatus); if (jobStatus != JobStatus.IN_PROGRESS) { // set meta members native ids in step data in WF String opId = _metaVolumeTaskCompleter.getVolumeTaskCompleter().getOpId(); WorkflowService.getInstance().storeStepData(opId, _metaMembers); _log.debug("Set meta members for meta volume in WF. Members: {}", _metaMembers); // Also set meta members in volume itself. Can be used to do cleanup at delete time // (in case rollback fails). StringSet metaMembersSet = new StringSet(_metaMembers); _metaHead.setMetaVolumeMembers(metaMembersSet); dbClient.persistObject(_metaHead); _log.info("Set meta members for meta volume in metaHead. Members: {}", _metaMembers); // TEMPER USED for negative testing. // jobStatus = Job.JobStatus.FAILED; // TEMPER } // Do this last, after everything is complete. Do not update status in case of success. This is not independent // operation. if (isJobInTerminalFailedState()) { super.updateStatus(jobContext); } } } }