Search in sources :

Example 61 with Initiator

use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.

the class BlockRecoverPointIngestOrchestrator method performRPExportIngestion.

/**
 * RecoverPoint volumes are expected to have export masks where the volume is exported to
 * a RecoverPoint site. Therefore every RP volume (sources, targets, journals) will need to
 * go through this code and have their export mask ingested. Even if the mask has already been
 * ingested by a previous volume ingestion, this method still needs to update the ExportGroup and
 * ExportMask objects to reflect the newly ingested volume as part of its management.
 *
 * @param volumeContext the RecoverPointVolumeIngestionContext for the volume currently being ingested
 * @param unManagedVolume unmanaged volume
 * @param volume managed volume
 * @return managed volume with export ingested
 */
private void performRPExportIngestion(IngestionRequestContext parentRequestContext, RecoverPointVolumeIngestionContext volumeContext, UnManagedVolume unManagedVolume, Volume volume) {
    _logger.info("starting RecoverPoint export ingestion for volume {}", volume.forDisplay());
    Project project = volumeContext.getProject();
    ProtectionSystem protectionSystem = _dbClient.queryObject(ProtectionSystem.class, volume.getProtectionController());
    StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, volume.getStorageController());
    List<UnManagedExportMask> unManagedRPExportMasks = findUnManagedRPExportMask(protectionSystem, unManagedVolume);
    if (unManagedRPExportMasks.isEmpty()) {
        _logger.error("Could not find any unmanaged export masks associated with volume: " + unManagedVolume.getLabel());
        throw IngestionException.exceptions.noUnManagedExportMaskFound(unManagedVolume.getNativeGuid());
    }
    // Keep a map for internal site name name and varray
    Map<String, VirtualArray> internalSiteToVarrayMap = new HashMap<String, VirtualArray>();
    internalSiteToVarrayMap.put(volume.getInternalSiteName(), volumeContext.getVarray(unManagedVolume));
    // If this is a MetroPoint volume we're going to have multiple ExportMasks/ExportGroups to deal with.
    // We'll need to query the backend volumes for extra info to populate internalSiteToVarrayMap so
    // we can properly line up the ExportMasks/ExportGroups.
    boolean metropoint = RPHelper.isMetroPointVolume(_dbClient, volume);
    if (metropoint) {
        // We need the VPLEX ingest context to get the backend volume info
        VplexVolumeIngestionContext vplexVolumeContext = ((RpVplexVolumeIngestionContext) volumeContext.getVolumeContext()).getVplexVolumeIngestionContext();
        for (String associatedVolumeIdStr : vplexVolumeContext.getAssociatedVolumeIds(volume)) {
            // Find the associated volumes using the context maps or the db if they are already there
            Volume associatedVolume = VolumeIngestionUtil.findVolume(_dbClient, vplexVolumeContext.getBlockObjectsToBeCreatedMap(), vplexVolumeContext.getDataObjectsToBeUpdatedMap(), associatedVolumeIdStr);
            String internalSiteName = associatedVolume.getInternalSiteName();
            // If we don't already have an entry for this internal site name, let's add it now.
            if (!internalSiteToVarrayMap.containsKey(internalSiteName)) {
                internalSiteToVarrayMap.put(internalSiteName, _dbClient.queryObject(VirtualArray.class, associatedVolume.getVirtualArray()));
            }
        }
    }
    // this will more than likely only loop once.
    for (Entry<String, VirtualArray> entry : internalSiteToVarrayMap.entrySet()) {
        String internalSiteName = entry.getKey();
        VirtualArray virtualArray = entry.getValue();
        UnManagedExportMask em = null;
        if (metropoint) {
            // Since we're flagged for MetroPoint we need to determine which ExportMask to use.
            // We need the MetroPoint volume to be added to BOTH ExportGroups that represent the
            // two Storage Views on VPLEX for cluster-1 and cluster-2.
            // So let's use the varray to find the cluster we're looking for on this pass and match
            // it to the maskingViewParth of the UnManagedExportMask.
            // This should line things up roughly as:
            // VPLEX Storage View 1 -> VPLEX Cluster1 + RPA1
            // VPLEX Storage View 2 -> VPLEX Cluster2 + RPA2
            String vplexCluster = ConnectivityUtil.getVplexClusterForVarray(virtualArray.getId(), storageSystem.getId(), _dbClient);
            // First try and match based on UnManagedExportMask ports
            for (UnManagedExportMask exportMask : unManagedRPExportMasks) {
                for (String portUri : exportMask.getKnownStoragePortUris()) {
                    StoragePort port = _dbClient.queryObject(StoragePort.class, URI.create(portUri));
                    if (port != null && !port.getInactive()) {
                        String vplexClusterForMask = ConnectivityUtil.getVplexClusterOfPort(port);
                        if (vplexCluster.equals(vplexClusterForMask)) {
                            em = exportMask;
                            break;
                        }
                    }
                }
                if (em != null) {
                    break;
                }
            }
            if (em == null) {
                // It really shouldn't come to this, but leaving this code just in case.
                for (UnManagedExportMask exportMask : unManagedRPExportMasks) {
                    if (exportMask.getMaskingViewPath().contains("cluster-" + vplexCluster)) {
                        em = exportMask;
                        break;
                    }
                }
            }
        } else {
            em = unManagedRPExportMasks.get(0);
        }
        // If the mask for ingested volume is in a mask that contains JOURNAL keyword, make sure the ExportGroup created contains
        // that internal flag.
        boolean isJournalExport = false;
        if (em.getMaskName().toLowerCase().contains(VolumeIngestionUtil.RP_JOURNAL)) {
            isJournalExport = true;
        }
        String exportGroupGeneratedName = RPHelper.generateExportGroupName(protectionSystem, storageSystem, internalSiteName, virtualArray, isJournalExport);
        ExportGroup exportGroup = VolumeIngestionUtil.verifyExportGroupExists(parentRequestContext, exportGroupGeneratedName, project.getId(), em.getKnownInitiatorUris(), virtualArray.getId(), _dbClient);
        boolean exportGroupCreated = false;
        if (null == exportGroup) {
            exportGroupCreated = true;
            Integer numPaths = em.getZoningMap().size();
            _logger.info("Creating Export Group with label {}", em.getMaskName());
            exportGroup = RPHelper.createRPExportGroup(exportGroupGeneratedName, virtualArray, project, numPaths, isJournalExport);
        }
        if (null != exportGroup) {
            // check if the ExportGroup has already been fetched
            ExportGroup loadedExportGroup = parentRequestContext.findExportGroup(exportGroup.getLabel(), project.getId(), virtualArray.getId(), null, null);
            if (null != loadedExportGroup) {
                exportGroup = loadedExportGroup;
            }
        }
        volumeContext.setExportGroup(exportGroup);
        volumeContext.setExportGroupCreated(exportGroupCreated);
        volumeContext.getRpExportGroupMap().put(exportGroup, exportGroupCreated);
        // set RP device initiators to be used as the "host" for export mask ingestion
        List<Initiator> initiators = new ArrayList<Initiator>();
        Iterator<Initiator> initiatorItr = _dbClient.queryIterativeObjects(Initiator.class, URIUtil.toURIList(em.getKnownInitiatorUris()));
        while (initiatorItr.hasNext()) {
            initiators.add(initiatorItr.next());
        }
        volumeContext.setDeviceInitiators(initiators);
        // find the ingest export strategy and call into for this unmanaged export mask
        IngestExportStrategy ingestStrategy = ingestStrategyFactory.buildIngestExportStrategy(unManagedVolume);
        volume = ingestStrategy.ingestExportMasks(unManagedVolume, volume, volumeContext);
        if (null == volume) {
            // ingestion did not succeed, but in case it wasn't, throw one
            throw IngestionException.exceptions.generalVolumeException(unManagedVolume.getLabel(), "check the logs for more details");
        }
    }
}
Also used : VirtualArray(com.emc.storageos.db.client.model.VirtualArray) HashMap(java.util.HashMap) VplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext) StoragePort(com.emc.storageos.db.client.model.StoragePort) ArrayList(java.util.ArrayList) ProtectionSystem(com.emc.storageos.db.client.model.ProtectionSystem) Project(com.emc.storageos.db.client.model.Project) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) Volume(com.emc.storageos.db.client.model.Volume) Initiator(com.emc.storageos.db.client.model.Initiator) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) UnManagedExportMask(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask)

Example 62 with Initiator

use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.

the class BlockVplexVolumeIngestOrchestrator method findOrCreateExportGroup.

/**
 * Find or Create an ExportGroup.
 *
 * @param vplex -- VPLEX StorageSystem
 * @param array -- Array StorageSystem
 * @param initiators -- Collection<Initiator> representing VPLEX back-end ports.
 * @param virtualArrayURI
 * @param projectURI
 * @param tenantURI
 * @param numPaths Value of maxPaths to be put in ExportGroup
 * @param unmanagedExportMask the unmanaged export mask
 * @return existing or newly created ExportGroup (not yet persisted)
 */
private ExportGroup findOrCreateExportGroup(IngestionRequestContext requestContext, StorageSystem array, Collection<Initiator> initiators, URI virtualArrayURI, URI projectURI, URI tenantURI, int numPaths, UnManagedExportMask unmanagedExportMask) {
    StorageSystem vplex = requestContext.getStorageSystem();
    String arrayName = array.getSystemType().replace("block", "") + array.getSerialNumber().substring(array.getSerialNumber().length() - 4);
    String groupName = unmanagedExportMask.getMaskName() + "_" + arrayName;
    ExportGroup exportGroup = requestContext.findExportGroup(groupName, projectURI, virtualArrayURI, null, null);
    if (null != exportGroup) {
        _logger.info(String.format("Returning existing ExportGroup %s", exportGroup.getLabel()));
        return exportGroup;
    }
    List<ExportGroup> exportGroups = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, ExportGroup.class, PrefixConstraint.Factory.getFullMatchConstraint(ExportGroup.class, "label", groupName));
    if (null != exportGroups && !exportGroups.isEmpty()) {
        for (ExportGroup group : exportGroups) {
            if (null != group) {
                _logger.info(String.format("Returning existing ExportGroup %s", group.getLabel()));
                exportGroup = group;
            }
        }
    } else {
        Map<String, ExportGroup> possibleExportGroups = new HashMap<String, ExportGroup>();
        Set<String> initiatorUris = new HashSet<String>();
        for (Initiator initiator : initiators) {
            // Determine all the possible existing Export Groups
            List<ExportGroup> groups = ExportUtils.getInitiatorExportGroups(initiator, _dbClient);
            for (ExportGroup group : groups) {
                if (!possibleExportGroups.containsKey(group.getId().toString())) {
                    possibleExportGroups.put(group.getId().toString(), group);
                }
            }
            initiatorUris.add(initiator.getId().toString());
        }
        // If there are possible Export Groups, look for one with that matches on inits, varray, project, and tenant.
        for (ExportGroup group : possibleExportGroups.values()) {
            if (URIUtil.identical(group.getVirtualArray(), virtualArrayURI) && URIUtil.identical(group.getProject().getURI(), projectURI) && URIUtil.identical(group.getTenant().getURI(), tenantURI)) {
                if (group.getInitiators().containsAll(initiatorUris)) {
                    _logger.info(String.format("Returning existing ExportGroup %s from database.", group.getLabel()));
                    return group;
                }
            }
        }
        // No existing group has the mask, let's create one.
        exportGroup = new ExportGroup();
        exportGroup.setLabel(groupName);
        exportGroup.setProject(new NamedURI(projectURI, exportGroup.getLabel()));
        exportGroup.setVirtualArray(vplex.getVirtualArray());
        exportGroup.setTenant(new NamedURI(tenantURI, exportGroup.getLabel()));
        exportGroup.setGeneratedName(groupName);
        exportGroup.setVolumes(new StringMap());
        exportGroup.setOpStatus(new OpStatusMap());
        exportGroup.setVirtualArray(virtualArrayURI);
        exportGroup.setNumPaths(numPaths);
        // Add the initiators into the ExportGroup.
        for (Initiator initiator : initiators) {
            exportGroup.addInitiator(initiator);
        }
        _logger.info(String.format("Returning new ExportGroup %s", exportGroup.getLabel()));
    }
    return exportGroup;
}
Also used : ExportGroup(com.emc.storageos.db.client.model.ExportGroup) StringMap(com.emc.storageos.db.client.model.StringMap) HashMap(java.util.HashMap) Initiator(com.emc.storageos.db.client.model.Initiator) NamedURI(com.emc.storageos.db.client.model.NamedURI) OpStatusMap(com.emc.storageos.db.client.model.OpStatusMap) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) HashSet(java.util.HashSet)

Example 63 with Initiator

use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.

the class ExportService method searchInDb.

// Sometimes there are multiple entries for the same initiator
// and so we return a list here
private Boolean searchInDb(String port, List<Initiator> list, String protocol) {
    SearchedResRepList resRepList = new SearchedResRepList(ResourceTypeEnum.INITIATOR);
    Boolean found = false;
    String formattedStr = "";
    if (protocol.equalsIgnoreCase(Protocol.FC.name())) {
        int index = 0;
        while (index < (port.length())) {
            formattedStr += port.substring(index, index + 2).toUpperCase();
            index = index + 2;
            if (index < (port.length())) {
                formattedStr += ":";
            }
        }
    } else if (protocol.equalsIgnoreCase(Protocol.iSCSI.name())) {
        formattedStr = port;
    }
    // Finds the Initiator that includes the initiator port specified, if any.
    _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getInitiatorPortInitiatorConstraint(formattedStr), resRepList);
    if (resRepList.iterator() != null) {
        for (SearchResultResourceRep res : resRepList) {
            Initiator initiator = _dbClient.queryObject(Initiator.class, res.getId());
            if ((initiator != null) && !(initiator.getInactive())) {
                list.add(initiator);
                _log.info("Found initiator in DB for port = {}", port);
                found = true;
            }
        }
    }
    return found;
}
Also used : Initiator(com.emc.storageos.db.client.model.Initiator) SearchResultResourceRep(com.emc.storageos.model.search.SearchResultResourceRep) SearchedResRepList(com.emc.storageos.api.service.impl.response.SearchedResRepList) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint)

Example 64 with Initiator

use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.

the class ExportService method getListOfInitiators.

private List<Initiator> getListOfInitiators(Connector connector, String tenant_id, String protocol, Volume vol) {
    List<Initiator> initiators = new ArrayList<Initiator>();
    boolean bFound = false;
    if (protocol.equals(Protocol.iSCSI.name())) {
        // this is an iSCSI request
        String port = connector.initiator;
        String hostname = connector.host;
        List<Initiator> iscsi_initiators = new ArrayList<Initiator>();
        Boolean found = searchInDb(port, iscsi_initiators, Protocol.iSCSI.name());
        if (found) {
            initiators.addAll(iscsi_initiators);
        } else {
            // not found, create a new one
            _log.info("Creating new iSCSI initiator, iqn = {}", port);
            // Make sure the port is a valid iSCSI port.
            if (!iSCSIUtility.isValidIQNPortName(port) && !iSCSIUtility.isValidEUIPortName(port))
                throw APIException.badRequests.invalidIscsiInitiatorPort();
            // Find host, and if not found, create new host
            Host host = getHost(hostname, tenant_id);
            // create and populate the initiator
            Initiator initiator = new Initiator();
            initiator.setHost(host.getId());
            initiator.setHostName(connector.host);
            if (!NullColumnValueGetter.isNullURI(host.getCluster())) {
                Cluster cluster = queryObject(Cluster.class, host.getCluster(), false);
                initiator.setClusterName(cluster.getLabel());
            }
            initiator.setId(URIUtil.createId(Initiator.class));
            initiator.setInitiatorPort(port);
            // allows deletion via UI
            initiator.setIsManualCreation(true);
            initiator.setProtocol(HostInterface.Protocol.iSCSI.name());
            addInitiatorToNetwork(initiator, vol);
            ScopedLabelSet tags = new ScopedLabelSet();
            tags.add(new ScopedLabel("openstack", "dynamic"));
            initiator.setTag(tags);
            _dbClient.createObject(initiator);
            initiators.add(initiator);
        }
    } else if (protocol.equals(Protocol.FC.name())) {
        // this is an FC request
        for (String fc_port : connector.wwpns) {
            // See if this initiator exists in our DB
            List<Initiator> fc_initiators = new ArrayList<Initiator>();
            Boolean found = searchInDb(fc_port, fc_initiators, Protocol.FC.name());
            if (found) {
                bFound = true;
                initiators.addAll(fc_initiators);
            } else {
                // not found, we don't create dynamically for FC
                _log.info("FC initiator for wwpn {} not found", fc_port);
            }
        }
        if (!bFound) {
            throw APIException.internalServerErrors.genericApisvcError("Export Failed", new Exception("No FC initiator found for export"));
        }
    } else {
        throw APIException.internalServerErrors.genericApisvcError("Unsupported volume protocol", new Exception("The protocol specified is not supported. The protocols supported are " + Protocol.FC.name() + " and " + Protocol.iSCSI.name()));
    }
    return initiators;
}
Also used : ArrayList(java.util.ArrayList) Cluster(com.emc.storageos.db.client.model.Cluster) Host(com.emc.storageos.db.client.model.Host) ScopedLabelSet(com.emc.storageos.db.client.model.ScopedLabelSet) APIException(com.emc.storageos.svcs.errorhandling.resources.APIException) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) Initiator(com.emc.storageos.db.client.model.Initiator) ScopedLabel(com.emc.storageos.db.client.model.ScopedLabel) ITLRestRepList(com.emc.storageos.model.block.export.ITLRestRepList) List(java.util.List) ArrayList(java.util.ArrayList) SearchedResRepList(com.emc.storageos.api.service.impl.response.SearchedResRepList)

Example 65 with Initiator

use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.

the class ExportService method processDetachRequest.

// INTERNAL FUNCTIONS
private boolean processDetachRequest(Volume vol, VolumeActionRequest.DetachVolume detach, String openstackTenantId, String protocol) throws InterruptedException {
    _log.info("Detach request");
    // Step 1: Find export group of volume
    ExportGroup exportGroup = findExportGroup(vol);
    if (exportGroup == null)
        throw APIException.badRequests.parameterIsNotValid("volume_id");
    Set<URI> addedClusters = new HashSet<>();
    Set<URI> removedClusters = new HashSet<>();
    Set<URI> addedHosts = new HashSet<>();
    Set<URI> removedHosts = new HashSet<>();
    Set<URI> addedInitiators = new HashSet<>();
    Set<URI> removedInitiators = new HashSet<>();
    // Step 2: Validate initiators are part of export group
    List<URI> currentURIs = new ArrayList<URI>();
    List<Initiator> detachInitiators = getListOfInitiators(detach.connector, openstackTenantId, protocol, vol);
    currentURIs = StringSetUtil.stringSetToUriList(exportGroup.getInitiators());
    for (Initiator initiator : detachInitiators) {
        URI uri = initiator.getId();
        if (!currentURIs.contains(uri)) {
            throw APIException.badRequests.parameterIsNotValid("volume_id");
        }
        removedInitiators.add(uri);
    }
    _log.info("updateExportGroup request is submitted.");
    // get block controller
    BlockExportController exportController = getController(BlockExportController.class, BlockExportController.EXPORT);
    // Now update export group
    String task = UUID.randomUUID().toString();
    initTaskStatus(exportGroup, task, Operation.Status.pending, ResourceOperationTypeEnum.DELETE_EXPORT_VOLUME);
    Map<URI, Integer> noUpdatesVolumeMap = new HashMap<URI, Integer>();
    exportController.exportGroupUpdate(exportGroup.getId(), noUpdatesVolumeMap, noUpdatesVolumeMap, addedClusters, removedClusters, addedHosts, removedHosts, addedInitiators, removedInitiators, task);
    return waitForTaskCompletion(exportGroup.getId(), task);
// TODO: If now the list is empty, change volume status to 'not exported'
// and delete the exportGroup
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) BlockExportController(com.emc.storageos.volumecontroller.BlockExportController) Initiator(com.emc.storageos.db.client.model.Initiator) HashSet(java.util.HashSet)

Aggregations

Initiator (com.emc.storageos.db.client.model.Initiator)487 URI (java.net.URI)345 ArrayList (java.util.ArrayList)266 HashMap (java.util.HashMap)170 HashSet (java.util.HashSet)161 ExportMask (com.emc.storageos.db.client.model.ExportMask)156 List (java.util.List)119 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)102 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)98 Map (java.util.Map)85 StringSet (com.emc.storageos.db.client.model.StringSet)83 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)82 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)81 StoragePort (com.emc.storageos.db.client.model.StoragePort)78 NamedURI (com.emc.storageos.db.client.model.NamedURI)73 Set (java.util.Set)72 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)58 StringSetMap (com.emc.storageos.db.client.model.StringSetMap)57 StringMap (com.emc.storageos.db.client.model.StringMap)55 Host (com.emc.storageos.db.client.model.Host)54