use of com.emc.storageos.svcs.errorhandling.resources.APIException in project coprhd-controller by CoprHD.
the class DisasterRecoveryServiceTest method testPrecheckForPlannedFailover.
@Test
public void testPrecheckForPlannedFailover() {
String standbyUUID = "a918ebd4-bbf4-378b-8034-b03423f9edfd";
// test for invalid uuid
try {
APIException e = APIException.internalServerErrors.switchoverPrecheckFailed(standby.getUuid(), "Standby uuid is not valid, can't find in ZK");
doThrow(e).when(drUtil).getSiteFromLocalVdc(standbyUUID);
drService.precheckForSwitchover(standbyUUID);
fail("should throw exception when met invalid standby uuid");
} catch (InternalServerErrorException e) {
assertEquals(e.getServiceCode(), ServiceCode.SYS_DR_OPERATION_PRECHECK_FAILED);
}
Site site = new Site();
site.setUuid(standbyUUID);
Configuration config = site.toConfiguration();
// test for failover to primary
try {
// Mock a standby in coordinator, so it would pass invalid standby checking, go to next check
doReturn(config).when(coordinator).queryConfiguration(String.format("%s/vdc1", Site.CONFIG_KIND), standbyUUID);
drService.precheckForSwitchover(standbyUUID);
fail("should throw exception when trying to failover to a primary site");
} catch (InternalServerErrorException e) {
assertEquals(e.getServiceCode(), ServiceCode.SYS_DR_OPERATION_PRECHECK_FAILED);
}
// test for primary unstable case
try {
// Mock a primary site with different uuid with to-be-failover standby, so go to next check
doReturn(false).when(drService).isClusterStable();
drService.precheckForSwitchover(standbyUUID);
fail("should throw exception when primary is not stable");
} catch (InternalServerErrorException e) {
assertEquals(e.getServiceCode(), ServiceCode.SYS_DR_OPERATION_PRECHECK_FAILED);
}
// test for standby unstable case
try {
// Mock a stable status for primary, so go to next check
doReturn(true).when(drService).isClusterStable();
doReturn(ClusterInfo.ClusterState.DEGRADED).when(coordinator).getControlNodesState(eq(standbyUUID));
drService.precheckForSwitchover(standbyUUID);
fail("should throw exception when site to failover to is not stable");
} catch (InternalServerErrorException e) {
assertEquals(e.getServiceCode(), ServiceCode.SYS_DR_OPERATION_PRECHECK_FAILED);
}
// test for standby not STANDBY_CYNCED state
try {
// Mock a stable status for standby, so go to next check
doReturn(ClusterInfo.ClusterState.STABLE).when(coordinator).getControlNodesState(anyString());
// not fully synced
config.setConfig("state", "STANDBY_SYNCING");
doReturn(config).when(coordinator).queryConfiguration(String.format("%s/vdc1", Site.CONFIG_KIND), standbyUUID);
drService.precheckForSwitchover(standbyUUID);
fail("should throw exception when standby site is not fully synced");
} catch (InternalServerErrorException e) {
assertEquals(e.getServiceCode(), ServiceCode.SYS_DR_OPERATION_PRECHECK_FAILED);
}
}
use of com.emc.storageos.svcs.errorhandling.resources.APIException in project coprhd-controller by CoprHD.
the class VolumeGroupService method restoreVolumeGroupFullCopy.
/**
* Restore the specified Volume group full copy.
* - Restores full copy for all the array replication groups within this Application.
* - If partial flag is specified, it restores full copy only for set of array replication groups.
* A Full Copy from each array replication group can be provided to indicate which array replication
* groups's full copies needs to be restored.
*
* @prereq Create Volume group full copy as active.
*
* @param volumeGroupId The URI of the Volume group.
* @param fullCopyURI The URI of the full copy.
*
* @brief Restore Volume group full copy.
*
* @return TaskList
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/protection/full-copies/restore")
@CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.ANY })
public TaskList restoreVolumeGroupFullCopy(@PathParam("id") final URI volumeGroupId, final VolumeGroupFullCopyRestoreParam param) {
ArgValidator.checkFieldUriType(volumeGroupId, VolumeGroup.class, "id");
// Query Volume Group
final VolumeGroup volumeGroup = (VolumeGroup) queryResource(volumeGroupId);
TaskList taskList = new TaskList();
// validate replica operation for volume group
validateCopyOperationForVolumeGroup(volumeGroup, ReplicaTypeEnum.FULL_COPY);
// validate the requested full copies
List<Volume> fullCopyVolumesInRequest = new ArrayList<Volume>();
boolean partial = validateFullCopiesInRequest(fullCopyVolumesInRequest, param.getFullCopies(), param.getCopySetName(), param.getSubGroups(), volumeGroupId);
/**
* 1. VolumeGroupService Clone API accepts a Clone URI (to identify clone set and RG)
* - then get All full copies belonging to same full copy set
* - get full copy set name from the requested full copy
* 2. If partial, there will be a List of Clone URIs (one from each RG)
* 3. Group the full copies by Replication Group(RG)
* 4. For each RG, invoke the ConsistencyGroup full copy API (CG uri, clone uri)
* - a. Skip the CG/RG calls when thrown error and continue with other entries; create 'ERROR' Task for this call
* - b. Finally return the Task List (RG tasks may finish at different times as they are different calls)
*/
if (!partial) {
Volume fullCopy = fullCopyVolumesInRequest.get(0);
log.info("Full Copy operation requested for entire Application, Considering full copy {} in request.", fullCopy.getLabel());
fullCopyVolumesInRequest.clear();
fullCopyVolumesInRequest.addAll(getClonesBySetName(fullCopy.getFullCopySetName(), volumeGroup.getId()));
} else {
log.info("Full Copy operation requested for subset of array replication groups in Application.");
}
checkForApplicationPendingTasks(volumeGroup, _dbClient, true);
Map<String, Volume> repGroupToFullCopyMap = groupVolumesByReplicationGroup(fullCopyVolumesInRequest);
for (Map.Entry<String, Volume> entry : repGroupToFullCopyMap.entrySet()) {
String replicationGroup = entry.getKey();
Volume fullCopy = entry.getValue();
log.info("Processing Array Replication Group {}, Full Copy {}", replicationGroup, fullCopy.getLabel());
try {
// get CG URI
URI cgURI = getConsistencyGroupForFullCopy(fullCopy);
// Restore the full copy. Note that it will take into account the
// fact that the volume is in a ReplicationGroup
// and all volumes in that ReplicationGroup will be restored.
taskList.getTaskList().addAll(_blockConsistencyGroupService.restoreConsistencyGroupFullCopy(cgURI, fullCopy.getId()).getTaskList());
} catch (InternalException | APIException e) {
String errMsg = String.format("Error restoring Array Replication Group %s, Full Copy %s", replicationGroup, fullCopy.getLabel());
log.error(errMsg, e);
TaskResourceRep task = BlockServiceUtils.createFailedTaskOnVolume(_dbClient, fullCopy, ResourceOperationTypeEnum.RESTORE_VOLUME_FULL_COPY, e);
taskList.addTask(task);
}
}
if (!partial) {
auditOp(OperationTypeEnum.RESTORE_VOLUME_GROUP_FULL_COPY, true, AuditLogManager.AUDITOP_BEGIN, volumeGroup.getId().toString(), fullCopyVolumesInRequest.get(0).getLabel());
}
return taskList;
}
use of com.emc.storageos.svcs.errorhandling.resources.APIException in project coprhd-controller by CoprHD.
the class VolumeGroupService method performVolumeGroupSnapshotOperation.
/*
* Wrapper of BlockConsistencyGroupService methods for snapshot operations
*
* @param volumeGroupId
* @param param
* @return a TaskList
*/
private TaskList performVolumeGroupSnapshotOperation(final URI volumeGroupId, final VolumeGroupSnapshotOperationParam param, OperationTypeEnum opType) {
Map<String, List<BlockSnapshot>> snapsetToSnapshots = getSnapshotsGroupedBySnapset(volumeGroupId, param);
// validate that it's ok to do the snapshot operation
validateSnapshotOperation(volumeGroupId, snapsetToSnapshots, opType);
auditOp(opType, true, AuditLogManager.AUDITOP_BEGIN, volumeGroupId.toString(), param.getSnapshots());
TaskList taskList = new TaskList();
Set<Entry<String, List<BlockSnapshot>>> entrySet = snapsetToSnapshots.entrySet();
for (Entry<String, List<BlockSnapshot>> entry : entrySet) {
Table<URI, String, BlockSnapshot> storageRgToSnapshot = ControllerUtils.getSnapshotForStorageReplicationGroup(entry.getValue());
for (Cell<URI, String, BlockSnapshot> cell : storageRgToSnapshot.cellSet()) {
log.info("{} for replication group {}", opType.getDescription(), cell.getColumnKey());
try {
BlockSnapshot snapshot = cell.getValue();
URI cgUri = snapshot.getConsistencyGroup();
URI snapshotUri = snapshot.getId();
switch(opType) {
case ACTIVATE_VOLUME_GROUP_SNAPSHOT:
taskList.addTask(_blockConsistencyGroupService.activateConsistencyGroupSnapshot(cgUri, snapshotUri));
break;
case RESTORE_VOLUME_GROUP_SNAPSHOT:
taskList.addTask(_blockConsistencyGroupService.restoreConsistencyGroupSnapshot(cgUri, snapshotUri));
break;
case RESYNCHRONIZE_VOLUME_GROUP_SNAPSHOT:
taskList.addTask(_blockConsistencyGroupService.resynchronizeConsistencyGroupSnapshot(cgUri, snapshotUri));
break;
case DEACTIVATE_VOLUME_GROUP_SNAPSHOT:
TaskList cgTaskList = _blockConsistencyGroupService.deactivateConsistencyGroupSnapshot(cgUri, snapshotUri);
List<TaskResourceRep> taskResourceRepList = cgTaskList.getTaskList();
if (taskResourceRepList != null && !taskResourceRepList.isEmpty()) {
for (TaskResourceRep taskResRep : taskResourceRepList) {
taskList.addTask(taskResRep);
}
}
break;
default:
log.error("Unsupported operation {}", opType.getDescription());
break;
}
} catch (InternalException | APIException e) {
log.error("Exception on {} for replication group {}: {}", opType.getDescription(), cell.getColumnKey(), e.getMessage());
}
}
}
auditOp(opType, true, AuditLogManager.AUDITOP_END, volumeGroupId.toString(), param.getSnapshots());
return taskList;
}
use of com.emc.storageos.svcs.errorhandling.resources.APIException in project coprhd-controller by CoprHD.
the class VolumeGroupService method resynchronizeVolumeGroupFullCopy.
/**
* Resynchronize the specified Volume group full copy.
* - Resynchronizes full copy for all the array replication groups within this Application.
* - If partial flag is specified, it resynchronizes full copy only for set of array replication groups.
* A Full Copy from each array replication group can be provided to indicate which array replication
* groups's full copies needs to be resynchronized.
*
* @prereq Create Volume group full copy as active.
*
* @param volumeGroupId The URI of the Volume group.
* @param fullCopyURI The URI of the full copy.
*
* @brief Resynchronize Volume group full copy.
*
* @return TaskList
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/protection/full-copies/resynchronize")
@CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.ANY })
public TaskList resynchronizeVolumeGroupFullCopy(@PathParam("id") final URI volumeGroupId, final VolumeGroupFullCopyResynchronizeParam param) {
ArgValidator.checkFieldUriType(volumeGroupId, VolumeGroup.class, "id");
// Query Volume Group
final VolumeGroup volumeGroup = (VolumeGroup) queryResource(volumeGroupId);
TaskList taskList = new TaskList();
// validate replica operation for volume group
validateCopyOperationForVolumeGroup(volumeGroup, ReplicaTypeEnum.FULL_COPY);
// validate the requested full copies
List<Volume> fullCopyVolumesInRequest = new ArrayList<Volume>();
boolean partial = validateFullCopiesInRequest(fullCopyVolumesInRequest, param.getFullCopies(), param.getCopySetName(), param.getSubGroups(), volumeGroupId);
/**
* 1. VolumeGroupService Clone API accepts a Clone URI (to identify clone set and RG)
* - then get All full copies belonging to same full copy set
* - get full copy set name from the requested full copy
* 2. If partial, there will be a List of Clone URIs (one from each RG)
* 3. Group the full copies by Replication Group(RG)
* 4. For each RG, invoke the ConsistencyGroup full copy API (CG uri, clone uri)
* - a. Skip the CG/RG calls when thrown error and continue with other entries; create 'ERROR' Task for this call
* - b. Finally return the Task List (RG tasks may finish at different times as they are different calls)
*/
if (!partial) {
Volume fullCopy = fullCopyVolumesInRequest.get(0);
log.info("Full Copy operation requested for entire Application, Considering full copy {} in request.", fullCopy.getLabel());
fullCopyVolumesInRequest.clear();
fullCopyVolumesInRequest.addAll(getClonesBySetName(fullCopy.getFullCopySetName(), volumeGroup.getId()));
} else {
log.info("Full Copy operation requested for subset of array replication groups in Application.");
}
checkForApplicationPendingTasks(volumeGroup, _dbClient, false);
Map<String, Volume> repGroupToFullCopyMap = groupVolumesByReplicationGroup(fullCopyVolumesInRequest);
for (Map.Entry<String, Volume> entry : repGroupToFullCopyMap.entrySet()) {
String replicationGroup = entry.getKey();
Volume fullCopy = entry.getValue();
log.info("Processing Array Replication Group {}, Full Copy {}", replicationGroup, fullCopy.getLabel());
try {
// get CG URI
URI cgURI = getConsistencyGroupForFullCopy(fullCopy);
// Resynchronize the full copy. Note that it will take into account the
// fact that the volume is in a ReplicationGroup
// and all volumes in that ReplicationGroup will be resynchronized.
taskList.getTaskList().addAll(_blockConsistencyGroupService.resynchronizeConsistencyGroupFullCopy(cgURI, fullCopy.getId()).getTaskList());
} catch (InternalException | APIException e) {
String errMsg = String.format("Error resynchronizing Array Replication Group %s, Full Copy %s", replicationGroup, fullCopy.getLabel());
log.error(errMsg, e);
TaskResourceRep task = BlockServiceUtils.createFailedTaskOnVolume(_dbClient, fullCopy, ResourceOperationTypeEnum.RESYNCHRONIZE_VOLUME_FULL_COPY, e);
taskList.addTask(task);
}
}
if (!partial) {
auditOp(OperationTypeEnum.RESYNCHRONIZE_VOLUME_GROUP_FULL_COPY, true, AuditLogManager.AUDITOP_BEGIN, volumeGroup.getId().toString(), fullCopyVolumesInRequest.get(0).getLabel());
}
return taskList;
}
use of com.emc.storageos.svcs.errorhandling.resources.APIException in project coprhd-controller by CoprHD.
the class VolumeGroupService method createVolumeGroupSnapshot.
/**
* Creates a volume group snapshot
* Creates snapshot for all the array replication groups within this Application.
* If partial flag is specified, it creates snapshot only for set of array replication groups.
* A Volume from each array replication group can be provided to indicate which array replication
* groups are required to take snapshot.
*
* @prereq none
*
* @param volumeGroupId the URI of the Volume Group
* - Volume group URI
* @param param VolumeGroupSnapshotCreateParam
*
* @brief Create volume group snapshot
* @return TaskList
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/protection/snapshots")
@CheckPermission(roles = { Role.SYSTEM_ADMIN }, acls = { ACL.ANY })
public TaskList createVolumeGroupSnapshot(@PathParam("id") final URI volumeGroupId, VolumeGroupSnapshotCreateParam param) {
// Query volume group
final VolumeGroup volumeGroup = (VolumeGroup) queryResource(volumeGroupId);
// validate replica operation for volume group
validateCopyOperationForVolumeGroup(volumeGroup, ReplicaTypeEnum.SNAPSHOT);
// validate name
String name = param.getName();
ArgValidator.checkFieldNotEmpty(name, NAME_FIELD);
name = TimeUtils.formatDateForCurrent(name);
// snapsetLabel is normalized in RP, do it here too to avoid potential mismatch
name = ResourceOnlyNameGenerator.removeSpecialCharsForName(name, SmisConstants.MAX_SNAPSHOT_NAME_LENGTH);
if (StringUtils.isEmpty(name)) {
// original name has special chars only
throw APIException.badRequests.invalidCopySetName(param.getName(), ReplicaTypeEnum.SNAPSHOT.toString());
}
// check name provided is not duplicate
VolumeGroupCopySetList copySetList = getVolumeGroupSnapshotSets(volumeGroup);
if (copySetList.getCopySets().contains(name)) {
// duplicate name
throw APIException.badRequests.duplicateCopySetName(param.getName(), ReplicaTypeEnum.SNAPSHOT.toString());
}
// volumes to be processed
List<Volume> volumes = new ArrayList<Volume>();
List<URI> partialVolumeList = new ArrayList<URI>();
boolean partial = isPartialRequest(param, volumeGroup, partialVolumeList);
if (partial) {
log.info("Snapshot requested for subset of array groups in Application.");
// validate that at least one volume URI is provided
ArgValidator.checkFieldNotEmpty(partialVolumeList, VOLUMES_FIELD);
// validate that provided volumes
for (URI volumeURI : partialVolumeList) {
ArgValidator.checkFieldUriType(volumeURI, Volume.class, VOLUME_FIELD);
// Get the volume
Volume volume = _dbClient.queryObject(Volume.class, volumeURI);
ArgValidator.checkEntity(volume, volumeURI, isIdEmbeddedInURL(volumeURI));
// validate that provided volume is part of Volume Group
if (!volume.getVolumeGroupIds().contains(volumeGroupId.toString())) {
throw APIException.badRequests.replicaOperationNotAllowedVolumeNotInVolumeGroup(ReplicaTypeEnum.SNAPSHOT.toString(), volume.getLabel());
}
volumes.add(volume);
}
} else {
log.info("Snapshot creation for entire Application");
// get all volumes
volumes.addAll(ControllerUtils.getVolumeGroupVolumes(_dbClient, volumeGroup));
// validate that there should be some volumes in VolumeGroup
if (volumes.isEmpty()) {
throw APIException.badRequests.replicaOperationNotAllowedOnEmptyVolumeGroup(volumeGroup.getLabel(), ReplicaTypeEnum.SNAPSHOT.toString());
}
}
// Check for pending tasks
checkForApplicationPendingTasks(volumeGroup, _dbClient, false);
auditOp(OperationTypeEnum.CREATE_VOLUME_GROUP_SNAPSHOT, true, AuditLogManager.AUDITOP_BEGIN, volumeGroupId.toString(), name);
TaskList taskList = new TaskList();
/**
* If there are VMAX3 volumes in the request, we need to create snap session for them.
* For others, create snapshot.
*
* vmax3Volumes - block VMAX3 or backend VMAX3 for VPLEX based on copy side requested
* volumes - except volumes filtered out for above case
*/
// TODO consider copyOnHaSide from user's request once the underlying implementation supports it.
List<Volume> vmax3Volumes = getVMAX3Volumes(volumes, false);
if (!vmax3Volumes.isEmpty()) {
// check snap session name provided is not duplicate
VolumeGroupCopySetList sessionSet = getVolumeGroupSnapsetSessionSets(volumeGroup);
if (sessionSet.getCopySets().contains(name)) {
// duplicate name
throw APIException.badRequests.duplicateCopySetName(name, ReplicaTypeEnum.SNAPSHOT_SESSION.toString());
}
}
// create snapshot
Map<URI, List<URI>> cgToVolUris = ControllerUtils.groupVolumeURIsByCG(volumes);
Set<Entry<URI, List<URI>>> entrySet = cgToVolUris.entrySet();
for (Entry<URI, List<URI>> entry : entrySet) {
URI cgUri = entry.getKey();
log.info("Create snapshot with consistency group {}", cgUri);
try {
BlockConsistencyGroupSnapshotCreate cgSnapshotParam = new BlockConsistencyGroupSnapshotCreate(name, entry.getValue(), param.getCreateInactive(), param.getReadOnly());
TaskList cgTaskList = _blockConsistencyGroupService.createConsistencyGroupSnapshot(cgUri, cgSnapshotParam);
List<TaskResourceRep> taskResourceRepList = cgTaskList.getTaskList();
if (taskResourceRepList != null && !taskResourceRepList.isEmpty()) {
for (TaskResourceRep taskResRep : taskResourceRepList) {
taskList.addTask(taskResRep);
}
}
} catch (InternalException | APIException e) {
log.error("Exception when creating snapshot for consistency group {}", cgUri, e);
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, cgUri);
TaskResourceRep task = BlockServiceUtils.createFailedTaskOnCG(_dbClient, cg, ResourceOperationTypeEnum.CREATE_CONSISTENCY_GROUP_SNAPSHOT, e);
taskList.addTask(task);
} catch (Exception ex) {
log.error("Unexpected Exception occurred when creating snapshot for consistency group {}", cgUri, ex);
}
}
// create snapshot session for VMAX3
Map<URI, List<URI>> cgToV3VolUris = ControllerUtils.groupVolumeURIsByCG(vmax3Volumes);
Set<Entry<URI, List<URI>>> entrySetV3 = cgToV3VolUris.entrySet();
for (Entry<URI, List<URI>> entry : entrySetV3) {
URI cgUri = entry.getKey();
log.info("Create snapshot session for consistency group {}, volumes {}", cgUri, Joiner.on(',').join(entry.getValue()));
try {
// create snap session with No targets
SnapshotSessionCreateParam cgSnapshotSessionParam = new SnapshotSessionCreateParam(name, null, entry.getValue());
taskList.getTaskList().addAll(_blockConsistencyGroupService.createConsistencyGroupSnapshotSession(cgUri, cgSnapshotSessionParam).getTaskList());
} catch (InternalException | APIException e) {
log.error("Exception while creating snapshot session for consistency group {}: {}", cgUri, e);
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, cgUri);
TaskResourceRep task = BlockServiceUtils.createFailedTaskOnCG(_dbClient, cg, ResourceOperationTypeEnum.CREATE_CONSISTENCY_GROUP_SNAPSHOT_SESSION, e);
taskList.addTask(task);
} catch (Exception ex) {
log.error("Unexpected Exception occurred while creating snapshot session for consistency group {}: {}", cgUri, ex);
}
}
auditOp(OperationTypeEnum.CREATE_VOLUME_GROUP_SNAPSHOT, true, AuditLogManager.AUDITOP_END, volumeGroupId.toString(), name);
return taskList;
}
Aggregations