use of com.evolveum.midpoint.provisioning.api.ResourceOperationDescription in project midpoint by Evolveum.
the class CommunicationExceptionHandler method handleError.
@Override
public <T extends ShadowType> T handleError(T shadow, FailedOperation op, Exception ex, boolean doDiscovery, boolean compensate, Task task, OperationResult parentResult) throws SchemaException, GenericFrameworkException, CommunicationException, ObjectNotFoundException, ObjectAlreadyExistsException, ConfigurationException {
if (!doDiscovery) {
parentResult.recordFatalError(ex);
if (ex instanceof CommunicationException) {
throw (CommunicationException) ex;
} else {
throw new CommunicationException(ex.getMessage(), ex);
}
}
Validate.notNull(shadow, "Shadow must not be null.");
OperationResult operationResult = parentResult.createSubresult("com.evolveum.midpoint.provisioning.consistency.impl.CommunicationExceptionHandler.handleError." + op.name());
operationResult.addParam("shadow", shadow);
operationResult.addParam("currentOperation", op);
operationResult.addParam("exception", ex.getMessage());
// first modify last availability status in the resource, so by others
// operations, we can know that it is down
resourceManager.modifyResourceAvailabilityStatus(shadow.getResource().asPrismObject(), AvailabilityStatusType.DOWN, operationResult);
if ((!isPostpone(shadow.getResource()) || !compensate) && !FailedOperation.GET.equals(op)) {
LOGGER.trace("Postponing operation turned off.");
operationResult.recordFatalError(ex.getMessage(), ex);
throw new CommunicationException(ex.getMessage(), ex);
}
// Task task = null;
ObjectDelta delta = null;
ResourceOperationDescription operationDescription = null;
switch(op) {
case ADD:
// if it is first time, just store the whole account to the repo
LOGGER.trace("Postponing ADD operation for {}", ObjectTypeUtil.toShortString(shadow));
ResourceType resource = shadow.getResource();
if (shadow.getFailedOperationType() == null) {
// ResourceType resource = shadow.getResource();
if (shadow.getName() == null) {
shadow.setName(new PolyStringType(ShadowUtil.determineShadowName(shadow.asPrismObject())));
}
if (shadow.getResourceRef() == null || shadow.getResourceRef().getOid() == null) {
if (resource != null) {
shadow.getResourceRef().setOid(shadow.getResource().getOid());
}
}
if (shadow.getResourceRef() != null && resource != null) {
shadow.setResource(null);
}
shadow.setAttemptNumber(getAttemptNumber(shadow));
shadow.setFailedOperationType(FailedOperationTypeType.ADD);
ConstraintsChecker.onShadowAddOperation(shadow);
// Unlike addObject calls during normal provisioning, here we preserve all activation information, including e.g. administrativeStatus.
// It is needed for shadow creation during error recovery.
String oid = cacheRepositoryService.addObject(shadow.asPrismObject(), null, operationResult);
shadow.setOid(oid);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Stored new shadow for unfinished operation:\n{}", shadow.asPrismObject().debugDump(1));
}
// if it is seccond time ,just increade the attempt number
} else {
if (FailedOperationTypeType.ADD == shadow.getFailedOperationType()) {
Collection<? extends ItemDelta> attemptdelta = createAttemptModification(shadow, null);
ConstraintsChecker.onShadowModifyOperation(attemptdelta);
cacheRepositoryService.modifyObject(ShadowType.class, shadow.getOid(), attemptdelta, operationResult);
}
}
// error
for (OperationResult subRes : parentResult.getSubresults()) {
subRes.muteError();
}
operationResult.computeStatus();
parentResult.recordHandledError("Could not create object=" + shadow.getName().getOrig() + " on the resource, because " + ObjectTypeUtil.toShortString(resource) + // there will be something like ": Add object failed" appended, so the final dot was a bit ugly here
" is unreachable at the moment. Shadow is stored in the repository and the resource object will be created when the resource goes online");
// task = taskManager.createTaskInstance();
delta = ObjectDelta.createAddDelta(shadow.asPrismObject());
operationDescription = createOperationDescription(shadow, ex, resource, delta, task, operationResult);
changeNotificationDispatcher.notifyInProgress(operationDescription, task, parentResult);
return shadow;
case MODIFY:
if (shadow.getFailedOperationType() == null || shadow.getFailedOperationType() == FailedOperationTypeType.MODIFY) {
shadow.setFailedOperationType(FailedOperationTypeType.MODIFY);
Collection<ItemDelta> modifications = createShadowModification(shadow);
ConstraintsChecker.onShadowModifyOperation(modifications);
getCacheRepositoryService().modifyObject(ShadowType.class, shadow.getOid(), modifications, operationResult);
delta = ObjectDelta.createModifyDelta(shadow.getOid(), modifications, shadow.asPrismObject().getCompileTimeClass(), prismContext);
// operationResult.recordSuccess();
// return shadow;
} else {
if (FailedOperationTypeType.ADD == shadow.getFailedOperationType()) {
if (shadow.getObjectChange() != null && shadow.getOid() != null) {
Collection<? extends ItemDelta> deltas = DeltaConvertor.toModifications(shadow.getObjectChange().getItemDelta(), shadow.asPrismObject().getDefinition());
ConstraintsChecker.onShadowModifyOperation(deltas);
cacheRepositoryService.modifyObject(ShadowType.class, shadow.getOid(), deltas, operationResult);
delta = ObjectDelta.createModifyDelta(shadow.getOid(), deltas, shadow.asPrismObject().getCompileTimeClass(), prismContext);
// return shadow;
// operationResult.recordSuccess();
}
}
}
for (OperationResult subRes : parentResult.getSubresults()) {
subRes.muteError();
}
operationResult.computeStatus();
parentResult.recordHandledError("Could not apply modifications to " + ObjectTypeUtil.toShortString(shadow) + " on the " + ObjectTypeUtil.toShortString(shadow.getResource()) + ", because resource is unreachable. Modifications will be applied when the resource goes online");
// task = taskManager.createTaskInstance();
//
operationDescription = createOperationDescription(shadow, ex, shadow.getResource(), delta, task, operationResult);
changeNotificationDispatcher.notifyInProgress(operationDescription, task, parentResult);
return shadow;
case DELETE:
shadow.setFailedOperationType(FailedOperationTypeType.DELETE);
Collection<ItemDelta> modifications = createShadowModification(shadow);
ConstraintsChecker.onShadowModifyOperation(modifications);
getCacheRepositoryService().modifyObject(ShadowType.class, shadow.getOid(), modifications, operationResult);
for (OperationResult subRes : parentResult.getSubresults()) {
subRes.muteError();
}
parentResult.recordHandledError("Could not delete " + ObjectTypeUtil.getShortTypeName(shadow) + " from the resource " + ObjectTypeUtil.toShortString(shadow.getResource()) + ", because resource is unreachable. Resource object will be delete when the resource goes online");
// operationResult.recordSuccess();
operationResult.computeStatus();
// task = taskManager.createTaskInstance();
// task.setChannel(QNameUtil.qNameToUri(SchemaConstants.CHANGE_CHANNEL_DISCOVERY));
delta = ObjectDelta.createDeleteDelta(shadow.asPrismObject().getCompileTimeClass(), shadow.getOid(), prismContext);
operationDescription = createOperationDescription(shadow, ex, shadow.getResource(), delta, task, operationResult);
changeNotificationDispatcher.notifyInProgress(operationDescription, task, parentResult);
return shadow;
case GET:
// result..
for (OperationResult subRes : parentResult.getSubresults()) {
subRes.muteError();
}
operationResult.recordPartialError("Could not get " + ObjectTypeUtil.toShortString(shadow) + " from the resource " + ObjectTypeUtil.toShortString(shadow.getResource()) + ", because resource is unreachable. Returning shadow from the repository");
shadow.setFetchResult(operationResult.createOperationResultType());
// operationResult.computeStatus();
return shadow;
default:
throw new CommunicationException(ex);
}
}
use of com.evolveum.midpoint.provisioning.api.ResourceOperationDescription in project midpoint by Evolveum.
the class SimpleResourceObjectNotifier method getSubject.
@Override
protected String getSubject(ResourceObjectEvent event, SimpleResourceObjectNotifierType configuration, String transport, Task task, OperationResult result) {
ResourceOperationDescription rod = event.getOperationDescription();
// noinspection unchecked
ObjectDelta<ShadowType> delta = (ObjectDelta<ShadowType>) rod.getObjectDelta();
String objectTypeDescription = event.isShadowKind(ShadowKindType.ACCOUNT) ? "Account" : "Resource object";
if (delta.isAdd()) {
return objectTypeDescription + " creation notification";
} else if (delta.isModify()) {
return objectTypeDescription + " modification notification";
} else if (delta.isDelete()) {
return objectTypeDescription + " deletion notification";
} else {
return "(unknown resource object operation)";
}
}
use of com.evolveum.midpoint.provisioning.api.ResourceOperationDescription in project midpoint by Evolveum.
the class AddHelper method addResourceObject.
String addResourceObject(@NotNull PrismObject<ShadowType> resourceObjectToAdd, OperationProvisioningScriptsType scripts, ProvisioningOperationOptions options, @NotNull Task task, @NotNull OperationResult result) throws CommunicationException, GenericFrameworkException, ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, EncryptionException {
InternalMonitor.recordCount(InternalCounters.SHADOW_CHANGE_OPERATION_COUNT);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Start adding shadow object{}:\n{}", getAdditionalOperationDesc(scripts, options), resourceObjectToAdd.debugDump(1));
}
ResourceType resource = ctxFactory.getResource(resourceObjectToAdd, task, result);
ProvisioningContext ctx;
try {
ctx = ctxFactory.createForShadow(resourceObjectToAdd, resource, task);
ctx.assertDefinition();
} catch (SchemaException e) {
result.recordFatalErrorNotFinish(e);
ResourceOperationDescription operationDescription = ProvisioningUtil.createResourceFailureDescription(resourceObjectToAdd, resource, resourceObjectToAdd.createAddDelta(), result);
eventDispatcher.notifyFailure(operationDescription, task, result);
throw e;
}
ProvisioningOperationState<AsynchronousOperationReturnValue<PrismObject<ShadowType>>> opState = new ProvisioningOperationState<>();
return addShadowAttempt(ctx, resourceObjectToAdd, scripts, opState, options, task, result);
}
use of com.evolveum.midpoint.provisioning.api.ResourceOperationDescription in project midpoint by Evolveum.
the class RefreshHelper method refreshShadowAsyncStatus.
/**
* Refresh status of asynchronous operation, e.g. status of manual connector ticket.
* This method will get new status from resourceObjectConverter and it will process the
* status in case that it has changed.
*/
private void refreshShadowAsyncStatus(ProvisioningContext ctx, PrismObject<ShadowType> repoShadow, List<PendingOperationType> sortedOperations, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
Duration gracePeriod = ProvisioningUtil.getGracePeriod(ctx);
List<ObjectDelta<ShadowType>> notificationDeltas = new ArrayList<>();
boolean shadowInception = false;
OperationResultStatusType shadowInceptionOutcome = null;
ObjectDelta<ShadowType> shadowDelta = repoShadow.createModifyDelta();
for (PendingOperationType pendingOperation : sortedOperations) {
if (!needsRefresh(pendingOperation)) {
continue;
}
ItemPath containerPath = pendingOperation.asPrismContainerValue().getPath();
String asyncRef = pendingOperation.getAsynchronousOperationReference();
if (asyncRef == null) {
continue;
}
AsynchronousOperationResult refreshAsyncResult;
try {
refreshAsyncResult = resourceObjectConverter.refreshOperationStatus(ctx, repoShadow, asyncRef, parentResult);
} catch (CommunicationException e) {
LOGGER.debug("Communication error while trying to refresh pending operation of {}. Skipping refresh of this operation.", repoShadow, e);
parentResult.recordPartialError(e);
continue;
}
OperationResultStatus newStatus = refreshAsyncResult.getOperationResult().getStatus();
if (newStatus == null) {
continue;
}
OperationResultStatusType newStatusType = newStatus.createStatusType();
if (newStatusType.equals(pendingOperation.getResultStatus())) {
continue;
}
boolean operationCompleted = ProvisioningUtil.isCompleted(newStatusType) && pendingOperation.getCompletionTimestamp() == null;
if (operationCompleted && gracePeriod == null) {
LOGGER.trace("Deleting pending operation because it is completed (no grace): {}", pendingOperation);
shadowDelta.addModificationDeleteContainer(ShadowType.F_PENDING_OPERATION, pendingOperation.clone());
ObjectDeltaType pendingDeltaType = pendingOperation.getDelta();
ObjectDelta<ShadowType> pendingDelta = DeltaConvertor.createObjectDelta(pendingDeltaType, prismContext);
if (pendingDelta.isAdd()) {
shadowInception = true;
shadowInceptionOutcome = newStatusType;
}
if (pendingDelta.isDelete()) {
shadowInception = false;
shadowManager.addDeadShadowDeltas(repoShadow, (List) shadowDelta.getModifications());
}
continue;
} else {
PropertyDelta<OperationResultStatusType> resultStatusDelta = shadowDelta.createPropertyModification(containerPath.append(PendingOperationType.F_RESULT_STATUS));
resultStatusDelta.setRealValuesToReplace(newStatusType);
shadowDelta.addModification(resultStatusDelta);
}
if (operationCompleted) {
// Operation completed
PropertyDelta<PendingOperationExecutionStatusType> executionStatusDelta = shadowDelta.createPropertyModification(containerPath.append(PendingOperationType.F_EXECUTION_STATUS));
executionStatusDelta.setRealValuesToReplace(PendingOperationExecutionStatusType.COMPLETED);
shadowDelta.addModification(executionStatusDelta);
PropertyDelta<XMLGregorianCalendar> completionTimestampDelta = shadowDelta.createPropertyModification(containerPath.append(PendingOperationType.F_COMPLETION_TIMESTAMP));
completionTimestampDelta.setRealValuesToReplace(clock.currentTimeXMLGregorianCalendar());
shadowDelta.addModification(completionTimestampDelta);
ObjectDeltaType pendingDeltaType = pendingOperation.getDelta();
ObjectDelta<ShadowType> pendingDelta = DeltaConvertor.createObjectDelta(pendingDeltaType, prismContext);
if (pendingDelta.isAdd()) {
shadowInception = true;
shadowInceptionOutcome = newStatusType;
}
if (pendingDelta.isModify()) {
// Apply shadow naming attribute modification
PrismContainer<ShadowAttributesType> shadowAttributesContainer = repoShadow.findContainer(ItemPath.create(ShadowType.F_ATTRIBUTES));
ResourceAttributeContainer resourceAttributeContainer = ResourceAttributeContainer.convertFromContainer(shadowAttributesContainer, ctx.getObjectDefinitionRequired());
ResourceAttributeContainerDefinition resourceAttrDefinition = resourceAttributeContainer.getDefinition();
if (resourceAttrDefinition != null) {
// If naming attribute is present in delta...
ResourceAttributeDefinition<?> namingAttribute = resourceAttrDefinition.getNamingAttribute();
if (namingAttribute != null) {
if (pendingDelta.hasItemDelta(ItemPath.create(ShadowType.F_ATTRIBUTES, namingAttribute.getItemName()))) {
// Retrieve a possible changed name per the defined naming attribute for the resource
ItemDelta namingAttributeDelta = pendingDelta.findItemDelta(ItemPath.create(ShadowType.F_ATTRIBUTES, namingAttribute.getItemName()));
Collection<?> valuesToReplace = namingAttributeDelta.getValuesToReplace();
Optional<?> valueToReplace = valuesToReplace.stream().findFirst();
if (valueToReplace.isPresent()) {
Object valueToReplaceObj = ((PrismPropertyValue) valueToReplace.get()).getValue();
if (valueToReplaceObj instanceof String) {
// Apply the new naming attribute value to the shadow name by adding the change to the modification set for shadow delta
PropertyDelta<PolyString> nameDelta = shadowDelta.createPropertyModification(ItemPath.create(ShadowType.F_NAME));
Collection<PolyString> modificationSet = new ArrayList<>();
PolyString nameAttributeReplacement = new PolyString((String) valueToReplaceObj);
modificationSet.add(nameAttributeReplacement);
nameDelta.setValuesToReplace(PrismValueCollectionsUtil.createCollection(prismContext, modificationSet));
shadowDelta.addModification(nameDelta);
}
}
}
}
}
// Apply shadow attribute modifications
for (ItemDelta<?, ?> pendingModification : pendingDelta.getModifications()) {
shadowDelta.addModification(pendingModification.clone());
}
}
if (pendingDelta.isDelete()) {
shadowInception = false;
shadowManager.addDeadShadowDeltas(repoShadow, (List) shadowDelta.getModifications());
}
notificationDeltas.add(pendingDelta);
}
}
if (shadowInception) {
// We do not need to care about attributes in add deltas here. The add operation is already applied to
// attributes. We need this to "allocate" the identifiers, so iteration mechanism in the
// model can find unique values while taking pending create operations into consideration.
PropertyDelta<Boolean> existsDelta = shadowDelta.createPropertyModification(ShadowType.F_EXISTS);
if (OperationResultUtil.isSuccessful(shadowInceptionOutcome)) {
existsDelta.setRealValuesToReplace(true);
} else {
existsDelta.setRealValuesToReplace(false);
}
shadowDelta.addModification(existsDelta);
}
XMLGregorianCalendar now = clock.currentTimeXMLGregorianCalendar();
expirePendingOperations(ctx, repoShadow, shadowDelta, now);
if (!shadowDelta.isEmpty()) {
shadowCaretaker.applyAttributesDefinition(ctx, shadowDelta);
shadowManager.modifyShadowAttributes(ctx, repoShadow, shadowDelta.getModifications(), parentResult);
}
for (ObjectDelta<ShadowType> notificationDelta : notificationDeltas) {
ResourceOperationDescription operationDescription = createSuccessOperationDescription(ctx, repoShadow, notificationDelta, parentResult);
operationListener.notifySuccess(operationDescription, task, parentResult);
}
if (!shadowDelta.isEmpty()) {
shadowDelta.applyTo(repoShadow);
}
}
use of com.evolveum.midpoint.provisioning.api.ResourceOperationDescription in project midpoint by Evolveum.
the class DeleteHelper method notifyAfterDelete.
void notifyAfterDelete(ProvisioningContext ctx, PrismObject<ShadowType> shadow, ProvisioningOperationState<AsynchronousOperationResult> opState, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
ObjectDelta<ShadowType> delta = prismContext.deltaFactory().object().createDeleteDelta(shadow.getCompileTimeClass(), shadow.getOid());
ResourceOperationDescription operationDescription = createSuccessOperationDescription(ctx, shadow, delta, parentResult);
if (opState.isExecuting()) {
eventDispatcher.notifyInProgress(operationDescription, task, parentResult);
} else {
eventDispatcher.notifySuccess(operationDescription, task, parentResult);
}
}
Aggregations