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;
}
use of com.emc.storageos.volumecontroller.ApplicationAddVolumeList in project coprhd-controller by CoprHD.
the class DefaultBlockServiceApiImpl method updateVolumesInVolumeGroup.
/**
* {@inheritDoc}
*/
@Override
public void updateVolumesInVolumeGroup(VolumeGroupVolumeList addVolumes, List<Volume> removeVolumes, URI volumeGroupId, String taskId) {
VolumeGroup volumeGroup = _dbClient.queryObject(VolumeGroup.class, volumeGroupId);
ApplicationAddVolumeList addVolumeList = null;
if (addVolumes != null && addVolumes.getVolumes() != null && !addVolumes.getVolumes().isEmpty()) {
addVolumeList = addVolumesToApplication(addVolumes, volumeGroup, taskId);
}
if (removeVolumes != null && !removeVolumes.isEmpty()) {
removeVolumesFromApplication(removeVolumes, volumeGroup, taskId);
}
// call controller to handle non application ready CG volumes
if ((addVolumeList != null && !addVolumeList.getVolumes().isEmpty())) {
List<URI> vols = addVolumeList.getVolumes();
Volume firstVolume = _dbClient.queryObject(Volume.class, vols.get(0));
URI systemURI = firstVolume.getStorageController();
StorageSystem system = _dbClient.queryObject(StorageSystem.class, systemURI);
BlockController controller = getController(BlockController.class, system.getSystemType());
controller.updateApplication(systemURI, addVolumeList, 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 DefaultBlockServiceApiImpl method addVolumesToApplication.
/**
* Update volumes with volumeGroup Id, if the volumes are application ready
* (non VNX, or VNX volumes not in a real replication group)
*
* @param volumesList
* The add volume list
* @param application
* The application that the volumes are added to
* @param taskId
* @return ApplicationVolumeList The volumes that are not application ready (in real VNX CG with array replication
* group)
*/
private ApplicationAddVolumeList addVolumesToApplication(VolumeGroupVolumeList volumeList, VolumeGroup application, String taskId) {
ApplicationAddVolumeList addVolumeList = new ApplicationAddVolumeList();
Map<URI, List<URI>> addCGVolsMap = new HashMap<URI, List<URI>>();
String newRGName = volumeList.getReplicationGroupName();
for (URI voluri : volumeList.getVolumes()) {
Volume volume = _dbClient.queryObject(Volume.class, voluri);
if (volume == null || volume.getInactive()) {
_log.info(String.format("The volume %s does not exist or has been deleted", voluri));
continue;
}
URI cgUri = volume.getConsistencyGroup();
if (!NullColumnValueGetter.isNullURI(cgUri)) {
List<URI> vols = addCGVolsMap.get(cgUri);
if (vols == null) {
vols = new ArrayList<URI>();
}
vols.add(voluri);
addCGVolsMap.put(cgUri, vols);
} else {
// The volume is not in CG
throw APIException.badRequests.volumeGroupCantBeUpdated(application.getLabel(), String.format("The volume %s is not in a consistency group", volume.getLabel()));
}
String rgName = volume.getReplicationGroupInstance();
if (NullColumnValueGetter.isNotNullValue(rgName) && !rgName.equals(newRGName)) {
throw APIException.badRequests.volumeGroupCantBeUpdated(application.getLabel(), String.format("The volume %s is already in an array replication group, only the existing group name is allowed.", volume.getLabel()));
}
}
Set<URI> appReadyCGUris = new HashSet<URI>();
Set<Volume> appReadyCGVols = new HashSet<Volume>();
Set<URI> nonAppReadyCGVolUris = new HashSet<URI>();
// validate input volumes first, then batch processing, to avoid partial success
for (Map.Entry<URI, List<URI>> entry : addCGVolsMap.entrySet()) {
URI cgUri = entry.getKey();
List<URI> cgVolsToAdd = entry.getValue();
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, cgUri);
List<Volume> cgVolumes = getActiveCGVolumes(cg);
Set<URI> cgVolumeURIs = new HashSet<URI>();
for (Volume cgVol : cgVolumes) {
cgVolumeURIs.add(cgVol.getId());
}
Volume firstVolume = _dbClient.queryObject(Volume.class, cgVolsToAdd.get(0));
// Check if all CG volumes are adding into the application
if (!cgVolumeURIs.containsAll(cgVolsToAdd) || cgVolsToAdd.size() != cgVolumeURIs.size()) {
throw APIException.badRequests.volumeCantBeAddedToVolumeGroup(firstVolume.getLabel(), "not all volumes in consistency group are in the add volume list");
}
if (ControllerUtils.isVnxVolume(firstVolume, _dbClient) && !ControllerUtils.isNotInRealVNXRG(firstVolume, _dbClient)) {
// VNX CG cannot have snapshots, user has to remove the snapshots first in order to add the CG to an
// application
URIQueryResultList cgSnapshotsResults = new URIQueryResultList();
_dbClient.queryByConstraint(getBlockSnapshotByConsistencyGroup(cgUri), cgSnapshotsResults);
Iterator<URI> cgSnapshotsIter = cgSnapshotsResults.iterator();
while (cgSnapshotsIter.hasNext()) {
BlockSnapshot cgSnapshot = _dbClient.queryObject(BlockSnapshot.class, cgSnapshotsIter.next());
if ((cgSnapshot != null) && (!cgSnapshot.getInactive())) {
throw APIException.badRequests.notAllowedWhenVNXCGHasSnapshot();
}
}
nonAppReadyCGVolUris.addAll(cgVolumeURIs);
} else {
// non VNX CG volume, or volume in VNX CG with no array replication group
appReadyCGUris.add(cgUri);
appReadyCGVols.addAll(cgVolumes);
}
}
if (!appReadyCGVols.isEmpty()) {
for (Volume cgVol : appReadyCGVols) {
StringSet applications = cgVol.getVolumeGroupIds();
applications.add(application.getId().toString());
cgVol.setVolumeGroupIds(applications);
// handle clones
StringSet fullCopies = cgVol.getFullCopies();
List<Volume> fullCopiesToUpdate = new ArrayList<Volume>();
if (fullCopies != null && !fullCopies.isEmpty()) {
for (String fullCopyId : fullCopies) {
Volume fullCopy = _dbClient.queryObject(Volume.class, URI.create(fullCopyId));
if (fullCopy != null && !fullCopy.getInactive()) {
fullCopy.setFullCopySetName(fullCopy.getReplicationGroupInstance());
fullCopiesToUpdate.add(fullCopy);
}
}
}
if (!fullCopiesToUpdate.isEmpty()) {
_dbClient.updateObject(fullCopiesToUpdate);
}
Operation op = cgVol.getOpStatus().get(taskId);
op.ready();
cgVol.getOpStatus().updateTaskStatus(taskId, op);
}
_dbClient.updateObject(appReadyCGVols);
}
if (!appReadyCGUris.isEmpty()) {
for (URI cgUri : appReadyCGUris) {
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, cgUri);
if (cg != null && !cg.getInactive()) {
cg.setArrayConsistency(false);
Operation op = cg.getOpStatus().get(taskId);
op.ready();
cg.getOpStatus().updateTaskStatus(taskId, op);
_dbClient.updateObject(cg);
}
}
}
addVolumeList.getVolumes().addAll(nonAppReadyCGVolUris);
_log.info("Added volumes in CG to the application");
return addVolumeList;
}
use of com.emc.storageos.volumecontroller.ApplicationAddVolumeList in project coprhd-controller by CoprHD.
the class BlockDeviceController method updateApplication.
/**
* Adding/removing volumes to/from an application is ViPR DB only operation (no controller side involved),
* except for adding VNX volumes to an application, if the VNX volumes are in a real replication group.
*
* 1. remove volumes from replication group, keep volume's replicationGroupInstance unchanged
* 2. delete the replication group from array, keep CG's systemConsistencyGroup unchanged
* 3. change CG's arrayConsistency to false, update volume's volumeGroupIds, update clone's fullCopySetName
* (performed in the completer class)
*/
@Override
public void updateApplication(URI storage, ApplicationAddVolumeList addVolList, URI application, String opId) throws ControllerException {
TaskCompleter completer = null;
String waitFor = null;
try {
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, UPDATE_VOLUMES_FOR_APPLICATION_WS_NAME, false, opId);
List<URI> volumesToAdd = null;
if (addVolList != null) {
volumesToAdd = addVolList.getVolumes();
}
if (volumesToAdd != null && !volumesToAdd.isEmpty()) {
Map<URI, List<URI>> addVolsMap = new HashMap<URI, List<URI>>();
for (URI voluri : volumesToAdd) {
Volume vol = _dbClient.queryObject(Volume.class, voluri);
if (vol != null && !vol.getInactive()) {
if (ControllerUtils.isVnxVolume(vol, _dbClient) && vol.isInCG() && !ControllerUtils.isNotInRealVNXRG(vol, _dbClient)) {
URI cguri = vol.getConsistencyGroup();
List<URI> vols = addVolsMap.get(cguri);
if (vols == null) {
vols = new ArrayList<URI>();
}
vols.add(voluri);
addVolsMap.put(cguri, vols);
}
}
}
List<URI> cgs = new ArrayList<URI>(addVolsMap.keySet());
completer = new ApplicationTaskCompleter(application, volumesToAdd, null, cgs, opId);
for (Map.Entry<URI, List<URI>> entry : addVolsMap.entrySet()) {
_log.info("Creating workflows for adding CG volumes to application");
URI cguri = entry.getKey();
List<URI> cgVolsToAdd = entry.getValue();
URI voluri = cgVolsToAdd.get(0);
Volume vol = _dbClient.queryObject(Volume.class, voluri);
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, vol.getStorageController());
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, cguri);
String groupName = ControllerUtils.generateReplicationGroupName(storageSystem, cguri, vol.getReplicationGroupInstance(), _dbClient);
// remove volumes from array replication group, and delete the group, but keep volumes reference
waitFor = workflow.createStep(UPDATE_CONSISTENCY_GROUP_STEP_GROUP, String.format("Removing volumes from consistency group %s", cg.getLabel()), waitFor, storage, storageSystem.getSystemType(), this.getClass(), removeFromConsistencyGroupMethod(storage, cguri, cgVolsToAdd, true), rollbackMethodNullMethod(), null);
// remove replication group
waitFor = workflow.createStep(UPDATE_CONSISTENCY_GROUP_STEP_GROUP, String.format("Deleting replication group for consistency group %s", cg.getLabel()), waitFor, storage, storageSystem.getSystemType(), this.getClass(), deleteConsistencyGroupMethod(storage, cguri, groupName, true, false, false), rollbackMethodNullMethod(), null);
}
}
// Finish up and execute the plan.
_log.info("Executing workflow plan {}", UPDATE_VOLUMES_FOR_APPLICATION_WS_NAME);
String successMessage = String.format("Update application successful for %s", application.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(application.toString(), e.getMessage()));
}
}
}
Aggregations