Search in sources :

Example 6 with VPlexApiClient

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

the class VPlexControllerUtils method getDistributedDevicePathToClusterMap.

/**
 * Returns a Map of distributed device component context
 * paths from the VPLEX API to VPLEX cluster names.
 *
 * @param vplexUri the VPLEX to query
 * @param dbClient a reference to the database client
 * @return a Map of distributed device component context
 *         paths from the VPLEX API to VPLEX cluster names
 *
 * @throws VPlexApiException
 */
public static Map<String, String> getDistributedDevicePathToClusterMap(URI vplexUri, DbClient dbClient) throws VPlexApiException {
    VPlexApiClient client = null;
    try {
        VPlexApiFactory vplexApiFactory = VPlexApiFactory.getInstance();
        client = VPlexControllerUtils.getVPlexAPIClient(vplexApiFactory, vplexUri, dbClient);
    } catch (URISyntaxException e) {
        log.error("cannot load vplex api client", e);
    }
    Map<String, String> distributedDevicePathToClusterMap = Collections.emptyMap();
    if (null != client) {
        distributedDevicePathToClusterMap = client.getDistributedDevicePathToClusterMap();
    }
    return distributedDevicePathToClusterMap;
}
Also used : VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) URISyntaxException(java.net.URISyntaxException) VPlexApiFactory(com.emc.storageos.vplex.api.VPlexApiFactory)

Example 7 with VPlexApiClient

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

the class VPlexControllerUtils method getVPlexClusterName.

/**
 * Determines the cluster name based on the volume's virtual array.
 *
 * @param dbClient db client
 * @param vplexURI The vplex system URI
 * @param vaURI The virtual array URI
 * @return The VPlex cluster name
 * @throws Exception
 * @throws URISyntaxException
 */
public static String getVPlexClusterName(DbClient dbClient, URI vaURI, URI vplexURI) {
    String clusterName = null;
    // Get the vplex storage system so we can a handle on the vplex client
    StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, dbClient);
    VPlexApiClient client = null;
    try {
        client = VPlexControllerUtils.getVPlexAPIClient(VPlexApiFactory.getInstance(), vplexSystem, dbClient);
    } catch (URISyntaxException e) {
        throw VPlexApiException.exceptions.connectionFailure(vplexURI.toString());
    }
    String vplexCluster = ConnectivityUtil.getVplexClusterForVarray(vaURI, vplexSystem.getId(), dbClient);
    if (vplexCluster.equals(ConnectivityUtil.CLUSTER_UNKNOWN)) {
        throw VPlexApiException.exceptions.couldNotFindCluster(vplexCluster);
    }
    clusterName = client.getClusterNameForId(vplexCluster);
    return clusterName;
}
Also used : VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) URISyntaxException(java.net.URISyntaxException) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 8 with VPlexApiClient

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

the class VPlexControllerUtils method validateSupportingDeviceStructure.

/**
 * Validates that the underlying structure of the given device name
 * satisfies the constraints for compatibility with ViPR.  Used for
 * validating unmanaged VPLEX volumes before ingestion.
 *
 * @param deviceName the device to validate
 * @param vplexUri the VPLEX to query
 * @param dbClient a reference to the database client
 * @throws VPlexApiException if the device structure is incompatible with ViPR
 */
public static void validateSupportingDeviceStructure(String deviceName, URI vplexUri, DbClient dbClient) throws VPlexApiException {
    VPlexApiClient client = null;
    try {
        VPlexApiFactory vplexApiFactory = VPlexApiFactory.getInstance();
        client = VPlexControllerUtils.getVPlexAPIClient(vplexApiFactory, vplexUri, dbClient);
    } catch (URISyntaxException e) {
        log.error("cannot load vplex api client", e);
    }
    if (null != client) {
        String drillDownResponse = client.getDrillDownInfoForDevice(deviceName);
        if (!VPlexUtil.isDeviceStructureValid(deviceName, drillDownResponse)) {
            throw VPlexApiException.exceptions.deviceStructureIsIncompatibleForIngestion(drillDownResponse);
        }
    } else {
        throw VPlexApiException.exceptions.failedToExecuteDrillDownCommand(deviceName, "cannot load vplex api client");
    }
}
Also used : VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) URISyntaxException(java.net.URISyntaxException) VPlexApiFactory(com.emc.storageos.vplex.api.VPlexApiFactory)

Example 9 with VPlexApiClient

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

the class VPlexControllerUtils method getStorageVolumeInfoForDevice.

/**
 * Returns a Map of lowest-level storage-volume resource's WWN to its VPlexStorageVolumeInfo
 * object for a given device name, virtual volume type, and cluster name. If
 * hasMirror is true, this indicates the top-level device is composed of a
 * RAID-1 mirror, so there's an extra layers of components to traverse in finding
 * the lowest-level storage-volume resources.
 *
 * @param deviceName the name of the top-level device to look at
 * @param virtualVolumeType the type of virtual volume (local or distributed)
 * @param clusterName the cluster name
 * @param hasMirror indicates if the top-level device is a RAID-1 mirror
 * @param vplexUri the URI of the VPLEX system
 * @param dbClient a reference to the database client
 *
 * @return a map of WWNs to VPlexStorageVolumeInfo objects
 * @throws VPlexApiException
 */
public static Map<String, VPlexStorageVolumeInfo> getStorageVolumeInfoForDevice(String deviceName, String virtualVolumeType, String clusterName, boolean hasMirror, URI vplexUri, DbClient dbClient) throws VPlexApiException {
    Map<String, VPlexStorageVolumeInfo> storageVolumeInfo = null;
    VPlexApiClient client = null;
    try {
        VPlexApiFactory vplexApiFactory = VPlexApiFactory.getInstance();
        client = VPlexControllerUtils.getVPlexAPIClient(vplexApiFactory, vplexUri, dbClient);
    } catch (URISyntaxException e) {
        log.error("cannot load vplex api client", e);
    }
    if (null != client) {
        storageVolumeInfo = client.getStorageVolumeInfoForDevice(deviceName, virtualVolumeType, clusterName, hasMirror);
    }
    log.info("Backend storage volume wwns for {} are {}", deviceName, storageVolumeInfo);
    return storageVolumeInfo;
}
Also used : VPlexStorageVolumeInfo(com.emc.storageos.vplex.api.VPlexStorageVolumeInfo) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) URISyntaxException(java.net.URISyntaxException) VPlexApiFactory(com.emc.storageos.vplex.api.VPlexApiFactory)

Example 10 with VPlexApiClient

use of com.emc.storageos.vplex.api.VPlexApiClient 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)

Aggregations

VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)81 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)57 URISyntaxException (java.net.URISyntaxException)57 ControllerException (com.emc.storageos.volumecontroller.ControllerException)55 WorkflowException (com.emc.storageos.workflow.WorkflowException)55 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)54 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)52 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)52 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)52 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)48 IOException (java.io.IOException)47 URI (java.net.URI)41 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)40 Volume (com.emc.storageos.db.client.model.Volume)34 ArrayList (java.util.ArrayList)34 NamedURI (com.emc.storageos.db.client.model.NamedURI)26 HashMap (java.util.HashMap)18 ExportMask (com.emc.storageos.db.client.model.ExportMask)16 VPlexStorageViewInfo (com.emc.storageos.vplex.api.VPlexStorageViewInfo)16 VPlexVirtualVolumeInfo (com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo)16