Search in sources :

Example 1 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VPlexCommunicationInterface method discover.

/**
 * Implementation for discovery of VPLEX storage systems.
 *
 * @param accessProfile providing context for this discovery session
 *
 * @throws BaseCollectionException
 */
@Override
public void discover(AccessProfile accessProfile) throws BaseCollectionException {
    s_logger.info("initiating discovery of VPLEX system {}", accessProfile.getProfileName());
    if ((null != accessProfile.getnamespace()) && (accessProfile.getnamespace().equals(StorageSystem.Discovery_Namespaces.UNMANAGED_VOLUMES.toString()))) {
        try {
            VPlexApiClient client = getVPlexAPIClient(accessProfile);
            long timer = System.currentTimeMillis();
            UnmanagedDiscoveryPerformanceTracker tracker = new UnmanagedDiscoveryPerformanceTracker();
            tracker.discoveryMode = ControllerUtils.getPropertyValueFromCoordinator(_coordinator, VplexBackendIngestionContext.DISCOVERY_MODE);
            // get all the detailed virtual volume info from the VPLEX API
            Map<String, VPlexVirtualVolumeInfo> vvolMap = client.getVirtualVolumes(true);
            tracker.virtualVolumeFetch = System.currentTimeMillis() - timer;
            tracker.totalVolumesFetched = vvolMap.size();
            // discover unmanaged storage views
            timer = System.currentTimeMillis();
            Map<String, Set<UnManagedExportMask>> volumeToExportMasksMap = new HashMap<String, Set<UnManagedExportMask>>();
            Map<String, Set<VPlexStorageViewInfo>> volumeToStorageViewMap = new HashMap<String, Set<VPlexStorageViewInfo>>();
            Set<String> recoverPointExportMasks = new HashSet<String>();
            discoverUnmanagedStorageViews(accessProfile, client, vvolMap, volumeToExportMasksMap, volumeToStorageViewMap, recoverPointExportMasks);
            tracker.storageViewFetch = System.currentTimeMillis() - timer;
            // discover unmanaged volumes
            timer = System.currentTimeMillis();
            discoverUnmanagedVolumes(accessProfile, client, vvolMap, volumeToExportMasksMap, volumeToStorageViewMap, recoverPointExportMasks, tracker);
            tracker.unmanagedVolumeProcessing = System.currentTimeMillis() - timer;
            // re-run vpool matching for all vpools so that backend volumes will
            // be updated after vvol discovery to match their parent's matched vpools
            timer = System.currentTimeMillis();
            List<URI> vpoolURIs = _dbClient.queryByType(VirtualPool.class, true);
            List<VirtualPool> vpoolList = _dbClient.queryObject(VirtualPool.class, vpoolURIs);
            Set<URI> srdfEnabledTargetVPools = SRDFUtils.fetchSRDFTargetVirtualPools(_dbClient);
            Set<URI> rpEnabledTargetVPools = RPHelper.fetchRPTargetVirtualPools(_dbClient);
            for (VirtualPool vpool : vpoolList) {
                ImplicitUnManagedObjectsMatcher.matchVirtualPoolsWithUnManagedVolumes(vpool, srdfEnabledTargetVPools, rpEnabledTargetVPools, _dbClient, true);
            }
            tracker.vpoolMatching = System.currentTimeMillis() - timer;
            s_logger.info(tracker.getPerformanceReport());
        } catch (URISyntaxException ex) {
            s_logger.error(ex.getLocalizedMessage());
            throw VPlexCollectionException.exceptions.vplexUnmanagedVolumeDiscoveryFailed(accessProfile.getSystemId().toString(), ex.getLocalizedMessage());
        }
    } else {
        discoverAll(accessProfile);
    }
}
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) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) URISyntaxException(java.net.URISyntaxException) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) URI(java.net.URI) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) UnManagedExportMask(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask) HashSet(java.util.HashSet)

Example 2 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VPlexCommunicationInterface method discoverUnmanagedStorageViews.

/**
 * Discovers storage views on the VPLEX and creates UnManagedExportMasks for any
 * that are not managed by ViPR.
 *
 * @param accessProfile providing context for this discovery session
 * @param client a reference to the VPLEX API client
 * @param vvolMap map of virtual volume names to virtual volume info objects
 * @param volumeToExportMasksMap map of volumes to a set of associated UnManagedExportMasks
 * @param volumeToStorageViewMap map of volumes to a set of associated VPlexStorageViewInfos
 * @param recoverpointExportMasks recoverpoint export mask uris
 * @throws BaseCollectionException
 */
private void discoverUnmanagedStorageViews(AccessProfile accessProfile, VPlexApiClient client, Map<String, VPlexVirtualVolumeInfo> vvolMap, Map<String, Set<UnManagedExportMask>> volumeToExportMasksMap, Map<String, Set<VPlexStorageViewInfo>> volumeToStorageViewMap, Set<String> recoverPointExportMasks) throws BaseCollectionException {
    String statusMessage = "Starting discovery of Unmanaged VPLEX Storage Views.";
    s_logger.info(statusMessage + " Access Profile Details :  IpAddress : " + "PortNumber : {}, namespace : {}", accessProfile.getIpAddress() + accessProfile.getPortNumber(), accessProfile.getnamespace());
    URI vplexUri = accessProfile.getSystemId();
    StorageSystem vplex = _dbClient.queryObject(StorageSystem.class, vplexUri);
    if (null == vplex) {
        s_logger.error("No VPLEX Device was found in ViPR for URI: " + vplexUri);
        s_logger.error("Unmanaged VPLEX StorageView discovery cannot continue.");
        return;
    }
    try {
        // this is a map of cluster id (1 or 2) to the actual cluster name
        Map<String, String> clusterIdToNameMap = client.getClusterIdToNameMap();
        // this is a map of the cluster names to a map of its target port names to wwpns
        Map<String, Map<String, String>> clusterPortMap = new HashMap<String, Map<String, String>>();
        for (String clusterName : clusterIdToNameMap.values()) {
            Map<String, String> targetPortToPwwnMap = VPlexControllerUtils.getTargetPortToPwwnMap(client, clusterName);
            clusterPortMap.put(clusterName, targetPortToPwwnMap);
        }
        Set<URI> allCurrentUnManagedExportMaskUris = new HashSet<URI>();
        List<UnManagedExportMask> unManagedExportMasksToCreate = new ArrayList<UnManagedExportMask>();
        List<UnManagedExportMask> unManagedExportMasksToUpdate = new ArrayList<UnManagedExportMask>();
        Set<URI> rpPortInitiators = RPHelper.getBackendPortInitiators(_dbClient);
        for (String clusterName : clusterIdToNameMap.values()) {
            List<VPlexStorageViewInfo> storageViews = client.getStorageViewsForCluster(clusterName);
            for (VPlexStorageViewInfo storageView : storageViews) {
                s_logger.info("discovering storage view: " + storageView.toString());
                List<Initiator> knownInitiators = new ArrayList<Initiator>();
                List<StoragePort> knownPorts = new ArrayList<StoragePort>();
                UnManagedExportMask uem = getUnManagedExportMaskFromDb(storageView);
                if (uem != null) {
                    s_logger.info("found an existing unmanaged export mask for storage view " + storageView.getName());
                    unManagedExportMasksToUpdate.add(uem);
                    // clean up collections (we'll be refreshing them)
                    uem.getKnownInitiatorUris().clear();
                    uem.getKnownInitiatorNetworkIds().clear();
                    uem.getKnownStoragePortUris().clear();
                    uem.getKnownVolumeUris().clear();
                    uem.getUnmanagedInitiatorNetworkIds().clear();
                    uem.getUnmanagedStoragePortNetworkIds().clear();
                    uem.getUnmanagedVolumeUris().clear();
                } else {
                    s_logger.info("creating a new unmanaged export mask for storage view " + storageView.getName());
                    uem = new UnManagedExportMask();
                    unManagedExportMasksToCreate.add(uem);
                }
                // set basic info
                uem.setNativeId(storageView.getPath());
                uem.setMaskingViewPath(storageView.getPath());
                uem.setMaskName(storageView.getName());
                uem.setStorageSystemUri(accessProfile.getSystemId());
                s_logger.info("now discovering host initiators in storage view " + storageView.getName());
                for (String initiatorNetworkId : storageView.getInitiatorPwwns()) {
                    s_logger.info("looking at initiator network id " + initiatorNetworkId);
                    if (initiatorNetworkId != null && initiatorNetworkId.matches(ISCSI_PATTERN) && (iSCSIUtility.isValidIQNPortName(initiatorNetworkId) || iSCSIUtility.isValidEUIPortName(initiatorNetworkId))) {
                        s_logger.info("\tiSCSI network id normalized to " + initiatorNetworkId);
                    } else if (initiatorNetworkId != null && initiatorNetworkId.matches(REGISTERED_PATTERN)) {
                        initiatorNetworkId = initiatorNetworkId.substring(REGISTERED_PORT_PREFIX.length());
                        initiatorNetworkId = WWNUtility.getWWNWithColons(initiatorNetworkId);
                        s_logger.info("\tRegistered network id normalized to " + initiatorNetworkId);
                    } else if (WWNUtility.isValidWWNAlias(initiatorNetworkId)) {
                        initiatorNetworkId = WWNUtility.getWWNWithColons(initiatorNetworkId);
                        s_logger.info("\twwn normalized to " + initiatorNetworkId);
                    } else {
                        s_logger.warn("\tthis is not a valid network id format, skipping");
                        continue;
                    }
                    // check if a host initiator exists for this id
                    // if so, add to _knownInitiators
                    // otherwise, add to _unmanagedInitiators
                    Initiator knownInitiator = NetworkUtil.getInitiator(initiatorNetworkId, _dbClient);
                    if (knownInitiator != null) {
                        s_logger.info("   found an initiator in ViPR on host " + knownInitiator.getHostName());
                        uem.getKnownInitiatorUris().add(knownInitiator.getId().toString());
                        uem.getKnownInitiatorNetworkIds().add(knownInitiator.getInitiatorPort());
                        knownInitiators.add(knownInitiator);
                    } else {
                        s_logger.info("   no hosts in ViPR found configured for initiator " + initiatorNetworkId);
                        uem.getUnmanagedInitiatorNetworkIds().add(initiatorNetworkId);
                    }
                }
                s_logger.info("now discovering storage ports in storage view " + storageView.getName());
                List<String> targetPortNames = storageView.getPorts();
                if (targetPortNames.isEmpty()) {
                    s_logger.info("no storage ports found in storage view " + storageView.getName());
                // continue; ?
                }
                // target port has value like - P0000000046E01E80-A0-FC02
                // PortWwn has value like - 0x50001442601e8002
                List<String> portWwns = new ArrayList<String>();
                for (String targetPortName : targetPortNames) {
                    Map<String, String> portToWwpnMap = clusterPortMap.get(clusterName);
                    if (portToWwpnMap.keySet().contains(targetPortName)) {
                        portWwns.add(WwnUtils.convertWWN(portToWwpnMap.get(targetPortName), WwnUtils.FORMAT.COLON));
                    }
                }
                for (String portNetworkId : portWwns) {
                    s_logger.info("looking at storage port network id " + portNetworkId);
                    // check if a storage port exists for this id in ViPR
                    // if so, add to _storagePorts
                    StoragePort knownStoragePort = NetworkUtil.getStoragePort(portNetworkId, _dbClient);
                    if (knownStoragePort != null) {
                        s_logger.info("   found a matching storage port in ViPR " + knownStoragePort.getLabel());
                        uem.getKnownStoragePortUris().add(knownStoragePort.getId().toString());
                        knownPorts.add(knownStoragePort);
                    } else {
                        s_logger.info("   no storage port in ViPR found matching portNetworkId " + portNetworkId);
                        uem.getUnmanagedStoragePortNetworkIds().add(portNetworkId);
                    }
                }
                s_logger.info("now discovering storage volumes in storage view " + storageView.getName());
                for (String volumeNameStr : storageView.getVirtualVolumes()) {
                    s_logger.info("found volume " + volumeNameStr);
                    // volumeNameStr contains value like
                    // (161,dd_V000195701573-00D57_VAPM00140801303-00614_vol,VPD83T3:6000144000000010f07dc46a0717e61d,2G)
                    String[] tokens = volumeNameStr.split(",");
                    String volumeName = tokens[1];
                    VPlexVirtualVolumeInfo vvol = vvolMap.get(volumeName);
                    Volume volume = findVirtualVolumeManagedByVipr(vvol);
                    if (volume != null) {
                        s_logger.info("this is a volume already managed by ViPR: " + volume.getLabel());
                        uem.getKnownVolumeUris().add(volume.getId().toString());
                    }
                    // add to map of volume paths to export masks
                    if (vvol != null) {
                        String nativeGuid = vvol.getPath();
                        s_logger.info("nativeGuid UnManagedVolume key for locating UnManagedExportMasks is " + nativeGuid);
                        Set<UnManagedExportMask> maskSet = volumeToExportMasksMap.get(nativeGuid);
                        if (maskSet == null) {
                            maskSet = new HashSet<UnManagedExportMask>();
                            s_logger.info("   creating new maskSet for nativeGuid " + nativeGuid);
                            volumeToExportMasksMap.put(nativeGuid, maskSet);
                        }
                        maskSet.add(uem);
                    }
                    // add this storage view to the volume to storage view map for this volume
                    Set<VPlexStorageViewInfo> storageViewSet = volumeToStorageViewMap.get(volumeName);
                    if (storageViewSet == null) {
                        storageViewSet = new HashSet<VPlexStorageViewInfo>();
                    }
                    storageViewSet.add(storageView);
                    volumeToStorageViewMap.put(volumeName, storageViewSet);
                }
                if (uem.getId() == null) {
                    uem.setId(URIUtil.createId(UnManagedExportMask.class));
                }
                if (checkRecoverPointExportMask(uem, knownInitiators, rpPortInitiators)) {
                    recoverPointExportMasks.add(uem.getId().toString());
                }
                updateZoningMap(uem, knownInitiators, knownPorts);
                persistUnManagedExportMasks(unManagedExportMasksToCreate, unManagedExportMasksToUpdate, false);
                allCurrentUnManagedExportMaskUris.add(uem.getId());
            }
        }
        persistUnManagedExportMasks(unManagedExportMasksToCreate, unManagedExportMasksToUpdate, true);
        cleanUpOrphanedExportMasks(vplexUri, allCurrentUnManagedExportMaskUris);
    } catch (Exception ex) {
        s_logger.error(ex.getLocalizedMessage(), ex);
        String vplexLabel = vplexUri.toString();
        if (null != vplex) {
            vplexLabel = vplex.getLabel();
        }
        throw VPlexCollectionException.exceptions.vplexUnmanagedExportMaskDiscoveryFailed(vplexLabel, ex.getLocalizedMessage());
    } finally {
        if (null != vplex) {
            try {
                vplex.setLastDiscoveryStatusMessage(statusMessage);
                _dbClient.updateObject(vplex);
            } catch (Exception ex) {
                s_logger.error("Error while saving VPLEX discovery status message: {} - Exception: {}", statusMessage, ex.getLocalizedMessage());
            }
        }
    }
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) Initiator(com.emc.storageos.db.client.model.Initiator) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) HashSet(java.util.HashSet) UnManagedExportMask(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask) StoragePort(com.emc.storageos.db.client.model.StoragePort) URISyntaxException(java.net.URISyntaxException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) BaseCollectionException(com.emc.storageos.plugins.BaseCollectionException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexCollectionException(com.emc.storageos.plugins.metering.vplex.VPlexCollectionException) IOException(java.io.IOException) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) Volume(com.emc.storageos.db.client.model.Volume) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) StringSetMap(com.emc.storageos.db.client.model.StringSetMap) TreeMap(java.util.TreeMap) StringMap(com.emc.storageos.db.client.model.StringMap)

Example 3 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VplexExportMaskValidator method validate.

@Override
public boolean validate() throws Exception {
    if (mask.getInactive()) {
        log.info("Export mask inactive: " + id);
        // no such export mask, ignore, but don't indicate pass
        return false;
    }
    log.info("Initiating validation of Vplex ExportMask: " + id);
    VPlexStorageViewInfo storageView = null;
    try {
        client = VPlexControllerUtils.getVPlexAPIClient(VPlexApiFactory.getInstance(), vplex, getDbClient());
        // This will throw an exception if the cluster name cannot be determined
        String vplexClusterName = VPlexUtil.getVplexClusterName(mask, vplex.getId(), client, getDbClient());
        // This will throw an exception if the StorageView cannot be found
        storageView = client.getStorageView(vplexClusterName, mask.getMaskName());
        if (volumesToValidate != null) {
            validateNoAdditionalVolumes(storageView);
        }
        if (initiatorsToValidate != null) {
            validateNoAdditionalInitiators(storageView);
        }
    } catch (Exception ex) {
        if (storageView == null) {
            // Not finding the storage view is not an error, so delete can be idempotent
            log.warn(String.format("Storage View %s cannot be located on VPLEX", id));
            return false;
        }
        log.error("Unexpected exception validating ExportMask: " + ex.getMessage(), ex);
        if (getValidatorConfig().isValidationEnabled()) {
            throw DeviceControllerException.exceptions.unexpectedCondition("Unexpected exception validating ExportMask: " + ex.getMessage());
        }
    }
    if (getValidatorLogger().hasErrors()) {
        return false;
    }
    log.info("Vplex ExportMask validation complete: " + id);
    return true;
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException)

Example 4 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VPlexControllerUtils method cleanStaleExportMasks.

/**
 * Cleans stale instances of ExportMasks from the database.  A stale instance is
 * one which no longer exists as a storage view on the VPLEX and also contains
 * no more user added volumes.
 *
 * @param dbClient a reference to the database client
 * @param vplexUri the VPLEX system URI
 */
public static void cleanStaleExportMasks(DbClient dbClient, URI vplexUri) {
    log.info("starting clean up of stale export masks for vplex {}", vplexUri);
    List<ExportMask> exportMasks = ExportMaskUtils.getExportMasksForStorageSystem(dbClient, vplexUri);
    // get a VPLEX API client for this VPLEX URI
    VPlexApiClient client = null;
    try {
        client = VPlexControllerUtils.getVPlexAPIClient(VPlexApiFactory.getInstance(), vplexUri, dbClient);
    } catch (URISyntaxException ex) {
        log.error("URISyntaxException encountered: ", ex);
    }
    if (null == client) {
        log.error("Couldn't load vplex api client, skipping stale export mask cleanup.");
        return;
    }
    // assemble collections of storage view native ids (VPLEX API context paths)
    // and export mask names (VPLEX API storage view names) for comparison with ViPR
    List<VPlexStorageViewInfo> storageViewsOnDevice = client.getStorageViewsLite();
    Set<String> svNativeIds = new HashSet<String>();
    Set<String> svNames = new HashSet<String>();
    for (VPlexStorageViewInfo sv : storageViewsOnDevice) {
        svNativeIds.add(sv.getPath());
        svNames.add(sv.getName());
    }
    // create collections to hold any stale data we find, for clean up all at once at the very end
    Set<ExportMask> staleExportMasks = new HashSet<ExportMask>();
    Map<ExportGroup, Set<ExportMask>> exportGroupToStaleMaskMap = new HashMap<ExportGroup, Set<ExportMask>>();
    Map<URI, ExportGroup> exportGroupUriMap = new HashMap<URI, ExportGroup>();
    // by ViPR in the database, but not yet created on the VPLEX device itself. skip those of course.
    for (ExportMask exportMask : exportMasks) {
        if (null != exportMask && !exportMask.getInactive() && (exportMask.getNativeId() != null && !exportMask.getNativeId().isEmpty())) {
            // we need to check both native id and export mask name to make sure we are NOT finding the storage view.
            // native id is most accurate, but greenfield ExportMasks for VPLEX don't have this property set.
            // native id will be set on ingested export masks, however, and we should check it, in case the same
            // storage view name is used on both vplex clusters.
            // greenfield VPLEX ExportMasks will always have unique mask names on both clusters (prefixed by V1_ or V2_),
            // so for greenfield export masks, we can check mask names if the native id property is not set.
            boolean noNativeIdMatch = (null != exportMask.getNativeId()) && !svNativeIds.contains(exportMask.getNativeId());
            boolean noMaskNameMatch = (null != exportMask.getMaskName()) && !svNames.contains(exportMask.getMaskName());
            if (noNativeIdMatch || noMaskNameMatch) {
                log.info("ExportMask {} is not found on VPLEX", exportMask.getMaskName());
                // if any user added volumes are still present, we will not do anything with this export mask
                boolean hasActiveVolumes = false;
                if (exportMask.hasAnyUserAddedVolumes()) {
                    List<URI> userAddedVolUris = URIUtil.toURIList(exportMask.getUserAddedVolumes().values());
                    List<Volume> userAddedVols = dbClient.queryObject(Volume.class, userAddedVolUris);
                    for (Volume vol : userAddedVols) {
                        if (null != vol && !vol.getInactive()) {
                            hasActiveVolumes = true;
                            break;
                        }
                    }
                }
                if (hasActiveVolumes) {
                    log.warn("ExportMask {} has active user added volumes, so will not remove from database.", exportMask.forDisplay());
                    continue;
                }
                // this is a stale export mask because it doesn't exist on the VPLEX and doesn't have user-added volumes
                staleExportMasks.add(exportMask);
                // we need to remove this stale ExportMask from any ExportGroups that contain it.
                // we use the exportGroupUriMap so that at the end of this process we will only
                // be updating a single ExportGroup instance from the database in case
                // multiple ExportMasks from the same ExportGroup need to be removed.
                List<ExportGroup> egList = ExportUtils.getExportGroupsForMask(exportMask.getId(), dbClient);
                if (!CollectionUtils.isEmpty(egList)) {
                    for (ExportGroup exportGroup : egList) {
                        // skip this one if the export group is no longer existent or active
                        if (null == exportGroup || exportGroup.getInactive()) {
                            continue;
                        }
                        // update or reuse from the cache of already-loaded ExportGroups
                        if (!exportGroupUriMap.containsKey(exportGroup.getId())) {
                            // add this one to the cache
                            exportGroupUriMap.put(exportGroup.getId(), exportGroup);
                        } else {
                            // just reuse the one already loaded from the database
                            exportGroup = exportGroupUriMap.get(exportGroup.getId());
                        }
                        // of associations at the end of this whole process
                        if (!exportGroupToStaleMaskMap.containsKey(exportGroup)) {
                            exportGroupToStaleMaskMap.put(exportGroup, new HashSet<ExportMask>());
                        }
                        exportGroupToStaleMaskMap.get(exportGroup).add(exportMask);
                        log.info("Stale ExportMask {} will be removed from ExportGroup {}", exportMask.getMaskName(), exportGroup.getLabel());
                    }
                }
            }
        }
    }
    if (!CollectionUtils.isEmpty(staleExportMasks)) {
        dbClient.markForDeletion(staleExportMasks);
        log.info("Deleted {} stale ExportMasks from database.", staleExportMasks.size());
        if (!CollectionUtils.isEmpty(exportGroupToStaleMaskMap.keySet())) {
            for (Entry<ExportGroup, Set<ExportMask>> entry : exportGroupToStaleMaskMap.entrySet()) {
                ExportGroup exportGroup = entry.getKey();
                for (ExportMask exportMask : entry.getValue()) {
                    log.info("Removing ExportMask {} from ExportGroup {}", exportMask.getMaskName(), exportGroup.getLabel());
                    exportGroup.removeExportMask(exportMask.getId());
                }
            }
            dbClient.updateObject(exportGroupToStaleMaskMap.keySet());
        }
    }
    log.info("Stale Export Mask cleanup complete.");
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) ExportMask(com.emc.storageos.db.client.model.ExportMask) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) HashSet(java.util.HashSet)

Example 5 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VPlexDeviceController method checkForExistingStorageViews.

/**
 * Checks for the existence of an existing Storage View on the VPLEX device based
 * on the host's initiator ports. Returns a flag indicating whether or not a
 * storage view was actually found on the device.
 *
 * @param client
 *            a VPLEX API client instance
 * @param targetPortToPwwnMap
 *            cached storage port data from the VPLEX API
 * @param vplexSystem
 *            a StorageSystem object representing the VPLEX system
 * @param vplexCluster
 *            a String indicating which VPLEX question to look at
 * @param inits
 *            the host initiators of the host in question
 * @param exportGroup
 *            the ViPR export group
 * @param varrayUri
 *            -- NOTE! The varrayUri may not be the same as the one in ExportGroup
 * @param blockObjectMap
 *            the map of URIs to block volumes for export
 * @param exportMasksToUpdateOnDevice
 *            collection of ExportMasks to update
 * @param exportMasksToUpdateOnDeviceWithInitiators
 *            a map of ExportMasks to initiators
 * @param exportMasksToUpdateOnDeviceWithStoragePorts
 *            a map of ExportMasks to storage ports
 * @param opId
 *            the workflow step id used to find the workflow to store/load zoning map
 * @return whether or not a storage view was actually found on the device
 */
private boolean checkForExistingStorageViews(VPlexApiClient client, Map<String, String> targetPortToPwwnMap, StorageSystem vplexSystem, String vplexCluster, List<Initiator> inits, ExportGroup exportGroup, URI varrayUri, Map<URI, Integer> blockObjectMap, List<ExportMask> exportMasksToUpdateOnDevice, Map<URI, List<Initiator>> exportMasksToUpdateOnDeviceWithInitiators, Map<URI, List<URI>> exportMasksToUpdateOnDeviceWithStoragePorts, Boolean[] doInitiatorRefresh, String opId) throws Exception {
    boolean foundMatchingStorageView = false;
    List<String> initiatorNames = getInitiatorNames(vplexSystem.getSerialNumber(), vplexCluster, client, inits.iterator(), doInitiatorRefresh);
    long start = new Date().getTime();
    List<VPlexStorageViewInfo> storageViewInfos = client.getStorageViewsContainingInitiators(vplexCluster, initiatorNames);
    long elapsed = new Date().getTime() - start;
    _log.info("TIMER: finding storage views containing initiators took {} ms", elapsed);
    if (storageViewInfos.size() > 1) {
        List<String> names = new ArrayList<String>();
        for (VPlexStorageViewInfo info : storageViewInfos) {
            names.add(info.getName());
        }
        // list of storage view names and initiators.
        throw VPlexApiException.exceptions.tooManyExistingStorageViewsFound(Joiner.on(", ").join(names), Joiner.on(", ").join(initiatorNames));
    } else if (storageViewInfos.size() == 1) {
        _log.info("a matching storage view was found on the VPLEX device, so ViPR will import it.");
        VPlexStorageViewInfo storageView = storageViewInfos.get(0);
        foundMatchingStorageView = true;
        // Grab the storage ports that have been allocated for this
        // existing mask.
        List<String> storagePorts = storageView.getPorts();
        if (storagePorts != null && storagePorts.isEmpty()) {
            _log.warn("No storage ports were found in the existing storage view {}, cannot reuse.", storageView.getName());
            return false;
        }
        // convert storage view target ports like P0000000046E01E80-A0-FC02
        // to port wwn format that ViPR better understands like 0x50001442601e8002
        List<String> portWwns = new ArrayList<String>();
        for (String storagePort : storagePorts) {
            if (targetPortToPwwnMap.keySet().contains(storagePort)) {
                portWwns.add(WwnUtils.convertWWN(targetPortToPwwnMap.get(storagePort), WwnUtils.FORMAT.COLON));
            }
        }
        List<String> storagePortURIs = ExportUtils.storagePortNamesToURIs(_dbClient, portWwns);
        _log.info("this storage view contains storage port URIs: " + storagePortURIs);
        // storageview is from.
        if (storagePortURIs == null || storagePortURIs.isEmpty()) {
            _log.warn("No storage ports managed by ViPR were found in the existing storage view {}, cannot reuse", storageView.getName());
            return false;
        }
        List<String> initiatorPorts = storageView.getInitiatorPwwns();
        for (Initiator init : inits) {
            String port = init.getInitiatorPort();
            String normalizedName = Initiator.normalizePort(port);
            _log.info("   looking at initiator " + normalizedName + " host " + VPlexUtil.getInitiatorHostResourceName(init));
            if (initiatorPorts.contains(normalizedName)) {
                _log.info("      found a matching initiator for " + normalizedName + " host " + VPlexUtil.getInitiatorHostResourceName(init) + " in storage view " + storageView.getName());
            }
        }
        ExportMask exportMask = new ExportMask();
        exportMask.setMaskName(storageView.getName());
        exportMask.setStorageDevice(vplexSystem.getId());
        exportMask.setId(URIUtil.createId(ExportMask.class));
        exportMask.setCreatedBySystem(false);
        exportMask.setNativeId(storageView.getPath());
        List<Initiator> initsToAdd = new ArrayList<Initiator>();
        for (Initiator init : inits) {
            // add all the the initiators the user has requested to add
            // to the exportMask initiators list
            exportMask.addInitiator(init);
            exportMask.addToUserCreatedInitiators(init);
            String normalInit = Initiator.normalizePort(init.getInitiatorPort());
            if (!storageView.getInitiatorPwwns().contains(normalInit)) {
                initsToAdd.add(init);
            }
        }
        exportMask.setStoragePorts(storagePortURIs);
        // Update the tracking containers
        exportMask.addToExistingVolumesIfAbsent(storageView.getWwnToHluMap());
        exportMask.addToExistingInitiatorsIfAbsent(initiatorPorts);
        // Create zoningMap for the matched initiators and storagePorts
        _networkDeviceController.updateZoningMapForInitiators(exportGroup, exportMask, false);
        _dbClient.createObject(exportMask);
        if (!initsToAdd.isEmpty()) {
            ExportPathParams pathParams = _blockScheduler.calculateExportPathParamForVolumes(blockObjectMap.keySet(), exportGroup.getNumPaths(), vplexSystem.getId(), exportGroup.getId());
            // Try to assign new ports by passing in existingMap
            Map<URI, List<URI>> assignments = _blockScheduler.assignStoragePorts(vplexSystem, exportGroup, initsToAdd, exportMask.getZoningMap(), pathParams, null, _networkDeviceController, varrayUri, opId);
            // Consolidate the prezoned ports with the new assignments to get the total ports needed in the mask
            if (assignments != null && !assignments.isEmpty()) {
                // Update zoningMap if there are new assignments
                exportMask = ExportUtils.updateZoningMap(_dbClient, exportMask, assignments, exportMasksToUpdateOnDeviceWithStoragePorts);
            }
        }
        exportMasksToUpdateOnDevice.add(exportMask);
        // add the initiators to the map for the exportMask that do not exist
        // already in the storage view as to create steps to add those initiators
        exportMasksToUpdateOnDeviceWithInitiators.put(exportMask.getId(), initsToAdd);
        // Storage ports that needs to be added will be calculated in the
        // add storage ports method from the zoning Map.
        exportMasksToUpdateOnDeviceWithStoragePorts.put(exportMask.getId(), new ArrayList<URI>());
        /*currently the Export Mask is added to the Export Group after all the hosts are being processed
              Change made for COP-31815
              This is so that ViPR can discover this ExportMask in the function:
               VPlexDEviceController.getInitiatorExportMasks 
            */
        exportGroup.addExportMask(exportMask.getId());
        _dbClient.updateObject(exportGroup);
    }
    return foundMatchingStorageView;
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) Date(java.util.Date) 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) Map(java.util.Map) OpStatusMap(com.emc.storageos.db.client.model.OpStatusMap) HashMap(java.util.HashMap) StringMap(com.emc.storageos.db.client.model.StringMap) ExportPathParams(com.emc.storageos.db.client.model.ExportPathParams)

Aggregations

VPlexStorageViewInfo (com.emc.storageos.vplex.api.VPlexStorageViewInfo)21 URI (java.net.URI)18 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)16 ExportMask (com.emc.storageos.db.client.model.ExportMask)15 ArrayList (java.util.ArrayList)15 NamedURI (com.emc.storageos.db.client.model.NamedURI)14 URISyntaxException (java.net.URISyntaxException)14 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)12 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)12 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)12 IOException (java.io.IOException)12 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)11 Initiator (com.emc.storageos.db.client.model.Initiator)10 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)10 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)10 ControllerException (com.emc.storageos.volumecontroller.ControllerException)10 WorkflowException (com.emc.storageos.workflow.WorkflowException)10 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)9 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)9 HashMap (java.util.HashMap)9