use of com.emc.storageos.volumecontroller.ApplicationAddVolumeList in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method updateVolumesInVolumeGroup.
/**
* {@inheritDoc}
*/
@Override
public void updateVolumesInVolumeGroup(VolumeGroupVolumeList addVolumes, List<Volume> removeVolumes, URI volumeGroupId, String taskId) {
ApplicationAddVolumeList addVols = new ApplicationAddVolumeList();
VolumeGroup volumeGroup = _dbClient.queryObject(VolumeGroup.class, volumeGroupId);
URI systemURI = getVolumesToAddToApplication(addVols, addVolumes, volumeGroup, taskId);
List<URI> removeVolIds = new ArrayList<URI>();
URI removeSystemURI = getVolumesToRemoveFromApplication(removeVolIds, removeVolumes);
if (systemURI == null) {
systemURI = removeSystemURI;
}
if (systemURI != null) {
VPlexController controller = getController();
controller.updateVolumeGroup(systemURI, addVols, removeVolIds, volumeGroup.getId(), taskId);
} else {
// No need to call to controller. update the application task
Operation op = volumeGroup.getOpStatus().get(taskId);
op.ready();
volumeGroup.getOpStatus().updateTaskStatus(taskId, op);
_dbClient.updateObject(volumeGroup);
}
}
use of com.emc.storageos.volumecontroller.ApplicationAddVolumeList in project coprhd-controller by CoprHD.
the class RPDeviceController method updateApplication.
/*
* (non-Javadoc)
*
* @see com.emc.storageos.protectioncontroller.RPController#updateApplication(java.net.URI,
* com.emc.storageos.volumecontroller.ApplicationAddVolumeList, java.util.List, java.net.URI, java.lang.String)
*/
@Override
public void updateApplication(URI systemURI, ApplicationAddVolumeList addVolList, List<URI> removeVolumeURIs, URI applicationId, String taskId) {
// get all source and target devices
// for remove volumes source and targets can be processed in the same step
// for add volumes, split up volumes into source and target
// assign a different replication group name for target volumes so they don't end up in the same group as source
// volumes
// create one step for remove volumes and add source volumes and a separate step for add target volumes
TaskCompleter completer = null;
try {
Set<URI> impactedCGs = new HashSet<URI>();
List<URI> allRemoveVolumes = new ArrayList<URI>();
Set<URI> removeVolumeSet = new HashSet<URI>();
if (removeVolumeURIs != null && !removeVolumeURIs.isEmpty()) {
// get source and target volumes to be removed from the application
removeVolumeSet = RPHelper.getReplicationSetVolumes(removeVolumeURIs, _dbClient);
for (URI removeUri : removeVolumeSet) {
Volume removeVol = _dbClient.queryObject(Volume.class, removeUri);
URI cguri = removeVol.getConsistencyGroup();
impactedCGs.add(cguri);
addBackendVolumes(removeVol, false, allRemoveVolumes, null);
}
}
Set<URI> vplexVolumes = new HashSet<URI>();
Set<URI> addVolumeSet = new HashSet<URI>();
ApplicationAddVolumeList addSourceVols = new ApplicationAddVolumeList();
ApplicationAddVolumeList addTargetVols = new ApplicationAddVolumeList();
boolean existingSnapOrClone = false;
URI protectionSystemId = null;
ProtectionSystem protectionSystem = null;
Set<String> volumeWWNs = new HashSet<String>();
Volume aSrcVolume = null;
if (addVolList != null && addVolList.getVolumes() != null && !addVolList.getVolumes().isEmpty()) {
URI addVolCg = null;
// get source and target volumes to be added the application
addVolumeSet = RPHelper.getReplicationSetVolumes(addVolList.getVolumes(), _dbClient);
// split up add volumes list by source and target
List<URI> allAddSourceVolumes = new ArrayList<URI>();
List<URI> allAddTargetVolumes = new ArrayList<URI>();
for (URI volUri : addVolumeSet) {
Volume vol = _dbClient.queryObject(Volume.class, volUri);
if (protectionSystemId == null) {
protectionSystemId = vol.getProtectionController();
}
URI cguri = vol.getConsistencyGroup();
if (addVolCg == null && cguri != null) {
addVolCg = cguri;
}
impactedCGs.add(cguri);
if (vol.checkPersonality(Volume.PersonalityTypes.SOURCE.name())) {
addBackendVolumes(vol, true, allAddSourceVolumes, vplexVolumes);
aSrcVolume = vol;
} else if (vol.checkPersonality(Volume.PersonalityTypes.TARGET.name())) {
addBackendVolumes(vol, true, allAddTargetVolumes, vplexVolumes);
volumeWWNs.add(RPHelper.getRPWWn(vol.getId(), _dbClient));
}
}
if (protectionSystemId != null) {
protectionSystem = _dbClient.queryObject(ProtectionSystem.class, protectionSystemId);
}
addSourceVols.setConsistencyGroup(addVolCg);
addSourceVols.setReplicationGroupName(addVolList.getReplicationGroupName());
addSourceVols.setVolumes(allAddSourceVolumes);
String targetReplicationGroupName = addVolList.getReplicationGroupName() + REPLICATION_GROUP_RPTARGET_SUFFIX;
addTargetVols.setConsistencyGroup(addVolCg);
addTargetVols.setReplicationGroupName(targetReplicationGroupName);
addTargetVols.setVolumes(allAddTargetVolumes);
// if there are any target clones or snapshots, need to create a bookmark and enable image access
List<Volume> existingVols = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, Volume.class, AlternateIdConstraint.Factory.getVolumeByReplicationGroupInstance(targetReplicationGroupName));
for (Volume existingVol : existingVols) {
if (existingVol.getFullCopies() != null && !existingVol.getFullCopies().isEmpty()) {
existingSnapOrClone = true;
break;
} else if (ControllerUtils.checkIfVolumeHasSnapshotSession(existingVol.getId(), _dbClient)) {
existingSnapOrClone = true;
break;
} else if (ControllerUtils.checkIfVolumeHasSnapshot(existingVol, _dbClient)) {
existingSnapOrClone = true;
break;
}
}
}
// Get a new workflow to execute the volume group update.
Workflow workflow = _workflowService.getNewWorkflow(this, BlockDeviceController.UPDATE_VOLUMES_FOR_APPLICATION_WS_NAME, false, taskId);
// create the completer add the steps and execute the plan.
completer = new VolumeGroupUpdateTaskCompleter(applicationId, addVolumeSet, removeVolumeSet, impactedCGs, taskId);
String waitFor = null;
if (existingSnapOrClone) {
// A temporary date/time stamp for the bookmark name
String bookmarkName = VIPR_SNAPSHOT_PREFIX + (new Random()).nextInt();
// Step 1 - Create a RP bookmark
String rpWaitFor = addCreateBookmarkStep(workflow, new ArrayList<URI>(), protectionSystem, bookmarkName, volumeWWNs, false, waitFor);
// Lock CG for the duration of the workflow so enable and disable can complete before another workflow
// tries to enable image
// access
List<String> locks = new ArrayList<String>();
String lockName = ControllerLockingUtil.getConsistencyGroupStorageKey(_dbClient, aSrcVolume.getConsistencyGroup(), protectionSystem.getId());
if (null != lockName) {
locks.add(lockName);
acquireWorkflowLockOrThrow(workflow, locks);
}
// Step 2 - Enable image access
waitFor = addEnableImageAccessForCreateReplicaStep(workflow, protectionSystem, null, new ArrayList<URI>(), bookmarkName, volumeWWNs, rpWaitFor);
}
// add steps for add source and remove vols
waitFor = _blockDeviceController.addStepsForUpdateApplication(workflow, addSourceVols, allRemoveVolumes, waitFor, taskId);
// add steps for add target vols
waitFor = _blockDeviceController.addStepsForUpdateApplication(workflow, addTargetVols, null, waitFor, taskId);
if (existingSnapOrClone) {
waitFor = addDisableImageAccessForCreateReplicaStep(workflow, protectionSystem, null, new ArrayList<URI>(), volumeWWNs, waitFor);
}
if (!vplexVolumes.isEmpty()) {
_vplexDeviceController.addStepsForImportClonesOfApplicationVolumes(workflow, waitFor, new ArrayList<URI>(vplexVolumes), taskId);
}
_log.info("Executing workflow plan {}", BlockDeviceController.UPDATE_VOLUMES_FOR_APPLICATION_WS_NAME);
String successMessage = String.format("Update application successful for %s", applicationId.toString());
workflow.executePlan(completer, successMessage);
} catch (Exception e) {
_log.error("Exception while updating the application", e);
if (completer != null) {
completer.error(_dbClient, DeviceControllerException.exceptions.failedToUpdateVolumesFromAppication(applicationId.toString(), e.getMessage()));
}
throw e;
}
}
use of com.emc.storageos.volumecontroller.ApplicationAddVolumeList in project coprhd-controller by CoprHD.
the class BlockDeviceController method addStepsForUpdateApplication.
/**
* add step for update application, using by VPLEX and RP to
* add/remove block volumes to/from replication groups on multiple storage systems
*
* @param workflow
* @param addVolList
* @param removeVolumeURIs
* @param waitForStep
* @param taskId
* @return
*/
public String addStepsForUpdateApplication(Workflow workflow, ApplicationAddVolumeList addVolList, List<URI> removeVolumeURIs, String waitForStep, String taskId) {
String waitFor = waitForStep;
// split up volumes by storage system, replication group, and add steps for each storage system and RG
Table<URI, String, List<URI>> storageRGToRemoveVolumes = getStorageSystemRGVolumes(removeVolumeURIs, null);
// map volumes to add by storage system, replication group
if (addVolList != null) {
// add source and target volumes from array replication groups
Table<URI, String, List<URI>> storageRGToAddVolumes = getStorageSystemRGVolumes(addVolList.getVolumes(), addVolList.getReplicationGroupName());
for (Cell<URI, String, List<URI>> cell : storageRGToAddVolumes.cellSet()) {
URI storage = cell.getRowKey();
String rgName = cell.getColumnKey();
List<URI> addVolumes = cell.getValue();
List<URI> removeVolumes = new ArrayList<URI>();
if (NullColumnValueGetter.isNotNullValue(rgName)) {
// volumes have already been in a RG, need remove them from original RG
removeVolumes.addAll(addVolumes);
}
if (storageRGToRemoveVolumes.contains(storage, rgName)) {
removeVolumes.addAll(storageRGToRemoveVolumes.remove(storage, rgName));
}
waitFor = addStepsForUpdateApplicationSingleStorage(workflow, storage, addVolList.getReplicationGroupName(), addVolumes, removeVolumes, waitFor, taskId);
}
}
// process remaining storage system and RG that has volumes to remove from application
for (Cell<URI, String, List<URI>> cell : storageRGToRemoveVolumes.cellSet()) {
waitFor = addStepsForUpdateApplicationSingleStorage(workflow, cell.getRowKey(), null, null, cell.getValue(), waitFor, taskId);
}
return waitFor;
}
use of com.emc.storageos.volumecontroller.ApplicationAddVolumeList in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method updateVolumesInVolumeGroup.
/**
* {@inheritDoc}
*/
@Override
public void updateVolumesInVolumeGroup(VolumeGroupVolumeList addVolumes, List<Volume> removeVolumes, URI applicationId, String taskId) {
VolumeGroup volumeGroup = _dbClient.queryObject(VolumeGroup.class, applicationId);
ApplicationAddVolumeList addVolumeList = null;
List<URI> removeVolumesURI = null;
RPController controller = null;
URI protSystemUri = null;
Volume firstVolume = null;
if (addVolumes != null && addVolumes.getVolumes() != null && !addVolumes.getVolumes().isEmpty()) {
addVolumeList = addVolumesToApplication(addVolumes, volumeGroup);
List<URI> vols = addVolumeList.getVolumes();
if (vols != null && !vols.isEmpty()) {
firstVolume = _dbClient.queryObject(Volume.class, vols.get(0));
}
}
if (removeVolumes != null && !removeVolumes.isEmpty()) {
removeVolumesURI = getValidVolumesToRemoveFromCG(removeVolumes);
if (firstVolume == null) {
firstVolume = removeVolumes.get(0);
}
}
if ((addVolumeList != null && !addVolumeList.getVolumes().isEmpty()) || (removeVolumesURI != null && !removeVolumesURI.isEmpty())) {
protSystemUri = firstVolume.getProtectionController();
ProtectionSystem system = _dbClient.queryObject(ProtectionSystem.class, protSystemUri);
controller = getController(RPController.class, system.getSystemType());
controller.updateApplication(protSystemUri, addVolumeList, removeVolumesURI, volumeGroup.getId(), taskId);
} else {
// No need to call to controller. update the application task
Operation op = volumeGroup.getOpStatus().get(taskId);
op.ready();
volumeGroup.getOpStatus().updateTaskStatus(taskId, op);
_dbClient.updateObject(volumeGroup);
}
}
use of com.emc.storageos.volumecontroller.ApplicationAddVolumeList in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method addVolumesToApplication.
/**
* Get ApplicationAddVolumeList
*
* @param volumesList The add volume list
* @param application The application that the volumes are added to
* @return ApplicationVolumeList The volumes that are in the add volume list
*/
private ApplicationAddVolumeList addVolumesToApplication(VolumeGroupVolumeList volumeList, VolumeGroup application) {
List<URI> addVolumeURIs = volumeList.getVolumes();
String groupName = volumeList.getReplicationGroupName();
Set<URI> allVolumes = RPHelper.getReplicationSetVolumes(addVolumeURIs, _dbClient);
Map<String, Boolean> checkedRGMap = new HashMap<String, Boolean>();
for (URI volumeUri : allVolumes) {
Volume volume = _dbClient.queryObject(Volume.class, volumeUri);
if (volume == null || volume.getInactive()) {
throw APIException.badRequests.volumeCantBeAddedToVolumeGroup(volumeUri.toString(), "Volume has been deleted");
}
BlockServiceUtils.validateVolumeNoReplica(volume, application, _dbClient);
boolean vplex = RPHelper.isVPlexVolume(volume, _dbClient);
if (vplex) {
// get the backend volume
Volume backendVol = VPlexUtil.getVPLEXBackendVolume(volume, true, _dbClient);
if (backendVol == null || backendVol.getInactive()) {
throw APIException.badRequests.volumeCantBeAddedToVolumeGroup(volume.getLabel(), "The backing volume for the VPLEX virtual volume has been deleted");
}
String rgName = backendVol.getReplicationGroupInstance();
if (NullColumnValueGetter.isNotNullValue(rgName) && rgName.equals(groupName)) {
if (!vplexBlockServiceApiImpl.checkAllVPlexVolsInRequest(backendVol, allVolumes, checkedRGMap)) {
throw APIException.badRequests.volumeCantBeAddedToVolumeGroup(volume.getLabel(), "Volume has to be added to a different replication group than it is currently in");
}
}
// Check if the backend volume is unity, and the subgroup already has snapshot.
if (!BlockServiceUtils.checkUnityVolumeCanBeAddedOrRemovedToCG(volumeList.getReplicationGroupName(), backendVol, _dbClient, true)) {
throw APIException.badRequests.volumeCantBeAddedToVolumeGroup(volume.getLabel(), "the Unity subgroup has snapshot.");
}
} else {
if (!BlockServiceUtils.checkUnityVolumeCanBeAddedOrRemovedToCG(volumeList.getReplicationGroupName(), volume, _dbClient, true)) {
throw APIException.badRequests.volumeCantBeAddedToVolumeGroup(volume.getLabel(), "the Unity subgroup has snapshot.");
}
}
}
ApplicationAddVolumeList outVolumesList = new ApplicationAddVolumeList();
outVolumesList.setConsistencyGroup(volumeList.getConsistencyGroup());
outVolumesList.setReplicationGroupName(groupName);
outVolumesList.setVolumes(addVolumeURIs);
return outVolumesList;
}
Aggregations