use of com.vmware.xenon.common.DeferredResult in project photon-model by vmware.
the class EndpointEnumerationProcess method disassociateLocalResourceStates.
/**
* Disassociate stale local resource states. The logic works by recording a timestamp when
* enumeration starts. This timestamp is used to lookup resources which have not been touched as
* part of current enumeration cycle. Resources not associated with any endpointLink will be
* removed by the groomer task.
* <p>
* Here is the list of criteria used to locate the stale local resources states:
* <ul>
* <li>Add local documents' kind:
* {@code qBuilder.addKindFieldClause(context.localStateClass)}</li>
* <li>Add time stamp older than current enumeration cycle:
* {@code qBuilder.addRangeClause(ServiceDocument.FIELD_NAME_UPDATE_TIME_MICROS, createLessThanRange(context.enumStartTimeInMicros))}</li>
* <li>Add {@code tenantLinks} and {@code endpointLink} criteria as defined by
* {@code QueryTemplate}</li>
* <li>Add descendant specific criteria as defined by
* {@link #customizeLocalStatesQuery(com.vmware.xenon.services.common.QueryTask.Query.Builder)}</li>
* </ul>
*/
protected DeferredResult<T> disassociateLocalResourceStates(T context) {
final String msg = "Disassociate %ss that no longer exist in the endpoint: %s";
context.service.logFine(() -> String.format(msg, context.localStateClass.getSimpleName(), "STARTING"));
Query.Builder qBuilder = Query.Builder.create().addKindFieldClause(context.localStateClass).addRangeClause(ServiceDocument.FIELD_NAME_UPDATE_TIME_MICROS, createLessThanRange(context.enumStartTimeInMicros));
if (getEndpointRegion() != null) {
// Limit documents within end-point region
qBuilder.addFieldClause(ResourceState.FIELD_NAME_REGION_ID, getEndpointRegion());
}
if (!this.enumExternalResourcesIds.isEmpty() && this.enumExternalResourcesIds.size() <= MAX_RESOURCES_TO_QUERY_ON_DELETE) {
// do not load resources from enumExternalResourcesIds
qBuilder.addInClause(ResourceState.FIELD_NAME_ID, this.enumExternalResourcesIds, Occurance.MUST_NOT_OCCUR);
}
// Delegate to descendants to any doc specific criteria
customizeLocalStatesQuery(qBuilder);
QueryByPages<LOCAL_STATE> queryLocalStates = new QueryByPages<>(context.service.getHost(), qBuilder.build(), context.localStateClass, isApplyInfraFields() ? context.endpointState.tenantLinks : null, isApplyEndpointLink() ? context.endpointState.documentSelfLink : null, null).setQueryTaskTenantLinks(context.endpointState.tenantLinks);
queryLocalStates.setClusterType(ServiceTypeCluster.INVENTORY_SERVICE);
List<DeferredResult<Operation>> disassociateDRs = new ArrayList<>();
// Delete stale resources.
return queryLocalStates.queryDocuments(localState -> {
if (!shouldDelete(localState)) {
return;
}
// Deleting the localResourceState is done by disassociating the
// endpointLink from the localResourceState. If the localResourceState
// isn't associated with any other endpointLink, it should be eventually
// deleted by the groomer task
Operation disassociateOp = PhotonModelUtils.createRemoveEndpointLinksOperation(context.service, context.endpointState.documentSelfLink, localState);
if (disassociateOp == null) {
return;
}
// NOTE: The original Op is set with completion that must be executed.
// Since sendWithDeferredResult is used we must manually call it, otherwise it's
// just ignored.
CompletionHandler disassociateOpCompletion = disassociateOp.getCompletion();
DeferredResult<Operation> disassociateDR = context.service.sendWithDeferredResult(disassociateOp).whenComplete(disassociateOpCompletion::handle).whenComplete((o, e) -> {
final String message = "Disassociate stale %s state";
if (e != null) {
context.service.logWarning(message + ": FAILED with %s", localState.documentSelfLink, Utils.toString(e));
} else {
context.service.log(Level.FINEST, message + ": SUCCESS", localState.documentSelfLink);
}
});
disassociateDRs.add(disassociateDR);
}).thenCompose(ignore -> DeferredResult.allOf(disassociateDRs)).thenApply(ignore -> context);
}
use of com.vmware.xenon.common.DeferredResult in project photon-model by vmware.
the class VSphereAdapterSnapshotService method performSnapshotOperation.
private DeferredResult<SnapshotContext> performSnapshotOperation(SnapshotContext context) {
DeferredResult<SnapshotContext> result = new DeferredResult<>();
VSphereIOThreadPool pool = VSphereIOThreadPoolAllocator.getPool(this);
DeferredResult<AuthCredentialsService.AuthCredentialsServiceState> credentials;
if (IAAS_API_ENABLED) {
credentials = SessionUtil.retrieveExternalToken(this, context.operation.getAuthorizationContext());
} else {
URI authUri = createInventoryUri(this.getHost(), context.parentComputeDescription.description.authCredentialsLink);
Operation op = Operation.createGet(authUri);
credentials = this.sendWithDeferredResult(op, AuthCredentialsService.AuthCredentialsServiceState.class);
}
switch(context.requestType) {
case CREATE:
BiConsumer<AuthCredentialsService.AuthCredentialsServiceState, Throwable> create = (authCredentialsServiceState, throwable) -> {
if (throwable != null) {
result.fail(throwable);
return;
}
pool.submit(context.parentComputeDescription.adapterManagementReference, authCredentialsServiceState, (connection, e) -> {
if (e != null) {
result.fail(e);
} else {
createSnapshot(connection, context, result);
}
});
};
credentials.whenComplete(create);
break;
case DELETE:
BiConsumer<AuthCredentialsService.AuthCredentialsServiceState, Throwable> delete = (authCredentialsServiceState, throwable) -> {
if (throwable != null) {
result.fail(throwable);
return;
}
pool.submit(context.parentComputeDescription.adapterManagementReference, authCredentialsServiceState, (connection, e) -> {
if (e != null) {
result.fail(e);
} else {
deleteSnapshot(context, connection, result);
}
});
};
credentials.whenComplete(delete);
break;
case REVERT:
BiConsumer<AuthCredentialsService.AuthCredentialsServiceState, Throwable> revert = (authCredentialsServiceState, throwable) -> {
if (throwable != null) {
result.fail(throwable);
return;
}
pool.submit(context.parentComputeDescription.adapterManagementReference, authCredentialsServiceState, (connection, e) -> {
if (e != null) {
result.fail(e);
} else {
revertSnapshot(context, connection, result);
}
});
};
credentials.whenComplete(revert);
break;
default:
result.fail(new IllegalStateException("Unsupported requestType " + context.requestType));
}
return result;
}
use of com.vmware.xenon.common.DeferredResult in project photon-model by vmware.
the class VSphereAdapterSnapshotService method getChildSnapshots.
private DeferredResult<List<SnapshotState>> getChildSnapshots(String snapshotLink) {
DeferredResult<List<SnapshotState>> snapshotStates = new DeferredResult<>();
// find the child snapshots for the given snapshot document link
QueryTask qTask = getQueryWithFilters(snapshotLink, SnapshotState.FIELD_NAME_PARENT_LINK);
QueryUtils.startInventoryQueryTask(this, qTask).whenComplete((o, e) -> {
if (e != null) {
logWarning(String.format("Failure retrieving the child snapshots %s", Utils.toString(e)));
snapshotStates.fail(e);
return;
}
QueryResultsProcessor rp = QueryResultsProcessor.create(o);
List<SnapshotState> snapshotsTemp = new ArrayList<>();
if (rp.hasResults()) {
snapshotsTemp = rp.streamDocuments(SnapshotState.class).collect(Collectors.toList());
}
snapshotStates.complete(snapshotsTemp);
});
return snapshotStates;
}
use of com.vmware.xenon.common.DeferredResult in project photon-model by vmware.
the class VSphereAdapterSnapshotService method createSnapshot.
private void createSnapshot(Connection connection, SnapshotContext context, DeferredResult<SnapshotContext> deferredResult) {
ManagedObjectReference vmMoRef = CustomProperties.of(context.computeDescription).getMoRef(CustomProperties.MOREF);
if (vmMoRef == null) {
deferredResult.fail(new IllegalStateException("Cannot find VM to snapshot"));
return;
}
ManagedObjectReference task;
TaskInfo info;
try {
logInfo("Creating snapshot for compute resource %s", context.computeDescription.name);
task = connection.getVimPort().createSnapshotTask(vmMoRef, context.snapshotState.name, context.snapshotState.description, context.snapshotMemory, false);
info = VimUtils.waitTaskEnd(connection, task);
if (info.getState() != TaskInfoState.SUCCESS) {
VimUtils.rethrow(info.getError());
}
} catch (Exception e) {
deferredResult.fail(e);
return;
}
CustomProperties.of(context.snapshotState).put(CustomProperties.MOREF, (ManagedObjectReference) info.getResult());
// mark this as current snapshot
context.snapshotState.isCurrent = true;
// create a new xenon SnapshotState
logInfo(String.format("Creating a new snapshot state for compute : %s", context.computeDescription.name));
Operation createSnapshotState = Operation.createPost(PhotonModelUriUtils.createInventoryUri(getHost(), SnapshotService.FACTORY_LINK)).setBody(context.snapshotState);
if (context.existingSnapshotState != null) {
// un-mark old snapshot as current snapshot
context.existingSnapshotState.isCurrent = false;
Operation patchOldSnapshot = Operation.createPatch(UriUtils.buildUri(getHost(), context.existingSnapshotState.documentSelfLink)).setBody(context.existingSnapshotState);
OperationSequence.create(createSnapshotState).next(patchOldSnapshot).setCompletion((o, e) -> {
if (e != null && !e.isEmpty()) {
deferredResult.fail(e.values().iterator().next());
}
deferredResult.complete(context);
}).sendWith(this);
} else {
context.computeDescription.customProperties.put(ComputeProperties.CUSTOM_PROP_COMPUTE_HAS_SNAPSHOTS, "true");
// patch compute adding the property '_hasSnapshots' with true
Operation patchCompute = Operation.createPatch(UriUtils.buildUri(getHost(), context.snapshotState.computeLink)).setBody(context.computeDescription);
OperationSequence.create(createSnapshotState).next(patchCompute).setCompletion((o, e) -> {
if (e != null && !e.isEmpty()) {
deferredResult.fail(e.values().iterator().next());
}
logInfo(String.format("Created a new snapshot state for compute : %s", context.computeDescription.name));
deferredResult.complete(context);
}).sendWith(this);
}
}
use of com.vmware.xenon.common.DeferredResult in project photon-model by vmware.
the class VSphereIncrementalEnumerationService method collectAllEndpointResources.
private DeferredResult<Set<String>> collectAllEndpointResources(ComputeEnumerateResourceRequest req, String parentLink) {
QueryTask.Query combinedClause = new QueryTask.Query().setOccurance(Occurance.MUST_OCCUR);
// The next clauses are the boolean clauses that will be added to the
// combinedClause. At the top, all further queries should have SHOULD_OCCUR
QueryTask.Query resourceClause = QueryTask.Query.Builder.create().addFieldClause(ResourceState.FIELD_NAME_ENDPOINT_LINK, req.endpointLink).addFieldClause(ComputeService.ComputeState.FIELD_NAME_LIFECYCLE_STATE, ComputeService.LifecycleState.PROVISIONING.toString(), QueryTask.QueryTerm.MatchType.TERM, QueryTask.Query.Occurance.MUST_NOT_OCCUR).addFieldClause(ServiceDocument.FIELD_NAME_SELF_LINK, parentLink, QueryTask.Query.Occurance.MUST_NOT_OCCUR).addInClause(ServiceDocument.FIELD_NAME_KIND, Arrays.asList(Utils.buildKind(ComputeService.ComputeState.class), Utils.buildKind(NetworkService.NetworkState.class), Utils.buildKind(StorageDescriptionService.StorageDescription.class), Utils.buildKind(SubnetService.SubnetState.class))).build().setOccurance(Occurance.SHOULD_OCCUR);
// The below two queries are added to get the Folders and Datacenters that are enumerated
// They are persisted as ResourceGroupState documents, and there are other documents of the same
// kind (which have a different lifecycle), we're filtering on the "__computeType" property
// Adding these documents here will enable automatic deletion of "untouched" resources in
// the further logic
QueryTask.Query folderClause = QueryTask.Query.Builder.create().addCompositeFieldClause(ResourceState.FIELD_NAME_CUSTOM_PROPERTIES, CustomProperties.TYPE, VimNames.TYPE_FOLDER).addKindFieldClause(ResourceGroupState.class).build().setOccurance(Occurance.SHOULD_OCCUR);
QueryTask.Query datacenterClause = QueryTask.Query.Builder.create().addCompositeFieldClause(ResourceState.FIELD_NAME_CUSTOM_PROPERTIES, CustomProperties.TYPE, VimNames.TYPE_DATACENTER).addKindFieldClause(ResourceGroupState.class).build().setOccurance(Occurance.SHOULD_OCCUR);
// Add all the clauses to the combined clause
// The query structure is now --> MUST(SHOULD A + SHOULD B + SHOULD C)
// where A, B, C are independent queries
combinedClause.addBooleanClause(resourceClause).addBooleanClause(folderClause).addBooleanClause(datacenterClause);
QueryTask task = QueryTask.Builder.createDirectTask().setQuery(combinedClause).setResultLimit(QueryUtils.DEFAULT_RESULT_LIMIT).build();
DeferredResult<Set<String>> res = new DeferredResult<>();
Set<String> links = new ConcurrentSkipListSet<>();
QueryUtils.startInventoryQueryTask(this, task).whenComplete((result, e) -> {
if (e != null) {
res.complete(new HashSet<>());
return;
}
if (result.results.nextPageLink == null) {
res.complete(links);
return;
}
Operation.createGet(PhotonModelUriUtils.createInventoryUri(getHost(), result.results.nextPageLink)).setCompletion(makeCompletion(links, res)).sendWith(this);
});
return res;
}
Aggregations