Search in sources :

Example 71 with VPlexApiClient

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

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

the class AbstractConsistencyGroupManager method deleteConsistencyGroupVolume.

@Override
public void deleteConsistencyGroupVolume(URI vplexURI, Volume volume, BlockConsistencyGroup cg) throws Exception {
    VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexURI, dbClient);
    // Determine the VPlex CG corresponding to the this volume
    ClusterConsistencyGroupWrapper clusterCg = getClusterConsistencyGroup(volume, cg);
    if (clusterCg != null) {
        log.info(String.format("Removing VPlex virtual volume [%s - %s] from VPLEX CG [%s]", volume.getLabel(), volume.getDeviceLabel(), clusterCg.getCgName()));
        // Remove the volume from the CG. Delete the CG if it's empty
        // and the deleteCGWhenEmpty flag is set.
        client.removeVolumesFromConsistencyGroup(Arrays.asList(volume.getDeviceLabel()), clusterCg.getCgName(), false);
        // De-reference the CG
        volume.setConsistencyGroup(NullColumnValueGetter.getNullURI());
        dbClient.updateObject(volume);
    }
}
Also used : ClusterConsistencyGroupWrapper(com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient)

Example 73 with VPlexApiClient

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

the class RPVplexConsistencyGroupManager 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 list of URIs of the VPLEX volumes being
 *            added to the vplex CG
 * @param stepId The workflow step id.
 *
 * @throws WorkflowException When an error occurs updating the workflow step
 *             state.
 */
public void createCG(URI vplexURI, URI cgURI, Collection<URI> vplexVolumeURIs, String stepId) throws WorkflowException {
    try {
        // Update workflow step.
        WorkflowStepCompleter.stepExecuting(stepId);
        log.info("Updated step state for consistency group creation to execute.");
        if (vplexVolumeURIs == null || vplexVolumeURIs.isEmpty()) {
            log.info("empty volume list; no CG will be created");
            // Update workflow step state to success.
            WorkflowStepCompleter.stepSucceded(stepId);
            log.info("Updated workflow step for consistency group creation to success.");
            return;
        }
        // Get the API client.
        StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, dbClient);
        VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexSystem, dbClient);
        log.debug("Got VPLEX API client.");
        // For the following cases we need special steps for the CG to choose the HA side/leg on the VPLEX to be the winner:
        // 1. In an RP+VPLEX distributed setup, the user can choose to protect only the HA side.
        // 2. In a MetroPoint setup, the user can choose the HA side as the Active side.
        // Get the first source volume
        Volume firstVplexVolume = null;
        for (URI volURI : vplexVolumeURIs) {
            Volume vol = dbClient.queryObject(Volume.class, volURI);
            if (vol != null && PersonalityTypes.SOURCE.name().equalsIgnoreCase(vol.getPersonality())) {
                // found the first source volume so break
                firstVplexVolume = vol;
                break;
            }
        }
        if (firstVplexVolume != null && NullColumnValueGetter.isNotNullValue(firstVplexVolume.getPersonality()) && firstVplexVolume.getPersonality().equals(PersonalityTypes.SOURCE.toString())) {
            VirtualPool vpool = getDataObject(VirtualPool.class, firstVplexVolume.getVirtualPool(), dbClient);
            boolean haIsWinningCluster = VirtualPool.isRPVPlexProtectHASide(vpool) || (vpool.getMetroPoint() && NullColumnValueGetter.isNotNullValue(vpool.getHaVarrayConnectedToRp()));
            if (haIsWinningCluster) {
                log.info("Force HA side as winning cluster for VPLEX CG.");
                // Temporarily change the varray to the HA varray.
                // NOTE: Do not persist!
                firstVplexVolume.setLabel("DO NOT PERSIST THIS VOLUME");
                firstVplexVolume.setVirtualArray(URI.create(vpool.getHaVarrayConnectedToRp()));
            }
        }
        // acquire a lock to serialize create cg requests to the VPLEX
        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 consistency group
        BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, dbClient);
        // group the volumes by the cluster/CG that they will go in
        Map<String, List<URI>> cgToVolListMap = new HashMap<String, List<URI>>();
        for (URI vplexVolumeURI : vplexVolumeURIs) {
            Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, dbClient);
            // Lets determine the VPlex consistency group that need to be created for this volume.
            ClusterConsistencyGroupWrapper clusterConsistencyGroup = getClusterConsistencyGroup(vplexVolume, cg);
            String cgName = clusterConsistencyGroup.getCgName();
            String clusterName = clusterConsistencyGroup.getClusterName();
            boolean isDistributed = clusterConsistencyGroup.isDistributed();
            String cgKey = String.format("%s:%s:%s", cgName, clusterName, (isDistributed ? "dist" : "local"));
            if (!cgToVolListMap.containsKey(cgKey)) {
                cgToVolListMap.put(cgKey, new ArrayList<URI>());
            }
            cgToVolListMap.get(cgKey).add(vplexVolumeURI);
        }
        // loop through each cluster/CG; create the CG and add the volumes
        for (Entry<String, List<URI>> entry : cgToVolListMap.entrySet()) {
            String[] elems = StringUtils.delimitedListToStringArray(entry.getKey(), ":");
            if (elems.length != 3) {
                // serious coding error see above loop which creates the key
                log.error("Error in vplex cg mapping key. Expect <cgname>:<clustername>:<dist|local>; got: " + entry.getKey());
                continue;
            }
            String cgName = elems[0];
            String clusterName = elems[1];
            boolean isDistributed = elems[2].equals("dist");
            // Verify that the VPlex CG has been created for this VPlex system and cluster.
            if (!BlockConsistencyGroupUtils.isVplexCgCreated(cg, vplexURI.toString(), clusterName, cgName, isDistributed)) {
                createVplexCG(vplexSystem, client, cg, firstVplexVolume, cgName, clusterName, isDistributed);
            } else {
                modifyCGSettings(client, cgName, clusterName, isDistributed);
            }
            addVolumesToCG(cgURI, entry.getValue(), cgName, clusterName, client);
        }
        // Update workflow step state to success.
        WorkflowStepCompleter.stepSucceded(stepId);
        log.info("Updated workflow step for consistency group creation to success.");
    } catch (Exception ex) {
        log.error("Exception creating consistency group: " + ex.getMessage(), ex);
        ServiceError serviceError = VPlexApiException.errors.jobFailed(ex);
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ClusterConsistencyGroupWrapper(com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) URI(java.net.URI) WorkflowException(com.emc.storageos.workflow.WorkflowException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) ArrayList(java.util.ArrayList) List(java.util.List) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 74 with VPlexApiClient

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

Example 75 with VPlexApiClient

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

the class VPlexConsistencyGroupManager method createVplexCG.

/**
 * Create a Vplex CG within a step. This routine does not complete the step unless there is an error (and it returns false).
 * @param vplexSystem -- StorageSystem of the VPLEX
 * @param cg -- BlockConsistencyGroup object
 * @param protoVolume -- A prototypical Vplex volume
 * @param stepId -- String stepId, completed only if error
 * @return true if no error, false if error
 */
private boolean createVplexCG(StorageSystem vplexSystem, BlockConsistencyGroup cg, Volume protoVolume, String stepId) {
    try {
        VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexSystem, dbClient);
        log.info("Got VPLEX API client.");
        // Check to see if it was created since we defined the workflow.
        if (cg.created(vplexSystem.getId())) {
            StringSet cgNames = cg.getSystemConsistencyGroups().get(vplexSystem.getId().toString());
            log.info("Consistency group(s) already created: " + cgNames.toString());
            return true;
        }
        // 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.
        // Lets determine the VPlex consistency group that need to be created for this volume.
        ClusterConsistencyGroupWrapper clusterConsistencyGroup = getClusterConsistencyGroup(protoVolume, cg);
        String cgName = clusterConsistencyGroup.getCgName();
        String clusterName = clusterConsistencyGroup.getClusterName();
        boolean isDistributed = clusterConsistencyGroup.isDistributed();
        URI vaURI = protoVolume.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.");
        // Now update the CG in the DB.
        cg.setVirtualArray(vaURI);
        cg.addSystemConsistencyGroup(vplexSystem.getId().toString(), BlockConsistencyGroupUtils.buildClusterCgName(clusterName, cgName));
        cg.addConsistencyGroupTypes(Types.VPLEX.name());
        dbClient.updateObject(cg);
        log.info("Updated consistency group in DB.");
    } catch (VPlexApiException vex) {
        log.error("Exception creating consistency group: " + vex.getMessage(), vex);
        WorkflowStepCompleter.stepFailed(stepId, vex);
        return false;
    } 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);
        return false;
    }
    return true;
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ClusterConsistencyGroupWrapper(com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) StringSet(com.emc.storageos.db.client.model.StringSet) 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)

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