Search in sources :

Example 1 with VPlexDeviceInfo

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

the class VplexVolumeValidator method validateVolume.

/**
 * Validates an individual volume.
 *
 * @param virtualVolume the Volume to validate
 * @param delete boolean indicating if this validation is part of a delete operation
 * @param remediate boolean indicating whether or not remediation should be attempted
 * @param checks variable list of ValCks
 */
public void validateVolume(Volume virtualVolume, boolean delete, boolean remediate, ValCk... checks) {
    List<ValCk> checkList = Arrays.asList(checks);
    String volumeId = String.format("%s (%s)(%s)", virtualVolume.getLabel(), virtualVolume.getNativeGuid(), virtualVolume.getId());
    log.info("Initiating Vplex Volume validation: " + volumeId);
    VPlexVirtualVolumeInfo vvinfo = null;
    try {
        vvinfo = client.findVirtualVolume(virtualVolume.getDeviceLabel(), virtualVolume.getNativeId());
    } catch (VPlexApiException ex) {
        log.info(ex.getMessage());
    }
    if (vvinfo == null) {
        try {
            // Didn't find the virtual volume. Look at the storage volume, and from that determine
            // the deviceName. Then lookup the Device or DistributedDevice and check to see if
            // the device has been reassigned to a different virtual volume.
            Volume storageVolume = VPlexUtil.getVPLEXBackendVolume(virtualVolume, true, getDbClient(), false);
            if (storageVolume != null) {
                StorageSystem system = getDbClient().queryObject(StorageSystem.class, storageVolume.getStorageController());
                // Look up the corresponding device name to our Storage Volume
                VolumeInfo volumeInfo = new VolumeInfo(system.getNativeGuid(), system.getSystemType(), storageVolume.getWWN().toUpperCase().replaceAll(":", ""), storageVolume.getNativeId(), storageVolume.getThinlyProvisioned().booleanValue(), VPlexControllerUtils.getVolumeITLs(storageVolume));
                String deviceName = client.getDeviceForStorageVolume(volumeInfo);
                log.info("device name is " + deviceName);
                if (deviceName == null) {
                    if (!delete) {
                        // We didn't find a device name for the storage volume. Error if not deleting.
                        getValidatorLogger().logDiff(volumeId, "Vplex device-name", system.getSerialNumber() + "-" + storageVolume.getNativeId(), ValidatorLogger.NO_MATCHING_ENTRY);
                        return;
                    }
                }
                if (null != deviceName && !deviceName.trim().matches(VPlexApiConstants.STORAGE_VOLUME_NOT_IN_USE)) {
                    String volumeType = VPlexApiConstants.LOCAL_VIRTUAL_VOLUME;
                    if (virtualVolume.getAssociatedVolumes() != null && virtualVolume.getAssociatedVolumes().size() > 1) {
                        volumeType = VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME;
                    }
                    VPlexResourceInfo resourceInfo = client.getDeviceStructure(deviceName, volumeType);
                    if (resourceInfo instanceof VPlexDeviceInfo) {
                        // local device
                        VPlexDeviceInfo localDeviceInfo = (VPlexDeviceInfo) resourceInfo;
                        String virtualVolumeName = localDeviceInfo.getVirtualVolume();
                        if (virtualVolumeName != null && !virtualVolumeName.equals(virtualVolume.getDeviceLabel())) {
                            getValidatorLogger().logDiff(volumeId, "virtual-volume name changed", virtualVolume.getDeviceLabel(), virtualVolumeName);
                        }
                    } else if (resourceInfo instanceof VPlexDistributedDeviceInfo) {
                        VPlexDistributedDeviceInfo distDeviceInfo = (VPlexDistributedDeviceInfo) resourceInfo;
                        String virtualVolumeName = distDeviceInfo.getVirtualVolume();
                        if (virtualVolumeName != null && !virtualVolumeName.equals(virtualVolume.getDeviceLabel())) {
                            getValidatorLogger().logDiff(volumeId, "virtual-volume name changed", virtualVolume.getDeviceLabel(), virtualVolumeName);
                        }
                    }
                }
            }
        } catch (VPlexApiException ex) {
            log.error("Unable to determine if VPLEX device reused: " + volumeId, ex);
            if (getValidatorConfig().isValidationEnabled()) {
                throw ex;
            }
        }
        if (!delete) {
            // If we didn't log an error above indicating that the volume was reused,
            // and we are not deleting, it is still an error.
            // If we are deleting we won't error if it's just not there.
            getValidatorLogger().logDiff(volumeId, "virtual-volume", virtualVolume.getDeviceLabel(), ValidatorLogger.NO_MATCHING_ENTRY);
        }
        log.info("Vplex Validation complete (no vvinfo found); " + volumeId);
        return;
    }
    if (checkList.contains(ValCk.ID)) {
        if (!virtualVolume.getDeviceLabel().equals(vvinfo.getName())) {
            getValidatorLogger().logDiff(volumeId, "native-id", virtualVolume.getNativeId(), vvinfo.getName());
        }
        if (!NullColumnValueGetter.isNullValue(virtualVolume.getWWN()) && vvinfo.getWwn() != null && !virtualVolume.getWWN().equalsIgnoreCase(vvinfo.getWwn())) {
            getValidatorLogger().logDiff(volumeId, "wwn", virtualVolume.getWWN(), vvinfo.getWwn());
        }
        if (virtualVolume.getAssociatedVolumes() != null && !virtualVolume.getAssociatedVolumes().isEmpty()) {
            String locality = virtualVolume.getAssociatedVolumes().size() > 1 ? VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME : VPlexApiConstants.LOCAL_VIRTUAL_VOLUME;
            if (!locality.equalsIgnoreCase(vvinfo.getLocality())) {
                getValidatorLogger().logDiff(volumeId, "locality", locality, vvinfo.getLocality());
            }
        }
    }
    if (checkList.contains(ValCk.VPLEX) && !virtualVolume.isIngestedVolumeWithoutBackend(getDbClient())) {
        try {
            String drillDownInfo = client.getDrillDownInfoForDevice(vvinfo.getSupportingDevice());
            VPlexDrillDownParser parser = new VPlexDrillDownParser(drillDownInfo);
            VPlexDrillDownParser.Node root = parser.parse();
            boolean distributed = (root.getType() == VPlexDrillDownParser.NodeType.DIST) ? true : false;
            if (distributed) {
                List<VPlexDrillDownParser.Node> svols = root.getNodesOfType(NodeType.SVOL);
                boolean hasMirror = svols.size() > 2;
                String clusterName = VPlexControllerUtils.getVPlexClusterName(getDbClient(), virtualVolume);
                for (VPlexDrillDownParser.Node child : root.getChildren()) {
                    if (child.getArg2().equals(clusterName)) {
                        validateStorageVolumes(virtualVolume, volumeId, root.getArg1(), true, child.getArg2(), hasMirror);
                    }
                }
            } else {
                List<VPlexDrillDownParser.Node> svols = root.getNodesOfType(NodeType.SVOL);
                boolean hasMirror = svols.size() > 1;
                validateStorageVolumes(virtualVolume, volumeId, root.getArg1(), false, root.getArg2(), hasMirror);
            }
        } catch (Exception ex) {
            getValidatorLogger().logDiff(volumeId, "exception trying to validate storage volumes", virtualVolume.getDeviceLabel(), "N/A");
        }
    }
    log.info("Vplex Validation complete; " + volumeId);
}
Also used : ValCk(com.emc.storageos.volumecontroller.impl.validators.ValCk) VPlexDistributedDeviceInfo(com.emc.storageos.vplex.api.VPlexDistributedDeviceInfo) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) VPlexStorageVolumeInfo(com.emc.storageos.vplex.api.VPlexStorageVolumeInfo) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) VPlexDrillDownParser(com.emc.storageos.util.VPlexDrillDownParser) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexDeviceInfo(com.emc.storageos.vplex.api.VPlexDeviceInfo) VPlexResourceInfo(com.emc.storageos.vplex.api.VPlexResourceInfo) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 2 with VPlexDeviceInfo

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

the class VPlexDeviceController method migrationSupportedForVolume.

/**
 * Determines if the controller can support migration for the passed VPLEX volume.
 *
 * @param volume
 *            A reference to a VPLEX volume.
 * @param varrayURI
 *            A reference to a varray or null.
 *
 * @return true if migration is supported, false otherwise.
 */
public static boolean migrationSupportedForVolume(Volume volume, URI varrayURI, DbClient dbClient) {
    boolean supported = true;
    // Migration is supported for all volumes that were not ingested.
    if (volume.isIngestedVolumeWithoutBackend(dbClient)) {
        VirtualPool vpool = dbClient.queryObject(VirtualPool.class, volume.getVirtualPool());
        // Migration is supported for all local volumes.
        if (VirtualPool.HighAvailabilityType.vplex_distributed.name().equals(vpool.getHighAvailability())) {
            StorageSystem vplexSystem = dbClient.queryObject(StorageSystem.class, volume.getStorageController());
            try {
                VPlexApiFactory apiFactory = VPlexApiFactory.getInstance();
                VPlexApiClient client = getVPlexAPIClient(apiFactory, vplexSystem, dbClient);
                VPlexVirtualVolumeInfo vvInfo = client.getVirtualVolumeStructure(volume.getDeviceLabel());
                VPlexDistributedDeviceInfo ddInfo = (VPlexDistributedDeviceInfo) vvInfo.getSupportingDeviceInfo();
                List<VPlexDeviceInfo> localDeviceInfoList = ddInfo.getLocalDeviceInfo();
                for (VPlexDeviceInfo localDeviceInfo : localDeviceInfoList) {
                    _log.info("localDeviceInfo: {}, {}", localDeviceInfo.getName(), localDeviceInfo.getCluster());
                    // the passed varray.
                    if (varrayURI != null) {
                        _log.info("varrayURI:{}", varrayURI);
                        String varrayCluster = ConnectivityUtil.getVplexClusterForVarray(varrayURI, vplexSystem.getId(), dbClient);
                        _log.info("varrayCluster:{}", varrayCluster);
                        if (!localDeviceInfo.getCluster().contains(varrayCluster)) {
                            continue;
                        }
                    }
                    // For distributed volumes, the local device must be built
                    // on a single extent.
                    _log.info("Local device: {}", localDeviceInfo.getName());
                    _log.info("Extent count: {}", localDeviceInfo.getExtentInfo().size());
                    if (localDeviceInfo.getExtentInfo().size() != 1) {
                        supported = false;
                        break;
                    }
                }
            } catch (VPlexApiException vae) {
                _log.error("Exception checking if migration supported for volume:", vae);
                throw vae;
            } catch (Exception ex) {
                _log.error("Exception checking if migration supported for volume", ex);
                throw VPlexApiException.exceptions.failedGettingMigrationSupportedForVolume(vplexSystem.getId().toString(), volume.getLabel());
            }
        }
    }
    return supported;
}
Also used : VPlexDistributedDeviceInfo(com.emc.storageos.vplex.api.VPlexDistributedDeviceInfo) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) VPlexDeviceInfo(com.emc.storageos.vplex.api.VPlexDeviceInfo) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) VPlexApiFactory(com.emc.storageos.vplex.api.VPlexApiFactory)

Example 3 with VPlexDeviceInfo

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

the class VPlexDeviceController method createMirrors.

/**
 * Do the creation of a VPlex Mirror device and attach it as a mirror to the Virtual Volume.
 * This is called as a Workflow Step.
 * NOTE: The parameters here must match createMirrorsMethod above (except stepId).
 *
 * @param vplexURI
 *            URI of the VPlex StorageSystem
 * @param vplexMirrorURIs
 *            URI of the mirrors to be created.
 * @param workflowTaskId
 *            The workflow taskId.
 * @param stepId
 *            The stepId used for completion.
 *
 * @throws WorkflowException
 *             When an error occurs updating the workflow step
 *             state.
 */
public void createMirrors(URI vplexURI, List<URI> vplexMirrorURIs, String workflowTaskId, String stepId) throws WorkflowException {
    List<VolumeInfo> rollbackData = new ArrayList<VolumeInfo>();
    List<URI> createdVplexMirrorURIs = new ArrayList<URI>();
    VplexMirrorTaskCompleter completer = new VplexMirrorTaskCompleter(VplexMirror.class, vplexMirrorURIs, workflowTaskId);
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        // Get the API client.
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        // Make a map of StorageSystem ids to Storage System
        Map<URI, StorageSystem> storageMap = new HashMap<URI, StorageSystem>();
        // Make a map of Mirrors to Storage Volumes.
        Map<VplexMirror, Volume> mirrorMap = new HashMap<VplexMirror, Volume>();
        for (URI vplexMirrorURI : vplexMirrorURIs) {
            VplexMirror vplexMirror = getDataObject(VplexMirror.class, vplexMirrorURI, _dbClient);
            // Find the underlying Storage Volume, there will be only one associated storage volume
            for (String associatedVolume : vplexMirror.getAssociatedVolumes()) {
                Volume storageVolume = getDataObject(Volume.class, new URI(associatedVolume), _dbClient);
                URI storageSystemId = storageVolume.getStorageController();
                if (storageMap.containsKey(storageSystemId) == false) {
                    StorageSystem storage = _dbClient.queryObject(StorageSystem.class, storageSystemId);
                    storageMap.put(storageSystemId, storage);
                }
                mirrorMap.put(vplexMirror, storageVolume);
            }
        }
        // Now make a call to the VPlexAPIClient.createDeviceAndAttachAsMirror for each vplex mirror.
        StringBuilder buf = new StringBuilder();
        buf.append("Vplex: " + vplexURI + " created mirror(s): ");
        for (VplexMirror vplexMirror : mirrorMap.keySet()) {
            URI vplexMirrorId = vplexMirror.getId();
            Volume sourceVplexVolume = getDataObject(Volume.class, vplexMirror.getSource().getURI(), _dbClient);
            VPlexVirtualVolumeInfo vplexVolumeInfo = new VPlexVirtualVolumeInfo();
            vplexVolumeInfo.setName(sourceVplexVolume.getDeviceLabel());
            vplexVolumeInfo.setPath(sourceVplexVolume.getNativeId());
            if (null == sourceVplexVolume.getAssociatedVolumes() || sourceVplexVolume.getAssociatedVolumes().isEmpty()) {
                _log.error("VPLEX volume {} has no backend volumes.", sourceVplexVolume.forDisplay());
                throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(sourceVplexVolume.forDisplay());
            }
            if (sourceVplexVolume.getAssociatedVolumes().size() > 1) {
                vplexVolumeInfo.setLocality(VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME);
            } else {
                vplexVolumeInfo.setLocality(VPlexApiConstants.LOCAL_VIRTUAL_VOLUME);
            }
            _log.info(String.format("Creating mirror: %s (%s)", vplexMirror.getLabel(), vplexMirrorId));
            Volume storageVolume = mirrorMap.get(vplexMirror);
            long totalProvisioned = storageVolume.getProvisionedCapacity();
            StorageSystem storage = storageMap.get(storageVolume.getStorageController());
            List<String> itls = VPlexControllerUtils.getVolumeITLs(storageVolume);
            VolumeInfo vinfo = new VolumeInfo(storage.getNativeGuid(), storage.getSystemType(), storageVolume.getWWN().toUpperCase().replaceAll(":", ""), storageVolume.getNativeId(), storageVolume.getThinlyProvisioned().booleanValue(), itls);
            // Update rollback information.
            rollbackData.add(vinfo);
            List<VolumeInfo> vinfos = new ArrayList<VolumeInfo>();
            vinfos.add(vinfo);
            _workflowService.storeStepData(stepId, rollbackData);
            // Make the call to create device and attach it as mirror to the source virtual volume device.
            VPlexDeviceInfo vInfo = client.createDeviceAndAttachAsMirror(vplexVolumeInfo, vinfos, true, false);
            buf.append(vInfo.getName() + " ");
            _log.info(String.format("Created mirror : %s path: %s : for virtual volume %s device label %s", vInfo.getName(), vInfo.getPath(), sourceVplexVolume.getLabel(), sourceVplexVolume.getDeviceLabel()));
            vplexMirror.setNativeId(vInfo.getPath());
            vplexMirror.setDeviceLabel(vInfo.getName());
            // For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
            vplexMirror.setAllocatedCapacity(0L);
            vplexMirror.setProvisionedCapacity(totalProvisioned);
            if (vplexVolumeInfo.isThinEnabled() != sourceVplexVolume.getThinlyProvisioned()) {
                _log.info("Thin provisioned setting changed after mirror operation to " + vplexVolumeInfo.isThinEnabled());
                sourceVplexVolume.setThinlyProvisioned(vplexVolumeInfo.isThinEnabled());
                _dbClient.updateObject(sourceVplexVolume);
            }
            vplexMirror.setThinlyProvisioned(vplexVolumeInfo.isThinEnabled());
            _dbClient.updateObject(vplexMirror);
            // Record VPLEX volume created event.
            createdVplexMirrorURIs.add(vplexMirrorId);
            recordBourneVplexMirrorEvent(vplexMirrorId, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(true), Operation.Status.ready, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
        }
        completer.ready(_dbClient);
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        _log.error("Exception creating Mirror for the Virtual Volume: " + vae.getMessage(), vae);
        // not created.
        for (URI vplexMirrorURI : vplexMirrorURIs) {
            if (!createdVplexMirrorURIs.contains(vplexMirrorURI)) {
                recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(false), Operation.Status.error, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
            }
        }
        failStep(completer, stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception creating Mirror for the Virtual Volume: " + ex.getMessage(), ex);
        // not created.
        for (URI vplexMirrorURI : vplexMirrorURIs) {
            if (!createdVplexMirrorURIs.contains(vplexMirrorURI)) {
                recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(false), Operation.Status.error, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
            }
        }
        ServiceError serviceError = VPlexApiException.errors.createMirrorsFailed(ex);
        failStep(completer, stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) VplexMirrorTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VplexMirrorTaskCompleter) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) VPlexDeviceInfo(com.emc.storageos.vplex.api.VPlexDeviceInfo) VplexMirror(com.emc.storageos.db.client.model.VplexMirror) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 4 with VPlexDeviceInfo

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

the class VplexBackendIngestionContext method getMirrorMap.

/**
 * Creates a Map of cluster name to sorted Map of slot numbers to VPlexDeviceInfos
 * for use in describing the layout of VPLEX native mirrors.
 *
 * @return a Map of cluster id to sorted Map of slot numbers to VPlexDeviceInfos
 */
private Map<String, Map<String, VPlexDeviceInfo>> getMirrorMap() {
    if (null != mirrorMap) {
        return mirrorMap;
    }
    // the mirror map is a mapping of:
    // 
    // cluster id (e.g., cluster-1 and cluster-2) to:
    // a sorted map of device slot-number to:
    // the VPlexDeviceInfo in that slot
    // sort of like: Map<ClusterName, Map<SlotNumber, VPlexDeviceInfo>>
    // 
    // if distributed, it assumes only one mirror set
    // can be present on each side of the vplex
    _logger.info("assembling mirror map");
    mirrorMap = new HashMap<String, Map<String, VPlexDeviceInfo>>();
    VPlexResourceInfo device = getTopLevelDevice();
    if (isLocal() && (device instanceof VPlexDeviceInfo)) {
        VPlexDeviceInfo localDevice = ((VPlexDeviceInfo) device);
        if (VPlexApiConstants.ARG_GEOMETRY_RAID1.equals(((VPlexDeviceInfo) device).getGeometry())) {
            mirrorMap.put(localDevice.getCluster(), mapDevices(localDevice));
        }
    } else {
        for (VPlexDeviceInfo localDevice : ((VPlexDistributedDeviceInfo) device).getLocalDeviceInfo()) {
            if (VPlexApiConstants.ARG_GEOMETRY_RAID1.equals(((VPlexDistributedDeviceInfo) device).getGeometry())) {
                mirrorMap.put(localDevice.getCluster(), mapDevices(localDevice));
            }
        }
    }
    _logger.info("mirror map is: " + mirrorMap);
    return mirrorMap;
}
Also used : VPlexDistributedDeviceInfo(com.emc.storageos.vplex.api.VPlexDistributedDeviceInfo) VPlexDeviceInfo(com.emc.storageos.vplex.api.VPlexDeviceInfo) HashMap(java.util.HashMap) Map(java.util.Map) StringSetMap(com.emc.storageos.db.client.model.StringSetMap) TreeMap(java.util.TreeMap) StringMap(com.emc.storageos.db.client.model.StringMap) VPlexResourceInfo(com.emc.storageos.vplex.api.VPlexResourceInfo)

Example 5 with VPlexDeviceInfo

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

the class VplexBackendIngestionContext method getUnmanagedVplexMirrors.

/**
 * Returns a Map of UnManagedVolume objects that are parts
 * of a VplexMirror to their device context path from the
 * VPLEX API.
 *
 * @return a map of UnManagedVolume to device context paths
 */
public Map<UnManagedVolume, String> getUnmanagedVplexMirrors() {
    if (null != unmanagedMirrors) {
        return unmanagedMirrors;
    }
    if (!isDiscoveryInProgress()) {
        // first check the database for this unmanaged volume's backend mirrors
        StringSet mirrorMapFromTheDatabase = extractValuesFromStringSet(SupportedVolumeInformation.VPLEX_MIRROR_MAP.toString(), _unmanagedVirtualVolume.getVolumeInformation());
        if (null != mirrorMapFromTheDatabase && !mirrorMapFromTheDatabase.isEmpty()) {
            _logger.info("fetching mirror map from database");
            for (String mirrorEntry : mirrorMapFromTheDatabase) {
                // extract 'n' parse the mirror info from the database
                // pair[0] is the native id of the mirror
                // pair[1] is the device context path from the VPLEX API
                String[] pair = mirrorEntry.split("=");
                UnManagedVolume mirrorVolume = null;
                String contextPath = pair[1];
                // find the mirror UnManagedVolume object
                URIQueryResultList unManagedVolumeList = new URIQueryResultList();
                _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getVolumeInfoNativeIdConstraint(pair[0]), unManagedVolumeList);
                if (unManagedVolumeList.iterator().hasNext()) {
                    mirrorVolume = _dbClient.queryObject(UnManagedVolume.class, unManagedVolumeList.iterator().next());
                }
                // add to the map that will be returned from this method
                if (null != mirrorVolume && null != contextPath) {
                    if (null == unmanagedMirrors) {
                        unmanagedMirrors = new HashMap<UnManagedVolume, String>();
                    }
                    unmanagedMirrors.put(mirrorVolume, contextPath);
                    // now remove the mirror from the list of regular backend volumes
                    // so that it won't be ingested that way
                    Iterator<UnManagedVolume> itr = getUnmanagedBackendVolumes().iterator();
                    while (itr.hasNext()) {
                        if (mirrorVolume.getId().toString().equals(itr.next().getId().toString())) {
                            itr.remove();
                        }
                    }
                }
            }
            if (null != unmanagedMirrors && !unmanagedMirrors.isEmpty()) {
                _logger.info("found mirror map: " + unmanagedMirrors);
                return unmanagedMirrors;
            }
        }
    }
    unmanagedMirrors = new HashMap<UnManagedVolume, String>();
    // to check for native mirrors
    if (!_shouldCheckForMirrors) {
        return unmanagedMirrors;
    }
    // if we're in discovery only mode, don't check again during ingestion
    if (isIngestionInProgress() && isInDiscoveryOnlyMode()) {
        return unmanagedMirrors;
    }
    // if the mirror map couldn't be found in the database,
    // we will query the VPLEX API for this information
    long start = System.currentTimeMillis();
    _logger.info("getting unmanaged mirrors");
    if (!getMirrorMap().isEmpty()) {
        for (Entry<String, Map<String, VPlexDeviceInfo>> mirrorMapEntry : getMirrorMap().entrySet()) {
            _logger.info("looking at mirrors for device leg on cluster " + mirrorMapEntry.getKey());
            Map<String, VPlexDeviceInfo> slotToDeviceMap = mirrorMapEntry.getValue();
            if (null != slotToDeviceMap && !slotToDeviceMap.isEmpty()) {
                // figure out the source and target (mirror) UnManagedVolumes for this leg
                UnManagedVolume associatedVolumeSource = null;
                UnManagedVolume associatedVolumeMirror = null;
                // source will be in slot-0, target/mirror will be in slot-1
                for (Entry<String, VPlexDeviceInfo> entry : slotToDeviceMap.entrySet()) {
                    if (SLOT_0.equals(entry.getKey())) {
                        _logger.info("looking at slot-0");
                        associatedVolumeSource = getAssociatedVolumeForComponentDevice(entry.getValue());
                    }
                    if (SLOT_1.equals(entry.getKey())) {
                        _logger.info("looking at slot-1");
                        associatedVolumeMirror = getAssociatedVolumeForComponentDevice(entry.getValue());
                    }
                }
                // once found, wire them together:
                if (null != associatedVolumeMirror && null != associatedVolumeSource) {
                    // 1. remove the mirror volume from the general backend volumes
                    _logger.info("removing mirror volume {} from associated " + "vols and adding to mirrors", associatedVolumeMirror.getLabel());
                    getUnmanagedBackendVolumes().remove(associatedVolumeMirror);
                    // 2. add the mirror the unmanagedMirrors map that will be returned by this method
                    unmanagedMirrors.put(associatedVolumeMirror, slotToDeviceMap.get("1").getPath());
                    // 3. update the source volume with the target mirror information
                    StringSet set = new StringSet();
                    set.add(associatedVolumeMirror.getNativeGuid());
                    _logger.info("adding mirror set {} to source unmanaged volume {}", set, associatedVolumeSource);
                    associatedVolumeSource.putVolumeInfo(SupportedVolumeInformation.VPLEX_NATIVE_MIRROR_TARGET_VOLUME.toString(), set);
                    _logger.info("setting VPLEX_BACKEND_CLUSTER_ID on mirrored volumes: " + mirrorMapEntry.getKey());
                    StringSet clusterIds = new StringSet();
                    clusterIds.add(mirrorMapEntry.getKey());
                    associatedVolumeSource.putVolumeInfo(SupportedVolumeInformation.VPLEX_BACKEND_CLUSTER_ID.name(), clusterIds);
                    // 4. update the target volume with the source volume information
                    set = new StringSet();
                    set.add(associatedVolumeSource.getNativeGuid());
                    associatedVolumeMirror.putVolumeInfo(SupportedVolumeInformation.VPLEX_NATIVE_MIRROR_SOURCE_VOLUME.toString(), set);
                    associatedVolumeMirror.putVolumeInfo(SupportedVolumeInformation.VPLEX_BACKEND_CLUSTER_ID.name(), clusterIds);
                    // 5. need to go ahead and persist any changes to backend volume info
                    _dbClient.updateObject(associatedVolumeSource);
                    _dbClient.updateObject(associatedVolumeMirror);
                } else {
                    String reason = "couldn't find all associated device components in mirror device: ";
                    reason += " associatedVolumeSource is " + associatedVolumeSource;
                    reason += " and associatedVolumeMirror is " + associatedVolumeMirror;
                    _logger.error(reason);
                    throw VPlexApiException.exceptions.backendIngestionContextLoadFailure(reason);
                }
            }
        }
    }
    _logger.info("unmanaged mirrors found: " + unmanagedMirrors);
    _tracker.fetchMirrors = System.currentTimeMillis() - start;
    if (!unmanagedMirrors.isEmpty()) {
        StringSet mirrorEntries = new StringSet();
        for (Entry<UnManagedVolume, String> mirrorEntry : unmanagedMirrors.entrySet()) {
            mirrorEntries.add(mirrorEntry.getKey().getNativeGuid() + "=" + mirrorEntry.getValue());
        }
        if (mirrorEntries != null && !mirrorEntries.isEmpty()) {
            _logger.info("setting VPLEX_MIRROR_MAP: " + mirrorEntries);
            _unmanagedVirtualVolume.putVolumeInfo(SupportedVolumeInformation.VPLEX_MIRROR_MAP.name(), mirrorEntries);
        }
        // need to update the backend volumes because a mirror target shouldn't be considered a direct backend volume
        updateUnmanagedBackendVolumesInParent();
    }
    return unmanagedMirrors;
}
Also used : URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) StringSet(com.emc.storageos.db.client.model.StringSet) VPlexDeviceInfo(com.emc.storageos.vplex.api.VPlexDeviceInfo) HashMap(java.util.HashMap) Map(java.util.Map) StringSetMap(com.emc.storageos.db.client.model.StringSetMap) TreeMap(java.util.TreeMap) StringMap(com.emc.storageos.db.client.model.StringMap)

Aggregations

VPlexDeviceInfo (com.emc.storageos.vplex.api.VPlexDeviceInfo)6 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)3 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)3 VPlexDistributedDeviceInfo (com.emc.storageos.vplex.api.VPlexDistributedDeviceInfo)3 VPlexVirtualVolumeInfo (com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo)3 HashMap (java.util.HashMap)3 TreeMap (java.util.TreeMap)3 StringMap (com.emc.storageos.db.client.model.StringMap)2 StringSetMap (com.emc.storageos.db.client.model.StringSetMap)2 Volume (com.emc.storageos.db.client.model.Volume)2 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)2 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)2 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)2 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)2 ControllerException (com.emc.storageos.volumecontroller.ControllerException)2 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)2 VPlexResourceInfo (com.emc.storageos.vplex.api.VPlexResourceInfo)2 VolumeInfo (com.emc.storageos.vplex.api.clientdata.VolumeInfo)2 WorkflowException (com.emc.storageos.workflow.WorkflowException)2 IOException (java.io.IOException)2