use of com.emc.storageos.svcs.errorhandling.resources.InternalException in project coprhd-controller by CoprHD.
the class ImageServerControllerImpl method deleteImage.
/**
* Delete image from all available imageServers
*
* @param task {@link AsyncTask} instance
*/
@Override
public void deleteImage(AsyncTask task) throws InternalException {
log.info("deleteImage " + task._id);
URI ciId = task._id;
TaskCompleter completer = null;
try {
completer = new ComputeImageCompleter(ciId, task._opId, OperationTypeEnum.DELETE_COMPUTE_IMAGE, EVENT_SERVICE_TYPE);
Workflow workflow = workflowService.getNewWorkflow(this, DELETE_IMAGE_WF, true, task._opId);
List<URI> ids = dbClient.queryByType(ComputeImageServer.class, true);
for (URI imageServerId : ids) {
ComputeImageServer imageServer = dbClient.queryObject(ComputeImageServer.class, imageServerId);
if (imageServer.getComputeImages() != null && imageServer.getComputeImages().contains(ciId.toString())) {
boolean imageServerVerified = verifyImageServer(imageServer);
if (!imageServerVerified) {
throw ImageServerControllerException.exceptions.imageServerNotSetup("Can't delete image: " + imageServerErrorMsg);
}
workflow.createStep(DELETE_IMAGE_STEP, String.format("removing image %s", ciId), null, ciId, ciId.toString(), this.getClass(), new Workflow.Method("deleteImageMethod", ciId, imageServer.getId()), new Workflow.Method(ROLLBACK_NOTHING_METHOD), null);
}
// So this cleanup needs to be performed.
if (imageServer.getFailedComputeImages() != null && imageServer.getFailedComputeImages().contains(ciId.toString())) {
imageServer.getFailedComputeImages().remove(ciId.toString());
dbClient.updateObject(imageServer);
}
}
workflow.executePlan(completer, SUCCESS);
} catch (Exception e) {
log.error("deleteImage caught an exception.", e);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
completer.error(dbClient, serviceError);
}
}
use of com.emc.storageos.svcs.errorhandling.resources.InternalException in project coprhd-controller by CoprHD.
the class RPDeviceController method exportGroupDelete.
/*
* RPDeviceController.exportGroupDelete()
*
* This method is a mini-orchestration of all of the steps necessary to delete an export group.
*
* This controller does not service block devices for export, only RP bookmark snapshots.
*
* The method is responsible for performing the following steps:
* - Call the block controller to delete the export of the target volumes
* - Disable the bookmarks associated with the snapshots.
*
* @param protectionDevice The RP System used to manage the protection
*
* @param exportgroupID The export group
*
* @param token The task object associated with the volume creation task that we piggy-back our events on
*/
@Override
public void exportGroupDelete(URI protectionDevice, URI exportGroupID, String token) throws InternalException {
TaskCompleter taskCompleter = null;
try {
// Grab the RP System information; we'll need it to talk to the RP client
ProtectionSystem rpSystem = getRPSystem(protectionDevice);
taskCompleter = new RPCGExportDeleteCompleter(exportGroupID, token);
// Create a new token/taskid and use that in the workflow. Multiple threads entering this method might
// collide with each others
// workflows in cassandra if the taskid is not unique.
String newToken = UUID.randomUUID().toString();
// Set up workflow steps.
Workflow workflow = _workflowService.getNewWorkflow(this, "exportGroupDelete", true, newToken);
// Task 1: deactivate the bookmarks
//
// Disable image access on the target volumes
// This is important to do first because:
// After the export group is deleted (in the next step), we may not have access to the object.
// If export delete itself were to fail, it's good that we at least got this step done. Easier to remediate.
addDisableImageAccessSteps(workflow, rpSystem, exportGroupID);
// Task 2: Export Delete Volumes
//
// Delete of the export group with the volumes associated with the snapshots to the host
addExportSnapshotDeleteSteps(workflow, rpSystem, exportGroupID);
// Execute the plan and allow the WorkflowExecutor to fire the taskCompleter.
String successMessage = String.format("Workflow of Export Group %s Delete successfully created", exportGroupID);
workflow.executePlan(taskCompleter, successMessage);
} catch (InternalException e) {
_log.error("Operation failed with Exception: ", e);
if (taskCompleter != null) {
taskCompleter.error(_dbClient, e);
}
} catch (Exception e) {
_log.error("Operation failed with Exception: ", e);
if (taskCompleter != null) {
taskCompleter.error(_dbClient, DeviceControllerException.errors.jobFailed(e));
}
}
}
use of com.emc.storageos.svcs.errorhandling.resources.InternalException in project coprhd-controller by CoprHD.
the class RPDeviceController method deleteSnapshot.
@Override
public void deleteSnapshot(URI protectionDevice, URI snapshotURI, String opId) throws InternalException {
TaskCompleter taskCompleter = null;
try {
BlockSnapshot snap = _dbClient.queryObject(BlockSnapshot.class, snapshotURI);
taskCompleter = BlockSnapshotDeleteCompleter.createCompleter(_dbClient, snap, opId);
List<BlockSnapshot> snapshots = new ArrayList<BlockSnapshot>();
URI cgId = null;
if (snap.getConsistencyGroup() != null) {
cgId = snap.getConsistencyGroup();
}
if (cgId != null) {
// Account for all CG BlockSnapshots if this requested BlockSnapshot
// references a CG.
snapshots = ControllerUtils.getSnapshotsPartOfReplicationGroup(snap, _dbClient);
} else {
snapshots.add(snap);
}
for (BlockSnapshot snapshot : snapshots) {
if (snapshot != null && !snapshot.getInactive()) {
snapshot.setInactive(true);
snapshot.setIsSyncActive(false);
_dbClient.updateObject(snapshot);
}
// Perhaps the snap is already deleted/inactive.
// In that case, we'll just say all is well, so that this operation
// is idempotent.
}
taskCompleter.ready(_dbClient);
} catch (InternalException e) {
String message = String.format("Generic exception when trying to delete snapshot %s on protection system %s", String.valueOf(snapshotURI), protectionDevice);
_log.error(message, e);
taskCompleter.error(_dbClient, e);
} catch (Exception e) {
String message = String.format("Generic exception when trying to delete snapshot %s on protection system %s", String.valueOf(snapshotURI), protectionDevice);
_log.error(message, e);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
taskCompleter.error(_dbClient, serviceError);
}
}
use of com.emc.storageos.svcs.errorhandling.resources.InternalException in project coprhd-controller by CoprHD.
the class RPDeviceController method performProtectionOperationStep.
/**
* Workflow step to perform RP protection operation
*
* @param protectionSystem
* @param cgId
* @param volId
* @param copyID
* @param pointInTime
* @param imageAccessMode
* @param op
* @param stepId
* @return
* @throws ControllerException
*/
public boolean performProtectionOperationStep(URI protectionSystem, URI cgId, URI volId, URI copyID, String pointInTime, String imageAccessMode, String op, String stepId) throws ControllerException {
WorkflowStepCompleter.stepExecuting(stepId);
RPHelper.setLinkStateWaitTimeOut(_coordinator);
try {
ProtectionSystem rpSystem = getRPSystem(protectionSystem);
// Take out a workflow step lock on the CG
_workflowService.getWorkflowFromStepId(stepId);
List<String> lockKeys = new ArrayList<String>();
lockKeys.add(ControllerLockingUtil.getConsistencyGroupStorageKey(_dbClient, cgId, rpSystem.getId()));
boolean lockAcquired = _workflowService.acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.RP_CG));
if (!lockAcquired) {
throw DeviceControllerException.exceptions.failedToAcquireLock(lockKeys.toString(), String.format("failed to get lock while restoring volumes in RP consistency group: %s", cgId.toString()));
}
// set the protection volume to the source volume if the copyID is null (operation is performed on all
// copies)
// otherwise set it to the volume referenced by the copyID (operation is performed on specifc copy)
Volume protectionVolume = (copyID == null) ? _dbClient.queryObject(Volume.class, volId) : _dbClient.queryObject(Volume.class, copyID);
RecoverPointClient rp = RPHelper.getRecoverPointClient(rpSystem);
RecoverPointVolumeProtectionInfo volumeProtectionInfo = rp.getProtectionInfoForVolume(RPHelper.getRPWWn(protectionVolume.getId(), _dbClient));
if (op.equals(STOP)) {
rp.disableProtection(volumeProtectionInfo);
setProtectionSetStatus(volumeProtectionInfo, ProtectionStatus.DISABLED.toString(), rpSystem);
_log.info("doStopProtection {} - complete", rpSystem.getId());
} else if (op.equals(START)) {
rp.enableProtection(volumeProtectionInfo);
setProtectionSetStatus(volumeProtectionInfo, ProtectionStatus.ENABLED.toString(), rpSystem);
} else if (op.equals(SYNC)) {
Set<String> volumeWWNs = new HashSet<String>();
volumeWWNs.add(RPHelper.getRPWWn(protectionVolume.getId(), _dbClient));
// Create and enable a temporary bookmark for the volume associated with this volume
CreateBookmarkRequestParams request = new CreateBookmarkRequestParams();
request.setVolumeWWNSet(volumeWWNs);
request.setBookmark("Sync-Snapshot");
rp.createBookmarks(request);
} else if (op.equals(PAUSE)) {
rp.pauseTransfer(volumeProtectionInfo);
setProtectionSetStatus(volumeProtectionInfo, ProtectionStatus.PAUSED.toString(), rpSystem);
} else if (op.equals(RESUME)) {
rp.resumeTransfer(volumeProtectionInfo);
setProtectionSetStatus(volumeProtectionInfo, ProtectionStatus.ENABLED.toString(), rpSystem);
} else if (op.equals(FAILOVER_TEST)) {
RPCopyRequestParams copyParams = new RPCopyRequestParams();
copyParams.setCopyVolumeInfo(volumeProtectionInfo);
rp.failoverCopyTest(copyParams);
} else if (op.equals(FAILOVER)) {
// cancel.
if (protectionVolume.getLinkStatus() != null && protectionVolume.getLinkStatus().equalsIgnoreCase(Volume.LinkStatus.FAILED_OVER.name())) {
// TODO: ViPR 2.0 needs to support this.
// TODO BEGIN: allow re-failover perform the same as a failback in 2.0 since the UI support will not
// be there to do a
// swap or cancel.
// Jira CTRL-2773: Once UI adds support for /swap and /failover-cancel, we can remove this and
// replace with an error.
// If protectionVolume is a source, then the "source" sent in must be a target. Verify.
Volume targetVolume = null;
if (protectionVolume.checkPersonality(Volume.PersonalityTypes.SOURCE.toString())) {
targetVolume = _dbClient.queryObject(Volume.class, volId);
} else {
targetVolume = protectionVolume;
}
// Disable the image access that is in effect.
volumeProtectionInfo = rp.getProtectionInfoForVolume(RPHelper.getRPWWn(targetVolume.getId(), _dbClient));
RPCopyRequestParams copyParams = new RPCopyRequestParams();
copyParams.setCopyVolumeInfo(volumeProtectionInfo);
rp.failoverCopyCancel(copyParams);
// Set the flags back to where they belong.
updatePostFailoverCancel(targetVolume);
// TODO END
// Replace with this error: taskCompleter.error(_dbClient, _locker,
// DeviceControllerErrors.recoverpoint.stepFailed("performFailoverOperation: source volume specified
// for failover where target volume specified is not in failover state"));
} else {
// Standard failover case.
RPCopyRequestParams copyParams = new RPCopyRequestParams();
copyParams.setCopyVolumeInfo(volumeProtectionInfo);
if (pointInTime != null) {
// Build a Date reference.
copyParams.setApitTime(TimeUtils.getDateTimestamp(pointInTime));
}
rp.failoverCopy(copyParams);
updatePostFailover(protectionVolume);
}
} else if (op.equals(FAILOVER_CANCEL)) {
// cancel.
if (protectionVolume.checkPersonality(Volume.PersonalityTypes.SOURCE.name())) {
throw DeviceControllerExceptions.recoverpoint.failoverWrongTargetSpecified();
} else {
if (protectionVolume.getLinkStatus() != null && protectionVolume.getLinkStatus().equalsIgnoreCase(Volume.LinkStatus.FAILED_OVER.name())) {
// Disable the image access that is in effect.
volumeProtectionInfo = rp.getProtectionInfoForVolume(RPHelper.getRPWWn(protectionVolume.getId(), _dbClient));
RPCopyRequestParams copyParams = new RPCopyRequestParams();
copyParams.setCopyVolumeInfo(volumeProtectionInfo);
rp.failoverCopyCancel(copyParams);
// Set the flags back to where they belong.
updatePostFailoverCancel(protectionVolume);
} else {
// failed over target.
throw DeviceControllerExceptions.recoverpoint.failoverWrongTargetSpecified();
}
}
} else if (op.equals(SWAP)) {
RPCopyRequestParams copyParams = new RPCopyRequestParams();
copyParams.setCopyVolumeInfo(volumeProtectionInfo);
rp.swapCopy(copyParams);
protectionVolume = updatePostSwapPersonalities(protectionVolume);
rp.setCopyAsProduction(copyParams);
// 3. add back the standby CDP copy
if (RPHelper.isMetroPointVolume(_dbClient, protectionVolume)) {
// copy exists, we can skip all the CG reconstruction steps.
if (!rp.doesStandbyProdCopyExist(volumeProtectionInfo)) {
_log.info(String.format("Adding back standby production copy after swap back to original VPlex Metro for Metropoint volume %s (%s)", protectionVolume.getLabel(), protectionVolume.getId().toString()));
List<Volume> standbyLocalCopyVols = RPHelper.getMetropointStandbyCopies(protectionVolume, _dbClient);
CreateCopyParams standbyLocalCopyParams = null;
List<CreateRSetParams> rSets = new ArrayList<CreateRSetParams>();
Set<URI> journalVolumes = new HashSet<URI>();
List<String> deletedCopies = new ArrayList<>();
if (!standbyLocalCopyVols.isEmpty()) {
for (Volume standbyCopyVol : standbyLocalCopyVols) {
// For case where there are multiple Rsets, we should invoke deleteCopy only once, it shall
// remove the related copy information from other Rsets as well. rpCopyName is same across
// all Rpsets, so track the delete based on rpCopyName
String rpCopyName = standbyCopyVol.getRpCopyName().trim();
if (!deletedCopies.contains(rpCopyName)) {
// 1. delete the standby CDP copy if it exists
if (rp.doesProtectionVolumeExist(RPHelper.getRPWWn(standbyCopyVol.getId(), _dbClient))) {
RecoverPointVolumeProtectionInfo standbyCdpCopy = rp.getProtectionInfoForVolume(RPHelper.getRPWWn(standbyCopyVol.getId(), _dbClient));
rp.deleteCopy(standbyCdpCopy);
deletedCopies.add(rpCopyName);
}
}
// set up volume info for the standby copy volume
CreateVolumeParams vol = new CreateVolumeParams();
vol.setWwn(RPHelper.getRPWWn(standbyCopyVol.getId(), _dbClient));
vol.setInternalSiteName(standbyCopyVol.getInternalSiteName());
vol.setProduction(false);
List<CreateVolumeParams> volumes = new ArrayList<CreateVolumeParams>();
volumes.add(vol);
CreateRSetParams rSet = new CreateRSetParams();
rSet.setName(standbyCopyVol.getRSetName());
rSet.setVolumes(volumes);
rSets.add(rSet);
List<Volume> standbyJournals = RPHelper.findExistingJournalsForCopy(_dbClient, standbyCopyVol.getConsistencyGroup(), standbyCopyVol.getRpCopyName());
// compile a unique set of journal volumes
for (Volume standbyJournal : standbyJournals) {
journalVolumes.add(standbyJournal.getId());
}
}
// prepare journal volumes info
String rpCopyName = null;
List<CreateVolumeParams> journalVols = new ArrayList<CreateVolumeParams>();
for (URI journalVolId : journalVolumes) {
Volume standbyLocalJournal = _dbClient.queryObject(Volume.class, journalVolId);
if (standbyLocalJournal != null) {
_log.info(String.format("Found standby local journal volume %s (%s) for metropoint volume %s (%s)", standbyLocalJournal.getLabel(), standbyLocalJournal.getId().toString(), protectionVolume.getLabel(), protectionVolume.getId().toString()));
rpCopyName = standbyLocalJournal.getRpCopyName();
CreateVolumeParams journalVolParams = new CreateVolumeParams();
journalVolParams.setWwn(RPHelper.getRPWWn(standbyLocalJournal.getId(), _dbClient));
journalVolParams.setInternalSiteName(standbyLocalJournal.getInternalSiteName());
journalVols.add(journalVolParams);
}
}
// if we found any journal volumes, add them to the local copies list
if (!journalVols.isEmpty()) {
standbyLocalCopyParams = new CreateCopyParams();
standbyLocalCopyParams.setName(rpCopyName);
standbyLocalCopyParams.setJournals(journalVols);
} else {
_log.error("no journal volumes found for standby production copy for source volume " + protectionVolume.getLabel());
}
}
String standbyProductionCopyName = RPHelper.getStandbyProductionCopyName(_dbClient, protectionVolume);
// Build standby production journal
if (standbyProductionCopyName != null) {
List<Volume> existingStandbyJournals = RPHelper.findExistingJournalsForCopy(_dbClient, protectionVolume.getConsistencyGroup(), standbyProductionCopyName);
// Get the first standby production journal
Volume standbyProdJournal = existingStandbyJournals.get(0);
if (standbyProdJournal != null) {
_log.info(String.format("Found standby production journal volume %s (%s) for metropoint volume %s (%s)", standbyProdJournal.getLabel(), standbyProdJournal.getId().toString(), protectionVolume.getLabel(), protectionVolume.getId().toString()));
List<CreateVolumeParams> journalVols = new ArrayList<CreateVolumeParams>();
CreateVolumeParams journalVolParams = new CreateVolumeParams();
journalVolParams.setWwn(RPHelper.getRPWWn(standbyProdJournal.getId(), _dbClient));
journalVolParams.setInternalSiteName(standbyProdJournal.getInternalSiteName());
journalVols.add(journalVolParams);
CreateCopyParams standbyProdCopyParams = new CreateCopyParams();
standbyProdCopyParams.setName(standbyProdJournal.getRpCopyName());
standbyProdCopyParams.setJournals(journalVols);
// 2. and 3. add back the standby production copy; add back the standby CDP copy
rp.addStandbyProductionCopy(standbyProdCopyParams, standbyLocalCopyParams, rSets, copyParams);
} else {
_log.error(String.format("Cannot add standby production copy because the standby production journal could not be found for copy %s.", standbyProductionCopyName));
}
}
}
}
// copy bookmarks before we cleanup the corresponding BlockSnapshot objects from ViPR.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// When we perform a swap, the target swap copy will become the production copy and lose all
// its bookmarks so we need to sync with RP.
RPHelper.cleanupSnapshots(_dbClient, rpSystem);
} else if (op.equals(FAILOVER_TEST_CANCEL)) {
RPCopyRequestParams copyParams = new RPCopyRequestParams();
copyParams.setCopyVolumeInfo(volumeProtectionInfo);
rp.failoverCopyTestCancel(copyParams);
} else if (op.equals(CHANGE_ACCESS_MODE)) {
RPCopyRequestParams copyParams = new RPCopyRequestParams();
copyParams.setCopyVolumeInfo(volumeProtectionInfo);
copyParams.setImageAccessMode(imageAccessMode);
if (imageAccessMode != null) {
rp.updateImageAccessMode(copyParams);
// BlockSnapshot objects that reference the target copy being set to direct access mode.
if (Copy.ImageAccessMode.DIRECT_ACCESS.name().equalsIgnoreCase(imageAccessMode)) {
_log.info(String.format("Updated imaged access mode for copy %s at %s to DIRECT_ACCESS. Removing all bookmarks associated with that copy and site.", volumeProtectionInfo.getRpCopyName(), volumeProtectionInfo.getRpSiteName()));
// Wait for RP to remove copy snapshots
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
RPHelper.cleanupSnapshots(_dbClient, rpSystem);
}
} else {
throw DeviceControllerExceptions.recoverpoint.imageAccessModeNotSupported(imageAccessMode);
}
} else {
throw DeviceControllerExceptions.recoverpoint.protectionOperationNotSupported(op);
}
_log.info("performProtectionOperation: after " + op + " operation successful");
WorkflowStepCompleter.stepSucceded(stepId);
return true;
} catch (InternalException e) {
_log.error("Operation failed with Exception: ", e);
return stepFailed(stepId, (ServiceCoded) e, "removeProtection operation failed.");
} catch (Exception e) {
stepFailed(stepId, e, "removeProtection operation failed.");
return false;
}
}
use of com.emc.storageos.svcs.errorhandling.resources.InternalException 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;
RPHelper.setLinkStateWaitTimeOut(_coordinator);
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;
}
Aggregations