use of com.emc.storageos.recoverpoint.responses.RecoverPointCGResponse in project coprhd-controller by CoprHD.
the class RPDeviceController method cgCreateStep.
/**
* Workflow step method for creating/updating a consistency group.
*
* @param rpSystemId
* RP system Id
* @param recommendation
* parameters needed to create the CG
* @param token
* the task
* @return
* @throws InternalException
*/
public boolean cgCreateStep(URI rpSystemId, List<VolumeDescriptor> volumeDescriptors, String token) throws InternalException {
RecoverPointClient rp;
CGRequestParams cgParams = null;
boolean metropoint = false;
boolean lockException = false;
try {
// Get only the RP volumes from the descriptors.
List<VolumeDescriptor> sourceVolumeDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.RP_SOURCE, VolumeDescriptor.Type.RP_EXISTING_SOURCE, VolumeDescriptor.Type.RP_VPLEX_VIRT_SOURCE }, new VolumeDescriptor.Type[] {});
WorkflowStepCompleter.stepExecuting(token);
ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, rpSystemId);
URI cgId = volumeDescriptors.iterator().next().getCapabilitiesValues().getBlockConsistencyGroup();
boolean attachAsClean = true;
for (VolumeDescriptor sourceVolumedescriptor : sourceVolumeDescriptors) {
Volume sourceVolume = _dbClient.queryObject(Volume.class, sourceVolumedescriptor.getVolumeURI());
metropoint = RPHelper.isMetroPointVolume(_dbClient, sourceVolume);
// if this is a change vpool, attachAsClean should be false so that source and target are synchronized
if (VolumeDescriptor.Type.RP_EXISTING_SOURCE.equals(sourceVolumedescriptor.getType())) {
attachAsClean = false;
}
}
// Build the CG Request params
cgParams = getCGRequestParams(volumeDescriptors, rpSystem);
updateCGParams(cgParams);
// Validate the source/target volumes before creating a CG.
validateCGVolumes(volumeDescriptors);
rp = RPHelper.getRecoverPointClient(rpSystem);
// Scan the rp sites for volume visibility
rp.waitForVolumesToBeVisible(cgParams);
// Before acquiring a lock on the CG we need to ensure that the
// CG is created. If it hasn't, then the first CGRequestParams
// to be allowed to pass through needs to have the journals
// defined.
//
// NOTE: The CG may not yet be created on the RP protection system and
// that's OK since this might be the first request going in.
waitForCGToBeCreated(cgId, cgParams);
// lock around create and delete operations on the same CG
List<String> lockKeys = new ArrayList<String>();
lockKeys.add(ControllerLockingUtil.getConsistencyGroupStorageKey(_dbClient, cgId, rpSystem.getId()));
boolean lockAcquired = _workflowService.acquireWorkflowStepLocks(token, lockKeys, LockTimeoutValue.get(LockType.RP_CG));
if (!lockAcquired) {
lockException = true;
throw DeviceControllerException.exceptions.failedToAcquireLock(lockKeys.toString(), String.format("Create or add volumes to RP consistency group id: %s", cgId.toString()));
}
RecoverPointCGResponse response = null;
// The CG already exists if it contains volumes and is of type RP
_log.info("Submitting RP Request: " + cgParams);
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, cgId);
// Check to see if the CG has been created in ViPR and on the RP protection system
boolean cgAlreadyExists = rpCGExists(cg, rp, cgParams.getCgName(), rpSystem.getId());
if (cgAlreadyExists) {
// cg exists in both the ViPR db and on the RP system
_log.info(String.format("RP CG [%s] already exists, adding replication set(s) to it...", cgParams.getCgName()));
response = rp.addReplicationSetsToCG(cgParams, metropoint, attachAsClean);
} else {
_log.info(String.format("RP CG [%s] does not already exist, creating it now and adding replication set(s) to it...", cgParams.getCgName()));
response = rp.createCG(cgParams, metropoint, attachAsClean);
// "Turn-on" the consistency group
cg = _dbClient.queryObject(BlockConsistencyGroup.class, cgParams.getCgUri());
cg.addSystemConsistencyGroup(rpSystemId.toString(), cgParams.getCgName());
cg.addConsistencyGroupTypes(Types.RP.name());
}
// At this point, always clear the journal provisioning lock on the
// CG for any concurrent orders that may come in.
cg.setJournalProvisioningLock(0L);
_dbClient.updateObject(cg);
setVolumeConsistencyGroup(volumeDescriptors, cgParams.getCgUri());
// If this was a vpool Update, now is a good time to update the vpool and Volume information
if (VolumeDescriptor.getVirtualPoolChangeVolume(volumeDescriptors) != null) {
Volume volume = _dbClient.queryObject(Volume.class, VolumeDescriptor.getVirtualPoolChangeVolume(volumeDescriptors));
URI newVpoolURI = getVirtualPoolChangeNewVirtualPool(volumeDescriptors);
volume.setVirtualPool(newVpoolURI);
volume.setPersonality(Volume.PersonalityTypes.SOURCE.toString());
volume.setAccessState(Volume.VolumeAccessState.READWRITE.name());
volume.setLinkStatus(Volume.LinkStatus.IN_SYNC.name());
volume.setProtectionController(rpSystemId);
_dbClient.updateObject(volume);
// We might need to update the vpools of the backing volumes if this is an RP+VPLEX
// or MetroPoint change vpool.
VPlexUtil.updateVPlexBackingVolumeVpools(volume, newVpoolURI, _dbClient);
// Record Audit operation. (virtualpool change only)
AuditBlockUtil.auditBlock(_dbClient, OperationTypeEnum.CHANGE_VOLUME_VPOOL, true, AuditLogManager.AUDITOP_END, token);
}
// Create the ProtectionSet to contain the CG UID (which is truly unique to the protection system)
if (response.getCgId() != null) {
List<ProtectionSet> protectionSets = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, ProtectionSet.class, AlternateIdConstraint.Factory.getConstraint(ProtectionSet.class, "protectionId", response.getCgId().toString()));
ProtectionSet protectionSet = null;
if (protectionSets.isEmpty()) {
// A protection set corresponding to the CG does not exist so we need to create one
protectionSet = createProtectionSet(rpSystem, cgParams, response.getCgId());
} else {
// Update the existing protection set. We will only have 1 protection set
// get the first one.
protectionSet = protectionSets.get(0);
protectionSet = updateProtectionSet(protectionSet, cgParams);
}
_dbClient.updateObject(protectionSet);
}
// Set the CG last created time to now.
rpSystem.setCgLastCreatedTime(Calendar.getInstance());
_dbClient.updateObject(rpSystem);
// Update the workflow state.
WorkflowStepCompleter.stepSucceded(token);
// collect and update the protection system statistics to account for
// the newly created CG.
_log.info("Collecting RP statistics post CG create.");
collectRPStatistics(rpSystem);
} catch (Exception e) {
if (lockException) {
List<URI> volUris = VolumeDescriptor.getVolumeURIs(volumeDescriptors);
ServiceError serviceError = DeviceControllerException.errors.createVolumesAborted(volUris.toString(), e);
doFailCgCreateStep(volumeDescriptors, cgParams, rpSystemId, token);
stepFailed(token, serviceError, "cgCreateStep");
} else {
doFailCgCreateStep(volumeDescriptors, cgParams, rpSystemId, token);
stepFailed(token, e, "cgCreateStep");
}
return false;
}
return true;
}
use of com.emc.storageos.recoverpoint.responses.RecoverPointCGResponse in project coprhd-controller by CoprHD.
the class RecoverPointClient method addReplicationSetsToCG.
/**
* Updates an existing CG by adding new replication sets.
*
* @param request - contains all the information required to create the consistency group
*
* @param attachAsClean attach as clean can be true if source and target are guaranteed to be the same (as in create
* new volume). for change vpool, attach as clean should be false
*
* @return RecoverPointCGResponse - response as to success or fail of creating the consistency group
*
* @throws RecoverPointException
*/
public RecoverPointCGResponse addReplicationSetsToCG(CGRequestParams request, boolean metropoint, boolean attachAsClean) throws RecoverPointException {
if (null == _endpoint.toASCIIString()) {
throw RecoverPointException.exceptions.noRecoverPointEndpoint();
}
RecoverPointCGResponse response = new RecoverPointCGResponse();
List<ConsistencyGroupCopySettings> groupCopySettings = null;
ConsistencyGroupUID cgUID = null;
try {
// Make sure the CG name is unique.
List<ConsistencyGroupUID> allCgs = functionalAPI.getAllConsistencyGroups();
for (ConsistencyGroupUID cg : allCgs) {
ConsistencyGroupSettings settings = functionalAPI.getGroupSettings(cg);
if (settings.getName().toString().equalsIgnoreCase(request.getCgName())) {
cgUID = settings.getGroupUID();
groupCopySettings = settings.getGroupCopiesSettings();
break;
}
}
if (cgUID == null) {
// The CG does not exist so we cannot add replication sets
throw RecoverPointException.exceptions.failedToAddReplicationSetCgDoesNotExist(request.getCgName());
}
response.setCgId(cgUID.getId());
// caches site names to cluster id's to reduce calls to fapi for the same information
Map<String, ClusterUID> clusterIdCache = new HashMap<String, ClusterUID>();
// prodSites is used for logging and to determine if a non-production copy is local or remote
List<ClusterUID> prodSites = new ArrayList<ClusterUID>();
// used to set the copy uid on the rset volume when adding rsets
Map<Long, ConsistencyGroupCopyUID> productionCopiesUID = new HashMap<Long, ConsistencyGroupCopyUID>();
Map<Long, ConsistencyGroupCopyUID> nonProductionCopiesUID = new HashMap<Long, ConsistencyGroupCopyUID>();
// get a list of CG production copies so we can determine which copies are production and which
// are not.
List<ConsistencyGroupCopyUID> productionCopiesUIDs = functionalAPI.getGroupSettings(cgUID).getProductionCopiesUIDs();
for (ConsistencyGroupCopySettings copySettings : groupCopySettings) {
GlobalCopyUID globalCopyUID = copySettings.getCopyUID().getGlobalCopyUID();
ConsistencyGroupCopyUID copyUID = copySettings.getCopyUID();
if (RecoverPointUtils.isProductionCopy(copyUID, productionCopiesUIDs)) {
productionCopiesUID.put(Long.valueOf(globalCopyUID.getClusterUID().getId()), copySettings.getCopyUID());
prodSites.add(globalCopyUID.getClusterUID());
} else {
nonProductionCopiesUID.put(Long.valueOf(globalCopyUID.getClusterUID().getId()), copySettings.getCopyUID());
}
}
StringBuffer sb = new StringBuffer();
for (ClusterUID prodSite : prodSites) {
sb.append(prodSite.getId());
sb.append(" ");
}
logger.info("RecoverPointClient: Adding replication set(s) to consistency group " + request.getCgName() + " for endpoint: " + _endpoint.toASCIIString() + " and production sites: " + sb.toString());
ConsistencyGroupSettingsChangesParam cgSettingsParam = configureCGSettingsChangeParams(request, cgUID, prodSites, clusterIdCache, productionCopiesUID, nonProductionCopiesUID, attachAsClean);
logger.info("Adding journals and rsets for CG " + request.getCgName());
functionalAPI.setConsistencyGroupSettings(cgSettingsParam);
// Sometimes the CG is still active when we start polling for link state and then
// starts initializing some time afterwards. Adding this sleep to make sure the CG
// starts initializing before we check the link states
waitForRpOperation();
RecoverPointImageManagementUtils rpiMgmt = new RecoverPointImageManagementUtils();
logger.info("Waiting for links to become active for CG " + request.getCgName());
// Wait for the CG link state to be active or paused. We can add replication sets to a CG that has a target
// copy in DIRECT_ACCESS mode. In this image access mode, the link state is PAUSED and is therefore a valid
// link state.
rpiMgmt.waitForCGLinkState(functionalAPI, cgUID, RecoverPointImageManagementUtils.getPipeActiveState(functionalAPI, cgUID), PipeState.PAUSED);
logger.info(String.format("Replication sets have been added to consistency group %s.", request.getCgName()));
response.setReturnCode(RecoverPointReturnCode.SUCCESS);
return response;
} catch (Exception e) {
logger.info("Failed to add replication set(s) to CG");
throw RecoverPointException.exceptions.failedToAddReplicationSetToConsistencyGroup(request.getCgName(), getCause(e));
}
}
use of com.emc.storageos.recoverpoint.responses.RecoverPointCGResponse in project coprhd-controller by CoprHD.
the class RecoverPointClient method createCG.
/**
* Creates a consistency group
*
* @param request - contains all the information required to create the consistency group
*
* @param attachAsClean attach as clean can be true if source and target are guaranteed to be the same (as in create
* new volume). for change vpool, attach as clean should be false
*
* @return CreateCGResponse - response as to success or fail of creating the consistency group
*
* @throws RecoverPointException
*/
public RecoverPointCGResponse createCG(CGRequestParams request, boolean metropoint, boolean attachAsClean) throws RecoverPointException {
if (null == _endpoint.toASCIIString()) {
throw RecoverPointException.exceptions.noRecoverPointEndpoint();
}
RecoverPointCGResponse response = new RecoverPointCGResponse();
ConsistencyGroupUID cgUID = null;
try {
// Make sure the CG name is unique.
int cgSuffix = 0;
String cgName = request.getCgName();
while (doesCgExist(request.getCgName())) {
request.setCgName(String.format("%s-%d", cgName, ++cgSuffix));
}
// caches site names to cluster id's to reduce calls to fapi for the same information
Map<String, ClusterUID> clusterIdCache = new HashMap<String, ClusterUID>();
// prodSites is used for logging and to determine if a non-production copy is local or remote
List<ClusterUID> prodSites = getProdSites(request, clusterIdCache);
StringBuffer sb = new StringBuffer();
for (ClusterUID prodSite : prodSites) {
sb.append(prodSite.getId());
sb.append(" ");
}
logger.info("RecoverPointClient: Creating recoverPoint consistency group " + request.getCgName() + " for endpoint: " + _endpoint.toASCIIString() + " and production sites: " + sb.toString());
// used to set the copy uid on the rset volume when adding rsets
Map<Long, ConsistencyGroupCopyUID> productionCopiesUID = new HashMap<Long, ConsistencyGroupCopyUID>();
Map<Long, ConsistencyGroupCopyUID> nonProductionCopiesUID = new HashMap<Long, ConsistencyGroupCopyUID>();
Map<ConsistencyGroupCopyUID, String> cgCopyNames = new HashMap<ConsistencyGroupCopyUID, String>();
FullConsistencyGroupPolicy fullConsistencyGroupPolicy = configureCGPolicy(request, prodSites, clusterIdCache, productionCopiesUID, nonProductionCopiesUID, cgCopyNames);
// create the CG with copies
logger.info("Adding cg, copies and links for CG: " + request.getCgName());
functionalAPI.validateAddConsistencyGroupAndCopies(fullConsistencyGroupPolicy);
cgUID = functionalAPI.addConsistencyGroupAndCopies(fullConsistencyGroupPolicy);
response.setCgId(cgUID.getId());
ConsistencyGroupSettingsChangesParam cgSettingsParam = configureCGSettingsChangeParams(request, cgUID, prodSites, clusterIdCache, productionCopiesUID, nonProductionCopiesUID, attachAsClean);
logger.info("Adding journals and rsets for CG " + request.getCgName());
functionalAPI.setConsistencyGroupSettings(cgSettingsParam);
RecoverPointImageManagementUtils rpiMgmt = new RecoverPointImageManagementUtils();
logger.info("Waiting for links to become active for CG " + request.getCgName());
rpiMgmt.waitForCGLinkState(functionalAPI, cgUID, RecoverPointImageManagementUtils.getPipeActiveState(functionalAPI, cgUID));
logger.info(String.format("Consistency group %s has been created.", request.getCgName()));
response.setReturnCode(RecoverPointReturnCode.SUCCESS);
return response;
} catch (Exception e) {
if (cgUID != null) {
try {
RecoverPointUtils.cleanupCG(functionalAPI, cgUID);
} catch (Exception e1) {
logger.error("Error removing CG " + request.getCgName() + " after create CG failure");
logger.error(e1.getMessage(), e1);
}
}
throw RecoverPointException.exceptions.failedToCreateConsistencyGroup(request.getCgName(), getCause(e));
}
}
Aggregations