Search in sources :

Example 1 with ConnectorOperationOptions

use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions in project midpoint by Evolveum.

the class AddHelper method addShadowAttempt.

String addShadowAttempt(ProvisioningContext ctx, PrismObject<ShadowType> resourceObjectToAdd, OperationProvisioningScriptsType scripts, ProvisioningOperationState<AsynchronousOperationReturnValue<PrismObject<ShadowType>>> opState, ProvisioningOperationOptions options, Task task, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, EncryptionException {
    PrismContainer<?> attributesContainer = resourceObjectToAdd.findContainer(ShadowType.F_ATTRIBUTES);
    if (attributesContainer == null || attributesContainer.isEmpty()) {
        SchemaException e = new SchemaException("Attempt to add resource object without any attributes: " + resourceObjectToAdd);
        parentResult.recordFatalError(e);
        ResourceOperationDescription operationDescription = ProvisioningUtil.createResourceFailureDescription(resourceObjectToAdd, ctx.getResource(), resourceObjectToAdd.createAddDelta(), parentResult);
        eventDispatcher.notifyFailure(operationDescription, task, parentResult);
        throw e;
    }
    if (!(attributesContainer instanceof ResourceAttributeContainer)) {
        shadowCaretaker.applyAttributesDefinition(ctx, resourceObjectToAdd);
    }
    preAddChecks(ctx, resourceObjectToAdd, opState, task, parentResult);
    shadowManager.addNewProposedShadow(ctx, resourceObjectToAdd, opState, task, parentResult);
    entitlementsHelper.preprocessEntitlements(ctx, resourceObjectToAdd, parentResult);
    shadowCaretaker.applyAttributesDefinition(ctx, resourceObjectToAdd);
    shadowManager.setKindIfNecessary(resourceObjectToAdd.asObjectable(), ctx);
    accessChecker.checkAdd(ctx, resourceObjectToAdd, parentResult);
    PrismObject<ShadowType> addedShadow = null;
    OperationResultStatus finalOperationStatus = null;
    if (shouldExecuteResourceOperationDirectly(ctx)) {
        ConnectorOperationOptions connOptions = commonHelper.createConnectorOperationOptions(ctx, options, parentResult);
        LOGGER.trace("ADD {}: resource operation, execution starting", resourceObjectToAdd);
        try {
            if (ResourceTypeUtil.isInMaintenance(ctx.getResource())) {
                // this tells mp to create pending delta
                throw new MaintenanceException("Resource " + ctx.getResource() + " is in the maintenance");
            }
            // RESOURCE OPERATION: add
            AsynchronousOperationReturnValue<PrismObject<ShadowType>> asyncReturnValue = resourceObjectConverter.addResourceObject(ctx, resourceObjectToAdd, scripts, connOptions, false, parentResult);
            opState.processAsyncResult(asyncReturnValue);
            addedShadow = asyncReturnValue.getReturnValue();
        } catch (ObjectAlreadyExistsException e) {
            LOGGER.trace("Object already exists error when trying to add {}, exploring the situation", ShadowUtil.shortDumpShadowLazily(resourceObjectToAdd));
            // This exception may still be OK in some cases. Such as:
            // We are trying to add a shadow to a semi-manual connector.
            // But the resource object was recently deleted. The object is
            // still in the backing store (CSV file) because of a grace
            // period. Obviously, attempt to add such object would fail.
            // So, we need to handle this case specially. (MID-4414)
            OperationResult failedOperationResult = parentResult.getLastSubresult();
            if (hasDeadShadowWithDeleteOperation(ctx, resourceObjectToAdd, parentResult)) {
                if (failedOperationResult.isError()) {
                    failedOperationResult.setStatus(OperationResultStatus.HANDLED_ERROR);
                }
                // Try again, this time without explicit uniqueness check
                try {
                    LOGGER.trace("ADD {}: retrying resource operation without uniqueness check (previous dead shadow found), execution starting", resourceObjectToAdd);
                    AsynchronousOperationReturnValue<PrismObject<ShadowType>> asyncReturnValue = resourceObjectConverter.addResourceObject(ctx, resourceObjectToAdd, scripts, connOptions, true, parentResult);
                    opState.processAsyncResult(asyncReturnValue);
                    addedShadow = asyncReturnValue.getReturnValue();
                } catch (ObjectAlreadyExistsException innerException) {
                    // Mark shadow dead before we handle the error. ADD operation obviously failed. Therefore this particular
                    // shadow was not created as resource object. It is dead on the spot. Make sure that error handler won't confuse
                    // this shadow with the conflicting shadow that it is going to discover.
                    // This may also be a gestation quantum state collapsing to tombstone
                    shadowManager.markShadowTombstone(opState.getRepoShadow(), task, parentResult);
                    finalOperationStatus = handleAddError(ctx, resourceObjectToAdd, options, opState, innerException, failedOperationResult, task, parentResult);
                } catch (Exception innerException) {
                    finalOperationStatus = handleAddError(ctx, resourceObjectToAdd, options, opState, innerException, parentResult.getLastSubresult(), task, parentResult);
                }
            } else {
                // Mark shadow dead before we handle the error. ADD operation obviously failed. Therefore this particular
                // shadow was not created as resource object. It is dead on the spot. Make sure that error handler won't confuse
                // this shadow with the conflicting shadow that it is going to discover.
                // This may also be a gestation quantum state collapsing to tombstone
                shadowManager.markShadowTombstone(opState.getRepoShadow(), task, parentResult);
                finalOperationStatus = handleAddError(ctx, resourceObjectToAdd, options, opState, e, failedOperationResult, task, parentResult);
            }
        } catch (MaintenanceException e) {
            finalOperationStatus = handleAddError(ctx, resourceObjectToAdd, options, opState, e, parentResult.getLastSubresult(), task, parentResult);
            if (opState.getRepoShadow() != null) {
                setParentOperationStatus(parentResult, opState, finalOperationStatus);
                return opState.getRepoShadow().getOid();
            }
        } catch (Exception e) {
            finalOperationStatus = handleAddError(ctx, resourceObjectToAdd, options, opState, e, parentResult.getLastSubresult(), task, parentResult);
        }
        LOGGER.debug("ADD {}: resource operation executed, operation state: {}", resourceObjectToAdd, opState.shortDumpLazily());
    } else {
        opState.setExecutionStatus(PendingOperationExecutionStatusType.EXECUTION_PENDING);
        // Create dummy subresult with IN_PROGRESS state.
        // This will force the entire result (parent) to be IN_PROGRESS rather than SUCCESS.
        parentResult.createSubresult(OP_DELAYED_OPERATION).recordInProgress();
        LOGGER.debug("ADD {}: resource operation NOT executed, execution pending", resourceObjectToAdd);
    }
    // REPO OPERATION: add
    // This is where the repo shadow is created or updated (if needed)
    shadowManager.recordAddResult(ctx, resourceObjectToAdd, opState, parentResult);
    if (addedShadow == null) {
        addedShadow = resourceObjectToAdd;
    }
    addedShadow.setOid(opState.getRepoShadow().getOid());
    notifyAfterAdd(ctx, addedShadow, opState, task, parentResult);
    setParentOperationStatus(parentResult, opState, finalOperationStatus);
    return opState.getRepoShadow().getOid();
}
Also used : AsynchronousOperationReturnValue(com.evolveum.midpoint.schema.result.AsynchronousOperationReturnValue) ResourceAttributeContainer(com.evolveum.midpoint.schema.processor.ResourceAttributeContainer) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) EncryptionException(com.evolveum.midpoint.prism.crypto.EncryptionException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) OperationResultStatus(com.evolveum.midpoint.schema.result.OperationResultStatus) PrismObject(com.evolveum.midpoint.prism.PrismObject) ResourceOperationDescription(com.evolveum.midpoint.provisioning.api.ResourceOperationDescription) ConnectorOperationOptions(com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions)

Example 2 with ConnectorOperationOptions

use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions in project midpoint by Evolveum.

the class CommonHelper method createConnectorOperationOptions.

ConnectorOperationOptions createConnectorOperationOptions(ProvisioningContext ctx, ProvisioningOperationOptions options, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException {
    if (options == null) {
        return null;
    }
    String runAsAccountOid = options.getRunAsAccountOid();
    if (runAsAccountOid == null) {
        return null;
    }
    RunAsCapabilityType capRunAs = ctx.getEffectiveCapability(RunAsCapabilityType.class);
    if (capRunAs == null) {
        LOGGER.trace("Operation runAs requested, but resource does not have the capability. Ignoring runAs");
        return null;
    }
    PrismObject<ShadowType> runAsShadow;
    try {
        runAsShadow = shadowManager.getShadow(runAsAccountOid, result);
    } catch (ObjectNotFoundException e) {
        throw new ConfigurationException("Requested non-existing 'runAs' shadow", e);
    }
    ProvisioningContext runAsCtx = ctxFactory.createForShadow(runAsShadow, ctx.getResource(), ctx.getTask());
    shadowCaretaker.applyAttributesDefinition(runAsCtx, runAsShadow);
    ResourceObjectIdentification runAsIdentification = ResourceObjectIdentification.createFromShadow(runAsCtx.getObjectDefinitionRequired(), runAsShadow.asObjectable());
    ConnectorOperationOptions connOptions = new ConnectorOperationOptions();
    LOGGER.trace("RunAs identification: {}", runAsIdentification);
    connOptions.setRunAsIdentification(runAsIdentification);
    return connOptions;
}
Also used : ProvisioningContext(com.evolveum.midpoint.provisioning.impl.ProvisioningContext) ResourceObjectIdentification(com.evolveum.midpoint.schema.processor.ResourceObjectIdentification) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) RunAsCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.RunAsCapabilityType) ConnectorOperationOptions(com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions)

Example 3 with ConnectorOperationOptions

use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions in project midpoint by Evolveum.

the class ModifyHelper method modifyShadowAttempt.

/**
 * @param inRefresh True if we are already in refresh shadow method. This means we shouldn't refresh ourselves!
 */
String modifyShadowAttempt(ProvisioningContext ctx, Collection<? extends ItemDelta<?, ?>> modifications, OperationProvisioningScriptsType scripts, ProvisioningOperationOptions options, ProvisioningOperationState<AsynchronousOperationReturnValue<Collection<PropertyDelta<PrismPropertyValue>>>> opState, boolean inRefresh, Task task, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, ObjectNotFoundException, SchemaException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, EncryptionException, ObjectAlreadyExistsException {
    PrismObject<ShadowType> repoShadow = opState.getRepoShadow();
    XMLGregorianCalendar now = clock.currentTimeXMLGregorianCalendar();
    PendingOperationType duplicateOperation = shadowManager.checkAndRecordPendingModifyOperationBeforeExecution(ctx, modifications, opState, parentResult);
    if (duplicateOperation != null) {
        parentResult.setInProgress();
        return repoShadow.getOid();
    }
    shadowCaretaker.applyAttributesDefinition(ctx, repoShadow);
    accessChecker.checkModify(ctx, modifications, parentResult);
    entitlementsHelper.preprocessEntitlements(ctx, modifications, "delta for shadow " + repoShadow.getOid(), parentResult);
    OperationResultStatus finalOperationStatus = null;
    if (shadowManager.isRepositoryOnlyModification(modifications)) {
        opState.setExecutionStatus(PendingOperationExecutionStatusType.COMPLETED);
        LOGGER.debug("MODIFY {}: repository-only modification", repoShadow);
    } else {
        if (shouldExecuteResourceOperationDirectly(ctx)) {
            LOGGER.trace("MODIFY {}: resource modification, execution starting\n{}", repoShadow, DebugUtil.debugDumpLazily(modifications));
            RefreshShadowOperation refreshShadowOperation = null;
            if (!inRefresh && Util.shouldRefresh(repoShadow)) {
                refreshShadowOperation = refreshHelper.refreshShadow(repoShadow, options, task, parentResult);
            }
            if (refreshShadowOperation != null) {
                repoShadow = refreshShadowOperation.getRefreshedShadow();
            }
            if (repoShadow == null) {
                LOGGER.trace("Shadow is gone. Nothing more to do");
                parentResult.recordPartialError("Shadow disappeared during modify.");
                throw new ObjectNotFoundException("Shadow is gone.");
            }
            ConnectorOperationOptions connOptions = commonHelper.createConnectorOperationOptions(ctx, options, parentResult);
            try {
                if (ResourceTypeUtil.isInMaintenance(ctx.getResource())) {
                    throw new MaintenanceException("Resource " + ctx.getResource() + " is in the maintenance");
                }
                if (!shouldExecuteModify(refreshShadowOperation)) {
                    ProvisioningUtil.postponeModify(ctx, repoShadow, modifications, opState, refreshShadowOperation.getRefreshResult(), parentResult);
                    shadowManager.recordModifyResult(ctx, repoShadow, modifications, opState, now, parentResult);
                    return repoShadow.getOid();
                } else {
                    LOGGER.trace("Shadow exists: {}", repoShadow.debugDump());
                }
                AsynchronousOperationReturnValue<Collection<PropertyDelta<PrismPropertyValue>>> asyncReturnValue = resourceObjectConverter.modifyResourceObject(ctx, repoShadow, scripts, connOptions, modifications, now, parentResult);
                opState.processAsyncResult(asyncReturnValue);
                Collection<PropertyDelta<PrismPropertyValue>> knownExecutedDeltas = asyncReturnValue.getReturnValue();
                if (knownExecutedDeltas != null) {
                    ItemDeltaCollectionsUtil.addNotEquivalent(modifications, knownExecutedDeltas);
                }
            } catch (Exception ex) {
                LOGGER.debug("Provisioning exception: {}:{}, attempting to handle it", ex.getClass(), ex.getMessage(), ex);
                finalOperationStatus = handleModifyError(ctx, repoShadow, modifications, options, opState, ex, parentResult.getLastSubresult(), task, parentResult);
            }
            LOGGER.debug("MODIFY {}: resource operation executed, operation state: {}", repoShadow, opState.shortDumpLazily());
        } else {
            opState.setExecutionStatus(PendingOperationExecutionStatusType.EXECUTION_PENDING);
            // Create dummy subresult with IN_PROGRESS state.
            // This will force the entire result (parent) to be IN_PROGRESS rather than SUCCESS.
            parentResult.createSubresult(OP_DELAYED_OPERATION).recordInProgress();
            LOGGER.debug("MODIFY {}: Resource operation NOT executed, execution pending", repoShadow);
        }
    }
    shadowManager.recordModifyResult(ctx, repoShadow, modifications, opState, now, parentResult);
    notifyAfterModify(ctx, repoShadow, modifications, opState, task, parentResult);
    setParentOperationStatus(parentResult, opState, finalOperationStatus);
    return repoShadow.getOid();
}
Also used : PendingOperationType(com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) RefreshShadowOperation(com.evolveum.midpoint.schema.RefreshShadowOperation) EncryptionException(com.evolveum.midpoint.prism.crypto.EncryptionException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) OperationResultStatus(com.evolveum.midpoint.schema.result.OperationResultStatus) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) Collection(java.util.Collection) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) ConnectorOperationOptions(com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions) PrismPropertyValue(com.evolveum.midpoint.prism.PrismPropertyValue)

Example 4 with ConnectorOperationOptions

use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions in project midpoint by Evolveum.

the class ModifyHelper method executeResourceModify.

/**
 * Used to execute delayed operations.
 * Mostly copy&paste from modifyShadow(). But as consistency (handleError()) branch expects to return immediately
 * I could not find a more elegant way to structure this without complicating the code too much.
 */
ProvisioningOperationState<AsynchronousOperationReturnValue<Collection<PropertyDelta<PrismPropertyValue>>>> executeResourceModify(ProvisioningContext ctx, PrismObject<ShadowType> repoShadow, Collection<? extends ItemDelta<?, ?>> modifications, OperationProvisioningScriptsType scripts, ProvisioningOperationOptions options, XMLGregorianCalendar now, Task task, OperationResult parentResult) throws SchemaException, GenericFrameworkException, CommunicationException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException {
    ProvisioningOperationState<AsynchronousOperationReturnValue<Collection<PropertyDelta<PrismPropertyValue>>>> opState = new ProvisioningOperationState<>();
    opState.setRepoShadow(repoShadow);
    ConnectorOperationOptions connOptions = commonHelper.createConnectorOperationOptions(ctx, options, parentResult);
    try {
        LOGGER.trace("Applying change: {}", DebugUtil.debugDumpLazily(modifications));
        AsynchronousOperationReturnValue<Collection<PropertyDelta<PrismPropertyValue>>> asyncReturnValue = resourceObjectConverter.modifyResourceObject(ctx, repoShadow, scripts, connOptions, modifications, now, parentResult);
        opState.processAsyncResult(asyncReturnValue);
        Collection<PropertyDelta<PrismPropertyValue>> knownExecutedDeltas = asyncReturnValue.getReturnValue();
        if (knownExecutedDeltas != null) {
            ItemDeltaCollectionsUtil.addNotEquivalent(modifications, knownExecutedDeltas);
        }
    } catch (Exception ex) {
        LOGGER.debug("Provisioning exception: {}:{}, attempting to handle it", ex.getClass(), ex.getMessage(), ex);
        try {
            handleModifyError(ctx, repoShadow, modifications, options, opState, ex, parentResult.getLastSubresult(), task, parentResult);
            parentResult.computeStatus();
        } catch (ObjectAlreadyExistsException e) {
            parentResult.recordFatalError("While compensating communication problem for modify operation got: " + ex.getMessage(), ex);
            throw new SystemException(e);
        }
    }
    return opState;
}
Also used : AsynchronousOperationReturnValue(com.evolveum.midpoint.schema.result.AsynchronousOperationReturnValue) Collection(java.util.Collection) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) ConnectorOperationOptions(com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions) EncryptionException(com.evolveum.midpoint.prism.crypto.EncryptionException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) PrismPropertyValue(com.evolveum.midpoint.prism.PrismPropertyValue)

Example 5 with ConnectorOperationOptions

use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions in project midpoint by Evolveum.

the class DeleteHelper method executeResourceDelete.

ProvisioningOperationState<AsynchronousOperationResult> executeResourceDelete(ProvisioningContext ctx, PrismObject<ShadowType> shadow, OperationProvisioningScriptsType scripts, ProvisioningOperationOptions options, Task task, OperationResult parentResult) throws SchemaException, GenericFrameworkException, CommunicationException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException {
    ProvisioningOperationState<AsynchronousOperationResult> opState = new ProvisioningOperationState<>();
    opState.setRepoShadow(shadow);
    ConnectorOperationOptions connOptions = commonHelper.createConnectorOperationOptions(ctx, options, parentResult);
    try {
        AsynchronousOperationResult asyncReturnValue = resourceObjectConverter.deleteResourceObject(ctx, shadow, scripts, connOptions, parentResult);
        opState.processAsyncResult(asyncReturnValue);
    } catch (Exception ex) {
        try {
            handleDeleteError(ctx, shadow, options, opState, ex, parentResult.getLastSubresult(), task, parentResult);
        } catch (ObjectAlreadyExistsException e) {
            parentResult.recordFatalError(e);
            throw new SystemException(e.getMessage(), e);
        }
    }
    return opState;
}
Also used : AsynchronousOperationResult(com.evolveum.midpoint.schema.result.AsynchronousOperationResult) ConnectorOperationOptions(com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions) EncryptionException(com.evolveum.midpoint.prism.crypto.EncryptionException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException)

Aggregations

ConnectorOperationOptions (com.evolveum.midpoint.provisioning.ucf.api.ConnectorOperationOptions)6 EncryptionException (com.evolveum.midpoint.prism.crypto.EncryptionException)5 GenericFrameworkException (com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException)5 PrismPropertyValue (com.evolveum.midpoint.prism.PrismPropertyValue)2 PropertyDelta (com.evolveum.midpoint.prism.delta.PropertyDelta)2 AsynchronousOperationResult (com.evolveum.midpoint.schema.result.AsynchronousOperationResult)2 AsynchronousOperationReturnValue (com.evolveum.midpoint.schema.result.AsynchronousOperationReturnValue)2 OperationResultStatus (com.evolveum.midpoint.schema.result.OperationResultStatus)2 ShadowType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType)2 Collection (java.util.Collection)2 PrismObject (com.evolveum.midpoint.prism.PrismObject)1 ResourceOperationDescription (com.evolveum.midpoint.provisioning.api.ResourceOperationDescription)1 ProvisioningContext (com.evolveum.midpoint.provisioning.impl.ProvisioningContext)1 RefreshShadowOperation (com.evolveum.midpoint.schema.RefreshShadowOperation)1 ResourceAttributeContainer (com.evolveum.midpoint.schema.processor.ResourceAttributeContainer)1 ResourceObjectIdentification (com.evolveum.midpoint.schema.processor.ResourceObjectIdentification)1 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)1 PendingOperationType (com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType)1 RunAsCapabilityType (com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.RunAsCapabilityType)1 XMLGregorianCalendar (javax.xml.datatype.XMLGregorianCalendar)1