Search in sources :

Example 51 with VPlexApiException

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

the class VplexCinderMaskingOrchestrator method updateZoningMapAndvalidateExportMask.

/**
 * Re-validate the ExportMask
 *
 * This is required to be done as the ExportMask
 * gets updated by reading the cinder export volume
 * response.
 *
 * @param varrayURI
 * @param initiatorPortMap
 * @param mask
 * @param invalidMasks
 * @param directorToInitiatorIds
 * @param idToInitiatorMap
 * @param dbClient
 * @param portWwnToClusterMap
 */
public void updateZoningMapAndvalidateExportMask(URI varrayURI, Map<URI, List<StoragePort>> initiatorPortMap, URI exportMaskURI, Map<String, Set<String>> directorToInitiatorIds, Map<String, Initiator> idToInitiatorMap, Map<String, String> portWwnToClusterMap, StorageSystem vplex, StorageSystem array, String clusterId, String stepId) {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        // Export Mask is updated, read it from DB
        ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
        // First step would be to update the zoning map based on the connectivity
        updateZoningMap(initiatorPortMap, directorToInitiatorIds, exportMask);
        StringBuilder errorMessages = new StringBuilder();
        boolean passed = VPlexBackEndOrchestratorUtil.validateExportMask(varrayURI, initiatorPortMap, exportMask, null, directorToInitiatorIds, idToInitiatorMap, _dbClient, _coordinator, portWwnToClusterMap, errorMessages);
        if (!passed) {
            // Mark this mask as inactive, so that we dont pick it in the next iteration
            exportMask.setInactive(Boolean.TRUE);
            _dbClient.updateObject(exportMask);
            _log.error("Export Mask is not suitable for VPLEX to backend storage system");
            WorkflowStepCompleter.stepFailed(stepId, VPlexApiException.exceptions.couldNotFindValidArrayExportMask(vplex.getNativeGuid(), array.getNativeGuid(), clusterId, errorMessages.toString()));
            throw VPlexApiException.exceptions.couldNotFindValidArrayExportMask(vplex.getNativeGuid(), array.getNativeGuid(), clusterId, errorMessages.toString());
        }
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (Exception ex) {
        _log.error("Failed to validate export mask for cinder: ", ex);
        VPlexApiException vplexex = DeviceControllerExceptions.vplex.failedToValidateExportMask(exportMaskURI.toString(), ex);
        WorkflowStepCompleter.stepFailed(stepId, vplexex);
    }
}
Also used : ExportMask(com.emc.storageos.db.client.model.ExportMask) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException)

Example 52 with VPlexApiException

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

the class VplexCinderMaskingOrchestrator method deleteOrRemoveVolumesFromExportMask.

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

Example 53 with VPlexApiException

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

the class VplexCinderMaskingOrchestrator method createOrAddVolumesToExportMask.

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

Example 54 with VPlexApiException

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

the class AbstractConsistencyGroupManager method removeVolumesFromCGInternal.

/**
 * The method called by the workflow to remove VPLEX volumes from a VPLEX
 * consistency group.
 * @param vplexURI -- URI of VPlex device
 * @param cgURI -- URI of Consistency Group
 * @param vplexVolumeURIs -- URI list of volumes that will be removed
 * @return ServiceCoded exception if an error occurred, otherwise null if no error occurred.
 */
protected ServiceCoded removeVolumesFromCGInternal(URI vplexURI, URI cgURI, List<URI> vplexVolumeURIs) {
    try {
        if (vplexVolumeURIs.isEmpty()) {
            log.info("Empty volume list; no volumes to remove from CG %s", cgURI.toString());
            return null;
        }
        // Get the API client.
        StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, dbClient);
        VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexSystem, dbClient);
        log.info("Got VPLEX API client.");
        Map<String, List<String>> cgToVolumesMap = new HashMap<String, List<String>>();
        // Get the names of the volumes to be removed.
        List<Volume> vplexVolumes = new ArrayList<Volume>();
        for (URI vplexVolumeURI : vplexVolumeURIs) {
            Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, dbClient);
            if (vplexVolume == null || vplexVolume.getInactive()) {
                log.error(String.format("Skipping null or inactive vplex volume %s", vplexVolumeURI.toString()));
                continue;
            }
            // Remove CG reference from volume, it won't be persisted until after the operation completes.
            vplexVolume.setConsistencyGroup(NullColumnValueGetter.getNullURI());
            vplexVolumes.add(vplexVolume);
            // Get the CG name for this VPLEX volume, it could be a CG
            // that is distributed, a CG on cluster-1, or a CG on cluster-2.
            String cgName = getVplexCgName(vplexVolume, cgURI);
            // Keep a map of CG name grouped by all VPLEX volumes in that same CG.
            List<String> vplexVolumeNames = cgToVolumesMap.get(cgName);
            if (vplexVolumeNames == null) {
                vplexVolumeNames = new ArrayList<String>();
                cgToVolumesMap.put(cgName, vplexVolumeNames);
            }
            vplexVolumeNames.add(vplexVolume.getDeviceLabel());
            log.info(String.format("Adding VPLEX volume [%s](%s) with device label [%s] to be removed from VPLEX CG [%s]", vplexVolume.getLabel(), vplexVolume.getId(), vplexVolume.getDeviceLabel(), cgName));
        }
        for (Map.Entry<String, List<String>> entry : cgToVolumesMap.entrySet()) {
            String cgName = entry.getKey();
            List<String> vplexVolumeNames = entry.getValue();
            log.info(String.format("Removing the following VPLEX volumes from VPLEX CG [%s]: %s", cgName, Joiner.on(", ").join(vplexVolumeNames)));
            // Remove the volumes from the CG.
            client.removeVolumesFromConsistencyGroup(vplexVolumeNames, cgName, false);
        }
        log.info("Removed volumes from consistency group.");
        dbClient.updateObject(vplexVolumes);
        return null;
    } catch (VPlexApiException vae) {
        log.error("Exception removing volumes from consistency group: " + vae.getMessage(), vae);
        return vae;
    } catch (Exception ex) {
        log.error("Exception removing volumes from consistency group: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.DELETE_CG_VOLUME.getName();
        ServiceError serviceError = VPlexApiException.errors.removeVolumesFromCGFailed(opName, ex);
        return serviceError;
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) WorkflowException(com.emc.storageos.workflow.WorkflowException) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) StringSetMap(com.emc.storageos.db.client.model.StringSetMap) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 55 with VPlexApiException

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

the class VPlexConsistencyGroupManager method createCG.

/**
 * Called by the workflow to create a new VPLEX consistency group.
 *
 * @param vplexURI The URI of the VPLEX storage system.
 * @param cgURI The URI of the Bourne consistency group
 * @param vplexVolumeURIs The URI of the VPLEX used to determine the VPlex
 *            cluster/distributed information.
 * @param stepId The workflow step id.
 *
 * @throws WorkflowException When an error occurs updating the workflow step
 *             state.
 */
public void createCG(URI vplexURI, URI cgURI, List<URI> vplexVolumeURIs, String stepId) throws WorkflowException {
    try {
        // Update workflow step.
        WorkflowStepCompleter.stepExecuting(stepId);
        log.info("Updated step state for consistency group creation to execute.");
        // Lock the CG for the step duration.
        List<String> lockKeys = new ArrayList<String>();
        lockKeys.add(ControllerLockingUtil.getConsistencyGroupStorageKey(dbClient, cgURI, vplexURI));
        workflowService.acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.RP_VPLEX_CG));
        // Get the API client.
        StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, dbClient);
        VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexSystem, dbClient);
        log.info("Got VPLEX API client.");
        // Get the consistency group
        BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, dbClient);
        // Check to see if it was created since we defined the workflow.
        if (cg.created(vplexURI)) {
            StringSet cgNames = cg.getSystemConsistencyGroups().get(vplexURI.toString());
            log.info("Consistency group(s) already created: " + cgNames.toString());
            if (!cg.getTypes().contains(Types.VPLEX.name())) {
                // SRDF will reset the CG types. If the CG was existing on VPLEX need to make sure it is in types.
                cg.addConsistencyGroupTypes(Types.VPLEX.name());
                dbClient.updateObject(cg);
            }
            WorkflowStepCompleter.stepSucceded(stepId);
            return;
        }
        // We need to know on what cluster to create the consistency group.
        // The cluster would be determined by the virtual array specified in
        // a volume creation request, which is the virtual array of the
        // passed virtual volumes. Get the virtual array for one of the
        // vplex volumes.
        Volume firstVPlexVolume = getDataObject(Volume.class, vplexVolumeURIs.get(0), dbClient);
        // Lets determine the VPlex consistency group that need to be created for this volume.
        ClusterConsistencyGroupWrapper clusterConsistencyGroup = getClusterConsistencyGroup(firstVPlexVolume, cg);
        String cgName = clusterConsistencyGroup.getCgName();
        String clusterName = clusterConsistencyGroup.getClusterName();
        boolean isDistributed = clusterConsistencyGroup.isDistributed();
        URI vaURI = firstVPlexVolume.getVirtualArray();
        log.info("Got virtual array for VPLEX volume.");
        // Now we can create the consistency group.
        client.createConsistencyGroup(cgName, clusterName, isDistributed);
        log.info("Created VPLEX consistency group.");
        // Create the rollback data in case this needs to be deleted.
        VPlexCGRollbackData rbData = new VPlexCGRollbackData();
        rbData.setVplexSystemURI(vplexURI);
        rbData.setCgName(cgName);
        rbData.setClusterName(clusterName);
        rbData.setIsDistributed(new Boolean(getIsCGDistributed(client, cgName, clusterName)));
        workflowService.storeStepData(stepId, rbData);
        // Now update the CG in the DB.
        cg.setVirtualArray(vaURI);
        cg.setStorageController(vplexURI);
        cg.addSystemConsistencyGroup(vplexSystem.getId().toString(), BlockConsistencyGroupUtils.buildClusterCgName(clusterName, cgName));
        cg.addConsistencyGroupTypes(Types.VPLEX.name());
        dbClient.persistObject(cg);
        log.info("Updated consistency group in DB.");
        // Update workflow step state to success.
        WorkflowStepCompleter.stepSucceded(stepId);
        log.info("Updated workflow step for consistency group creation to success.");
    } catch (VPlexApiException vex) {
        log.error("Exception creating consistency group: " + vex.getMessage(), vex);
        WorkflowStepCompleter.stepFailed(stepId, vex);
    } catch (Exception ex) {
        log.error("Exception creating consistency group: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.CREATE_CONSISTENCY_GROUP.getName();
        ServiceError serviceError = VPlexApiException.errors.createConsistencyGroupFailed(opName, ex);
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ClusterConsistencyGroupWrapper(com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper) ArrayList(java.util.ArrayList) URI(java.net.URI) WorkflowException(com.emc.storageos.workflow.WorkflowException) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) StringSet(com.emc.storageos.db.client.model.StringSet) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Aggregations

VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)59 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)53 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)43 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)43 ControllerException (com.emc.storageos.volumecontroller.ControllerException)43 WorkflowException (com.emc.storageos.workflow.WorkflowException)43 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)41 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)41 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)40 URI (java.net.URI)39 ArrayList (java.util.ArrayList)39 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)34 IOException (java.io.IOException)34 URISyntaxException (java.net.URISyntaxException)34 ExportMask (com.emc.storageos.db.client.model.ExportMask)26 Volume (com.emc.storageos.db.client.model.Volume)25 NamedURI (com.emc.storageos.db.client.model.NamedURI)21 Initiator (com.emc.storageos.db.client.model.Initiator)20 BlockStorageDevice (com.emc.storageos.volumecontroller.BlockStorageDevice)14 VPlexVirtualVolumeInfo (com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo)12