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();
}
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;
}
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();
}
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;
}
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;
}
Aggregations