/*
* Copyright (c) 2012 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.smis.job;
import java.net.URI;
import java.util.Calendar;
import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import javax.wbem.CloseableIterator;
import javax.wbem.client.WBEMClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.BlockObject;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.db.client.model.BlockSnapshotSession;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.volumecontroller.JobContext;
import com.emc.storageos.volumecontroller.TaskCompleter;
import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator;
import com.emc.storageos.volumecontroller.impl.smis.CIMConnectionFactory;
import com.emc.storageos.volumecontroller.impl.smis.CIMPropertyFactory;
import com.emc.storageos.volumecontroller.impl.smis.SmisConstants;
/**
* ViPR Job created when an underlying CIM job is created to create
* and link a new target volume to an array array snapshot point-in-time
* copy represented in ViPR by a BlockSnapshotSession instance.
*
* TBD - Maybe use or inherit from SmisCreateBlockSnapshotJob
* Issues
* - Different completer.
*/
@SuppressWarnings("serial")
public class SmisBlockSnapshotSessionLinkTargetJob extends SmisSnapShotJob {
// The unique job name.
private static final String JOB_NAME = "SmisBlockSnapshotSessionLinkTargetJob";
// The URI of the snapshot
private final URI _snapshotURI;
// The copy mode in which the target is linked to the snapshot.
@SuppressWarnings("unused")
private final String _copyMode;
// Reference to a logger.
private static final Logger s_logger = LoggerFactory.getLogger(SmisBlockSnapshotSessionLinkTargetJob.class);
/**
* Constructor.
*
* @param cimJob The CIM object path of the underlying CIM Job.
* @param systemURI The URI of the storage system.
* @param snapshotURI The URI of the snapshot.
* @param copyMode The copy mode in which the target is linked to the snapshot.
* @param taskCompleter A reference to the task completer.
*/
public SmisBlockSnapshotSessionLinkTargetJob(CIMObjectPath cimJob, URI systemURI, URI snapshotURI, String copyMode,
TaskCompleter taskCompleter) {
super(cimJob, systemURI, taskCompleter, JOB_NAME);
_snapshotURI = snapshotURI;
_copyMode = copyMode;
}
/**
* {@inheritDoc}
*/
@Override
public void updateStatus(JobContext jobContext) throws Exception {
JobStatus jobStatus = getJobStatus();
CloseableIterator<CIMObjectPath> volumeIter = null;
try {
DbClient dbClient = jobContext.getDbClient();
TaskCompleter completer = getTaskCompleter();
BlockSnapshot snapshot = dbClient.queryObject(BlockSnapshot.class, _snapshotURI);
if (jobStatus == JobStatus.IN_PROGRESS) {
return;
}
if (jobStatus == JobStatus.SUCCESS) {
s_logger.info("Post-processing successful link snapshot session target {} for task {}", snapshot.getId(),
completer.getOpId());
// Get the snapshot session to which the target is being linked.
BlockSnapshotSession snapSession = dbClient.queryObject(BlockSnapshotSession.class, completer.getId());
// Get the snapshot device ID and set it against the BlockSnapshot object.
BlockObject sourceObj = BlockObject.fetch(dbClient, snapshot.getParent().getURI());
CIMConnectionFactory cimConnectionFactory = jobContext.getCimConnectionFactory();
WBEMClient client = getWBEMClient(dbClient, cimConnectionFactory);
volumeIter = client.associatorNames(getCimJob(), null, SmisConstants.CIM_STORAGE_VOLUME, null, null);
while (volumeIter.hasNext()) {
// Get the sync volume native device id
CIMObjectPath volumePath = volumeIter.next();
s_logger.info("volumePath: {}", volumePath.toString());
CIMInstance volume = client.getInstance(volumePath, false, false, null);
String volumeDeviceId = volumePath.getKey(SmisConstants.CP_DEVICE_ID).getValue().toString();
s_logger.info("volumeDeviceId: {}", volumeDeviceId);
if (volumeDeviceId.equals(sourceObj.getNativeId())) {
// Don't want the source, we want the linked target.
continue;
}
String volumeElementName = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_ELEMENT_NAME);
s_logger.info("volumeElementName: {}", volumeElementName);
String volumeWWN = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_WWN_NAME);
s_logger.info("volumeWWN: {}", volumeWWN);
String volumeAltName = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_NAME);
s_logger.info("volumeAltName: {}", volumeAltName);
StorageSystem system = dbClient.queryObject(StorageSystem.class, getStorageSystemURI());
snapshot.setNativeId(volumeDeviceId);
snapshot.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(system, snapshot));
snapshot.setDeviceLabel(volumeElementName);
snapshot.setInactive(false);
snapshot.setIsSyncActive(Boolean.TRUE);
snapshot.setCreationTime(Calendar.getInstance());
snapshot.setWWN(volumeWWN.toUpperCase());
snapshot.setAlternateName(volumeAltName);
snapshot.setSettingsInstance(snapSession.getSessionInstance());
commonSnapshotUpdate(snapshot, volume, client, system, sourceObj.getNativeId(), volumeDeviceId, false, dbClient);
s_logger.info(String
.format("For target volume path %1$s, going to set blocksnapshot %2$s nativeId to %3$s (%4$s). Associated volume is %5$s (%6$s)",
volumePath.toString(), snapshot.getId().toString(), volumeDeviceId,
volumeElementName, sourceObj.getNativeId(), sourceObj.getDeviceLabel()));
dbClient.updateObject(snapshot);
}
} else if (jobStatus == JobStatus.FAILED || jobStatus == JobStatus.FATAL_ERROR) {
s_logger.info("Failed to link snapshot session target {} for task {}", snapshot.getId(), completer.getOpId());
snapshot.setInactive(true);
dbClient.updateObject(snapshot);
}
} catch (Exception e) {
setPostProcessingErrorStatus("Encountered an internal error in link snapshot session target job status processing: "
+ e.getMessage());
s_logger.error("Encountered an internal error in link snapshot session target job status processing", e);
} finally {
if (volumeIter != null) {
volumeIter.close();
}
super.updateStatus(jobContext);
}
}
}