Search in sources :

Example 11 with ProvisioningOperationOptions

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

the class GetHelper method toProvisioningOperationOptions.

private ProvisioningOperationOptions toProvisioningOperationOptions(GetOperationOptions getOpts) {
    if (getOpts == null) {
        return null;
    }
    ProvisioningOperationOptions provisioningOpts = new ProvisioningOperationOptions();
    // for now, we are interested in forceRetry option. In the future, there can be more.
    provisioningOpts.setForceRetry(getOpts.getForceRetry());
    return provisioningOpts;
}
Also used : ProvisioningOperationOptions(com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions)

Example 12 with ProvisioningOperationOptions

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

the class GetHelper method getShadow.

@NotNull
public PrismObject<ShadowType> getShadow(String oid, PrismObject<ShadowType> repoShadow, Collection<ResourceAttribute<?>> identifiersOverride, Collection<SelectorOptions<GetOperationOptions>> options, Task task, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, EncryptionException {
    Validate.notNull(oid, "Object id must not be null.");
    if (repoShadow == null) {
        LOGGER.trace("Start getting object with oid {}; identifiers override = {}", oid, identifiersOverride);
    } else {
        LOGGER.trace("Start getting object '{}'; identifiers override = {}", repoShadow, identifiersOverride);
    }
    GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options);
    // have a fully cached object from the resource.
    if (repoShadow == null) {
        repoShadow = repositoryService.getObject(ShadowType.class, oid, null, parentResult);
        LOGGER.trace("Got repository shadow object:\n{}", repoShadow.debugDumpLazily());
    }
    // Sanity check
    if (!oid.equals(repoShadow.getOid())) {
        parentResult.recordFatalError("Provided OID is not equal to OID of repository shadow");
        throw new IllegalArgumentException("Provided OID is not equal to OID of repository shadow");
    }
    ProvisioningContext ctx;
    try {
        ctx = ctxFactory.createForShadow(repoShadow, task, parentResult);
        ctx.setGetOperationOptions(options);
        ctx.assertDefinition();
    } catch (SchemaException | ConfigurationException | ObjectNotFoundException | CommunicationException | ExpressionEvaluationException e) {
        if (isRaw(rootOptions)) {
            // when using raw (repository option), return the repo shadow as it is. it's better than nothing and in this case we don't even need resource
            // TODO maybe change assertDefinition to consider rawOption?
            parentResult.computeStatusIfUnknown();
            parentResult.muteError();
            shadowCaretaker.updateShadowStateInEmergency(repoShadow);
            return repoShadow;
        }
        throw e;
    }
    if (repoShadow.isImmutable()) {
        repoShadow = shadowCaretaker.applyAttributesDefinitionToImmutable(ctx, repoShadow);
    } else {
        shadowCaretaker.applyAttributesDefinition(ctx, repoShadow);
    }
    ResourceType resource = ctx.getResource();
    XMLGregorianCalendar now = clock.currentTimeXMLGregorianCalendar();
    if (isNoFetch(rootOptions) || isRaw(rootOptions)) {
        return processNoFetchGet(ctx, repoShadow, options, now, task, parentResult);
    }
    if (!ResourceTypeUtil.isReadCapabilityEnabled(resource)) {
        UnsupportedOperationException e = new UnsupportedOperationException("Resource does not support 'read' operation");
        parentResult.recordFatalError(e);
        throw e;
    }
    if (ResourceTypeUtil.isInMaintenance(resource)) {
        try {
            MaintenanceException ex = new MaintenanceException("Resource " + resource + " is in the maintenance");
            PrismObject<ShadowType> handledShadow = handleGetError(ctx, repoShadow, rootOptions, ex, task, parentResult);
            validateShadow(handledShadow, true);
            shadowCaretaker.applyAttributesDefinition(ctx, handledShadow);
            shadowCaretaker.updateShadowState(ctx, handledShadow);
            return handledShadow;
        } catch (GenericFrameworkException | ObjectAlreadyExistsException | PolicyViolationException e) {
            throw new SystemException(e.getMessage(), e);
        }
    }
    if (shouldRefreshOnRead(resource, rootOptions)) {
        LOGGER.trace("Refreshing {} before reading", repoShadow);
        ProvisioningOperationOptions refreshOpts = toProvisioningOperationOptions(rootOptions);
        RefreshShadowOperation refreshShadowOperation = refreshHelper.refreshShadow(repoShadow, refreshOpts, task, parentResult);
        if (refreshShadowOperation != null) {
            repoShadow = refreshShadowOperation.getRefreshedShadow();
        }
        LOGGER.trace("Refreshed repository shadow:\n{}", DebugUtil.debugDumpLazily(repoShadow, 1));
    }
    if (repoShadow == null) {
        // Dead shadow was just removed
        // TODO: is this OK? What about re-appeared objects
        LOGGER.warn("DEAD shadow {} DEAD?", oid);
        ObjectNotFoundException e = new ObjectNotFoundException("Resource object does not exist");
        parentResult.recordFatalError(e);
        throw e;
    }
    ShadowLifecycleStateType shadowState = shadowCaretaker.updateAndReturnShadowState(ctx, repoShadow, now);
    LOGGER.trace("State of shadow {}: {}", repoShadow, shadowState);
    if (canImmediatelyReturnCached(options, repoShadow, shadowState, resource)) {
        LOGGER.trace("Returning cached (repository) version of shadow {}", repoShadow);
        PrismObject<ShadowType> resultShadow = commonHelper.futurizeShadow(ctx, repoShadow, null, options, now);
        shadowCaretaker.applyAttributesDefinition(ctx, resultShadow);
        validateShadow(resultShadow, true);
        return resultShadow;
    }
    PrismObject<ShadowType> resourceObject;
    Collection<? extends ResourceAttribute<?>> identifiers;
    if (identifiersOverride != null) {
        identifiers = identifiersOverride;
    } else {
        Collection<? extends ResourceAttribute<?>> primaryIdentifiers = ShadowUtil.getPrimaryIdentifiers(repoShadow);
        if (primaryIdentifiers == null || primaryIdentifiers.isEmpty()) {
            if (ProvisioningUtil.hasPendingAddOperation(repoShadow) || ShadowUtil.isDead(repoShadow.asObjectable())) {
                if (ProvisioningUtil.isFuturePointInTime(options)) {
                    // Get of uncreated or dead shadow, we want to see future state (how the shadow WILL look like).
                    // We cannot even try fetch operation here. We do not have the identifiers.
                    // But we have quite a good idea how the shadow is going to look like. Therefore we can return it.
                    PrismObject<ShadowType> resultShadow = commonHelper.futurizeShadow(ctx, repoShadow, null, options, now);
                    shadowCaretaker.applyAttributesDefinition(ctx, resultShadow);
                    validateShadow(resultShadow, true);
                    // re-trying the operation here would not provide big benefits and it will complicate the code.
                    return resultShadow;
                } else {
                    // The object might have been created in the meantime.
                    throw new GenericConnectorException("Unable to get object from the resource. Probably it has not been created yet because " + "of previous unavailability of the resource.");
                }
            }
            // No identifiers found
            SchemaException ex = new SchemaException("No primary identifiers found in the repository shadow " + repoShadow + " with respect to " + resource);
            parentResult.recordFatalError("No primary identifiers found in the repository shadow " + repoShadow, ex);
            throw ex;
        }
        identifiers = ShadowUtil.getAllIdentifiers(repoShadow);
    }
    try {
        try {
            resourceObject = resourceObjectConverter.getResourceObject(ctx, identifiers, repoShadow, true, parentResult);
        } catch (ObjectNotFoundException e) {
            // This may be OK, e.g. for connectors that have running async add operation.
            if (shadowState == ShadowLifecycleStateType.CONCEIVED || shadowState == ShadowLifecycleStateType.GESTATING) {
                LOGGER.trace("{} was not found, but we can return cached shadow because it is in {} state", repoShadow, shadowState);
                // we don't want to see 'warning-like' orange boxes in GUI (TODO reconsider this)
                parentResult.deleteLastSubresultIfError();
                parentResult.recordSuccess();
                PrismObject<ShadowType> resultShadow = commonHelper.futurizeShadow(ctx, repoShadow, null, options, now);
                shadowCaretaker.applyAttributesDefinition(ctx, resultShadow);
                LOGGER.trace("Returning futurized shadow:\n{}", DebugUtil.debugDumpLazily(resultShadow));
                validateShadow(resultShadow, true);
                return resultShadow;
            } else {
                LOGGER.trace("{} was not found, following normal error processing because shadow is in {} state", repoShadow, shadowState);
                // be caught later and the usual error handlers will bury the shadow.
                throw e;
            }
        }
        LOGGER.trace("Shadow returned by ResourceObjectConverter:\n{}", resourceObject.debugDumpLazily(1));
        // TODO this looks like a hack. We should not set kind/intent to the resource object...
        // Resource shadow may have different auxiliary object classes than
        // the original repo shadow. Make sure we have the definition that
        // applies to resource shadow. We will fix repo shadow later.
        // BUT we need also information about kind/intent and these information is only
        // in repo shadow, therefore the following 2 lines..
        resourceObject.asObjectable().setKind(repoShadow.asObjectable().getKind());
        resourceObject.asObjectable().setIntent(repoShadow.asObjectable().getIntent());
        ProvisioningContext shadowCtx = ctx.spawnForShadow(resourceObject);
        String operationCtx = "getting " + repoShadow + " was successful.";
        resourceManager.modifyResourceAvailabilityStatus(resource.getOid(), AvailabilityStatusType.UP, operationCtx, task, parentResult, false);
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Shadow from repository:\n{}", repoShadow.debugDump(1));
            LOGGER.trace("Resource object fetched from resource:\n{}", resourceObject.debugDump(1));
        }
        repoShadow = shadowManager.updateShadow(shadowCtx, resourceObject, null, repoShadow, shadowState, parentResult);
        LOGGER.trace("Repository shadow after update:\n{}", repoShadow.debugDumpLazily(1));
        // Complete the shadow by adding attributes from the resource object
        // This also completes the associations by adding shadowRefs
        PrismObject<ShadowType> shadowedObject = shadowedObjectConstructionHelper.constructShadowedObject(shadowCtx, repoShadow, resourceObject, parentResult);
        LOGGER.trace("Shadowed resource object:\n{}", shadowedObject.debugDumpLazily(1));
        PrismObject<ShadowType> resultShadow = commonHelper.futurizeShadow(ctx, repoShadow, shadowedObject, options, now);
        LOGGER.trace("Futurized shadowed resource:\n{}", resultShadow.debugDumpLazily(1));
        parentResult.recordSuccess();
        validateShadow(resultShadow, true);
        return resultShadow;
    } catch (Exception ex) {
        try {
            PrismObject<ShadowType> handledShadow = handleGetError(ctx, repoShadow, rootOptions, ex, task, parentResult);
            if (handledShadow == null) {
                throw ex;
            }
            if (parentResult.getStatus() == OperationResultStatus.FATAL_ERROR) {
                // We are going to return an object. Therefore this cannot
                // be fatal error, as at least some information
                // is returned
                parentResult.setStatus(OperationResultStatus.PARTIAL_ERROR);
            }
            // We update the shadow lifecycle state because we are not sure if the handledShadow is the same
            // as repoShadow (that has its state set).
            // must be called before futurizeShadow
            shadowCaretaker.updateShadowState(ctx, handledShadow);
            PrismObject<ShadowType> futurizedShadow = commonHelper.futurizeShadow(ctx, handledShadow, null, options, now);
            validateShadow(futurizedShadow, true);
            return futurizedShadow;
        } catch (GenericFrameworkException | ObjectAlreadyExistsException | PolicyViolationException e) {
            throw new SystemException(e.getMessage(), e);
        }
    } finally {
        // We need to record the fetch down here. Now it is certain that we
        // are going to fetch from resource (we do not have raw/noFetch option)
        InternalMonitor.recordCount(InternalCounters.SHADOW_FETCH_OPERATION_COUNT);
    }
}
Also used : PrismObject(com.evolveum.midpoint.prism.PrismObject) GetOperationOptions(com.evolveum.midpoint.schema.GetOperationOptions) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) ProvisioningOperationOptions(com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions) EncryptionException(com.evolveum.midpoint.prism.crypto.EncryptionException) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) NotNull(org.jetbrains.annotations.NotNull)

Example 13 with ProvisioningOperationOptions

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

the class ChangeExecutor method executeModification.

private <T extends ObjectType, F extends ObjectType> void executeModification(ObjectDelta<T> change, LensContext<F> context, LensElementContext<T> objectContext, ModelExecuteOptions options, ResourceType resource, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
    Class<T> objectTypeClass = change.getObjectTypeClass();
    PrismObject<T> objectNew = objectContext.getObjectNew();
    OwnerResolver ownerResolver = createOwnerResolver(context, task, result);
    try {
        securityEnforcer.authorize(ModelAuthorizationAction.MODIFY.getUrl(), AuthorizationPhaseType.EXECUTION, objectNew, change, null, ownerResolver, result);
        metadataManager.applyMetadataModify(change, objectContext, objectTypeClass, clock.currentTimeXMLGregorianCalendar(), task, context, result);
        if (change.isEmpty()) {
            // Nothing to do
            return;
        }
        if (TaskType.class.isAssignableFrom(objectTypeClass)) {
            taskManager.modifyTask(change.getOid(), change.getModifications(), result);
        } else if (NodeType.class.isAssignableFrom(objectTypeClass)) {
            throw new UnsupportedOperationException("NodeType is not modifiable using model interface");
        } else if (ObjectTypes.isClassManagedByProvisioning(objectTypeClass)) {
            ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options);
            String oid = modifyProvisioningObject(objectTypeClass, change.getOid(), change.getModifications(), context, objectContext, provisioningOptions, resource, task, result);
            if (!oid.equals(change.getOid())) {
                change.setOid(oid);
            }
        } else {
            FocusConstraintsChecker.clearCacheForDelta(change.getModifications());
            cacheRepositoryService.modifyObject(objectTypeClass, change.getOid(), change.getModifications(), result);
        }
        task.recordObjectActionExecuted(objectNew, objectTypeClass, change.getOid(), ChangeType.MODIFY, context.getChannel(), null);
    } catch (Throwable t) {
        task.recordObjectActionExecuted(objectNew, objectTypeClass, change.getOid(), ChangeType.MODIFY, context.getChannel(), t);
        throw t;
    }
}
Also used : OwnerResolver(com.evolveum.midpoint.security.api.OwnerResolver) ProvisioningOperationOptions(com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions)

Example 14 with ProvisioningOperationOptions

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

the class ChangeExecutor method updateSituationInShadow.

private <F extends ObjectType> void updateSituationInShadow(Task task, SynchronizationSituationType situation, LensFocusContext<F> focusContext, LensProjectionContext projectionCtx, OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
    String projectionOid = projectionCtx.getOid();
    OperationResult result = new OperationResult(OPERATION_UPDATE_SITUATION_ACCOUNT);
    result.addParam("situation", situation);
    result.addParam("accountRef", projectionOid);
    PrismObject<ShadowType> account = null;
    GetOperationOptions getOptions = GetOperationOptions.createNoFetch();
    getOptions.setAllowNotFound(true);
    try {
        account = provisioning.getObject(ShadowType.class, projectionOid, SelectorOptions.createCollection(getOptions), task, result);
    } catch (Exception ex) {
        LOGGER.trace("Problem with getting account, skipping modifying situation in account.");
        return;
    }
    List<PropertyDelta<?>> syncSituationDeltas = SynchronizationUtils.createSynchronizationSituationAndDescriptionDelta(account, situation, task.getChannel(), projectionCtx.hasFullShadow());
    try {
        Utils.setRequestee(task, focusContext);
        ProvisioningOperationOptions options = ProvisioningOperationOptions.createCompletePostponed(false);
        options.setDoNotDiscovery(true);
        String changedOid = provisioning.modifyObject(ShadowType.class, projectionOid, syncSituationDeltas, null, options, task, result);
        // modifyProvisioningObject(AccountShadowType.class, accountRef,
        // syncSituationDeltas,
        // ProvisioningOperationOptions.createCompletePostponed(false),
        // task, result);
        projectionCtx.setSynchronizationSituationResolved(situation);
        LOGGER.trace("Situation in projection {} was updated to {}.", projectionCtx, situation);
    } catch (ObjectNotFoundException ex) {
        // if the object not found exception is thrown, it's ok..probably
        // the account was deleted by previous execution of changes..just
        // log in the trace the message for the user..
        LOGGER.trace("Situation in account could not be updated. Account not found on the resource. Skipping modifying situation in account");
        return;
    } catch (Exception ex) {
        throw new SystemException(ex.getMessage(), ex);
    } finally {
        Utils.clearRequestee(task);
    }
    // if everything is OK, add result of the situation modification to the
    // parent result
    result.recordSuccess();
    parentResult.addSubresult(result);
}
Also used : GetOperationOptions(com.evolveum.midpoint.schema.GetOperationOptions) ProvisioningOperationOptions(com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) EncryptionException(com.evolveum.midpoint.prism.crypto.EncryptionException)

Example 15 with ProvisioningOperationOptions

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

the class OperationCompletionActivityRun method processItem.

@Override
public boolean processItem(@NotNull ShadowType object, @NotNull ItemProcessingRequest<ShadowType> request, RunningTask workerTask, OperationResult result) throws CommonException {
    RepositoryCache.enterLocalCaches(getModelBeans().cacheConfigurationManager);
    try {
        ProvisioningOperationOptions options = ProvisioningOperationOptions.createForceRetry(Boolean.TRUE);
        ModelImplUtils.clearRequestee(workerTask);
        getModelBeans().provisioningService.refreshShadow(object.asPrismObject(), options, workerTask, result);
        return true;
    } finally {
        RepositoryCache.exitLocalCaches();
    }
}
Also used : ProvisioningOperationOptions(com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions)

Aggregations

ProvisioningOperationOptions (com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions)18 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)5 PrismObject (com.evolveum.midpoint.prism.PrismObject)3 ItemDelta (com.evolveum.midpoint.prism.delta.ItemDelta)3 OwnerResolver (com.evolveum.midpoint.security.api.OwnerResolver)3 EncryptionException (com.evolveum.midpoint.prism.crypto.EncryptionException)2 PropertyDelta (com.evolveum.midpoint.prism.delta.PropertyDelta)2 GetOperationOptions (com.evolveum.midpoint.schema.GetOperationOptions)2 SelectorOptions (com.evolveum.midpoint.schema.SelectorOptions)2 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)2 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)2 XMLGregorianCalendar (javax.xml.datatype.XMLGregorianCalendar)2 ModelExecuteOptions (com.evolveum.midpoint.model.api.ModelExecuteOptions)1 ObjectDelta (com.evolveum.midpoint.prism.delta.ObjectDelta)1 ObjectQuery (com.evolveum.midpoint.prism.query.ObjectQuery)1 GenericConnectorException (com.evolveum.midpoint.provisioning.api.GenericConnectorException)1 ResourceObjectShadowChangeDescription (com.evolveum.midpoint.provisioning.api.ResourceObjectShadowChangeDescription)1 ResourceOperationDescription (com.evolveum.midpoint.provisioning.api.ResourceOperationDescription)1 GenericFrameworkException (com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException)1 RepoAddOptions (com.evolveum.midpoint.repo.api.RepoAddOptions)1