use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class AsyncProvisioningConnectorInstance method deleteObject.
@Override
public AsynchronousOperationResult deleteObject(ResourceObjectDefinition objectDefinition, PrismObject<ShadowType> shadow, Collection<? extends ResourceAttribute<?>> identifiers, UcfExecutionContext ctx, OperationResult parentResult) throws SchemaException {
InternalMonitor.recordConnectorOperation("deleteObject");
OperationResult result = parentResult.createSubresult(OP_DELETE_OBJECT);
try {
OperationRequested operation = new OperationRequested.Delete(objectDefinition, asObjectable(shadow), identifiers, getPrismContext());
return createAndSendRequest(operation, ctx.getTask(), result);
} catch (Throwable t) {
result.recordFatalError(t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}
use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class PropagateHelper method propagateOperations.
public void propagateOperations(PrismObject<ResourceType> resource, PrismObject<ShadowType> shadow, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, GenericFrameworkException, ObjectAlreadyExistsException, SecurityViolationException, PolicyViolationException, EncryptionException {
ResourceConsistencyType resourceConsistencyType = resource.asObjectable().getConsistency();
if (resourceConsistencyType == null) {
LOGGER.warn("Skipping propagation of {} because no there is no consistency definition in resource", shadow);
return;
}
Duration operationGroupingInterval = resourceConsistencyType.getOperationGroupingInterval();
if (operationGroupingInterval == null) {
LOGGER.warn("Skipping propagation of {} because no there is no operationGroupingInterval defined in resource", shadow);
return;
}
XMLGregorianCalendar now = clock.currentTimeXMLGregorianCalendar();
List<PendingOperationType> pendingExecutionOperations = new ArrayList<>();
boolean triggered = false;
for (PendingOperationType pendingOperation : shadow.asObjectable().getPendingOperation()) {
PendingOperationExecutionStatusType executionStatus = pendingOperation.getExecutionStatus();
if (executionStatus == PendingOperationExecutionStatusType.EXECUTION_PENDING) {
pendingExecutionOperations.add(pendingOperation);
if (isPropagationTriggered(pendingOperation, operationGroupingInterval, now)) {
triggered = true;
}
}
}
if (!triggered) {
LOGGER.debug("Skipping propagation of {} because no pending operation triggered propagation", shadow);
return;
}
if (pendingExecutionOperations.isEmpty()) {
LOGGER.debug("Skipping propagation of {} because there are no pending executions", shadow);
return;
}
LOGGER.debug("Propagating {} pending operations in {} ", pendingExecutionOperations.size(), shadow);
ObjectDelta<ShadowType> operationDelta = null;
List<PendingOperationType> sortedOperations = shadowCaretaker.sortPendingOperations(pendingExecutionOperations);
for (PendingOperationType pendingOperation : sortedOperations) {
ObjectDeltaType pendingDeltaType = pendingOperation.getDelta();
ObjectDelta<ShadowType> pendingDelta = DeltaConvertor.createObjectDelta(pendingDeltaType, prismContext);
definitionsHelper.applyDefinition(pendingDelta, shadow.asObjectable(), task, result);
if (operationDelta == null) {
operationDelta = pendingDelta;
} else {
operationDelta.merge(pendingDelta);
}
}
// there is at least one pending operation
assert operationDelta != null;
ProvisioningContext ctx = ctxFactory.createForShadow(shadow, task, result);
ctx.setPropagation(true);
shadowCaretaker.applyAttributesDefinition(ctx, shadow);
shadowCaretaker.applyAttributesDefinition(ctx, operationDelta);
LOGGER.trace("Merged operation for {}:\n{} ", shadow, operationDelta.debugDumpLazily(1));
if (operationDelta.isAdd()) {
PrismObject<ShadowType> shadowToAdd = operationDelta.getObjectToAdd();
ProvisioningOperationState<AsynchronousOperationReturnValue<PrismObject<ShadowType>>> opState = ProvisioningOperationState.fromPendingOperations(shadow, sortedOperations);
shadowToAdd.setOid(shadow.getOid());
addHelper.addShadowAttempt(ctx, shadowToAdd, null, opState, null, task, result);
opState.determineExecutionStatusFromResult();
shadowManager.updatePendingOperations(ctx, shadow, opState, pendingExecutionOperations, now, result);
addHelper.notifyAfterAdd(ctx, opState.getAsyncResult().getReturnValue(), opState, task, result);
} else if (operationDelta.isModify()) {
Collection<? extends ItemDelta<?, ?>> modifications = operationDelta.getModifications();
ProvisioningOperationState<AsynchronousOperationReturnValue<Collection<PropertyDelta<PrismPropertyValue>>>> opState = modifyHelper.executeResourceModify(ctx, shadow, modifications, null, null, now, task, result);
opState.determineExecutionStatusFromResult();
shadowManager.updatePendingOperations(ctx, shadow, opState, pendingExecutionOperations, now, result);
modifyHelper.notifyAfterModify(ctx, shadow, modifications, opState, task, result);
} else if (operationDelta.isDelete()) {
ProvisioningOperationState<AsynchronousOperationResult> opState = deleteHelper.executeResourceDelete(ctx, shadow, null, null, task, result);
opState.determineExecutionStatusFromResult();
shadowManager.updatePendingOperations(ctx, shadow, opState, pendingExecutionOperations, now, result);
deleteHelper.notifyAfterDelete(ctx, shadow, opState, task, result);
} else {
throw new IllegalStateException("Delta from outer space: " + operationDelta);
}
// do we need to modify exists/dead flags?
}
use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult 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.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class RefreshHelper method retryOperation.
private void retryOperation(ProvisioningContext ctx, ObjectDelta<ShadowType> pendingDelta, ProvisioningOperationState<? extends AsynchronousOperationResult> opState, Task task, OperationResult result) throws CommunicationException, GenericFrameworkException, ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, EncryptionException {
ProvisioningOperationOptions options = ProvisioningOperationOptions.createForceRetry(false);
// TODO
OperationProvisioningScriptsType scripts = null;
if (pendingDelta.isAdd()) {
PrismObject<ShadowType> resourceObjectToAdd = pendingDelta.getObjectToAdd();
addHelper.addShadowAttempt(ctx, resourceObjectToAdd, scripts, (ProvisioningOperationState<AsynchronousOperationReturnValue<PrismObject<ShadowType>>>) opState, options, task, result);
}
if (pendingDelta.isModify()) {
if (opState.objectExists()) {
modifyHelper.modifyShadowAttempt(ctx, pendingDelta.getModifications(), scripts, options, (ProvisioningOperationState<AsynchronousOperationReturnValue<Collection<PropertyDelta<PrismPropertyValue>>>>) opState, true, task, result);
} else {
result.recordFatalError("Object does not exist on the resource yet, modification attempt was skipped");
}
}
if (pendingDelta.isDelete()) {
if (opState.objectExists()) {
deleteHelper.deleteShadowAttempt(ctx, options, scripts, (ProvisioningOperationState<AsynchronousOperationResult>) opState, task, result);
} else {
result.recordFatalError("Object does not exist on the resource yet, deletion attempt was skipped");
}
}
}
use of com.evolveum.midpoint.schema.result.AsynchronousOperationResult in project midpoint by Evolveum.
the class ErrorHandler method postponeDelete.
protected OperationResultStatus postponeDelete(ProvisioningContext ctx, PrismObject<ShadowType> repoShadow, ProvisioningOperationState<AsynchronousOperationResult> opState, OperationResult failedOperationResult, OperationResult result) {
LOGGER.trace("Postponing DELETE operation for {}", repoShadow);
opState.setExecutionStatus(PendingOperationExecutionStatusType.EXECUTING);
AsynchronousOperationResult asyncResult = new AsynchronousOperationResult();
asyncResult.setOperationResult(failedOperationResult);
asyncResult.setOperationType(PendingOperationTypeType.RETRY);
opState.setAsyncResult(asyncResult);
if (opState.getAttemptNumber() == null) {
opState.setAttemptNumber(1);
}
result.setInProgress();
return OperationResultStatus.IN_PROGRESS;
}
Aggregations