Search in sources :

Example 6 with ClusterConsistencyGroupWrapper

use of com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper in project coprhd-controller by CoprHD.

the class VPlexConsistencyGroupManager method updateConsistencyGroupReadOnlyState.

/**
 * Step to call the VPLEX to update the read-only flag on a consistency group.
 * If the Vplex Api library detects the firmware does not properly handle the flag,
 * a warning message is put in the SUCCESS status.
 * @param vplexVolumeURIs -- List of at least some volumes in the consistency group.
 * @param isReadOnly - if true marks read-only, false read-write
 * @param stepId - Workflow step id
 */
public void updateConsistencyGroupReadOnlyState(List<URI> vplexVolumeURIs, Boolean isReadOnly, String stepId) {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        // Get the first virtual volume, as all volumes should be in the same CG
        Volume vplexVolume = dbClient.queryObject(Volume.class, vplexVolumeURIs.get(0));
        // Get the storage system for the Vplex.
        StorageSystem vplexSystem = dbClient.queryObject(StorageSystem.class, vplexVolume.getStorageController());
        // And from that a handle to the VplexApiClient
        VPlexApiClient client = getVPlexAPIClient(vplexApiFactory, vplexSystem, dbClient);
        // From that get the Consistency Group, if there is not one, just return success
        if (NullColumnValueGetter.isNullURI(vplexVolume.getConsistencyGroup())) {
            log.info("Volume has no ConsistencyGroup: " + vplexVolume.getLabel());
            WorkflowStepCompleter.stepSucceded(stepId);
            return;
        }
        BlockConsistencyGroup cg = dbClient.queryObject(BlockConsistencyGroup.class, vplexVolume.getConsistencyGroup());
        // Get the consistency group parameters.
        ClusterConsistencyGroupWrapper clusterConsistencyGroup = getClusterConsistencyGroup(vplexVolume, cg);
        String cgName = clusterConsistencyGroup.getCgName();
        String clusterName = clusterConsistencyGroup.getClusterName();
        boolean isDistributed = clusterConsistencyGroup.isDistributed();
        // Make the call to update the consistency group read-only status
        client.updateConsistencyGroupReadOnly(cgName, clusterName, isDistributed, isReadOnly);
        // Complete the step
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException ex) {
        if (ServiceCode.VPLEX_API_FIRMWARE_UPDATE_NEEDED.equals(ex.getServiceCode())) {
            // The firmware doesn't support read-only flag, inform the user, but do not fail.
            WorkflowStepCompleter.stepSucceeded(stepId, ex.getLocalizedMessage());
        } else {
            log.info("Exception setting Consistency Group read-only state: " + ex.getMessage());
            ServiceError svcError = VPlexApiException.errors.jobFailed(ex);
            WorkflowStepCompleter.stepFailed(stepId, svcError);
        }
    } catch (Exception ex) {
        log.info("Exception setting Consistency Group read-only state: " + ex.getMessage());
        ServiceError svcError = VPlexApiException.errors.jobFailed(ex);
        WorkflowStepCompleter.stepFailed(stepId, svcError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ClusterConsistencyGroupWrapper(com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) 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) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup)

Example 7 with ClusterConsistencyGroupWrapper

use of com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper in project coprhd-controller by CoprHD.

the class AbstractConsistencyGroupManager method addVolumeToClusterConsistencyGroup.

/**
 * Builds and adds a VPlex cluster/consistency group mapping for a given VPlex volume and ViPR
 * BlockConsistencyGroup name.
 *
 * @param vplexVolume The VPlex virtual volume for which we want to find a VPlex cluster/
 *            consistency group mapping.
 * @param clusterConsistencyGroupVolumes The Map to which we want to add the VPlex cluster/
 *            consistency group volume mapping.
 * @param cgName The ViPR BlockConsistencyGroup name.
 * @throws Exception
 */
protected void addVolumeToClusterConsistencyGroup(Volume vplexVolume, Map<ClusterConsistencyGroupWrapper, List<URI>> clusterConsistencyGroupVolumes, BlockConsistencyGroup cg) throws Exception {
    ClusterConsistencyGroupWrapper clusterConsistencyGroup = getClusterConsistencyGroup(vplexVolume, cg);
    if (!clusterConsistencyGroupVolumes.containsKey(clusterConsistencyGroup)) {
        clusterConsistencyGroupVolumes.put(clusterConsistencyGroup, new ArrayList<URI>());
    }
    clusterConsistencyGroupVolumes.get(clusterConsistencyGroup).add(vplexVolume.getId());
}
Also used : ClusterConsistencyGroupWrapper(com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper) URI(java.net.URI)

Example 8 with ClusterConsistencyGroupWrapper

use of com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper 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 9 with ClusterConsistencyGroupWrapper

use of com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper 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 10 with ClusterConsistencyGroupWrapper

use of com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper 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

ClusterConsistencyGroupWrapper (com.emc.storageos.volumecontroller.impl.utils.ClusterConsistencyGroupWrapper)14 BlockConsistencyGroup (com.emc.storageos.db.client.model.BlockConsistencyGroup)8 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)7 Volume (com.emc.storageos.db.client.model.Volume)6 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)6 ControllerException (com.emc.storageos.volumecontroller.ControllerException)6 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)6 WorkflowException (com.emc.storageos.workflow.WorkflowException)6 URI (java.net.URI)6 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)5 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)5 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)5 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)5 ArrayList (java.util.ArrayList)5 StringSet (com.emc.storageos.db.client.model.StringSet)4 HashMap (java.util.HashMap)2 List (java.util.List)2 VirtualPool (com.emc.storageos.db.client.model.VirtualPool)1 ServiceCoded (com.emc.storageos.svcs.errorhandling.model.ServiceCoded)1 VPlexConsistencyGroupInfo (com.emc.storageos.vplex.api.VPlexConsistencyGroupInfo)1