use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class ResourceObjectConverter method deleteResourceObject.
public AsynchronousOperationResult deleteResourceObject(ProvisioningContext ctx, PrismObject<ShadowType> shadow, OperationProvisioningScriptsType scripts, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
OperationResult result = parentResult.createSubresult(OPERATION_DELETE_RESOURCE_OBJECT);
LOGGER.trace("Deleting resource object {}", shadow);
Collection<? extends ResourceAttribute<?>> identifiers = ShadowUtil.getAllIdentifiers(shadow);
if (ProvisioningUtil.isProtectedShadow(ctx.getObjectClassDefinition(), shadow, matchingRuleRegistry)) {
LOGGER.error("Attempt to delete protected resource object " + ctx.getObjectClassDefinition() + ": " + identifiers + "; ignoring the request");
SecurityViolationException e = new SecurityViolationException("Cannot delete protected resource object " + ctx.getObjectClassDefinition() + ": " + identifiers);
result.recordFatalError(e);
throw e;
}
//check idetifier if it is not null
if (identifiers.isEmpty() && shadow.asObjectable().getFailedOperationType() != null) {
throw new GenericConnectorException("Unable to delete object from the resource. Probably it has not been created yet because of previous unavailability of the resource.");
}
// Execute entitlement modification on other objects (if needed)
executeEntitlementChangesDelete(ctx, shadow, scripts, result);
Collection<Operation> additionalOperations = new ArrayList<Operation>();
addExecuteScriptOperation(additionalOperations, ProvisioningOperationTypeType.DELETE, scripts, ctx.getResource(), result);
ConnectorInstance connector = ctx.getConnector(DeleteCapabilityType.class, result);
try {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("PROVISIONING DELETE operation on {}\n DELETE object, object class {}, identified by:\n{}\n additional operations:\n{}", ctx.getResource(), shadow.asObjectable().getObjectClass(), SchemaDebugUtil.debugDump(identifiers), SchemaDebugUtil.debugDump(additionalOperations));
}
if (!ResourceTypeUtil.isDeleteCapabilityEnabled(ctx.getResource())) {
UnsupportedOperationException e = new UnsupportedOperationException("Resource does not support 'delete' operation");
result.recordFatalError(e);
throw e;
}
connector.deleteObject(ctx.getObjectClassDefinition(), additionalOperations, identifiers, ctx, result);
computeResultStatus(result);
LOGGER.debug("PROVISIONING DELETE: {}", result.getStatus());
} catch (ObjectNotFoundException ex) {
result.recordFatalError("Can't delete object " + shadow + ". Reason: " + ex.getMessage(), ex);
throw new ObjectNotFoundException("An error occured while deleting resource object " + shadow + "whith identifiers " + identifiers + ": " + ex.getMessage(), ex);
} catch (CommunicationException ex) {
result.recordFatalError("Error communicating with the connector " + connector + ": " + ex.getMessage(), ex);
throw new CommunicationException("Error communicating with the connector " + connector + ": " + ex.getMessage(), ex);
} catch (ConfigurationException ex) {
result.recordFatalError("Configuration error in connector " + connector + ": " + ex.getMessage(), ex);
throw new ConfigurationException("Configuration error in connector " + connector + ": " + ex.getMessage(), ex);
} catch (ExpressionEvaluationException ex) {
result.recordFatalError("Expression error while setting up the resource: " + ex.getMessage(), ex);
throw new ExpressionEvaluationException("Expression error while setting up the resource: " + ex.getMessage(), ex);
} catch (GenericFrameworkException ex) {
result.recordFatalError("Generic error in connector: " + ex.getMessage(), ex);
throw new GenericConnectorException("Generic error in connector: " + ex.getMessage(), ex);
}
LOGGER.trace("Deleted resource object {}", shadow);
return AsynchronousOperationResult.wrap(result);
}
use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class AbstractManualConnectorInstance method deleteObject.
@Override
public AsynchronousOperationResult deleteObject(ObjectClassComplexTypeDefinition objectClass, Collection<Operation> additionalOperations, Collection<? extends ResourceAttribute<?>> identifiers, StateReporter reporter, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException {
OperationResult result = parentResult.createSubresult(OPERATION_DELETE);
String ticketIdentifier = null;
try {
ticketIdentifier = createTicketDelete(objectClass, identifiers, result);
} catch (ObjectNotFoundException | CommunicationException | GenericFrameworkException | SchemaException | ConfigurationException | RuntimeException | Error e) {
result.recordFatalError(e);
throw e;
}
result.recordInProgress();
result.setAsynchronousOperationReference(ticketIdentifier);
return AsynchronousOperationResult.wrap(result);
}
use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method deleteObject.
@Override
public AsynchronousOperationResult deleteObject(ResourceObjectDefinition objectDefinition, PrismObject<ShadowType> shadow, Collection<? extends ResourceAttribute<?>> identifiers, UcfExecutionContext ctx, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException {
Validate.notNull(objectDefinition, "No objectclass");
OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".deleteObject");
result.addArbitraryObjectCollectionAsParam("identifiers", identifiers);
ObjectClass objClass = objectClassToConnId(objectDefinition);
Uid uid;
try {
uid = getUid(objectDefinition, identifiers);
} catch (SchemaException e) {
result.recordFatalError(e);
throw e;
}
OperationResult icfResult = result.createSubresult(ConnectorFacade.class.getName() + ".delete");
icfResult.addArbitraryObjectAsParam("uid", uid);
icfResult.addArbitraryObjectAsParam("objectClass", objClass);
icfResult.addContext("connector", connIdConnectorFacade.getClass());
InternalMonitor.recordConnectorOperation("delete");
InternalMonitor.recordConnectorModification("delete");
ConnIdOperation operation = recordIcfOperationStart(ctx, ProvisioningOperation.ICF_DELETE, objectDefinition, uid);
LOGGER.trace("Invoking ConnId delete operation: {}", operation);
try {
connIdConnectorFacade.delete(objClass, uid, new OperationOptionsBuilder().build());
recordIcfOperationEnd(ctx, operation, null);
icfResult.recordSuccess();
} catch (Throwable ex) {
recordIcfOperationEnd(ctx, operation, ex);
String desc = this.getHumanReadableName() + " while deleting object identified by ConnId UID '" + uid.getUidValue() + "'";
Throwable midpointEx = processConnIdException(ex, desc, icfResult);
result.computeStatus("Removing attribute values failed");
// exception
if (midpointEx instanceof ObjectNotFoundException) {
throw (ObjectNotFoundException) midpointEx;
} else if (midpointEx instanceof CommunicationException) {
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
// Schema exception during delete? It must be a missing UID
throw new IllegalArgumentException(midpointEx.getMessage(), midpointEx);
} else if (midpointEx instanceof RuntimeException) {
throw (RuntimeException) midpointEx;
} else if (midpointEx instanceof Error) {
throw (Error) midpointEx;
} else {
throw new SystemException("Got unexpected exception: " + ex.getClass().getName() + ": " + ex.getMessage(), ex);
}
}
result.computeStatus();
return AsynchronousOperationResult.wrap(result);
}
use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class RefreshHelper method refreshShadowRetryOperations.
private RefreshShadowOperation refreshShadowRetryOperations(ProvisioningContext ctx, PrismObject<ShadowType> repoShadow, List<PendingOperationType> sortedOperations, ProvisioningOperationOptions options, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, EncryptionException {
ShadowType shadowType = repoShadow.asObjectable();
OperationResult retryResult = new OperationResult(OP_REFRESH_RETRY);
if (ShadowUtil.isDead(shadowType)) {
RefreshShadowOperation rso = new RefreshShadowOperation();
retryResult.recordSuccess();
rso.setRefreshedShadow(repoShadow);
rso.setRefreshResult(retryResult);
return rso;
}
Duration retryPeriod = ProvisioningUtil.getRetryPeriod(ctx);
Collection<ObjectDeltaOperation<ShadowType>> executedDeltas = new ArrayList<>();
for (PendingOperationType pendingOperation : sortedOperations) {
if (!needsRetry(pendingOperation)) {
continue;
}
// We really want to get "now" here. Retrying operation may take some time. We want good timestamps that do not lie.
XMLGregorianCalendar now = clock.currentTimeXMLGregorianCalendar();
if (!isAfterRetryPeriod(pendingOperation, retryPeriod, now)) {
if (PendingOperationTypeType.RETRY != pendingOperation.getType()) {
continue;
}
if (!ProvisioningOperationOptions.isForceRetry(options)) {
continue;
}
}
LOGGER.trace("Going to retry operation {} on {}", pendingOperation, repoShadow);
// Record attempt number and timestamp before the operation
// TODO: later use this as an optimistic lock to make sure that two threads won't retry the operation at the same time
// TODO: move to a better place
ObjectDelta<ShadowType> shadowDelta = repoShadow.createModifyDelta();
ItemPath containerPath = pendingOperation.asPrismContainerValue().getPath();
int attemptNumber = pendingOperation.getAttemptNumber() + 1;
PropertyDelta<Integer> attemptNumberDelta = shadowDelta.createPropertyModification(containerPath.append(PendingOperationType.F_ATTEMPT_NUMBER));
attemptNumberDelta.setRealValuesToReplace(attemptNumber);
shadowDelta.addModification(attemptNumberDelta);
PropertyDelta<XMLGregorianCalendar> lastAttemptTimestampDelta = shadowDelta.createPropertyModification(containerPath.append(PendingOperationType.F_LAST_ATTEMPT_TIMESTAMP));
lastAttemptTimestampDelta.setRealValuesToReplace(now);
shadowDelta.addModification(lastAttemptTimestampDelta);
PropertyDelta<OperationResultStatusType> resultStatusDelta = shadowDelta.createPropertyModification(containerPath.append(PendingOperationType.F_RESULT_STATUS));
resultStatusDelta.setRealValuesToReplace(OperationResultStatusType.IN_PROGRESS);
shadowDelta.addModification(resultStatusDelta);
shadowManager.modifyShadowAttributes(ctx, repoShadow, shadowDelta.getModifications(), parentResult);
shadowDelta.applyTo(repoShadow);
ObjectDeltaType pendingDeltaType = pendingOperation.getDelta();
ObjectDelta<ShadowType> pendingDelta = DeltaConvertor.createObjectDelta(pendingDeltaType, prismContext);
ProvisioningOperationState<? extends AsynchronousOperationResult> opState = ProvisioningOperationState.fromPendingOperation(repoShadow, pendingOperation);
LOGGER.debug("Retrying operation {} on {}, attempt #{}", pendingDelta, repoShadow, attemptNumber);
ObjectDeltaOperation<ShadowType> objectDeltaOperation = new ObjectDeltaOperation<>(pendingDelta);
OperationResult result = parentResult.createSubresult(OP_OPERATION_RETRY);
try {
retryOperation(ctx, pendingDelta, opState, task, result);
repoShadow = opState.getRepoShadow();
result.computeStatus();
if (result.isError()) {
retryResult.setStatus(result.getStatus());
}
// TODO maybe add whole "result" as subresult to the retryResult?
result.muteError();
} catch (CommunicationException | GenericFrameworkException | ObjectAlreadyExistsException | SchemaException | ObjectNotFoundException | ConfigurationException | SecurityViolationException e) {
// This is final failure: the error is not handled.
// Therefore the operation is now completed - finished with an error.
// But we do not want to stop the task. Just log the error.
LOGGER.error("Operation {} on {} ended up with an error after {} retries: {}", pendingDelta, repoShadow, attemptNumber, e.getMessage(), e);
// The retry itself was a success. Operation that was retried might have failed.
// And that is recorded in the shadow. But we have successfully retried the operation.
result.recordHandledError(e);
retryResult.recordFatalError("Operation " + pendingDelta + " on " + repoShadow + " ended with an error after " + attemptNumber + " retries: " + e.getMessage());
} catch (Throwable e) {
// This is unexpected error during retry. This means that there was other
// failure that we did not expected. This is likely to be bug - or maybe wrong
// error handling. This means that the retry was a failure.
result.recordFatalError(e);
retryResult.recordFatalError(e);
} finally {
// Status should be set by now, we just want to close the result
result.computeStatusIfUnknown();
}
objectDeltaOperation.setExecutionResult(result);
executedDeltas.add(objectDeltaOperation);
}
RefreshShadowOperation rso = new RefreshShadowOperation();
rso.setExecutedDeltas(executedDeltas);
rso.setRefreshedShadow(repoShadow);
parentResult.computeStatus();
rso.setRefreshResult(retryResult);
LOGGER.trace("refreshShadowOperation {}", rso.debugDumpLazily());
return rso;
}
use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class MaintenanceExceptionHandler method handleDeleteError.
@Override
public OperationResultStatus handleDeleteError(ProvisioningContext ctx, PrismObject<ShadowType> repoShadow, ProvisioningOperationOptions options, ProvisioningOperationState<AsynchronousOperationResult> opState, Exception cause, OperationResult failedOperationResult, Task task, OperationResult parentResult) {
OperationResult result = parentResult.createSubresult(OPERATION_HANDLE_DELETE_ERROR);
result.addParam("exception", cause.getMessage());
try {
failedOperationResult.setStatus(OperationResultStatus.IN_PROGRESS);
return postponeDelete(ctx, repoShadow, opState, failedOperationResult, result);
} catch (Throwable t) {
result.recordFatalError(t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}
Aggregations