use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.
the class AbstractConsistencyGroupManager method removeVolumesFromCG.
/**
* The method called by the workflow to remove VPLEX volumes from a VPLEX
* consistency group.
*
* @param vplexURI The URI of the VPLEX storage system.
* @param cgURI The URI of the consistency group.
* @param vplexVolumeURIs The URIs of the volumes to be removed from the
* consistency group.
* @param stepId The workflow step id.
*
* @throws WorkflowException When an error occurs updating the workflow step
* state.
*/
public void removeVolumesFromCG(URI vplexURI, URI cgURI, List<URI> vplexVolumeURIs, String stepId) throws WorkflowException {
try {
// Update workflow step.
WorkflowStepCompleter.stepExecuting(stepId);
log.info("Updated workflow step state to execute for remove volumes from consistency group.");
ServiceCoded codedError = removeVolumesFromCGInternal(vplexURI, cgURI, vplexVolumeURIs);
if (codedError != null) {
WorkflowStepCompleter.stepFailed(stepId, codedError);
} else {
WorkflowStepCompleter.stepSucceded(stepId);
}
} catch (Exception ex) {
log.error("Exception removing volumes from consistency group: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.DELETE_CG_VOLUME.getName();
ServiceError serviceError = VPlexApiException.errors.removeVolumesFromCGFailed(opName, ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.
the class RPVplexConsistencyGroupManager method createCG.
/**
* Called by the workflow to create a new VPLEX consistency group.
*
* @param vplexURI The URI of the VPLEX storage system.
* @param cgURI The URI of the Bourne consistency group
* @param vplexVolumeURIs The list of URIs of the VPLEX volumes being
* added to the vplex CG
* @param stepId The workflow step id.
*
* @throws WorkflowException When an error occurs updating the workflow step
* state.
*/
public void createCG(URI vplexURI, URI cgURI, Collection<URI> vplexVolumeURIs, String stepId) throws WorkflowException {
try {
// Update workflow step.
WorkflowStepCompleter.stepExecuting(stepId);
log.info("Updated step state for consistency group creation to execute.");
if (vplexVolumeURIs == null || vplexVolumeURIs.isEmpty()) {
log.info("empty volume list; no CG will be created");
// Update workflow step state to success.
WorkflowStepCompleter.stepSucceded(stepId);
log.info("Updated workflow step for consistency group creation to success.");
return;
}
// Get the API client.
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, dbClient);
VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexSystem, dbClient);
log.debug("Got VPLEX API client.");
// For the following cases we need special steps for the CG to choose the HA side/leg on the VPLEX to be the winner:
// 1. In an RP+VPLEX distributed setup, the user can choose to protect only the HA side.
// 2. In a MetroPoint setup, the user can choose the HA side as the Active side.
// Get the first source volume
Volume firstVplexVolume = null;
for (URI volURI : vplexVolumeURIs) {
Volume vol = dbClient.queryObject(Volume.class, volURI);
if (vol != null && PersonalityTypes.SOURCE.name().equalsIgnoreCase(vol.getPersonality())) {
// found the first source volume so break
firstVplexVolume = vol;
break;
}
}
if (firstVplexVolume != null && NullColumnValueGetter.isNotNullValue(firstVplexVolume.getPersonality()) && firstVplexVolume.getPersonality().equals(PersonalityTypes.SOURCE.toString())) {
VirtualPool vpool = getDataObject(VirtualPool.class, firstVplexVolume.getVirtualPool(), dbClient);
boolean haIsWinningCluster = VirtualPool.isRPVPlexProtectHASide(vpool) || (vpool.getMetroPoint() && NullColumnValueGetter.isNotNullValue(vpool.getHaVarrayConnectedToRp()));
if (haIsWinningCluster) {
log.info("Force HA side as winning cluster for VPLEX CG.");
// Temporarily change the varray to the HA varray.
// NOTE: Do not persist!
firstVplexVolume.setLabel("DO NOT PERSIST THIS VOLUME");
firstVplexVolume.setVirtualArray(URI.create(vpool.getHaVarrayConnectedToRp()));
}
}
// acquire a lock to serialize create cg requests to the VPLEX
List<String> lockKeys = new ArrayList<String>();
lockKeys.add(ControllerLockingUtil.getConsistencyGroupStorageKey(dbClient, cgURI, vplexURI));
workflowService.acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.RP_VPLEX_CG));
// Get the consistency group
BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, dbClient);
// group the volumes by the cluster/CG that they will go in
Map<String, List<URI>> cgToVolListMap = new HashMap<String, List<URI>>();
for (URI vplexVolumeURI : vplexVolumeURIs) {
Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, dbClient);
// Lets determine the VPlex consistency group that need to be created for this volume.
ClusterConsistencyGroupWrapper clusterConsistencyGroup = getClusterConsistencyGroup(vplexVolume, cg);
String cgName = clusterConsistencyGroup.getCgName();
String clusterName = clusterConsistencyGroup.getClusterName();
boolean isDistributed = clusterConsistencyGroup.isDistributed();
String cgKey = String.format("%s:%s:%s", cgName, clusterName, (isDistributed ? "dist" : "local"));
if (!cgToVolListMap.containsKey(cgKey)) {
cgToVolListMap.put(cgKey, new ArrayList<URI>());
}
cgToVolListMap.get(cgKey).add(vplexVolumeURI);
}
// loop through each cluster/CG; create the CG and add the volumes
for (Entry<String, List<URI>> entry : cgToVolListMap.entrySet()) {
String[] elems = StringUtils.delimitedListToStringArray(entry.getKey(), ":");
if (elems.length != 3) {
// serious coding error see above loop which creates the key
log.error("Error in vplex cg mapping key. Expect <cgname>:<clustername>:<dist|local>; got: " + entry.getKey());
continue;
}
String cgName = elems[0];
String clusterName = elems[1];
boolean isDistributed = elems[2].equals("dist");
// Verify that the VPlex CG has been created for this VPlex system and cluster.
if (!BlockConsistencyGroupUtils.isVplexCgCreated(cg, vplexURI.toString(), clusterName, cgName, isDistributed)) {
createVplexCG(vplexSystem, client, cg, firstVplexVolume, cgName, clusterName, isDistributed);
} else {
modifyCGSettings(client, cgName, clusterName, isDistributed);
}
addVolumesToCG(cgURI, entry.getValue(), cgName, clusterName, client);
}
// Update workflow step state to success.
WorkflowStepCompleter.stepSucceded(stepId);
log.info("Updated workflow step for consistency group creation to success.");
} catch (Exception ex) {
log.error("Exception creating consistency group: " + ex.getMessage(), ex);
ServiceError serviceError = VPlexApiException.errors.jobFailed(ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.
the class VPlexConsistencyGroupManager method createCG.
/**
* Called by the workflow to create a new VPLEX consistency group.
*
* @param vplexURI The URI of the VPLEX storage system.
* @param cgURI The URI of the Bourne consistency group
* @param vplexVolumeURIs The URI of the VPLEX used to determine the VPlex
* cluster/distributed information.
* @param stepId The workflow step id.
*
* @throws WorkflowException When an error occurs updating the workflow step
* state.
*/
public void createCG(URI vplexURI, URI cgURI, List<URI> vplexVolumeURIs, String stepId) throws WorkflowException {
try {
// Update workflow step.
WorkflowStepCompleter.stepExecuting(stepId);
log.info("Updated step state for consistency group creation to execute.");
// Lock the CG for the step duration.
List<String> lockKeys = new ArrayList<String>();
lockKeys.add(ControllerLockingUtil.getConsistencyGroupStorageKey(dbClient, cgURI, vplexURI));
workflowService.acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.RP_VPLEX_CG));
// Get the API client.
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, dbClient);
VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexSystem, dbClient);
log.info("Got VPLEX API client.");
// Get the consistency group
BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, dbClient);
// Check to see if it was created since we defined the workflow.
if (cg.created(vplexURI)) {
StringSet cgNames = cg.getSystemConsistencyGroups().get(vplexURI.toString());
log.info("Consistency group(s) already created: " + cgNames.toString());
if (!cg.getTypes().contains(Types.VPLEX.name())) {
// SRDF will reset the CG types. If the CG was existing on VPLEX need to make sure it is in types.
cg.addConsistencyGroupTypes(Types.VPLEX.name());
dbClient.updateObject(cg);
}
WorkflowStepCompleter.stepSucceded(stepId);
return;
}
// We need to know on what cluster to create the consistency group.
// The cluster would be determined by the virtual array specified in
// a volume creation request, which is the virtual array of the
// passed virtual volumes. Get the virtual array for one of the
// vplex volumes.
Volume firstVPlexVolume = getDataObject(Volume.class, vplexVolumeURIs.get(0), dbClient);
// Lets determine the VPlex consistency group that need to be created for this volume.
ClusterConsistencyGroupWrapper clusterConsistencyGroup = getClusterConsistencyGroup(firstVPlexVolume, cg);
String cgName = clusterConsistencyGroup.getCgName();
String clusterName = clusterConsistencyGroup.getClusterName();
boolean isDistributed = clusterConsistencyGroup.isDistributed();
URI vaURI = firstVPlexVolume.getVirtualArray();
log.info("Got virtual array for VPLEX volume.");
// Now we can create the consistency group.
client.createConsistencyGroup(cgName, clusterName, isDistributed);
log.info("Created VPLEX consistency group.");
// Create the rollback data in case this needs to be deleted.
VPlexCGRollbackData rbData = new VPlexCGRollbackData();
rbData.setVplexSystemURI(vplexURI);
rbData.setCgName(cgName);
rbData.setClusterName(clusterName);
rbData.setIsDistributed(new Boolean(getIsCGDistributed(client, cgName, clusterName)));
workflowService.storeStepData(stepId, rbData);
// Now update the CG in the DB.
cg.setVirtualArray(vaURI);
cg.setStorageController(vplexURI);
cg.addSystemConsistencyGroup(vplexSystem.getId().toString(), BlockConsistencyGroupUtils.buildClusterCgName(clusterName, cgName));
cg.addConsistencyGroupTypes(Types.VPLEX.name());
dbClient.persistObject(cg);
log.info("Updated consistency group in DB.");
// Update workflow step state to success.
WorkflowStepCompleter.stepSucceded(stepId);
log.info("Updated workflow step for consistency group creation to success.");
} catch (VPlexApiException vex) {
log.error("Exception creating consistency group: " + vex.getMessage(), vex);
WorkflowStepCompleter.stepFailed(stepId, vex);
} catch (Exception ex) {
log.error("Exception creating consistency group: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.CREATE_CONSISTENCY_GROUP.getName();
ServiceError serviceError = VPlexApiException.errors.createConsistencyGroupFailed(opName, ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.
the class VPlexConsistencyGroupManager method setCGProperties.
/**
* Called by the workflow to set the properties for an existing VPLEX
* consistency group with no volumes.
*
* @param vplexURI The URI of the VPLEX storage system.
* @param cgURI The URI of the Bourne consistency group.
* @param vplexVolumeURIs The URIs of the VPLEX volumes to be added to the
* consistency group.
* @param stepId The workflow step id.
*
* @throws WorkflowException When an error occurs updating the workflow step
* state.
*/
public void setCGProperties(URI vplexURI, URI cgURI, List<URI> vplexVolumeURIs, String stepId) throws WorkflowException {
try {
// Update workflow step.
WorkflowStepCompleter.stepExecuting(stepId);
log.info("Updated step state for consistency group properties to execute.");
// Lock the CG for the step duration.
List<String> lockKeys = new ArrayList<String>();
lockKeys.add(ControllerLockingUtil.getConsistencyGroupStorageKey(dbClient, cgURI, vplexURI));
workflowService.acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.RP_VPLEX_CG));
// Get the API client.
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, dbClient);
VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexSystem, dbClient);
log.info("Got VPLEX API client.");
// Get the consistency group
BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, dbClient);
// We need to know on what cluster to find the consistency group.
// The cluster would be determined by the virtual array specified in
// a volume creation request, which is the virtual array of the
// passed virtual volumes. Get the virtual array for one of the
// vplex volumes.
Volume firstVPlexVolume = getDataObject(Volume.class, vplexVolumeURIs.get(0), dbClient);
ClusterConsistencyGroupWrapper clusterConsistencyGroup = getClusterConsistencyGroup(firstVPlexVolume, cg);
String cgName = clusterConsistencyGroup.getCgName();
String clusterName = clusterConsistencyGroup.getClusterName();
boolean isDistributed = clusterConsistencyGroup.isDistributed();
// Now we can update the consistency group properties.
client.updateConsistencyGroupProperties(cgName, clusterName, isDistributed);
log.info("Updated VPLEX consistency group properties.");
// Update workflow step state to success.
WorkflowStepCompleter.stepSucceded(stepId);
log.info("Updated workflow step for consistency group properties to success.");
} catch (VPlexApiException vae) {
log.error("Exception updating consistency group properties: " + vae.getMessage(), vae);
WorkflowStepCompleter.stepFailed(stepId, vae);
} catch (Exception ex) {
log.error("Exception updating consistency group properties: " + ex.getMessage(), ex);
ServiceError serviceError = VPlexApiException.errors.jobFailed(ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.
the class VPlexConsistencyGroupManager method addVplexVolumesToSRDFTargetCG.
/**
* This workflow step will add vplex volumes fronting an SRDF target volume to the SRDF target consistency group.
* Note that the SRDF target consistency group may not be created until the SRDF Pairing operation has completed.
* At this time the underlying SRDF Targets will be associated with the correct CG. For this reason, we don't know
* what consistency group to associate the Vplex volumes with until the SRDF pairing operation has completed, and
* the workflow is executing.
*
* So here we find the appropriate SRDF target volume(s), determine the CG, and then set up code to
* create the Vplex CG and add the volume to that.
*
* @param vplexURI -- URI of VPlex system
* @param vplexVolumeURIs -- List of VPLEX Volume URIs fronting SRDF Target volumes
* @param stepId -- The step ID being processed
* @throws WorkflowException
*/
public void addVplexVolumesToSRDFTargetCG(URI vplexURI, List<URI> vplexVolumeURIs, String stepId) throws WorkflowException {
try {
// Make a map of the VPlex volume to corresponding SRDF volume
Map<Volume, Volume> vplexToSrdfVolumeMap = VPlexSrdfUtil.makeVplexToSrdfVolumeMap(dbClient, vplexVolumeURIs);
// Make sure that the SRDF volumes have a consistency group and it is the same.
URI cgURI = null;
for (Volume srdfVolume : vplexToSrdfVolumeMap.values()) {
if (srdfVolume.getConsistencyGroup() != null) {
if (cgURI == null) {
cgURI = srdfVolume.getConsistencyGroup();
} else {
if (srdfVolume.getConsistencyGroup() != cgURI) {
log.info("Multiple CGs discovered: " + cgURI.toString() + " " + srdfVolume.getConsistencyGroup().toString());
}
}
}
}
// If there is no consistency group, That is not an error.
if (cgURI == null) {
WorkflowStepCompleter.stepSucceded(stepId);
return;
}
// Get the consistency group, and make sure it has requested type Vplex. Change the VPlex volumes to point to the CG.
BlockConsistencyGroup consistencyGroup = dbClient.queryObject(BlockConsistencyGroup.class, cgURI);
if (!consistencyGroup.getRequestedTypes().contains(Types.VPLEX)) {
consistencyGroup.addRequestedTypes(Arrays.asList(Types.VPLEX.name()));
dbClient.updateObject(consistencyGroup);
}
Volume protoVolume = null;
for (Volume vplexVolume : vplexToSrdfVolumeMap.keySet()) {
protoVolume = vplexVolume;
break;
}
StorageSystem vplexSystem = dbClient.queryObject(StorageSystem.class, protoVolume.getStorageController());
// and we return.
if (createVplexCG(vplexSystem, consistencyGroup, protoVolume, stepId) == false) {
return;
}
// Add the Vplex volumes to the CG, and fire off the Step completer.
addVolumesToCG(vplexSystem, consistencyGroup, vplexToSrdfVolumeMap.keySet(), stepId);
} catch (Exception ex) {
log.info("Exception adding Vplex volumes to SRDF Target CG: " + ex.getMessage(), ex);
ServiceError svcError = VPlexApiException.errors.jobFailed(ex);
WorkflowStepCompleter.stepFailed(stepId, svcError);
}
}
Aggregations