use of com.emc.storageos.db.client.model.ExportGroup in project coprhd-controller by CoprHD.
the class RPDeviceController method exportOrchestrationSteps.
/**
* @param volumeDescriptors
* - Volume descriptors
* @param rpSystemId
* - RP system
* @param taskId
* - task ID
* @return - True on success, false otherwise
* @throws InternalException
*/
public boolean exportOrchestrationSteps(List<VolumeDescriptor> volumeDescriptors, URI rpSystemId, String taskId) throws InternalException {
List<URI> volUris = VolumeDescriptor.getVolumeURIs(volumeDescriptors);
RPCGExportOrchestrationCompleter completer = new RPCGExportOrchestrationCompleter(volUris, taskId);
Workflow workflow = null;
boolean lockException = false;
Map<URI, Set<URI>> exportGroupVolumesAdded = new HashMap<URI, Set<URI>>();
exportGroupsCreated = new ArrayList<URI>();
final String COMPUTE_RESOURCE_CLUSTER = "cluster";
try {
final String workflowKey = "rpExportOrchestration";
if (!WorkflowService.getInstance().hasWorkflowBeenCreated(taskId, workflowKey)) {
// Generate the Workflow.
workflow = _workflowService.getNewWorkflow(this, EXPORT_ORCHESTRATOR_WF_NAME, true, taskId);
// the wait for key returned by previous call
String waitFor = null;
ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, rpSystemId);
// Get the CG Params based on the volume descriptors
CGRequestParams params = this.getCGRequestParams(volumeDescriptors, rpSystem);
updateCGParams(params);
_log.info("Start adding RP Export Volumes steps....");
// Get the RP Exports from the CGRequestParams object
Collection<RPExport> rpExports = generateStorageSystemExportMaps(params, volumeDescriptors);
Map<String, Set<URI>> rpSiteInitiatorsMap = getRPSiteInitiators(rpSystem, rpExports);
// Acquire all the RP lock keys needed for export before we start assembling the export groups.
acquireRPLockKeysForExport(taskId, rpExports, rpSiteInitiatorsMap);
// or create a new one.
for (RPExport rpExport : rpExports) {
URI storageSystemURI = rpExport.getStorageSystem();
String internalSiteName = rpExport.getRpSite();
URI varrayURI = rpExport.getVarray();
List<URI> volumes = rpExport.getVolumes();
List<URI> initiatorSet = new ArrayList<URI>();
String rpSiteName = (rpSystem.getRpSiteNames() != null) ? rpSystem.getRpSiteNames().get(internalSiteName) : internalSiteName;
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, storageSystemURI);
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, varrayURI);
_log.info("--------------------");
_log.info(String.format("RP Export: StorageSystem = [%s] RPSite = [%s] VirtualArray = [%s]", storageSystem.getLabel(), rpSiteName, varray.getLabel()));
boolean isJournalExport = rpExport.getIsJournalExport();
String exportGroupGeneratedName = RPHelper.generateExportGroupName(rpSystem, storageSystem, internalSiteName, varray, isJournalExport);
// Setup the export group - we may or may not need to create it, but we need to have everything ready in case we do
ExportGroup exportGroup = RPHelper.createRPExportGroup(exportGroupGeneratedName, varray, _dbClient.queryObject(Project.class, params.getProject()), 0, isJournalExport);
// Get the initiators of the RP Cluster (all of the RPAs on one side of a configuration)
Map<String, Map<String, String>> rpaWWNs = RPHelper.getRecoverPointClient(rpSystem).getInitiatorWWNs(internalSiteName);
if (rpaWWNs == null || rpaWWNs.isEmpty()) {
throw DeviceControllerExceptions.recoverpoint.noInitiatorsFoundOnRPAs();
}
// Convert to initiator object
List<Initiator> initiators = new ArrayList<Initiator>();
for (String rpaId : rpaWWNs.keySet()) {
for (Map.Entry<String, String> rpaWWN : rpaWWNs.get(rpaId).entrySet()) {
Initiator initiator = ExportUtils.getInitiator(rpaWWN.getKey(), _dbClient);
initiators.add(initiator);
}
}
// We need to find and distill only those RP initiators that correspond to the network of the
// storage
// system and
// that network has front end port from the storage system.
// In certain lab environments, its quite possible that there are 2 networks one for the storage
// system
// FE ports and one for
// the BE ports.
// In such configs, RP initiators will be spread across those 2 networks. RP controller does not
// care
// about storage system
// back-end ports, so
// we will ignore those initiators that are connected to a network that has only storage system back
// end
// port connectivity.
Map<URI, Set<Initiator>> rpNetworkToInitiatorsMap = new HashMap<URI, Set<Initiator>>();
Set<URI> rpSiteInitiatorUris = rpSiteInitiatorsMap.get(internalSiteName);
if (rpSiteInitiatorUris != null) {
for (URI rpSiteInitiatorUri : rpSiteInitiatorUris) {
Initiator rpSiteInitiator = _dbClient.queryObject(Initiator.class, rpSiteInitiatorUri);
URI rpInitiatorNetworkURI = getInitiatorNetwork(exportGroup, rpSiteInitiator);
if (rpInitiatorNetworkURI != null) {
if (rpNetworkToInitiatorsMap.get(rpInitiatorNetworkURI) == null) {
rpNetworkToInitiatorsMap.put(rpInitiatorNetworkURI, new HashSet<Initiator>());
}
rpNetworkToInitiatorsMap.get(rpInitiatorNetworkURI).add(rpSiteInitiator);
_log.info(String.format("RP Initiator [%s] found on network: [%s]", rpSiteInitiator.getInitiatorPort(), rpInitiatorNetworkURI.toASCIIString()));
} else {
_log.info(String.format("RP Initiator [%s] was not found on any network. Excluding from automated exports", rpSiteInitiator.getInitiatorPort()));
}
}
}
// Compute numPaths. This is how its done:
// We know the RP site and the Network/TransportZone it is on.
// Determine all the storage ports for the storage array for all the networks they are on.
// Next, if we find the network for the RP site in the above list, return all the storage ports
// corresponding to that.
// For RP we will try and use as many Storage ports as possible.
Map<URI, List<StoragePort>> initiatorPortMap = getInitiatorPortsForArray(rpNetworkToInitiatorsMap, storageSystemURI, varrayURI, rpSiteName);
for (URI networkURI : initiatorPortMap.keySet()) {
for (StoragePort storagePort : initiatorPortMap.get(networkURI)) {
_log.info(String.format("Network : [%s] - Port : [%s]", networkURI.toString(), storagePort.getLabel()));
}
}
int numPaths = computeNumPaths(initiatorPortMap, varrayURI, storageSystem);
_log.info("Total paths = " + numPaths);
// Stems from above comment where we distill the RP network and the initiators in that network.
List<Initiator> initiatorList = new ArrayList<Initiator>();
for (URI rpNetworkURI : rpNetworkToInitiatorsMap.keySet()) {
if (initiatorPortMap.containsKey(rpNetworkURI)) {
initiatorList.addAll(rpNetworkToInitiatorsMap.get(rpNetworkURI));
}
}
for (Initiator initiator : initiatorList) {
initiatorSet.add(initiator.getId());
}
// See if the export group already exists
ExportGroup exportGroupInDB = exportGroupExistsInDB(exportGroup);
boolean addExportGroupToDB = false;
if (exportGroupInDB != null) {
exportGroup = exportGroupInDB;
// If the export already exists, check to see if any of the volumes have already been exported.
// No
// need to
// re-export volumes.
List<URI> volumesToRemove = new ArrayList<URI>();
for (URI volumeURI : volumes) {
if (exportGroup.getVolumes() != null && !exportGroup.getVolumes().isEmpty() && exportGroup.getVolumes().containsKey(volumeURI.toString())) {
_log.info(String.format("Volume [%s] already exported to export group [%s], " + "it will be not be re-exported", volumeURI.toString(), exportGroup.getGeneratedName()));
volumesToRemove.add(volumeURI);
}
}
// Remove volumes if they have already been exported
if (!volumesToRemove.isEmpty()) {
volumes.removeAll(volumesToRemove);
}
// nothing else needs to be done here.
if (volumes.isEmpty()) {
_log.info(String.format("No volumes needed to be exported to export group [%s], continue", exportGroup.getGeneratedName()));
continue;
}
} else {
addExportGroupToDB = true;
}
// Add volumes to the export group
Map<URI, Integer> volumesToAdd = new HashMap<URI, Integer>();
for (URI volumeID : volumes) {
exportGroup.addVolume(volumeID, ExportGroup.LUN_UNASSIGNED);
volumesToAdd.put(volumeID, ExportGroup.LUN_UNASSIGNED);
}
// Keep track of volumes added to export group
if (!volumesToAdd.isEmpty()) {
exportGroupVolumesAdded.put(exportGroup.getId(), volumesToAdd.keySet());
}
// volume
if (rpExport.getComputeResource() != null) {
URI computeResource = rpExport.getComputeResource();
_log.info(String.format("RP Export: ComputeResource : %s", computeResource.toString()));
if (computeResource.toString().toLowerCase().contains(COMPUTE_RESOURCE_CLUSTER)) {
Cluster cluster = _dbClient.queryObject(Cluster.class, computeResource);
exportGroup.addCluster(cluster);
} else {
Host host = _dbClient.queryObject(Host.class, rpExport.getComputeResource());
exportGroup.addHost(host);
}
}
// Persist the export group
if (addExportGroupToDB) {
exportGroup.addInitiators(initiatorSet);
exportGroup.setNumPaths(numPaths);
_dbClient.createObject(exportGroup);
// Keep track of newly created EGs in case of rollback
exportGroupsCreated.add(exportGroup.getId());
} else {
_dbClient.updateObject(exportGroup);
}
// If the export group already exists, add the volumes to it, otherwise create a brand new
// export group.
StringBuilder buffer = new StringBuilder();
buffer.append(String.format(DASHED_NEWLINE));
if (!addExportGroupToDB) {
buffer.append(String.format("Adding volumes to existing Export Group for Storage System [%s], RP Site [%s], Virtual Array [%s]%n", storageSystem.getLabel(), rpSiteName, varray.getLabel()));
buffer.append(String.format("Export Group name is : [%s]%n", exportGroup.getGeneratedName()));
buffer.append(String.format("Export Group will have these volumes added: [%s]%n", Joiner.on(',').join(volumes)));
buffer.append(String.format(DASHED_NEWLINE));
_log.info(buffer.toString());
waitFor = _exportWfUtils.generateExportGroupAddVolumes(workflow, STEP_EXPORT_GROUP, waitFor, storageSystemURI, exportGroup.getId(), volumesToAdd);
_log.info("Added Export Group add volumes step in workflow");
} else {
buffer.append(String.format("Creating new Export Group for Storage System [%s], RP Site [%s], Virtual Array [%s]%n", storageSystem.getLabel(), rpSiteName, varray.getLabel()));
buffer.append(String.format("Export Group name is: [%s]%n", exportGroup.getGeneratedName()));
buffer.append(String.format("Export Group will have these initiators: [%s]%n", Joiner.on(',').join(initiatorSet)));
buffer.append(String.format("Export Group will have these volumes added: [%s]%n", Joiner.on(',').join(volumes)));
buffer.append(String.format(DASHED_NEWLINE));
_log.info(buffer.toString());
String exportStep = workflow.createStepId();
initTaskStatus(exportGroup, exportStep, Operation.Status.pending, "create export");
waitFor = _exportWfUtils.generateExportGroupCreateWorkflow(workflow, STEP_EXPORT_GROUP, waitFor, storageSystemURI, exportGroup.getId(), volumesToAdd, initiatorSet);
_log.info("Added Export Group create step in workflow. New Export Group Id: " + exportGroup.getId());
}
}
String successMessage = "Export orchestration completed successfully";
// Finish up and execute the plan.
// The Workflow will handle the TaskCompleter
Object[] callbackArgs = new Object[] { volUris };
workflow.executePlan(completer, successMessage, new WorkflowCallback(), callbackArgs, null, null);
// Mark this workflow as created/executed so we don't do it again on retry/resume
WorkflowService.getInstance().markWorkflowBeenCreated(taskId, workflowKey);
}
} 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.warn(String.format("Lock retry exception key: %s remaining time %d", ex.getLockIdentifier(), ex.getRemainingWaitTimeSeconds()));
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) {
_log.error("Could not create volumes: " + volUris, ex);
// Rollback ViPR level RP export group changes
rpExportGroupRollback();
if (workflow != null) {
_workflowService.releaseAllWorkflowLocks(workflow);
}
String opName = ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME.getName();
ServiceError serviceError = null;
if (lockException) {
serviceError = DeviceControllerException.errors.createVolumesAborted(volUris.toString(), ex);
} else {
serviceError = DeviceControllerException.errors.createVolumesFailed(volUris.toString(), opName, ex);
}
completer.error(_dbClient, _locker, serviceError);
return false;
}
_log.info("End adding RP Export Volumes steps.");
return true;
}
use of com.emc.storageos.db.client.model.ExportGroup in project coprhd-controller by CoprHD.
the class RPDeviceController method createExportGroupRollbackStep.
/**
* Recoverpoint specific rollback for creating an Export Group
* NOTE: Workflow.Method requires that opId is added as a param.
*
* @param exportGroupURI
* @param opId
* @throws ControllerException
*/
public void createExportGroupRollbackStep(URI exportGroupURI, String opId) throws ControllerException {
try {
_log.info(String.format("rollbackCreateRPExportGroup start - Export Group: [%s]", exportGroupURI));
WorkflowStepCompleter.stepExecuting(opId);
// If there was a rollback triggered, we need to cleanup the Export Group we created.
ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
exportGroup.setInactive(true);
_dbClient.updateObject(exportGroup);
_log.info(String.format("Rollback complete for Export Group: [%s]", exportGroupURI));
WorkflowStepCompleter.stepSucceded(opId);
_log.info(String.format("rollbackCreateRPExportGroup end - Export Group: [%s]", exportGroupURI));
} catch (InternalException e) {
_log.error(String.format("rollbackCreateRPExportGroup Failed - Export Group: [%s]", exportGroupURI));
WorkflowStepCompleter.stepFailed(opId, e);
} catch (Exception e) {
_log.error(String.format("rollbackCreateRPExportGroup Failed - Export Group: [%s]", exportGroupURI));
WorkflowStepCompleter.stepFailed(opId, DeviceControllerException.errors.jobFailed(e));
}
}
use of com.emc.storageos.db.client.model.ExportGroup in project coprhd-controller by CoprHD.
the class RPDeviceController method rpExportGroupRollback.
/**
* ViPR level deletion/update of any RP Export Groups that are newly created. If they are pre-existing,
* then we simply want to remove any volume references that had been added to those Export Groups.
*/
private void rpExportGroupRollback() {
// Rollback any newly created export groups
if (exportGroupsCreated != null && !exportGroupsCreated.isEmpty()) {
for (URI exportGroupURI : exportGroupsCreated) {
ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
if (exportGroup != null && !exportGroup.getInactive()) {
_log.info(String.format("Marking ExportGroup [%s](%s) for deletion.", exportGroup.getLabel(), exportGroup.getId()));
_dbClient.markForDeletion(exportGroup);
}
}
}
// Rollback any volumes that have been added/persisted to existing export groups
if (exportGroupVolumesAdded != null && !exportGroupVolumesAdded.isEmpty()) {
for (Entry<URI, Set<URI>> entry : exportGroupVolumesAdded.entrySet()) {
if (entry.getValue() != null && !entry.getValue().isEmpty()) {
if (exportGroupsCreated != null && !exportGroupsCreated.isEmpty()) {
if (exportGroupsCreated.contains(entry.getKey())) {
// We already marked this EG for deletion, so keep going.
continue;
}
}
ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, entry.getKey());
_log.info(String.format("Removing volumes (%s) from ExportGroup (%s).", entry.getValue(), entry.getKey()));
exportGroup.removeVolumes(new ArrayList<URI>(entry.getValue()));
_dbClient.updateObject(exportGroup);
}
}
}
}
use of com.emc.storageos.db.client.model.ExportGroup in project coprhd-controller by CoprHD.
the class RPDeviceController method disableImageAccessStep.
/**
* Workflow step method for disabling an image access of all snapshots in an export group
*
* @param rpSystem
* RP system
* @param token
* the task
* @return true if successful
* @param exportGroupID
* export group ID
* @throws ControllerException
*/
public boolean disableImageAccessStep(URI rpSystemId, URI exportGroupURI, String token) throws ControllerException {
try {
WorkflowStepCompleter.stepExecuting(token);
List<URI> snapshots = new ArrayList<URI>();
// In order to find all of the snapshots to deactivate, go through the devices, find the RP snapshots, and
// deactivate any active
// ones
ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
for (String exportVolumeIDStr : exportGroup.getVolumes().keySet()) {
URI blockID;
blockID = new URI(exportVolumeIDStr);
BlockObject block = BlockObject.fetch(_dbClient, blockID);
if (block.getProtectionController() != null) {
if (block.getId().toString().contains("BlockSnapshot")) {
// Collect this snapshot; it needs to be disabled
snapshots.add(block.getId());
}
}
}
disableImageForSnapshots(rpSystemId, new ArrayList<URI>(snapshots), false, token);
// Update the workflow state.
WorkflowStepCompleter.stepSucceded(token);
} catch (Exception e) {
_log.error(String.format("disableImageAccessStep Failed - Protection System: %s, export group: %s", String.valueOf(rpSystemId), String.valueOf(exportGroupURI)));
return stepFailed(token, e, "disableImageAccessStep");
}
return true;
}
use of com.emc.storageos.db.client.model.ExportGroup in project coprhd-controller by CoprHD.
the class BlockDeviceExportController method updatePolicyAndLimits.
@Override
public void updatePolicyAndLimits(List<URI> volumeURIs, URI newVpoolURI, String opId) throws ControllerException {
_log.info("Received request to update Auto-tiering policy. Creating master workflow.");
VolumeVpoolAutoTieringPolicyChangeTaskCompleter taskCompleter = null;
URI oldVpoolURI = null;
List<Volume> volumes = new ArrayList<Volume>();
List<Volume> vplexBackendVolumes = new ArrayList<Volume>();
try {
// Read volume from database, update the vPool to the new vPool
// and update new auto tiering policy uri, and create task completer.
volumes = _dbClient.queryObject(Volume.class, volumeURIs);
VirtualPool newVpool = _dbClient.queryObject(VirtualPool.class, newVpoolURI);
Map<URI, URI> oldVolToPolicyMap = new HashMap<URI, URI>();
for (Volume volume : volumes) {
oldVpoolURI = volume.getVirtualPool();
volume.setVirtualPool(newVpoolURI);
_log.info(String.format("Changing VirtualPool Auto-tiering Policy for volume %s (%s) from %s to %s", volume.getLabel(), volume.getId(), oldVpoolURI, newVpoolURI));
oldVolToPolicyMap.put(volume.getId(), volume.getAutoTieringPolicyUri());
updateAutoTieringPolicyUriInVolume(volume, newVpool);
// 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);
vplexBackendVolumes.add(backendSrc);
_log.info(String.format("Changing VirtualPool Auto-tiering Policy for VPLEX backend source volume %s (%s) from %s to %s", backendSrc.getLabel(), backendSrc.getId(), oldVpoolURI, newVpoolURI));
oldVolToPolicyMap.put(backendSrc.getId(), backendSrc.getAutoTieringPolicyUri());
updateAutoTieringPolicyUriInVolume(backendSrc, newVpool);
// VPlex volume, check if it is distributed
Volume backendHa = VPlexUtil.getVPLEXBackendVolume(volume, false, _dbClient, false);
if (backendHa != null) {
VirtualPool newHAVpool = VirtualPool.getHAVPool(newVpool, _dbClient);
if (newHAVpool == null) {
// it may not be set
newHAVpool = newVpool;
}
backendHa.setVirtualPool(newHAVpool.getId());
vplexBackendVolumes.add(backendHa);
_log.info(String.format("Changing VirtualPool Auto-tiering Policy for VPLEX backend distributed volume %s (%s) from %s to %s", backendHa.getLabel(), backendHa.getId(), oldVpoolURI, newHAVpool.getId()));
oldVolToPolicyMap.put(backendHa.getId(), backendHa.getAutoTieringPolicyUri());
updateAutoTieringPolicyUriInVolume(backendHa, newHAVpool);
}
}
}
_dbClient.updateObject(volumes);
_dbClient.updateObject(vplexBackendVolumes);
// The VolumeVpoolChangeTaskCompleter will restore the old Virtual Pool
// and old auto tiering policy in event of error.
// Assume all volumes belong to the same vPool. This should be take care by BlockService API.
taskCompleter = new VolumeVpoolAutoTieringPolicyChangeTaskCompleter(volumeURIs, oldVpoolURI, oldVolToPolicyMap, opId);
} catch (Exception ex) {
_log.error("Unexpected exception reading volume or generating taskCompleter: ", ex);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
VolumeWorkflowCompleter completer = new VolumeWorkflowCompleter(volumeURIs, opId);
completer.error(_dbClient, serviceError);
}
try {
Workflow workflow = _wfUtils.newWorkflow("updateAutoTieringPolicy", false, opId);
/**
* For VMAX:
* get corresponding export mask for each volume
* group volumes by export mask
* create workflow step for each export mask.
*
* For VNX Block:
* Policy is set on volume during its creation.
* Whether it is exported or not, send all volumes
* to update StorageTierMethodology property on them.
* Create workflow step for each storage system.
*/
// Use backend volumes list if it is VPLEX volume
List<Volume> volumesToUse = !vplexBackendVolumes.isEmpty() ? vplexBackendVolumes : volumes;
// move applicable volumes from all volumes list to a separate list.
Map<URI, List<URI>> systemToVolumeMap = getVolumesToModify(volumesToUse);
String stepId = null;
for (URI systemURI : systemToVolumeMap.keySet()) {
stepId = _wfUtils.generateExportChangePolicyAndLimits(workflow, "updateAutoTieringPolicy", stepId, systemURI, null, null, systemToVolumeMap.get(systemURI), newVpoolURI, oldVpoolURI);
}
Map<URI, List<URI>> storageToNotExportedVolumesMap = new HashMap<URI, List<URI>>();
Map<URI, List<URI>> exportMaskToVolumeMap = new HashMap<URI, List<URI>>();
Map<URI, URI> maskToGroupURIMap = new HashMap<URI, URI>();
for (Volume volume : volumesToUse) {
// Locate all the ExportMasks containing the given volume
Map<ExportMask, ExportGroup> maskToGroupMap = ExportUtils.getExportMasks(volume, _dbClient);
if (maskToGroupMap.isEmpty()) {
URI storageURI = volume.getStorageController();
StorageSystem storage = _dbClient.queryObject(StorageSystem.class, storageURI);
if (storage.checkIfVmax3()) {
if (!storageToNotExportedVolumesMap.containsKey(storageURI)) {
storageToNotExportedVolumesMap.put(storageURI, new ArrayList<URI>());
}
storageToNotExportedVolumesMap.get(storageURI).add(volume.getId());
}
}
for (ExportMask mask : maskToGroupMap.keySet()) {
if (!exportMaskToVolumeMap.containsKey(mask.getId())) {
exportMaskToVolumeMap.put(mask.getId(), new ArrayList<URI>());
}
exportMaskToVolumeMap.get(mask.getId()).add(volume.getId());
maskToGroupURIMap.put(mask.getId(), maskToGroupMap.get(mask).getId());
}
}
VirtualPool oldVpool = _dbClient.queryObject(VirtualPool.class, oldVpoolURI);
for (URI exportMaskURI : exportMaskToVolumeMap.keySet()) {
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
List<URI> exportMaskVolumes = exportMaskToVolumeMap.get(exportMaskURI);
URI exportMaskNewVpool = newVpoolURI;
URI exportMaskOldVpool = oldVpoolURI;
Volume vol = _dbClient.queryObject(Volume.class, exportMaskVolumes.get(0));
// all volumes are already updated with respective new vPool
if (Volume.checkForVplexBackEndVolume(_dbClient, vol) && !newVpoolURI.equals(vol.getVirtualPool())) {
// backend distributed volume; HA vPool set in Vplex vPool
exportMaskNewVpool = vol.getVirtualPool();
VirtualPool oldHAVpool = VirtualPool.getHAVPool(oldVpool, _dbClient);
if (oldHAVpool == null) {
// it may not be set
oldHAVpool = oldVpool;
}
exportMaskOldVpool = oldHAVpool.getId();
}
stepId = _wfUtils.generateExportChangePolicyAndLimits(workflow, "updateAutoTieringPolicy", stepId, exportMask.getStorageDevice(), exportMaskURI, maskToGroupURIMap.get(exportMaskURI), exportMaskVolumes, exportMaskNewVpool, exportMaskOldVpool);
}
for (URI storageURI : storageToNotExportedVolumesMap.keySet()) {
stepId = _wfUtils.generateChangeAutoTieringPolicy(workflow, "updateAutoTieringPolicyForNotExportedVMAX3Volumes", stepId, storageURI, storageToNotExportedVolumesMap.get(storageURI), newVpoolURI, oldVpoolURI);
}
if (!workflow.getAllStepStatus().isEmpty()) {
_log.info("The updateAutoTieringPolicy workflow has {} step(s). Starting the workflow.", workflow.getAllStepStatus().size());
workflow.executePlan(taskCompleter, "Updated 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