Search in sources :

Example 16 with BlockStorageDevice

use of com.emc.storageos.volumecontroller.BlockStorageDevice in project coprhd-controller by CoprHD.

the class XIVMaskingOrchestrator method exportGroupAddVolumes.

@Override
public void exportGroupAddVolumes(URI storageURI, URI exportGroupURI, Map<URI, Integer> volumeMap, String token) throws Exception {
    ExportOrchestrationTask taskCompleter = null;
    try {
        BlockStorageDevice device = getDevice();
        taskCompleter = new ExportOrchestrationTask(exportGroupURI, token);
        StorageSystem storage = _dbClient.queryObject(StorageSystem.class, storageURI);
        ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
        boolean anyVolumesAdded = false;
        boolean createdNewMask = false;
        if (exportGroup != null && exportGroup.getExportMasks() != null) {
            // Set up workflow steps.
            Workflow workflow = _workflowService.getNewWorkflow(MaskingWorkflowEntryPoints.getInstance(), "exportGroupAddVolumes", true, token);
            List<ExportMask> exportMasksToZoneAddVolumes = new ArrayList<ExportMask>();
            List<URI> volumesToZoneAddVolumes = new ArrayList<URI>();
            // Add the volume to all the ExportMasks that are contained in the
            // ExportGroup. The volumes should be added only if they don't
            // already exist for the ExportMask.
            Collection<URI> initiatorURIs = Collections2.transform(exportGroup.getInitiators(), CommonTransformerFunctions.FCTN_STRING_TO_URI);
            List<URI> hostURIs = new ArrayList<URI>();
            Map<String, URI> portNameToInitiatorURI = new HashMap<String, URI>();
            List<String> portNames = new ArrayList<String>();
            processInitiators(exportGroup, initiatorURIs, portNames, portNameToInitiatorURI, hostURIs);
            // We always want to have the full list of initiators for the hosts involved in
            // this export. This will allow the export operation to always find any
            // existing exports for a given host.
            queryHostInitiatorsAndAddToList(portNames, portNameToInitiatorURI, initiatorURIs, hostURIs);
            Map<String, Set<URI>> foundMatches = device.findExportMasks(storage, portNames, false);
            // Need to maintain separate Export mask for Cluster and Host.
            // So remove off the Export mask not matching to the Export Group.
            filterExportMaskForGroup(exportGroup, foundMatches);
            Set<String> checkMasks = mergeWithExportGroupMaskURIs(exportGroup, foundMatches.values());
            for (String maskURIStr : checkMasks) {
                ExportMask exportMask = _dbClient.queryObject(ExportMask.class, URI.create(maskURIStr));
                _log.info(String.format("Checking mask %s", exportMask.getMaskName()));
                // Check for NO_VIPR. If found, avoid this mask.
                if (exportMask.getMaskName() != null && exportMask.getMaskName().toUpperCase().contains(ExportUtils.NO_VIPR)) {
                    _log.info(String.format("ExportMask %s disqualified because the name contains %s (in upper or lower case) to exclude it", exportMask.getMaskName(), ExportUtils.NO_VIPR));
                    continue;
                }
                if (!exportMask.getInactive() && exportMask.getStorageDevice().equals(storageURI)) {
                    exportMask = device.refreshExportMask(storage, exportMask);
                    // BlockStorageDevice level, so that it has up-to-date
                    // info from
                    // the array
                    Map<URI, Integer> volumesToAdd = new HashMap<URI, Integer>();
                    for (URI boURI : volumeMap.keySet()) {
                        BlockObject bo = Volume.fetchExportMaskBlockObject(_dbClient, boURI);
                        if (bo != null && !exportMask.hasExistingVolume(bo.getWWN()) && !exportMask.hasUserAddedVolume(bo.getWWN())) {
                            URI thisVol = bo.getId();
                            Integer hlu = volumeMap.get(boURI);
                            volumesToAdd.put(thisVol, hlu);
                        }
                        // Check if the requested HLU for the volume is
                        // already taken by a pre-existing volume.
                        Integer requestedHLU = volumeMap.get(boURI);
                        StringMap existingVolumesInMask = exportMask.getExistingVolumes();
                        if (existingVolumesInMask != null && requestedHLU.intValue() != ExportGroup.LUN_UNASSIGNED && !ExportGroup.LUN_UNASSIGNED_DECIMAL_STR.equals(requestedHLU.toString()) && existingVolumesInMask.containsValue(requestedHLU.toString())) {
                            ExportOrchestrationTask completer = new ExportOrchestrationTask(exportGroup.getId(), token);
                            ServiceError serviceError = DeviceControllerException.errors.exportHasExistingVolumeWithRequestedHLU(boURI.toString(), requestedHLU.toString());
                            completer.error(_dbClient, serviceError);
                            return;
                        }
                    }
                    _log.info(String.format("Mask %s, adding volumes %s", exportMask.getMaskName(), Joiner.on(',').join(volumesToAdd.entrySet())));
                    if (volumesToAdd.size() > 0) {
                        List<URI> volumeURIs = new ArrayList<URI>();
                        volumeURIs.addAll(volumesToAdd.keySet());
                        exportMasksToZoneAddVolumes.add(exportMask);
                        volumesToZoneAddVolumes.addAll(volumeURIs);
                        // Make sure the zoning map is getting updated for user-created masks
                        updateZoningMap(exportGroup, exportMask, true);
                        // Update volumeMap to find the next HLU here.
                        updateVolumeHLU(storage, initiatorURIs, volumesToAdd);
                        generateExportMaskAddVolumesWorkflow(workflow, EXPORT_GROUP_ZONING_TASK, storage, exportGroup, exportMask, volumesToAdd, null);
                        anyVolumesAdded = true;
                        // associated it with the ExportGroup.
                        if (!exportGroup.hasMask(exportMask.getId())) {
                            exportGroup.addExportMask(exportMask.getId());
                            _dbClient.updateAndReindexObject(exportGroup);
                        }
                    }
                }
            }
            if (!anyVolumesAdded) {
                String attachGroupSnapshot;
                // masks and if there are initiators for the export.
                if (!ExportMaskUtils.hasExportMaskForStorage(_dbClient, exportGroup, storageURI) && exportGroup.hasInitiators()) {
                    _log.info("No existing masks to which the requested volumes can be added. Creating a new mask");
                    List<URI> initiators = StringSetUtil.stringSetToUriList(exportGroup.getInitiators());
                    attachGroupSnapshot = checkForSnapshotsToCopyToTarget(workflow, storage, null, volumeMap, null);
                    Map<URI, List<URI>> hostInitiatorMap = new HashMap<URI, List<URI>>();
                    for (URI newExportMaskInitiator : initiators) {
                        Initiator initiator = _dbClient.queryObject(Initiator.class, newExportMaskInitiator);
                        // Not all initiators have hosts, be sure to handle either case.
                        URI hostURI = initiator.getHost();
                        if (hostURI == null) {
                            hostURI = NullColumnValueGetter.getNullURI();
                        }
                        List<URI> initiatorSet = hostInitiatorMap.get(hostURI);
                        if (initiatorSet == null) {
                            initiatorSet = new ArrayList<URI>();
                            hostInitiatorMap.put(hostURI, initiatorSet);
                        }
                        initiatorSet.add(initiator.getId());
                        _log.info(String.format("host = %s, " + "initiators to add: %d, ", hostURI, hostInitiatorMap.get(hostURI).size()));
                    }
                    if (!hostInitiatorMap.isEmpty()) {
                        for (URI hostID : hostInitiatorMap.keySet()) {
                            _log.info(String.format("new export masks %s", Joiner.on(",").join(hostInitiatorMap.get(hostID))));
                            String zoningStep = workflow.createStepId();
                            GenExportMaskCreateWorkflowResult result = generateExportMaskCreateWorkflow(workflow, zoningStep, storage, exportGroup, hostInitiatorMap.get(hostID), volumeMap, token);
                            List<URI> masks = new ArrayList<URI>();
                            masks.add(result.getMaskURI());
                            generateZoningCreateWorkflow(workflow, attachGroupSnapshot, exportGroup, masks, volumeMap, zoningStep);
                        }
                        createdNewMask = true;
                    }
                }
            }
            if (!exportMasksToZoneAddVolumes.isEmpty()) {
                generateZoningAddVolumesWorkflow(workflow, null, exportGroup, exportMasksToZoneAddVolumes, volumesToZoneAddVolumes);
            }
            String successMessage = String.format("Successfully added volumes to export on StorageArray %s", storage.getLabel());
            workflow.executePlan(taskCompleter, successMessage);
        } else {
            if (exportGroup.hasInitiators()) {
                _log.info("There are no masks for this export. Need to create anew.");
                List<URI> initiatorURIs = new ArrayList<URI>();
                for (String initiatorURIStr : exportGroup.getInitiators()) {
                    initiatorURIs.add(URI.create(initiatorURIStr));
                }
                // Invoke the export group create operation,
                // which should in turn create a workflow operations to
                // create the export for the newly added volume(s).
                exportGroupCreate(storageURI, exportGroupURI, initiatorURIs, volumeMap, token);
                anyVolumesAdded = true;
            } else {
                _log.warn("There are no initiator for export group: " + exportGroup.getLabel());
            }
        }
        if (!anyVolumesAdded && !createdNewMask) {
            taskCompleter.ready(_dbClient);
            _log.info("No volumes pushed to array because either they already exist " + "or there were no initiators added to the export yet.");
        }
    } catch (Exception ex) {
        _log.error("ExportGroup Orchestration failed.", ex);
        // TODO add service code here
        if (taskCompleter != null) {
            ServiceError serviceError = DeviceControllerException.errors.jobFailedMsg(ex.getMessage(), ex);
            taskCompleter.error(_dbClient, serviceError);
        }
    }
}
Also used : StringMap(com.emc.storageos.db.client.model.StringMap) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) BlockStorageDevice(com.emc.storageos.volumecontroller.BlockStorageDevice) Initiator(com.emc.storageos.db.client.model.Initiator) ArrayList(java.util.ArrayList) List(java.util.List) BlockObject(com.emc.storageos.db.client.model.BlockObject) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ExportMask(com.emc.storageos.db.client.model.ExportMask) Workflow(com.emc.storageos.workflow.Workflow) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) ExportOrchestrationTask(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportOrchestrationTask)

Example 17 with BlockStorageDevice

use of com.emc.storageos.volumecontroller.BlockStorageDevice in project coprhd-controller by CoprHD.

the class XIVMaskingOrchestrator method getDevice.

@Override
public BlockStorageDevice getDevice() {
    BlockStorageDevice device = XIV_BLOCK_DEVICE.get();
    synchronized (XIV_BLOCK_DEVICE) {
        if (device == null) {
            device = (BlockStorageDevice) ControllerServiceImpl.getBean(XIV_SMIS_DEVICE);
            XIV_BLOCK_DEVICE.compareAndSet(null, device);
        }
    }
    return device;
}
Also used : BlockStorageDevice(com.emc.storageos.volumecontroller.BlockStorageDevice)

Example 18 with BlockStorageDevice

use of com.emc.storageos.volumecontroller.BlockStorageDevice in project coprhd-controller by CoprHD.

the class XtremIOMaskingOrchestrator method getDevice.

@Override
public BlockStorageDevice getDevice() {
    BlockStorageDevice device = XTREMIO_BLOCK_DEVICE.get();
    synchronized (XTREMIO_BLOCK_DEVICE) {
        if (device == null) {
            device = (BlockStorageDevice) ControllerServiceImpl.getBean(XTREMIO_STORAGE_DEVICE);
            XTREMIO_BLOCK_DEVICE.compareAndSet(null, device);
        }
    }
    return device;
}
Also used : BlockStorageDevice(com.emc.storageos.volumecontroller.BlockStorageDevice)

Example 19 with BlockStorageDevice

use of com.emc.storageos.volumecontroller.BlockStorageDevice in project coprhd-controller by CoprHD.

the class VPlexHDSMaskingOrchestrator method createOrAddVolumesToExportMask.

/**
 * Create an ExportMask on the HDS if it does not exist. Otherwise, just add the indicated
 * volumes to the ExportMask.
 */
@Override
public void createOrAddVolumesToExportMask(URI arrayURI, URI exportGroupURI, URI exportMaskURI, Map<URI, Integer> volumeMap, List<URI> initiatorURIs, TaskCompleter completer, String stepId) {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        StorageSystem array = _dbClient.queryObject(StorageSystem.class, arrayURI);
        ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
        // If the exportMask isn't found, or has been deleted, fail, ask user to retry.
        if (exportMask == null || exportMask.getInactive()) {
            _log.info(String.format("ExportMask %s deleted or inactive, failing", exportMaskURI));
            ServiceError svcerr = VPlexApiException.errors.createBackendExportMaskDeleted(exportMaskURI.toString(), arrayURI.toString());
            WorkflowStepCompleter.stepFailed(stepId, svcerr);
            return;
        }
        // Protect concurrent operations by locking {host, array} dupple.
        // Lock will be released when workflow step completes.
        List<String> lockKeys = ControllerLockingUtil.getHostStorageLockKeys(_dbClient, ExportGroupType.Host, StringSetUtil.stringSetToUriList(exportMask.getInitiators()), arrayURI);
        getWorkflowService().acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.VPLEX_BACKEND_EXPORT));
        // Fetch the Initiators
        List<Initiator> initiators = new ArrayList<Initiator>();
        for (String initiatorId : exportMask.getInitiators()) {
            Initiator initiator = _dbClient.queryObject(Initiator.class, URI.create(initiatorId));
            if (initiator != null) {
                initiators.add(initiator);
            }
        }
        // Refresh the ExportMask
        BlockStorageDevice device = _blockController.getDevice(array.getSystemType());
        exportMask = refreshExportMask(array, device, exportMask);
        if (!exportMask.hasAnyVolumes()) {
            // We are creating this ExportMask on the hardware! (Maybe not the first time though...)
            // Fetch the targets
            List<URI> targets = new ArrayList<URI>();
            for (String targetId : exportMask.getStoragePorts()) {
                targets.add(URI.create(targetId));
            }
            device.doExportCreate(array, exportMask, volumeMap, initiators, targets, completer);
        } else {
            device.doExportAddVolumes(array, exportMask, initiators, volumeMap, completer);
        }
    } catch (Exception ex) {
        _log.error("Failed to create or add volumes to export mask for hds: ", ex);
        VPlexApiException vplexex = DeviceControllerExceptions.vplex.addStepsForCreateVolumesFailed(ex);
        WorkflowStepCompleter.stepFailed(stepId, vplexex);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) URI(java.net.URI) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) BlockStorageDevice(com.emc.storageos.volumecontroller.BlockStorageDevice) Initiator(com.emc.storageos.db.client.model.Initiator) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 20 with BlockStorageDevice

use of com.emc.storageos.volumecontroller.BlockStorageDevice in project coprhd-controller by CoprHD.

the class VPlexHDSMaskingOrchestrator method deleteOrRemoveVolumesFromExportMask.

@Override
public void deleteOrRemoveVolumesFromExportMask(URI arrayURI, URI exportGroupURI, URI exportMaskURI, List<URI> volumes, List<URI> initiatorURIs, String stepId) {
    ExportTaskCompleter completer = null;
    try {
        completer = new ExportMaskOnlyRemoveVolumeCompleter(exportGroupURI, exportMaskURI, volumes, stepId);
        WorkflowStepCompleter.stepExecuting(stepId);
        StorageSystem array = _dbClient.queryObject(StorageSystem.class, arrayURI);
        BlockStorageDevice device = _blockController.getDevice(array.getSystemType());
        ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
        // If the exportMask isn't found, or has been deleted, nothing to do.
        if (exportMask == null || exportMask.getInactive()) {
            _log.info(String.format("ExportMask %s inactive, returning success", exportMaskURI));
            completer.ready(_dbClient);
            return;
        }
        // Protect concurrent operations by locking {host, array} dupple.
        // Lock will be released when workflow step completes.
        List<String> lockKeys = ControllerLockingUtil.getHostStorageLockKeys(_dbClient, ExportGroupType.Host, StringSetUtil.stringSetToUriList(exportMask.getInitiators()), arrayURI);
        getWorkflowService().acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.VPLEX_BACKEND_EXPORT));
        // Refresh the ExportMask
        exportMask = refreshExportMask(array, device, exportMask);
        // Determine if we're deleting the last volume in the mask.
        StringMap maskVolumesMap = exportMask.getVolumes();
        Set<String> remainingVolumes = new HashSet<String>();
        List<URI> passedVolumesInMask = new ArrayList<>(volumes);
        if (maskVolumesMap != null) {
            remainingVolumes.addAll(maskVolumesMap.keySet());
        }
        for (URI volume : volumes) {
            remainingVolumes.remove(volume.toString());
            // are not in the mask to handle this condition.
            if ((maskVolumesMap != null) && (!maskVolumesMap.keySet().contains(volume.toString()))) {
                passedVolumesInMask.remove(volume);
            }
        }
        _log.info("passedVolumesInMask : {}", passedVolumesInMask);
        _log.info("remainingVolumes : {}", remainingVolumes);
        // None of the volumes is in the export mask, so we are done.
        if (passedVolumesInMask.isEmpty()) {
            _log.info("None of these volumes {} are in export mask {}", volumes, exportMask.forDisplay());
            completer.ready(_dbClient);
            return;
        }
        // If it is last volume and there are no existing volumes, delete the ExportMask.
        if (remainingVolumes.isEmpty() && !exportMask.hasAnyExistingVolumes()) {
            device.doExportDelete(array, exportMask, passedVolumesInMask, initiatorURIs, completer);
        } else {
            List<Initiator> initiators = null;
            if (initiatorURIs != null && !initiatorURIs.isEmpty()) {
                initiators = _dbClient.queryObject(Initiator.class, initiatorURIs);
            }
            device.doExportRemoveVolumes(array, exportMask, passedVolumesInMask, initiators, completer);
        }
    } catch (Exception ex) {
        _log.error("Failed to delete or remove volumes to export mask for hds: ", ex);
        VPlexApiException vplexex = DeviceControllerExceptions.vplex.addStepsForCreateVolumesFailed(ex);
        completer.error(_dbClient, vplexex);
    }
}
Also used : ExportTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter) StringMap(com.emc.storageos.db.client.model.StringMap) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) URI(java.net.URI) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) BlockStorageDevice(com.emc.storageos.volumecontroller.BlockStorageDevice) Initiator(com.emc.storageos.db.client.model.Initiator) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ExportMaskOnlyRemoveVolumeCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskOnlyRemoveVolumeCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) HashSet(java.util.HashSet)

Aggregations

BlockStorageDevice (com.emc.storageos.volumecontroller.BlockStorageDevice)49 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)36 URI (java.net.URI)29 ArrayList (java.util.ArrayList)28 ExportMask (com.emc.storageos.db.client.model.ExportMask)27 Initiator (com.emc.storageos.db.client.model.Initiator)23 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)19 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)17 HashSet (java.util.HashSet)17 ExportOrchestrationTask (com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportOrchestrationTask)16 Workflow (com.emc.storageos.workflow.Workflow)15 StringMap (com.emc.storageos.db.client.model.StringMap)14 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)14 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)14 HashMap (java.util.HashMap)11 List (java.util.List)11 ExportTaskCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter)10 BlockObject (com.emc.storageos.db.client.model.BlockObject)8 Map (java.util.Map)8 Set (java.util.Set)8