/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.smis.job;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.SYMM_LUNMASKINGVIEW;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import javax.cim.CIMProperty;
import javax.wbem.CloseableIterator;
import javax.wbem.WBEMException;
import javax.wbem.client.WBEMClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.cimadapter.connections.cim.CimConnection;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.model.BlockObject;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.db.client.model.ExportMask;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.emc.storageos.volumecontroller.JobContext;
import com.emc.storageos.volumecontroller.TaskCompleter;
import com.emc.storageos.volumecontroller.impl.ControllerServiceImpl;
import com.emc.storageos.volumecontroller.impl.VolumeURIHLU;
import com.emc.storageos.volumecontroller.impl.smis.CIMConnectionFactory;
import com.emc.storageos.volumecontroller.impl.smis.CIMPropertyFactory;
import com.emc.storageos.volumecontroller.impl.smis.ExportMaskOperationsHelper;
import com.emc.storageos.volumecontroller.impl.smis.SmisCommandHelper;
import com.emc.storageos.volumecontroller.impl.smis.SmisConstants;
import com.emc.storageos.volumecontroller.impl.smis.vmax.VmaxExportOperationContext;
import com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext;
/**
* A VMAX Create Masking View job
*/
public class SmisCreateMaskingViewJob extends SmisJob
{
private static final Logger _log = LoggerFactory.getLogger(SmisCreateMaskingViewJob.class);
private final URI _exportMaskURI;
private VolumeURIHLU[] _volumeURIHLUs;
private final CIMObjectPath _deviceGroupMaskingPath;
public SmisCreateMaskingViewJob(CIMObjectPath cimJob,
URI storageSystem,
URI exportMaskURI,
VolumeURIHLU[] volumeURIHLUs,
CIMObjectPath deviceGroupMaskingPath,
TaskCompleter taskCompleter) {
super(cimJob, storageSystem, taskCompleter, "CreateMaskingView");
_exportMaskURI = exportMaskURI;
if (volumeURIHLUs != null) {
_volumeURIHLUs = volumeURIHLUs.clone();
}
_deviceGroupMaskingPath = deviceGroupMaskingPath;
}
@Override
public void updateStatus(JobContext jobContext) throws Exception {
CloseableIterator<CIMObjectPath> iterator = null;
DbClient dbClient = jobContext.getDbClient();
JobStatus jobStatus = getJobStatus();
_log.info("Updating status of SmisCreateMaskingViewJob");
try {
if (jobStatus == JobStatus.SUCCESS) {
StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, getStorageSystemURI());
CimConnection cimConnection = jobContext.getCimConnectionFactory().getConnection(storageSystem);
CIMConnectionFactory cimConnectionFactory = jobContext.getCimConnectionFactory();
WBEMClient client = getWBEMClient(dbClient, cimConnectionFactory);
List<CIMObjectPath> maskingViews = new ArrayList<CIMObjectPath>();
iterator = client.associatorNames(getCimJob(), null, SYMM_LUNMASKINGVIEW, null, null);
while (iterator.hasNext()) {
CIMObjectPath cimObjectPath = iterator.next();
maskingViews.add(cimObjectPath);
ExportMask mask =
dbClient.queryObject(ExportMask.class, _exportMaskURI);
// Capture the device ID associated with the masking view. This is
// necessary for future reference to the MV.
if (mask != null) {
String deviceId =
cimObjectPath.getKey(SmisConstants.CP_DEVICE_ID)
.getValue().toString();
mask.setNativeId(deviceId);
dbClient.persistObject(mask);
ExportOperationContext.insertContextOperation(getTaskCompleter(),
VmaxExportOperationContext.OPERATION_CREATE_MASKING_VIEW, mask.getMaskName());
}
}
// Now perform RP protection tagging, if required, on the storage group
if (storageSystem.getUsingSmis80()) {
_log.info("Set RP tag on all volumes within SG for 8.0.3 Providers");
enableRecoverPointTagOn803(dbClient, client, storageSystem, jobContext);
} else {
_log.info("Set RP tag on SG for 4.6.2 Providers");
enableRecoverPointTag(dbClient, client, _deviceGroupMaskingPath);
}
// Now set the HLU on the volume URIs, if they haven't been set by user.
ExportMaskOperationsHelper.
setHLUFromProtocolControllers(dbClient, cimConnection, _exportMaskURI,
_volumeURIHLUs, maskingViews, getTaskCompleter());
}
} catch (Exception e) {
_log.error("Caught an exception while trying to updateStatus for SmisCreateMaskingViewJob", e);
setPostProcessingErrorStatus("Encountered an internal error during masking view create job status processing : "
+ e.getMessage());
} finally {
super.updateStatus(jobContext);
if (iterator != null) {
iterator.close();
}
}
}
/**
* Method will set the EMCRecoverPointEnabled flag on the device masking group for VMAX.
*
* @param dbClient [in] - Client instance for reading/writing from/to DB
* @param client [in] - WBEMClient used for reading/writing from/to SMI-S
* @param deviceGroupPath [in] - CIMObjectPath referencing the volume
*/
private void enableRecoverPointTag(DbClient dbClient, WBEMClient client, CIMObjectPath deviceGroupPath) {
try {
boolean isRPTagNeeded = false;
// Check if the volumes being protected are RP volumes
for (VolumeURIHLU volUriHlu : _volumeURIHLUs) {
URI volumeURI = volUriHlu.getVolumeURI();
BlockObject bo = null;
if (URIUtil.isType(volumeURI, BlockSnapshot.class)) {
bo = dbClient.queryObject(BlockSnapshot.class, volumeURI);
} else if (URIUtil.isType(volumeURI, Volume.class)) {
bo = dbClient.queryObject(Volume.class, volumeURI);
}
if (bo != null && BlockObject.checkForRP(dbClient, bo.getId())) {
isRPTagNeeded = true;
break;
}
}
// Do nothing and return from if none of the volumes are RP protected
if (isRPTagNeeded) {
_log.info("Attempting to enable RecoverPoint tag on Device Group : " + deviceGroupPath.toString());
CIMPropertyFactory factoryRef = (CIMPropertyFactory) ControllerServiceImpl.getBean("CIMPropertyFactory");
CIMInstance toUpdate = new CIMInstance(deviceGroupPath,
new CIMProperty[] {
factoryRef.bool(SmisConstants.EMC_RECOVERPOINT_ENABLED, true)
});
_log.debug("Params: " + toUpdate.toString());
client.modifyInstance(toUpdate, SmisConstants.CP_EMC_RECOVERPOINT_ENABLED);
_log.info(String.format("Device group has been successfully set with RecoverPoint tag "));
}
} catch (WBEMException e) {
_log.error("Encountered an error while trying to set the RecoverPoint tag", e);
} catch (DatabaseException e) {
_log.error("Encountered an error while trying to set the RecoverPoint tag", e);
}
}
/**
* Method will set the EMCRecoverPointEnabled flag on all the volumes within 8.0.3 Provider.
* 8.0.3 Provider doesnt support setting RP tag on Storage Groups.
*
* @param dbClient [in] - Client instance for reading/writing from/to DB
* @param client [in] - WBEMClient used for reading/writing from/to SMI-S
* @param deviceGroupPath [in] - CIMObjectPath referencing the volume
*/
private void enableRecoverPointTagOn803(DbClient dbClient, WBEMClient client, StorageSystem storage,
JobContext jobContext) {
try {
boolean isRPTagNeeded = false;
List<URI> blockObjectUris = new ArrayList<URI>();
// Check if the volumes being protected are RP volumes
for (VolumeURIHLU volUriHlu : _volumeURIHLUs) {
URI volumeURI = volUriHlu.getVolumeURI();
BlockObject bo = null;
if (URIUtil.isType(volumeURI, BlockSnapshot.class)) {
bo = dbClient.queryObject(BlockSnapshot.class, volumeURI);
} else if (URIUtil.isType(volumeURI, Volume.class)) {
bo = dbClient.queryObject(Volume.class, volumeURI);
}
if (bo != null) {
blockObjectUris.add(bo.getId());
if (BlockObject.checkForRP(dbClient, bo.getId())) {
isRPTagNeeded = true;
}
}
}
// Do nothing and return from if none of the volumes are RP protected
if (isRPTagNeeded) {
SmisCommandHelper helper = jobContext.getSmisCommandHelper();
helper.setRecoverPointTag(storage, helper.getVolumeMembers(storage, blockObjectUris), true);
}
} catch (WBEMException e) {
_log.error("Encountered an error while trying to set the RecoverPoint tag", e);
} catch (DatabaseException e) {
_log.error("Encountered an error while trying to set the RecoverPoint tag", e);
} catch (Exception e) {
_log.error("Encountered an error while trying to set the RecoverPoint tag", e);
}
}
}