Search in sources :

Example 1 with ExportMaskAddInitiatorCompleter

use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter in project coprhd-controller by CoprHD.

the class VPlexDeviceController method addStepsForAddInitiators.

/**
 * Add workflow steps for adding Initiators to a specific varray for the given VPlex.
 *
 * @param workflow
 *            -- Workflow steps go into
 * @param vplex
 *            -- Storage system
 * @param exportGroup
 *            -- ExportGroup operation invoked on
 * @param varrayURI
 *            -- Virtual Array URI that the Initiators are in
 * @param hostInitiatorURIs
 *            -- URIs of the Initiators
 * @param initiators
 *            -- list of Initiator objects
 * @param hostURI
 *            -- The hostURI
 * @param previousStepId
 *            -- wait on this step if non-null
 * @param opId
 *            -- step id for our operation
 * @return StepId of last step generated
 */
private String addStepsForAddInitiators(Workflow workflow, StorageSystem vplex, ExportGroup exportGroup, URI varrayURI, List<URI> hostInitiatorURIs, List<Initiator> initiators, URI hostURI, String previousStepId, String opId) throws Exception {
    String lastStepId = null;
    URI vplexURI = vplex.getId();
    URI exportURI = exportGroup.getId();
    String initListStr = Joiner.on(',').join(hostInitiatorURIs);
    // Find the ExportMask for my host.
    ExportMask exportMask = VPlexUtil.getExportMaskForHostInVarray(_dbClient, exportGroup, hostURI, vplexURI, varrayURI);
    if (exportMask == null) {
        _log.info("No export mask found for hostURI: " + hostURI + " varrayURI: " + varrayURI);
        Map<URI, Integer> volumeMap = ExportUtils.getExportGroupVolumeMap(_dbClient, vplex, exportGroup);
        // Partition the Volumes by varray.
        Map<URI, Set<URI>> varrayToVolumes = VPlexUtil.mapBlockObjectsToVarrays(_dbClient, volumeMap.keySet(), vplexURI, exportGroup);
        // Filter the volumes by our Varray.
        Map<URI, Integer> varrayVolumeMap = ExportMaskUtils.filterVolumeMap(volumeMap, varrayToVolumes.get(varrayURI));
        // Create the ExportMask if there are volumes in this varray.
        if (!varrayVolumeMap.isEmpty()) {
            lastStepId = assembleExportMasksWorkflow(vplexURI, exportURI, varrayURI, hostInitiatorURIs, varrayVolumeMap, true, workflow, previousStepId, opId);
        }
    } else {
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
        VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
        _log.info("Refreshing ExportMask {}", exportMask.getMaskName());
        VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName), _networkDeviceController);
        if (exportMask.getVolumes() == null) {
            // This can occur in Brownfield scenarios where we have not added any volumes yet to the HA side,
            // CTRL10760
            _log.info(String.format("No volumes in ExportMask %s (%s), so not adding initiators", exportMask.getMaskName(), exportMask.getId()));
            return lastStepId;
        }
        _log.info(String.format("Adding initiators %s for host %s mask %s (%s)", getInitiatorsWwnsString(initiators), hostURI.toString(), exportMask.getMaskName(), exportMask.getId()));
        // Calculate the path parameters for the volumes in this ExportMask
        Collection<URI> volumeURIs = new HashSet<URI>();
        if (exportMask.getVolumes() != null && !exportMask.getVolumes().isEmpty()) {
            volumeURIs = (Collections2.transform(exportMask.getVolumes().keySet(), CommonTransformerFunctions.FCTN_STRING_TO_URI));
        } else if (exportGroup.getVolumes() != null && !exportGroup.getVolumes().isEmpty()) {
            // Hit this condition
            // in CTRL-9944
            // (unknown why)
            _log.info(String.format("No volumes in ExportMask %s, using ExportGroup %s for ExportPathParam", exportMask.getId(), exportGroup.getId()));
            Map<URI, Integer> volumeMap = ExportUtils.getExportGroupVolumeMap(_dbClient, vplex, exportGroup);
            // Partition the Volumes by varray. Then use only the volumes in the requested varray.
            Map<URI, Set<URI>> varrayToVolumes = VPlexUtil.mapBlockObjectsToVarrays(_dbClient, volumeMap.keySet(), vplexURI, exportGroup);
            volumeURIs = varrayToVolumes.get(varrayURI);
        } else {
            _log.info(String.format("No volumes at all- using default path parameters: %s", exportMask.getId()));
        }
        ExportPathParams pathParams = _blockScheduler.calculateExportPathParamForVolumes(volumeURIs, exportGroup.getNumPaths(), exportMask.getStorageDevice(), exportGroup.getId());
        if (exportGroup.getType() != null) {
            pathParams.setExportGroupType(exportGroup.getType());
        }
        // Assign additional StoragePorts if needed.
        Map<URI, List<URI>> assignments = _blockScheduler.assignStoragePorts(vplex, exportGroup, initiators, exportMask.getZoningMap(), pathParams, volumeURIs, _networkDeviceController, varrayURI, opId);
        List<URI> newTargetURIs = BlockStorageScheduler.getTargetURIsFromAssignments(assignments);
        // Build a list of StoragePort targets to remove during rollback. Do not remove existing storage ports during rollback.
        List<URI> rollbackTargetURIs = new ArrayList<URI>();
        for (URI target : newTargetURIs) {
            if (exportMask.getStoragePorts().contains(target.toString())) {
                // Skip the target port if it exists in the ViPR ExportMask
                continue;
            }
            rollbackTargetURIs.add(target);
        }
        exportMask.addZoningMap(BlockStorageScheduler.getZoneMapFromAssignments(assignments));
        _dbClient.updateObject(exportMask);
        _log.info(String.format("Adding targets %s for host %s", newTargetURIs.toString(), hostURI.toString()));
        // Create a Step to add the SAN Zone
        String zoningStepId = workflow.createStepId();
        Workflow.Method zoningMethod = zoneAddInitiatorStepMethod(vplexURI, exportURI, hostInitiatorURIs, varrayURI);
        Workflow.Method zoningRollbackMethod = zoneRollbackMethod(exportURI, zoningStepId);
        zoningStepId = workflow.createStep(ZONING_STEP, String.format("Zone initiator %s to ExportGroup %s(%s)", initListStr, exportGroup.getLabel(), exportURI), previousStepId, vplexURI, vplex.getSystemType(), this.getClass(), zoningMethod, zoningRollbackMethod, zoningStepId);
        // Create a Step to add the initiator to the Storage View
        String message = String.format("initiators %s to StorageView %s", initListStr, exportGroup.getGeneratedName());
        ExportMask sharedExportMask = VPlexUtil.getSharedExportMaskInDb(exportGroup, vplexURI, _dbClient, varrayURI, null, null);
        boolean shared = false;
        if (null != sharedExportMask && sharedExportMask.getId().equals(exportMask.getId())) {
            shared = true;
        }
        String addInitStep = workflow.createStepId();
        ExportMaskAddInitiatorCompleter addInitCompleter = new ExportMaskAddInitiatorCompleter(exportURI, exportMask.getId(), hostInitiatorURIs, newTargetURIs, addInitStep);
        Workflow.Method addToViewMethod = storageViewAddInitiatorsMethod(vplexURI, exportURI, exportMask.getId(), hostInitiatorURIs, newTargetURIs, shared, addInitCompleter);
        Workflow.Method addToViewRollbackMethod = storageViewAddInitiatorsRollbackMethod(vplexURI, exportURI, exportMask.getId(), hostInitiatorURIs, rollbackTargetURIs, addInitStep);
        lastStepId = workflow.createStep("storageView", "Add " + message, zoningStepId, vplexURI, vplex.getSystemType(), this.getClass(), addToViewMethod, addToViewRollbackMethod, addInitStep);
    }
    return lastStepId;
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) Set(java.util.Set) HashSet(java.util.HashSet) StringSet(com.emc.storageos.db.client.model.StringSet) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) ExportMaskAddInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) ApplicationAddVolumeList(com.emc.storageos.volumecontroller.ApplicationAddVolumeList) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) Map(java.util.Map) OpStatusMap(com.emc.storageos.db.client.model.OpStatusMap) HashMap(java.util.HashMap) StringMap(com.emc.storageos.db.client.model.StringMap) HashSet(java.util.HashSet) ExportPathParams(com.emc.storageos.db.client.model.ExportPathParams)

Example 2 with ExportMaskAddInitiatorCompleter

use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter in project coprhd-controller by CoprHD.

the class VPlexDeviceController method portRebalance.

@Override
public void portRebalance(URI vplex, URI exportGroupURI, URI varray, URI exportMaskURI, Map<URI, List<URI>> adjustedPaths, Map<URI, List<URI>> removedPaths, boolean isAdd, String stepId) throws Exception {
    // Retrieve the ExportGroup and ExportMask and validate
    ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
    ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
    if (exportGroup == null || exportMask == null || exportGroup.getInactive() || exportMask.getInactive() || !exportGroup.hasMask(exportMaskURI)) {
        String reason = String.format("Bad exportGroup %s or exportMask %s", exportGroupURI, exportMaskURI);
        _log.error(reason);
        ServiceCoded coded = WorkflowException.exceptions.workflowConstructionError(reason);
        WorkflowStepCompleter.stepFailed(stepId, coded);
        return;
    }
    // Check if the ExportMask is in the desired varray (in cross-coupled ExportGroups)
    if (!ExportMaskUtils.exportMaskInVarray(_dbClient, exportMask, varray)) {
        _log.info(String.format("ExportMask %s (%s) not in specified varray %s", exportMask.getMaskName(), exportMask.getId(), varray));
        WorkflowStepCompleter.stepSucceeded(stepId, String.format("No operation done: Mask not in specified varray %s", varray));
        return;
    }
    // Refresh the ExportMask so we have the latest data.
    StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplex, _dbClient);
    VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
    String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplex, client, _dbClient);
    VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
    _log.info("Processing and Refreshing ExportMask {}", exportMask.getMaskName());
    Map<String, String> targetPortToPwwnMap = VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName);
    VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, targetPortToPwwnMap, _networkDeviceController);
    // Determine hosts in ExportMask
    Set<URI> hostsInExportMask = new HashSet<URI>();
    Set<String> hostNames = ExportMaskUtils.getHostNamesInMask(exportMask, _dbClient);
    Set<Initiator> initiatorsInMask = ExportMaskUtils.getInitiatorsForExportMask(_dbClient, exportMask, null);
    for (Initiator initiator : initiatorsInMask) {
        if (initiator.getHost() != null) {
            hostsInExportMask.add(initiator.getHost());
        }
    }
    boolean sharedMask = (hostsInExportMask.size() > 1);
    if (isAdd) {
        // Processing added paths only
        Workflow workflow = _workflowService.getNewWorkflow(this, "portRebalance", false, stepId);
        // Determine initiators and targets to be added.
        // These are initiators not in mask that are in a host in the mask.
        // Earlier versions of the Vplex code may not have had all the initiators in the mask, as
        // earlier code only put initiators in the Storage View for which ports were added.
        // Targets to be added may be on existing initiators or newly added initiators.
        List<URI> initiatorsToAdd = new ArrayList<URI>();
        List<URI> targetsToAdd = new ArrayList<URI>();
        for (URI initiatorURI : adjustedPaths.keySet()) {
            if (!exportMask.hasInitiator(initiatorURI.toString())) {
                // Initiator not in ExportMask
                Initiator initiator = _dbClient.queryObject(Initiator.class, initiatorURI);
                if (initiator != null && !initiator.getInactive()) {
                    if (hostsInExportMask.contains(initiator.getHost())) {
                        initiatorsToAdd.add(initiatorURI);
                        for (URI targetURI : adjustedPaths.get(initiatorURI)) {
                            if (!exportMask.hasTargets(Arrays.asList(targetURI)) && !targetsToAdd.contains(targetURI)) {
                                targetsToAdd.add(targetURI);
                            }
                        }
                    }
                }
            } else {
                // Initiator already in ExportMask, look for additional targets
                for (URI targetURI : adjustedPaths.get(initiatorURI)) {
                    if (!exportMask.hasTargets(Arrays.asList(targetURI)) && !targetsToAdd.contains(targetURI)) {
                        targetsToAdd.add(targetURI);
                    }
                }
            }
        }
        _log.info("Targets to add: " + targetsToAdd.toString());
        _log.info("Initiators to add: " + initiatorsToAdd.toString());
        // Invoke either storageViewAddInitiators if there are initiators to be added (it will add targets also),
        // or storageViewAddStoragePorts if no initiators to be added (which adds only targets).
        Workflow.Method addPathsMethod = null;
        if (!initiatorsToAdd.isEmpty() || !targetsToAdd.isEmpty()) {
            String addInitiatorStepId = workflow.createStepId();
            ExportMaskAddInitiatorCompleter completer = new ExportMaskAddInitiatorCompleter(exportGroupURI, exportMaskURI, initiatorsToAdd, targetsToAdd, addInitiatorStepId);
            ;
            if (!initiatorsToAdd.isEmpty()) {
                addPathsMethod = storageViewAddInitiatorsMethod(vplex, exportGroupURI, exportMaskURI, initiatorsToAdd, targetsToAdd, sharedMask, completer);
            } else if (!targetsToAdd.isEmpty()) {
                addPathsMethod = storageViewAddStoragePortsMethod(vplex, exportGroupURI, exportMaskURI, targetsToAdd, completer);
            }
            String description = String.format("Adding paths to ExportMask %s Hosts %s", exportMask.getMaskName(), hostNames.toString());
            workflow.createStep("addPaths", description, null, vplex, vplexSystem.getSystemType(), this.getClass(), addPathsMethod, null, false, addInitiatorStepId);
            ExportMaskAddPathsCompleter workflowCompleter = new ExportMaskAddPathsCompleter(exportGroupURI, exportMaskURI, stepId);
            workflow.executePlan(workflowCompleter, description + " completed successfully");
            return;
        }
    } else {
        // Processing the paths to be removed only, Paths not in the removedPaths map will be retained.
        // Note that we only remove ports (targets), never initiators.
        Workflow workflow = _workflowService.getNewWorkflow(this, "portRebalance", false, stepId);
        // Compute the targets to be removed.
        Set<URI> targetsToBeRemoved = ExportMaskUtils.getAllPortsInZoneMap(removedPaths);
        Collection<URI> targetsInMask = Collections2.transform(exportMask.getStoragePorts(), CommonTransformerFunctions.FCTN_STRING_TO_URI);
        targetsToBeRemoved.retainAll(targetsInMask);
        Set<URI> targetsToBeRetained = ExportMaskUtils.getAllPortsInZoneMap(adjustedPaths);
        targetsToBeRemoved.removeAll(targetsToBeRetained);
        List<URI> portsToBeRemoved = new ArrayList<URI>(targetsToBeRemoved);
        _log.info("Targets to be removed: " + portsToBeRemoved.toString());
        // Call storageViewRemoveStoragePorts to remove any necessary targets.
        Workflow.Method removePathsMethod = null;
        if (!portsToBeRemoved.isEmpty()) {
            String removeInitiatorStepId = workflow.createStepId();
            removePathsMethod = storageViewRemoveStoragePortsMethod(vplex, exportGroupURI, exportMaskURI, portsToBeRemoved, null);
            String description = String.format("Removing paths to ExportMask %s Hosts %s", exportMask.getMaskName(), hostNames.toString());
            workflow.createStep("removePaths", description, null, vplex, vplexSystem.getSystemType(), this.getClass(), removePathsMethod, null, false, removeInitiatorStepId);
            ExportMaskRemovePathsCompleter workflowCompleter = new ExportMaskRemovePathsCompleter(exportGroupURI, exportMaskURI, stepId);
            workflowCompleter.setRemovedStoragePorts(portsToBeRemoved);
            workflow.executePlan(workflowCompleter, description + " completed successfully");
            return;
        }
    }
    // Apparently nothing to do, return success
    WorkflowStepCompleter.stepSucceeded(stepId, "No operation performed on VPLEX mask");
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) ExportMask(com.emc.storageos.db.client.model.ExportMask) ExportMaskAddPathsCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddPathsCompleter) ArrayList(java.util.ArrayList) ExportMaskAddInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) Initiator(com.emc.storageos.db.client.model.Initiator) ServiceCoded(com.emc.storageos.svcs.errorhandling.model.ServiceCoded) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) ExportMaskRemovePathsCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemovePathsCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) HashSet(java.util.HashSet)

Example 3 with ExportMaskAddInitiatorCompleter

use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter in project coprhd-controller by CoprHD.

the class VPlexDeviceController method addStepsForExportMaskUpdate.

/**
 * Handles adding ExportMask updates into the export workflow.
 *
 * @param exportGroupUri
 *            the ViPR ExportGroup in question
 * @param blockObjectMap
 *            the map of URIs to block volumes for export
 * @param workflow
 *            the controller Workflow
 * @param vplexSystem
 *            a StorageSystem objet representing the VPLEX
 * @param exportMasksToUpdateOnDeviceWithInitiators
 *            map of ExportMasks to update to initiators
 * @param exportMasksToUpdateOnDeviceWithStoragePorts
 *            map of ExportMasks to update to storage ports
 * @param storageViewStepId
 *            the current workflow step id, to be updated on return
 * @param exportMask
 *            the ExportMask object to be updated
 * @param sharedVplexExportMask
 *            boolean that indicates whether passed exportMask is shared for multiple host
 * @return
 */
private String addStepsForExportMaskUpdate(URI exportGroupUri, Map<URI, Integer> blockObjectMap, Workflow workflow, StorageSystem vplexSystem, Map<URI, List<Initiator>> exportMasksToUpdateOnDeviceWithInitiators, Map<URI, List<URI>> exportMasksToUpdateOnDeviceWithStoragePorts, String storageViewStepId, ExportMask exportMask, boolean sharedVplexExportMask) {
    _log.info("adding steps to update export mask: " + exportMask.getMaskName());
    String addVolumeStepId = workflow.createStepId();
    // Add a step to update export mask on the VPlex.
    Workflow.Method storageViewExecuteMethod = new Workflow.Method(STORAGE_VIEW_ADD_VOLUMES_METHOD, vplexSystem.getId(), exportGroupUri, exportMask.getId(), blockObjectMap);
    Workflow.Method storageViewRollbackMethod = storageViewAddVolumesRollbackMethod(vplexSystem.getId(), exportGroupUri, exportMask.getId(), new ArrayList<URI>(blockObjectMap.keySet()), addVolumeStepId);
    storageViewStepId = workflow.createStep("storageView", String.format("Updating VPLEX Storage View for ExportGroup %s Mask %s", exportGroupUri, exportMask.getMaskName()), storageViewStepId, vplexSystem.getId(), vplexSystem.getSystemType(), this.getClass(), storageViewExecuteMethod, storageViewRollbackMethod, addVolumeStepId);
    if (exportMasksToUpdateOnDeviceWithInitiators.get(exportMask.getId()) != null) {
        List<Initiator> initiatorsToAdd = exportMasksToUpdateOnDeviceWithInitiators.get(exportMask.getId());
        List<URI> initiatorURIs = new ArrayList<URI>();
        for (Initiator initiator : initiatorsToAdd) {
            initiatorURIs.add(initiator.getId());
        }
        String addInitStep = workflow.createStepId();
        ExportMaskAddInitiatorCompleter completer = new ExportMaskAddInitiatorCompleter(exportGroupUri, exportMask.getId(), initiatorURIs, new ArrayList<URI>(), addInitStep);
        Workflow.Method addInitiatorMethod = storageViewAddInitiatorsMethod(vplexSystem.getId(), exportGroupUri, exportMask.getId(), initiatorURIs, null, sharedVplexExportMask, completer);
        Workflow.Method initiatorRollback = storageViewAddInitiatorsRollbackMethod(vplexSystem.getId(), exportGroupUri, exportMask.getId(), initiatorURIs, null, addInitStep);
        storageViewStepId = workflow.createStep("storageView", String.format("Updating VPLEX Storage View Initiators for ExportGroup %s Mask %s", exportGroupUri, exportMask.getMaskName()), storageViewStepId, vplexSystem.getId(), vplexSystem.getSystemType(), this.getClass(), addInitiatorMethod, initiatorRollback, addInitStep);
    }
    if (exportMasksToUpdateOnDeviceWithStoragePorts.containsKey(exportMask.getId())) {
        List<URI> storagePortURIsToAdd = exportMasksToUpdateOnDeviceWithStoragePorts.get(exportMask.getId());
        String addPortStep = workflow.createStepId();
        ExportMaskAddInitiatorCompleter completer = new ExportMaskAddInitiatorCompleter(exportGroupUri, exportMask.getId(), new ArrayList<URI>(), storagePortURIsToAdd, addPortStep);
        // Create a Step to add storage ports to the Storage View
        Workflow.Method addPortsToViewMethod = storageViewAddStoragePortsMethod(vplexSystem.getId(), exportGroupUri, exportMask.getId(), storagePortURIsToAdd, completer);
        Workflow.Method addToViewRollbackMethod = storageViewAddStoragePortsRollbackMethod(vplexSystem.getId(), exportGroupUri, exportMask.getId(), storagePortURIsToAdd, addPortStep);
        storageViewStepId = workflow.createStep("storageView", String.format("Updating VPLEX Storage View StoragePorts for ExportGroup %s Mask %s", exportGroupUri, exportMask.getMaskName()), storageViewStepId, vplexSystem.getId(), vplexSystem.getSystemType(), this.getClass(), addPortsToViewMethod, addToViewRollbackMethod, addPortStep);
    }
    return storageViewStepId;
}
Also used : Initiator(com.emc.storageos.db.client.model.Initiator) ArrayList(java.util.ArrayList) ExportMaskAddInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI)

Example 4 with ExportMaskAddInitiatorCompleter

use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter in project coprhd-controller by CoprHD.

the class VPlexDeviceController method increaseMaxPaths.

@Override
public void increaseMaxPaths(Workflow workflow, StorageSystem vplex, ExportGroup exportGroup, ExportMask exportMask, List<URI> newInitiators, String token) throws Exception {
    // Allocate any new ports that are required for the initiators
    // and update the zoning map in the exportMask.
    List<Initiator> initiators = _dbClient.queryObject(Initiator.class, newInitiators);
    Collection<URI> volumeURIs = (Collections2.transform(exportMask.getVolumes().keySet(), CommonTransformerFunctions.FCTN_STRING_TO_URI));
    ExportPathParams pathParams = _blockScheduler.calculateExportPathParamForVolumes(volumeURIs, exportGroup.getNumPaths(), vplex.getId(), exportGroup.getId());
    if (exportGroup.getType() != null) {
        pathParams.setExportGroupType(exportGroup.getType());
    }
    // Determine the Varray for the targets. Default to ExportGroup.virtualArray
    URI varrayURI = exportGroup.getVirtualArray();
    if (exportGroup.hasAltVirtualArray(vplex.getId().toString())) {
        URI altVarrayURI = URI.create(exportGroup.getAltVirtualArrays().get(vplex.getId().toString()));
        if (ExportMaskUtils.exportMaskInVarray(_dbClient, exportMask, altVarrayURI)) {
            // If the targets match the alternate varray, use that instead.
            varrayURI = altVarrayURI;
        }
    }
    // Assign additional storage port(s).
    Map<URI, List<URI>> assignments = _blockScheduler.assignStoragePorts(vplex, exportGroup, initiators, exportMask.getZoningMap(), pathParams, volumeURIs, _networkDeviceController, varrayURI, token);
    List<URI> newTargets = BlockStorageScheduler.getTargetURIsFromAssignments(assignments);
    exportMask.addZoningMap(BlockStorageScheduler.getZoneMapFromAssignments(assignments));
    _dbClient.updateObject(exportMask);
    if (newTargets.isEmpty() == false) {
        // Only include initiators that were assigned ports in the Storage View.
        // If we include any inititators that are not assigned and zoned to ports,
        // creation or update of the Storage View will fail because we won't be
        // able to register those initiators.
        List<URI> storageViewInitiators = newInitiators;
        // Create a Step to add the initiator to the Storage View
        String message = String.format("adding initiators %s to StorageView %s", storageViewInitiators.toString(), exportGroup.getGeneratedName());
        ExportMask sharedExportMask = VPlexUtil.getSharedExportMaskInDb(exportGroup, vplex.getId(), _dbClient, varrayURI, null, null);
        boolean shared = false;
        if (null != sharedExportMask && sharedExportMask.getId().equals(exportMask.getId())) {
            shared = true;
        }
        String addInitStep = workflow.createStepId();
        ExportMaskAddInitiatorCompleter completer = new ExportMaskAddInitiatorCompleter(exportGroup.getId(), exportMask.getId(), storageViewInitiators, new ArrayList<URI>(), addInitStep);
        Workflow.Method addToViewMethod = storageViewAddInitiatorsMethod(vplex.getId(), exportGroup.getId(), exportMask.getId(), storageViewInitiators, null, shared, completer);
        Workflow.Method addToViewRollbackMethod = storageViewAddInitiatorsRollbackMethod(vplex.getId(), exportGroup.getId(), exportMask.getId(), storageViewInitiators, null, addInitStep);
        workflow.createStep(STORAGE_VIEW_ADD_INITS_METHOD, message, null, vplex.getId(), vplex.getSystemType(), this.getClass(), addToViewMethod, addToViewRollbackMethod, addInitStep);
        // Create a Step to add storage ports to the Storage View
        String addPortStep = workflow.createStepId();
        ExportMaskAddInitiatorCompleter portCompleter = new ExportMaskAddInitiatorCompleter(exportGroup.getId(), exportMask.getId(), new ArrayList<URI>(), newTargets, addPortStep);
        Workflow.Method addPortsToViewMethod = storageViewAddStoragePortsMethod(vplex.getId(), exportGroup.getId(), exportMask.getId(), newTargets, portCompleter);
        Workflow.Method addPortsToViewRollbackMethod = storageViewAddStoragePortsRollbackMethod(vplex.getId(), exportGroup.getId(), exportMask.getId(), newTargets, addPortStep);
        workflow.createStep(STORAGE_VIEW_ADD_STORAGE_PORTS_METHOD, String.format("Adding storage ports %s to VPLEX storage View %s", Joiner.on(", ").join(newTargets), exportGroup.getGeneratedName()), addInitStep, vplex.getId(), vplex.getSystemType(), this.getClass(), addPortsToViewMethod, addPortsToViewRollbackMethod, addPortStep);
        List<ExportMask> exportMasks = ExportMaskUtils.getExportMasks(_dbClient, exportGroup, vplex.getId());
        Map<URI, List<URI>> maskToInitiatorsMap = new HashMap<URI, List<URI>>();
        Set<URI> zoningInitiators = new HashSet<>();
        for (ExportMask mask : exportMasks) {
            boolean sharedMask = false;
            if (sharedExportMask != null) {
                if (sharedExportMask.getId().equals(mask.getId())) {
                    sharedMask = true;
                }
            }
            maskToInitiatorsMap.put(mask.getId(), new ArrayList<URI>());
            Set<URI> exportMaskHosts = VPlexUtil.getExportMaskHosts(_dbClient, mask, sharedMask);
            // Only add initiators to this ExportMask that are on the host of the Export Mask
            for (Initiator initiator : initiators) {
                if (exportMaskHosts.contains(VPlexUtil.getInitiatorHost(initiator))) {
                    maskToInitiatorsMap.get(mask.getId()).add(initiator.getId());
                    zoningInitiators.add(initiator.getId());
                }
            }
        }
        // Create a Step to add the SAN Zone
        String zoningStepId = workflow.createStepId();
        Workflow.Method zoningMethod = _networkDeviceController.zoneExportAddInitiatorsMethod(exportGroup.getId(), maskToInitiatorsMap);
        List<NetworkZoningParam> zoningParams = NetworkZoningParam.convertExportMaskInitiatorMapsToNetworkZoningParam(exportGroup.getId(), maskToInitiatorsMap, _dbClient);
        Workflow.Method zoningRollbackMethod = _networkDeviceController.zoneExportRemoveInitiatorsMethod(zoningParams);
        zoningStepId = workflow.createStep(ZONING_STEP, String.format("Zone initiator %s to ExportGroup %s(%s)", Joiner.on(", ").join(zoningInitiators), exportGroup.getLabel(), exportGroup.getId()), addPortStep, vplex.getId(), vplex.getSystemType(), _networkDeviceController.getClass(), zoningMethod, zoningRollbackMethod, zoningStepId);
    }
}
Also used : HashMap(java.util.HashMap) ExportMask(com.emc.storageos.db.client.model.ExportMask) ExportMaskAddInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) NetworkZoningParam(com.emc.storageos.networkcontroller.impl.NetworkZoningParam) Initiator(com.emc.storageos.db.client.model.Initiator) ApplicationAddVolumeList(com.emc.storageos.volumecontroller.ApplicationAddVolumeList) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) ExportPathParams(com.emc.storageos.db.client.model.ExportPathParams) HashSet(java.util.HashSet)

Example 5 with ExportMaskAddInitiatorCompleter

use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter in project coprhd-controller by CoprHD.

the class AbstractDefaultMaskingOrchestrator method generateExportMaskAddInitiatorsWorkflow.

/**
 * Generate workflow steps to add initiators to an export mask
 *
 * @param workflow
 *            workflow
 * @param previousStep
 *            previous step ID
 * @param storage
 *            storage device
 * @param exportGroup
 *            export group
 * @param exportMask
 *            export mask
 * @param initiatorURIs
 *            initiator list
 * @param newVolumeURIs
 *            new volume IDs
 * @param token
 *            step ID
 * @return step ID
 * @throws Exception
 */
public String generateExportMaskAddInitiatorsWorkflow(Workflow workflow, String previousStep, StorageSystem storage, ExportGroup exportGroup, ExportMask exportMask, List<URI> initiatorURIs, Set<URI> newVolumeURIs, String token) throws Exception {
    URI exportGroupURI = exportGroup.getId();
    URI exportMaskURI = exportMask.getId();
    URI storageURI = storage.getId();
    List<URI> newTargetURIs = new ArrayList<>();
    List<Initiator> initiators = null;
    if (initiatorURIs != null && !initiatorURIs.isEmpty()) {
        initiators = _dbClient.queryObject(Initiator.class, initiatorURIs);
    } else {
        _log.error("Internal Error: Need to add the initiatorURIs to the call that assembles this step.");
    }
    // Allocate any new ports that are required for the initiators
    // and update the zoning map in the exportMask.
    Collection<URI> volumeURIs = (exportMask.getVolumes() == null) ? newVolumeURIs : (Collection<URI>) (Collections2.transform(exportMask.getVolumes().keySet(), CommonTransformerFunctions.FCTN_STRING_TO_URI));
    if (null == volumeURIs) {
        volumeURIs = new ArrayList<URI>();
    }
    ExportPathParams pathParams = _blockScheduler.calculateExportPathParamForVolumes(volumeURIs, exportGroup.getNumPaths(), storageURI, exportGroupURI);
    if (exportGroup.getType() != null) {
        pathParams.setExportGroupType(exportGroup.getType());
    }
    URI pgURI = exportMask.getPortGroup();
    if (!NullColumnValueGetter.isNullURI(pgURI)) {
        StoragePortGroup portGroup = _dbClient.queryObject(StoragePortGroup.class, pgURI);
        if (!portGroup.getInactive() && !portGroup.getMutable()) {
            _log.info(String.format("Using the port group %s for allocate ports for adding initiators", portGroup.getNativeGuid()));
            pathParams.setStoragePorts(portGroup.getStoragePorts());
        }
    }
    Map<URI, List<URI>> assignments = _blockScheduler.assignStoragePorts(storage, exportGroup, initiators, exportMask.getZoningMap(), pathParams, volumeURIs, _networkDeviceController, exportGroup.getVirtualArray(), token);
    newTargetURIs = BlockStorageScheduler.getTargetURIsFromAssignments(assignments);
    exportMask.addZoningMap(BlockStorageScheduler.getZoneMapFromAssignments(assignments));
    _dbClient.updateObject(exportMask);
    String maskingStep = workflow.createStepId();
    ExportTaskCompleter exportTaskCompleter = new ExportMaskAddInitiatorCompleter(exportGroupURI, exportMask.getId(), initiatorURIs, newTargetURIs, maskingStep);
    Workflow.Method maskingExecuteMethod = new Workflow.Method("doExportGroupAddInitiators", storageURI, exportGroupURI, exportMaskURI, new ArrayList<URI>(volumeURIs), initiatorURIs, newTargetURIs, exportTaskCompleter);
    Workflow.Method rollbackMethod = new Workflow.Method("rollbackExportGroupAddInitiators", storageURI, exportGroupURI, exportMaskURI, new ArrayList<URI>(volumeURIs), initiatorURIs, maskingStep);
    maskingStep = workflow.createStep(EXPORT_GROUP_MASKING_TASK, String.format("Adding initiators to mask %s (%s)", exportMask.getMaskName(), exportMask.getId().toString()), previousStep, storageURI, storage.getSystemType(), MaskingWorkflowEntryPoints.class, maskingExecuteMethod, rollbackMethod, maskingStep);
    return maskingStep;
}
Also used : StoragePortGroup(com.emc.storageos.db.client.model.StoragePortGroup) ExportTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter) ArrayList(java.util.ArrayList) ExportMaskAddInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter) Workflow(com.emc.storageos.workflow.Workflow) URI(java.net.URI) Initiator(com.emc.storageos.db.client.model.Initiator) List(java.util.List) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) ExportPathParams(com.emc.storageos.db.client.model.ExportPathParams)

Aggregations

ExportMaskAddInitiatorCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddInitiatorCompleter)6 Workflow (com.emc.storageos.workflow.Workflow)6 URI (java.net.URI)6 ArrayList (java.util.ArrayList)6 Initiator (com.emc.storageos.db.client.model.Initiator)5 ExportPathParams (com.emc.storageos.db.client.model.ExportPathParams)4 NamedURI (com.emc.storageos.db.client.model.NamedURI)4 List (java.util.List)4 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)3 ExportMask (com.emc.storageos.db.client.model.ExportMask)3 HashSet (java.util.HashSet)3 ApplicationAddVolumeList (com.emc.storageos.volumecontroller.ApplicationAddVolumeList)2 ExportTaskCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter)2 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)2 VPlexStorageViewInfo (com.emc.storageos.vplex.api.VPlexStorageViewInfo)2 HashMap (java.util.HashMap)2 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)1 OpStatusMap (com.emc.storageos.db.client.model.OpStatusMap)1 StoragePortGroup (com.emc.storageos.db.client.model.StoragePortGroup)1 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)1