Search in sources :

Example 16 with ResourceOperationDescription

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);
    }
}
Also used : PolyStringType(com.evolveum.prism.xml.ns._public.types_3.PolyStringType) CommunicationException(com.evolveum.midpoint.util.exception.CommunicationException) ResourceOperationDescription(com.evolveum.midpoint.provisioning.api.ResourceOperationDescription) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) ResourceType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta)

Example 17 with ResourceOperationDescription

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)";
    }
}
Also used : ResourceOperationDescription(com.evolveum.midpoint.provisioning.api.ResourceOperationDescription) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta)

Example 18 with ResourceOperationDescription

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);
}
Also used : ProvisioningContext(com.evolveum.midpoint.provisioning.impl.ProvisioningContext) AsynchronousOperationReturnValue(com.evolveum.midpoint.schema.result.AsynchronousOperationReturnValue) ResourceOperationDescription(com.evolveum.midpoint.provisioning.api.ResourceOperationDescription) ProvisioningOperationState(com.evolveum.midpoint.provisioning.impl.ProvisioningOperationState)

Example 19 with ResourceOperationDescription

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);
    }
}
Also used : ArrayList(java.util.ArrayList) ResourceAttributeContainer(com.evolveum.midpoint.schema.processor.ResourceAttributeContainer) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) PolyString(com.evolveum.midpoint.prism.polystring.PolyString) OperationResultStatus(com.evolveum.midpoint.schema.result.OperationResultStatus) ResourceOperationDescription(com.evolveum.midpoint.provisioning.api.ResourceOperationDescription) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta) ResourceAttributeContainerDefinition(com.evolveum.midpoint.schema.processor.ResourceAttributeContainerDefinition) Duration(javax.xml.datatype.Duration) ObjectDeltaType(com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) AsynchronousOperationResult(com.evolveum.midpoint.schema.result.AsynchronousOperationResult) PolyString(com.evolveum.midpoint.prism.polystring.PolyString) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 20 with ResourceOperationDescription

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);
    }
}
Also used : ResourceOperationDescription(com.evolveum.midpoint.provisioning.api.ResourceOperationDescription)

Aggregations

ResourceOperationDescription (com.evolveum.midpoint.provisioning.api.ResourceOperationDescription)21 ObjectDelta (com.evolveum.midpoint.prism.delta.ObjectDelta)10 ItemDelta (com.evolveum.midpoint.prism.delta.ItemDelta)5 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)5 ObjectDeltaType (com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType)5 GenericFrameworkException (com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException)4 CommunicationException (com.evolveum.midpoint.util.exception.CommunicationException)4 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)4 ConfigurationException (com.evolveum.midpoint.util.exception.ConfigurationException)3 ObjectAlreadyExistsException (com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException)3 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)3 ResourceObjectEvent (com.evolveum.midpoint.notifications.api.events.ResourceObjectEvent)2 PrismObject (com.evolveum.midpoint.prism.PrismObject)2 ResourceAttributeContainer (com.evolveum.midpoint.schema.processor.ResourceAttributeContainer)2 AsynchronousOperationReturnValue (com.evolveum.midpoint.schema.result.AsynchronousOperationReturnValue)2 OperationResultStatus (com.evolveum.midpoint.schema.result.OperationResultStatus)2 SecurityViolationException (com.evolveum.midpoint.util.exception.SecurityViolationException)2 ShadowType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType)2 Date (java.util.Date)2 Duration (javax.xml.datatype.Duration)2