use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.
the class BlockDeviceController method attachNativeContinuousCopies.
@Override
public void attachNativeContinuousCopies(URI storage, URI sourceVolume, List<URI> mirrorList, String opId) throws ControllerException {
_log.info("START attach continuous copies workflow");
Workflow workflow = _workflowService.getNewWorkflow(this, ATTACH_MIRRORS_WF_NAME, true, opId);
TaskCompleter taskCompleter = null;
Volume sourceVolumeObj = _dbClient.queryObject(Volume.class, sourceVolume);
boolean isCG = sourceVolumeObj.isInCG();
try {
addStepsForCreateMirrors(workflow, null, storage, sourceVolume, mirrorList, isCG);
taskCompleter = new BlockMirrorTaskCompleter(BlockMirror.class, mirrorList, opId);
workflow.executePlan(taskCompleter, "Successfully attached continuous copies");
} catch (Exception e) {
String msg = String.format("Failed to execute attach continuous copies workflow for volume %s", sourceVolume);
_log.error(msg, e);
if (taskCompleter != null) {
ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
taskCompleter.error(_dbClient, serviceError);
}
}
}
use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.
the class BlockDeviceController method addStepsForRestoreVolume.
@Override
public String addStepsForRestoreVolume(Workflow workflow, String waitFor, URI storage, URI pool, URI volume, URI snapshot, Boolean updateOpStatus, String syncDirection, String taskId, BlockSnapshotRestoreCompleter completer) throws ControllerException {
BlockSnapshot snap = _dbClient.queryObject(BlockSnapshot.class, snapshot);
URI parentVolumeURI = snap.getParent().getURI();
Volume parentVolume = _dbClient.queryObject(Volume.class, parentVolumeURI);
Volume associatedVPlexVolume = Volume.fetchVplexVolume(_dbClient, parentVolume);
// VPlex controller will add the required block restore steps.
if (NullColumnValueGetter.isNotNullValue(snap.getTechnologyType()) && !snap.getTechnologyType().equals(TechnologyType.NATIVE.toString()) || associatedVPlexVolume != null) {
return waitFor;
}
Workflow.Method restoreVolumeMethod = new Workflow.Method(RESTORE_VOLUME_METHOD_NAME, storage, pool, volume, snapshot, Boolean.TRUE, syncDirection);
workflow.createStep(RESTORE_VOLUME_STEP, String.format("Restore volume %s from snapshot %s", volume, snapshot), waitFor, storage, getDeviceType(storage), BlockDeviceController.class, restoreVolumeMethod, rollbackMethodNullMethod(), null);
_log.info("Created workflow step to restore block volume {} from snapshot {}", volume, snapshot);
return RESTORE_VOLUME_STEP;
}
use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.
the class BlockDeviceController method restoreVolume.
@Override
public void restoreVolume(URI storage, URI pool, URI volumeURI, URI snapshot, Boolean updateOpStatus, String syncDirection, String opId) throws ControllerException {
SimpleTaskCompleter completer = new SimpleTaskCompleter(BlockSnapshot.class, snapshot, opId);
try {
Workflow workflow = _workflowService.getNewWorkflow(this, RESTORE_VOLUME_WF_NAME, false, opId);
_log.info("Created new restore workflow with operation id {}", opId);
Volume volume = _dbClient.queryObject(Volume.class, volumeURI);
BlockSnapshot blockSnapshot = _dbClient.queryObject(BlockSnapshot.class, snapshot);
StorageSystem system = _dbClient.queryObject(StorageSystem.class, storage);
String description = String.format("Restore volume %s from snapshot %s", volumeURI, snapshot);
String waitFor = null;
URI srdfSourceStorageSystemURI = null;
Volume srdfSourceVolume = null;
Volume srdfTargetVolume = null;
boolean active = false;
/**
* We need to split the SRDF link for R2 snap restore if it is not paused already.
* Refer OPT#476788
*/
if (isNonSplitSRDFTargetVolume(volume)) {
URI srdfSourceVolumeURI = volume.getSrdfParent().getURI();
srdfSourceVolume = _dbClient.queryObject(Volume.class, srdfSourceVolumeURI);
srdfTargetVolume = volume;
srdfSourceStorageSystemURI = srdfSourceVolume.getStorageController();
if (Mode.ACTIVE.equals(Mode.valueOf(volume.getSrdfCopyMode()))) {
active = true;
waitFor = suspendSRDFLinkWorkflowStep(waitFor, srdfSourceStorageSystemURI, srdfSourceVolumeURI, volumeURI, workflow);
} else {
// split all members the group
Workflow.Method splitMethod = srdfDeviceController.splitSRDFGroupLinkMethod(srdfSourceStorageSystemURI, srdfSourceVolumeURI, volumeURI, false);
Workflow.Method splitRollbackMethod = srdfDeviceController.resumeGroupPairsMethod(srdfSourceStorageSystemURI, srdfSourceVolumeURI, volumeURI);
waitFor = workflow.createStep(SRDFDeviceController.SPLIT_SRDF_MIRRORS_STEP_GROUP, SRDFDeviceController.SPLIT_SRDF_MIRRORS_STEP_DESC, waitFor, srdfSourceStorageSystemURI, getDeviceType(srdfSourceStorageSystemURI), SRDFDeviceController.class, splitMethod, splitRollbackMethod, null);
}
} else if (isNonSplitSRDFSourceVolume(volume)) {
srdfSourceVolume = volume;
srdfSourceStorageSystemURI = volume.getStorageController();
StringSet targets = volume.getSrdfTargets();
if (null != targets) {
for (String target : targets) {
if (NullColumnValueGetter.isNotNullValue(target)) {
srdfTargetVolume = _dbClient.queryObject(Volume.class, URI.create(target));
if (null != srdfTargetVolume && Mode.ACTIVE.equals(Mode.valueOf(srdfTargetVolume.getSrdfCopyMode()))) {
active = true;
waitFor = suspendSRDFLinkWorkflowStep(waitFor, srdfSourceStorageSystemURI, volume.getId(), srdfTargetVolume.getId(), workflow);
}
break;
}
}
}
}
if (system.checkIfVmax3()) {
_log.info("Creating workflow for restore VMAX3 snapshot {}", blockSnapshot.getId());
// To restore the source from a linked target volume for VMAX3 SnapVX, we must
// do the following:
//
// 1. Terminate any stale restore sessions on the source.
// 2. Create a temporary snapvx snapshot session of the linked target volume or target group.
// 3. Link the source volume(s) of the BlockSnapshot(s) to the temporary snapshot session in copy mode.
// 4. Wait for the data from the session to be copied to the source volume(s)
// 5. Unlink the source volume(s) from the temporary snapvx snapshot session.
// 6. Delete the temporary session.
//
// This is essentially restoring by creating a cascaded snapshot session or group
// snapshot session on the linked target volume associated with the passed block
// snapshot or associated linked target group in the case of a group operation.
// Create a workflow step to terminate stale restore sessions.
waitFor = workflow.createStep(BLOCK_VOLUME_RESTORE_GROUP, String.format("Terminating VMAX restore session from %s to %s", blockSnapshot.getId(), volume.getId()), waitFor, system.getId(), system.getSystemType(), BlockDeviceController.class, terminateRestoreSessionsMethod(system.getId(), volume.getId(), blockSnapshot.getId()), rollbackMethodNullMethod(), null);
// Get all snapshots if this is a group snapshot.
String replicationGroupName = null;
List<BlockSnapshot> allSnapshots = new ArrayList<>();
String replicationGroupId = blockSnapshot.getReplicationGroupInstance();
if (!NullColumnValueGetter.isNullValue(replicationGroupId)) {
allSnapshots.addAll(ControllerUtils.getSnapshotsPartOfReplicationGroup(blockSnapshot, _dbClient));
int nameStartIndex = replicationGroupId.indexOf("+") + 1;
replicationGroupName = replicationGroupId.substring(nameStartIndex);
} else {
allSnapshots.add(blockSnapshot);
}
// Create a temporary BlockSnapshot instance to represent the parent source volumes
// for each block snapshot. Linking to a session required BlockSnapshot instances so
// we need to create some to represent the source volume(s).
StringSet linkedTargets = new StringSet();
List<BlockSnapshot> sourceSnapshots = new ArrayList<>();
List<URI> sourceSnapshotURIs = new ArrayList<>();
URI cgURI = blockSnapshot.getConsistencyGroup();
for (BlockSnapshot aSnapshot : allSnapshots) {
BlockObject aSourceObj = BlockObject.fetch(_dbClient, aSnapshot.getParent().getURI());
BlockSnapshot sourceSnapshot = new BlockSnapshot();
URI sourceSnapshotURI = URIUtil.createId(BlockSnapshot.class);
sourceSnapshot.setId(sourceSnapshotURI);
sourceSnapshot.setNativeId(aSourceObj.getNativeId());
sourceSnapshot.setParent(new NamedURI(aSnapshot.getId(), aSnapshot.getLabel()));
sourceSnapshot.setSourceNativeId(aSnapshot.getNativeId());
sourceSnapshot.setStorageController(storage);
sourceSnapshot.setSystemType(system.getSystemType());
if (!NullColumnValueGetter.isNullURI(cgURI)) {
sourceSnapshot.setConsistencyGroup(cgURI);
}
sourceSnapshot.addInternalFlags(Flag.INTERNAL_OBJECT);
sourceSnapshots.add(sourceSnapshot);
sourceSnapshotURIs.add(sourceSnapshotURI);
linkedTargets.add(sourceSnapshotURI.toString());
}
_dbClient.createObject(sourceSnapshots);
// Create a BlockSnapshotSession instance to represent the temporary snapshot session.
BlockSnapshotSession snapSession = new BlockSnapshotSession();
URI snapSessionURI = URIUtil.createId(BlockSnapshotSession.class);
snapSession.setId(snapSessionURI);
snapSession.setLabel(blockSnapshot.getLabel() + System.currentTimeMillis());
snapSession.setSessionLabel(snapSession.getLabel());
snapSession.setProject(blockSnapshot.getProject());
snapSession.setStorageController(storage);
snapSession.addInternalFlags(Flag.INTERNAL_OBJECT);
if (!NullColumnValueGetter.isNullURI(cgURI) && NullColumnValueGetter.isNotNullValue(replicationGroupName)) {
snapSession.setConsistencyGroup(cgURI);
snapSession.setReplicationGroupInstance(replicationGroupName);
snapSession.setSessionSetName(replicationGroupName);
} else {
snapSession.setParent(new NamedURI(blockSnapshot.getId(), blockSnapshot.getLabel()));
}
snapSession.setLinkedTargets(linkedTargets);
_dbClient.createObject(snapSession);
// Now create a workflow step that will create the snapshot session.
// This will create a group session in the case of a group operation.
waitFor = workflow.createStep(CREATE_SNAPSHOT_SESSION_STEP_GROUP, String.format("Create snapshot session %s for snapshot target volume %s", snapSessionURI, snapshot), waitFor, storage, getDeviceType(storage), BlockDeviceController.class, createBlockSnapshotSessionMethod(storage, snapSessionURI, replicationGroupName), deleteBlockSnapshotSessionMethod(storage, snapSessionURI, replicationGroupName, Boolean.TRUE), null);
// Create a workflow step to link the source volume for the passed snapshot
// to the snapshot session create by the previous step. We link the source
// volume in copy mode so that that the point-in-time copy of the snapshot
// target volume represented by the snapshot session is copied to the source
// volume. This is essentially the restore step so that the source will now
// reflect the data on the snapshot target volume. This step will not complete
// until the data is copied and the link has achieved the copied state. If this
// is group operation the source target group will be linked to the created
// group session.
Workflow.Method linkMethod;
if (!NullColumnValueGetter.isNullURI(cgURI) && NullColumnValueGetter.isNotNullValue(replicationGroupName)) {
linkMethod = linkBlockSnapshotSessionTargetGroupMethod(storage, snapSessionURI, sourceSnapshotURIs, BlockSnapshotSession.CopyMode.copy.name(), Boolean.TRUE);
} else {
linkMethod = linkBlockSnapshotSessionTargetMethod(storage, snapSessionURI, sourceSnapshotURIs.get(0), BlockSnapshotSession.CopyMode.copy.name(), Boolean.TRUE);
}
waitFor = workflow.createStep(LINK_SNAPSHOT_SESSION_TARGET_STEP_GROUP, String.format("Link source volume %s to snapshot session for snapshot target volume %s", volume, snapshot), waitFor, storage, getDeviceType(storage), BlockDeviceController.class, linkMethod, unlinkBlockSnapshotSessionTargetMethod(storage, snapSessionURI, sourceSnapshotURIs.get(0), Boolean.FALSE), null);
// Once the data is fully copied to the source, we can unlink the source from the session.
// Again, for a group operation, this will unlink the source group from the group session.
waitFor = workflow.createStep(UNLINK_SNAPSHOT_SESSION_TARGET_STEP_GROUP, String.format("Unlink source volume %s from snapshot session for snapshot target volume %s", volumeURI, snapshot), waitFor, storage, getDeviceType(storage), BlockDeviceController.class, unlinkBlockSnapshotSessionTargetMethod(storage, snapSessionURI, sourceSnapshotURIs.get(0), Boolean.FALSE), rollbackMethodNullMethod(), null);
// Finally create a step to delete the snapshot session we created on the snapshot
// target volume.
waitFor = workflow.createStep(DELETE_SNAPSHOT_SESSION_STEP_GROUP, String.format("Delete snapshot session %s for snapshot target volume %s", snapSessionURI, snapshot), waitFor, storage, getDeviceType(storage), BlockDeviceController.class, deleteBlockSnapshotSessionMethod(storage, snapSessionURI, replicationGroupName, Boolean.TRUE), rollbackMethodNullMethod(), null);
/*
* If Active mode then create a step to resume srdf group or restore R2 To R1 or do nothing.
* If syncdirection is not specified means its null then after R1 snapshot restore, resume.
* If syncdirection is not specified means its null then after R2 snapshot restore, restore R2 to R1.
* If syncdirection is SOURCE_TO_TARGET then after R1 or R2 snapshot restore, resume.
* If syncdirection is TARGET_TO_SOURCE then after R1 or R2 snapshot restore, restore R2 to R1.
* If syncdirection is NONE then do nothing, RDF group will stay in suspend state.
*/
if (active) {
if (null == syncDirection) {
if (null != srdfSourceVolume && volumeURI.equals(srdfSourceVolume.getId())) {
resumeSRDFLinkWorkflowStep(waitFor, srdfSourceStorageSystemURI, srdfSourceVolume.getId(), srdfTargetVolume.getId(), workflow);
} else if (null != srdfTargetVolume && volumeURI.equals(srdfTargetVolume.getId())) {
restoreWorkflowStep(waitFor, srdfTargetVolume.getStorageController(), srdfSourceVolume.getId(), srdfTargetVolume.getId(), workflow);
}
} else if (null != syncDirection) {
if (SRDFUtils.SyncDirection.SOURCE_TO_TARGET.toString().equals(syncDirection)) {
resumeSRDFLinkWorkflowStep(waitFor, srdfSourceStorageSystemURI, srdfSourceVolume.getId(), srdfTargetVolume.getId(), workflow);
} else if (SRDFUtils.SyncDirection.TARGET_TO_SOURCE.toString().equals(syncDirection)) {
restoreWorkflowStep(waitFor, srdfTargetVolume.getStorageController(), srdfSourceVolume.getId(), srdfTargetVolume.getId(), workflow);
} else if (SRDFUtils.SyncDirection.NONE.toString().equals(syncDirection)) {
_log.info("Sync direction is specified as {} hence no action will be done after retsore snapshot which" + " means the RDF group for volume {} will be in a suspended state.", syncDirection, volume.getLabel());
}
}
}
} else {
waitFor = workflow.createStep(BLOCK_VOLUME_RESTORE_GROUP, description, waitFor, storage, getDeviceType(storage), BlockDeviceController.class, restoreVolumeMethod(storage, pool, volumeURI, snapshot, updateOpStatus), rollbackMethodNullMethod(), null);
// Skip the step for VMAX3, as restore operation may still be in progress (OPT#476325)
// Regardless, termination of restore session should be call before restore
// Note this is not needed for VNX
addPostRestoreVolumeSteps(workflow, system, volume, blockSnapshot, waitFor);
}
_log.info("Executing workflow {}", BLOCK_VOLUME_RESTORE_GROUP);
String msg = String.format("Restore of volume %s from %s completed successfully", volumeURI, snapshot);
workflow.executePlan(completer, msg);
} catch (Exception e) {
String msg = String.format("Could not restore volume %s from snapshot %s", volumeURI, snapshot);
_log.error(msg, e);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
completer.error(_dbClient, serviceError);
}
}
use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.
the class BlockDeviceExportController method exportGroupUpdate.
@Override
public void exportGroupUpdate(URI export, Map<URI, Integer> addedBlockObjectMap, Map<URI, Integer> removedBlockObjectMap, Set<URI> addedClusters, Set<URI> removedClusters, Set<URI> addedHosts, Set<URI> removedHosts, Set<URI> addedInitiators, Set<URI> removedInitiators, String opId) throws ControllerException {
Map<URI, Map<URI, Integer>> addedStorageToBlockObjects = new HashMap<URI, Map<URI, Integer>>();
Map<URI, Map<URI, Integer>> removedStorageToBlockObjects = new HashMap<URI, Map<URI, Integer>>();
Workflow workflow = null;
List<Workflow> workflowList = new ArrayList<>();
try {
computeDiffs(export, addedBlockObjectMap, removedBlockObjectMap, addedStorageToBlockObjects, removedStorageToBlockObjects, addedInitiators, removedInitiators, addedHosts, removedHosts, addedClusters, removedClusters);
// Generate a flat list of volume/snap objects that will be added
// to the export update completer so the completer will know what
// to add upon task completion. We need not carry the block controller
// into the completer, so we strip that out of the map for the benefit of
// keeping the completer simple.
Map<URI, Integer> addedBlockObjects = new HashMap<>();
for (URI storageUri : addedStorageToBlockObjects.keySet()) {
addedBlockObjects.putAll(addedStorageToBlockObjects.get(storageUri));
}
// Generate a flat list of volume/snap objects that will be removed
// to the export update completer so the completer will know what
// to remove upon task completion.
Map<URI, Integer> removedBlockObjects = new HashMap<>();
for (URI storageUri : removedStorageToBlockObjects.keySet()) {
removedBlockObjects.putAll(removedStorageToBlockObjects.get(storageUri));
}
// Construct the export update completer with exactly which objects will
// be removed and added when it is complete.
ExportTaskCompleter taskCompleter = new ExportUpdateCompleter(export, addedBlockObjects, removedBlockObjects, addedInitiators, removedInitiators, addedHosts, removedHosts, addedClusters, removedClusters, opId);
_log.info("Received request to update export group. Creating master workflow.");
workflow = _wfUtils.newWorkflow("exportGroupUpdate", false, opId);
_log.info("Task id {} and workflow uri {}", opId, workflow.getWorkflowURI());
workflowList.add(workflow);
for (URI storageUri : addedStorageToBlockObjects.keySet()) {
_log.info("Creating sub-workflow for storage system {}", String.valueOf(storageUri));
// TODO: Need to fix, getExportMask() returns a single mask,
// but there could be more than 1 for a array and ExportGroup
_wfUtils.generateExportGroupUpdateWorkflow(workflow, null, null, export, getExportMask(export, storageUri), addedStorageToBlockObjects.get(storageUri), removedStorageToBlockObjects.get(storageUri), new ArrayList(addedInitiators), new ArrayList(removedInitiators), storageUri, workflowList);
}
if (!workflow.getAllStepStatus().isEmpty()) {
_log.info("The updateExportWorkflow has {} steps. Starting the workflow.", workflow.getAllStepStatus().size());
workflow.executePlan(taskCompleter, "Update the export group on all storage systems successfully.");
} else {
taskCompleter.ready(_dbClient);
}
} catch (LockRetryException ex) {
/**
* Added this catch block to mark the current workflow as completed so that lock retry will not get exception while creating new
* workflow using the same taskid.
*/
_log.info(String.format("Lock retry exception key: %s remaining time %d", ex.getLockIdentifier(), ex.getRemainingWaitTimeSeconds()));
for (Workflow workflow2 : workflowList) {
if (workflow2 != null) {
boolean status = _wfUtils.getWorkflowService().releaseAllWorkflowLocks(workflow2);
_log.info("Release locks from workflow {} status {}", workflow2.getWorkflowURI(), status);
}
}
if (workflow != null && !NullColumnValueGetter.isNullURI(workflow.getWorkflowURI()) && workflow.getWorkflowState() == WorkflowState.CREATED) {
com.emc.storageos.db.client.model.Workflow wf = _dbClient.queryObject(com.emc.storageos.db.client.model.Workflow.class, workflow.getWorkflowURI());
if (!wf.getCompleted()) {
_log.error("Marking the status to completed for the newly created workflow {}", wf.getId());
wf.setCompleted(true);
_dbClient.updateObject(wf);
}
}
throw ex;
} catch (Exception ex) {
ExportTaskCompleter taskCompleter = new ExportUpdateCompleter(export, opId);
String message = "exportGroupUpdate caught an exception.";
_log.error(message, ex);
for (Workflow workflow2 : workflowList) {
if (workflow2 != null) {
boolean status = _wfUtils.getWorkflowService().releaseAllWorkflowLocks(workflow2);
_log.info("Release locks from workflow {} status {}", workflow2.getWorkflowURI(), status);
}
}
ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
taskCompleter.error(_dbClient, serviceError);
}
}
use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.
the class BlockDeviceExportController method updateVolumePathParams.
@Override
public void updateVolumePathParams(URI volumeURI, URI newVpoolURI, String opId) throws ControllerException {
_log.info("Received request to update Volume path parameters. Creating master workflow.");
VolumeVpoolChangeTaskCompleter taskCompleter = null;
Volume volume = null;
try {
// Read volume from database, update the Vpool to the new completer, and create task completer.
volume = _dbClient.queryObject(Volume.class, volumeURI);
URI oldVpoolURI = volume.getVirtualPool();
List<URI> rollbackList = new ArrayList<URI>();
List<Volume> updatedVolumes = new ArrayList<Volume>();
rollbackList.add(volumeURI);
// Check if it is a VPlex volume, and get backend volumes
Volume backendSrc = VPlexUtil.getVPLEXBackendVolume(volume, true, _dbClient, false);
if (backendSrc != null) {
// Change the back end volume's vpool too
backendSrc.setVirtualPool(newVpoolURI);
rollbackList.add(backendSrc.getId());
updatedVolumes.add(backendSrc);
// VPlex volume, check if it is distributed
Volume backendHa = VPlexUtil.getVPLEXBackendVolume(volume, false, _dbClient, false);
if (backendHa != null && backendHa.getVirtualPool() != null && backendHa.getVirtualPool().toString().equals(oldVpoolURI.toString())) {
backendHa.setVirtualPool(newVpoolURI);
rollbackList.add(backendHa.getId());
updatedVolumes.add(backendHa);
}
}
// The VolumeVpoolChangeTaskCompleter will restore the old Virtual Pool in event of error.
taskCompleter = new VolumeVpoolChangeTaskCompleter(rollbackList, oldVpoolURI, opId);
volume.setVirtualPool(newVpoolURI);
updatedVolumes.add(volume);
_log.info(String.format("Changing VirtualPool PathParams for volume %s (%s) from %s to %s", volume.getLabel(), volume.getId(), oldVpoolURI, newVpoolURI));
_dbClient.updateObject(updatedVolumes);
} catch (Exception ex) {
_log.error("Unexpected exception reading volume or generating taskCompleter: ", ex);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
VolumeWorkflowCompleter completer = new VolumeWorkflowCompleter(volumeURI, opId);
completer.error(_dbClient, serviceError);
}
try {
Workflow workflow = _wfUtils.newWorkflow("updateVolumePathParams", false, opId);
// Locate all the ExportMasks containing the given volume, and their Export Group.
Map<ExportMask, ExportGroup> maskToGroupMap = ExportUtils.getExportMasks(volume, _dbClient);
Map<URI, StringSetMap> maskToZoningMap = new HashMap<URI, StringSetMap>();
// Store the original zoning maps of the export masks to be used to restore in case of a failure
for (ExportMask mask : maskToGroupMap.keySet()) {
maskToZoningMap.put(mask.getId(), mask.getZoningMap());
}
taskCompleter.setMaskToZoningMap(maskToZoningMap);
// Acquire all necessary locks for the workflow:
// For each export group lock initiator's hosts and storage array keys.
List<URI> initiatorURIs = new ArrayList<URI>();
for (ExportGroup exportGroup : maskToGroupMap.values()) {
initiatorURIs.addAll(StringSetUtil.stringSetToUriList(exportGroup.getInitiators()));
List<String> lockKeys = ControllerLockingUtil.getHostStorageLockKeys(_dbClient, ExportGroup.ExportGroupType.valueOf(exportGroup.getType()), initiatorURIs, volume.getStorageController());
initiatorURIs.clear();
boolean acquiredLocks = _wfUtils.getWorkflowService().acquireWorkflowLocks(workflow, lockKeys, LockTimeoutValue.get(LockType.EXPORT_GROUP_OPS));
if (!acquiredLocks) {
throw DeviceControllerException.exceptions.failedToAcquireLock(lockKeys.toString(), "UpdateVolumePathParams: " + volume.getLabel());
}
}
// These steps are serialized, which is required in case an ExportMask appears
// in multiple Export Groups.
String stepId = null;
for (ExportGroup exportGroup : maskToGroupMap.values()) {
stepId = _wfUtils.generateExportChangePathParams(workflow, "changePathParams", stepId, volume.getStorageController(), exportGroup.getId(), volumeURI);
}
if (!workflow.getAllStepStatus().isEmpty()) {
_log.info("The updateVolumePathParams workflow has {} steps. Starting the workflow.", workflow.getAllStepStatus().size());
workflow.executePlan(taskCompleter, "Update the export group on all storage systems successfully.");
} else {
taskCompleter.ready(_dbClient);
}
} catch (Exception ex) {
_log.error("Unexpected exception: ", ex);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
taskCompleter.error(_dbClient, serviceError);
}
}
Aggregations