@Override protected void handleStartedStagePatch(PlacementCapacityUpdateTaskState state) { switch (state.taskSubStage) { case CREATED: proceedTo(PlacementCapacityUpdateTaskState.SubStage.QUERY_COMPUTES); break; case QUERY_COMPUTES: startComputeQuery(state, null); break; case ACCUMMULATE_COMPUTE_FIGURES: handleComputePage(state); break; case UPDATE_RESOURCE_POOL: updateResourcePool(state); break; case UPDATE_PLACEMENTS: retrieveAndUpdatePlacements(state); break; case COMPLETED: complete(); break; case ERROR: completeWithError(); break; default: break; } }
private void handleComputePage(PlacementCapacityUpdateTaskState state) { sendRequest(Operation .createGet(getHost(), state.nextPageLink) .setCompletion((o, e) -> { if (e != null) { failTask("Error retrieving computes", e); return; } ServiceDocumentQueryResult result = o.getBody(QueryTask.class).results; List<ComputeState> computes = result.documents.values().stream() .map(json -> Utils.fromJson(json, ComputeState.class)) .collect(Collectors.toList()); if (computes.isEmpty()) { proceedTo(PlacementCapacityUpdateTaskState.SubStage.UPDATE_RESOURCE_POOL); } else { queryComputeDescriptions(state, computes, result.nextPageLink); } })); }
private ComputeStats getComputeStats(PlacementCapacityUpdateTaskState state, ComputeState compute, ComputeDescription computeDescription) { if (computeDescription.supportedChildren != null) { if (computeDescription.supportedChildren.contains(ComputeType.DOCKER_CONTAINER.name())) { return getContainerHostStats(compute, computeDescription); } else if (computeDescription.supportedChildren.contains(ComputeType.VM_GUEST.name())) { return getComputeHostStats(compute, computeDescription); } } return null; }
private AggregatedComputeStats accummulateComputeFigures( PlacementCapacityUpdateTaskState state, List<ComputeState> computes, Map<String, ComputeDescription> computeDescriptions) { AggregatedComputeStats aggregatedStats = state.aggregatedStats != null ? state.aggregatedStats : new AggregatedComputeStats(); for (ComputeState compute : computes) { ComputeDescription computeDescription = computeDescriptions.get(compute.descriptionLink); if (computeDescription == null) { logWarning("No description found for compute '%s', skipping it", compute.documentSelfLink); continue; } ComputeStats stats = getComputeStats(state, compute, computeDescription); if (stats == null) { continue; } aggregatedStats.computeCount++; aggregatedStats.totalMemoryBytes += stats.totalMemoryBytes; aggregatedStats.cpuCoreCount += stats.cpuCoreCount; aggregatedStats.totalCpuMhz += stats.cpuCoreCount * stats.cpuMhzPerCore; aggregatedStats.availableMemoryBytes += stats.availableMemoryBytes; aggregatedStats.cpuUsageSumAllCores += stats.cpuCoreCount * stats.cpuUsage; } return aggregatedStats; }
private void startComputeQuery(PlacementCapacityUpdateTaskState state, ResourcePoolState resourcePoolState) { if (resourcePoolState == null) { sendRequest(Operation.createGet(getHost(), state.resourcePoolLink) .setCompletion((o, e) -> { if (e != null) { failTask(String.format("Error retrieving resource pool %s", state.resourcePoolLink), e, !(e instanceof ServiceNotFoundException)); startComputeQuery(state, o.getBody(ResourcePoolState.class)); })); return; sendRequest(Operation .createPost(this, ServiceUriPaths.CORE_QUERY_TASKS) .setBody(queryTask) .setCompletion((o, e) -> { if (e != null) { failTask("Error quering for computes", e); return; logFine("No computes found in resource pool %s", state.resourcePoolLink); proceedTo(PlacementCapacityUpdateTaskState.SubStage.UPDATE_RESOURCE_POOL, s -> { s.aggregatedStats = new AggregatedComputeStats(); }); } else { proceedTo(PlacementCapacityUpdateTaskState.SubStage.ACCUMMULATE_COMPUTE_FIGURES, s -> { s.aggregatedStats = new AggregatedComputeStats(); s.nextPageLink = result.nextPageLink;
- state.aggregatedStats.totalMemoryBytes; if (diff <= 0) { logFine("No placement update needed for resource pool '%s'", state.resourcePoolLink); proceedTo(PlacementCapacityUpdateTaskState.SubStage.COMPLETED); return; q2) -> Double.compare( ((double) q2.priority) / sumOfPrioritiesByGroup.get(getTenantAndGroupIdentifier(q2)), ((double) q1.priority) / sumOfPrioritiesByGroup.get(getTenantAndGroupIdentifier(q1))); .map(p -> Operation.createPut(this, p.documentSelfLink) .setBody(p) .setReferer(getUri())) .collect(Collectors.toList()); OperationJoin.create(placementUpdateOps).setCompletion((ops, exs) -> { if (exs != null) { failTask("Error updating placements", exs.values().iterator().next()); } else { proceedTo(PlacementCapacityUpdateTaskState.SubStage.COMPLETED);
new ServiceDocumentQuery<ComputeDescription>(getHost(), ComputeDescription.class) .query(queryTask, (r) -> { if (r.hasException()) { failTask("Error querying for compute descriptions.", r.getException()); } else if (r.hasResult()) { computeDescriptions.put(r.getDocumentSelfLink(), r.getResult()); } else { AggregatedComputeStats aggregatedStats = accummulateComputeFigures( state, computes, computeDescriptions); proceedTo(PlacementCapacityUpdateTaskState.SubStage.UPDATE_RESOURCE_POOL, s -> { s.aggregatedStats = aggregatedStats; }); } else { proceedTo(state.taskSubStage, s -> { s.aggregatedStats = aggregatedStats; s.nextPageLink = nextPageLink;
private void updateResourcePool(PlacementCapacityUpdateTaskState state) { // calculate average cpu usage per core double totalCpuUsage = 0.0; if (state.aggregatedStats.cpuCoreCount > 0) { totalCpuUsage = state.aggregatedStats.cpuUsageSumAllCores / state.aggregatedStats.cpuCoreCount; } ResourcePoolState rpPatchState = new ResourcePoolState(); rpPatchState.customProperties = new HashMap<>(); rpPatchState.customProperties.put( ContainerHostDataCollectionService.RESOURCE_POOL_CPU_USAGE_CUSTOM_PROP, Double.toString(totalCpuUsage)); rpPatchState.customProperties.put( ContainerHostDataCollectionService.RESOURCE_POOL_AVAILABLE_MEMORY_CUSTOM_PROP, Long.toString(state.aggregatedStats.availableMemoryBytes)); rpPatchState.maxMemoryBytes = state.aggregatedStats.totalMemoryBytes; sendRequest(Operation.createPatch(this, state.resourcePoolLink) .setBody(rpPatchState) .setCompletion((o, e) -> { if (e != null) { failTask(String.format("Unable to update resource pool '%s'", state.resourcePoolLink), e); return; } proceedTo(PlacementCapacityUpdateTaskState.SubStage.UPDATE_PLACEMENTS); })); }
private void retrieveAndUpdatePlacements(PlacementCapacityUpdateTaskState state) { Query query = Query.Builder.create() .addKindFieldClause(GroupResourcePlacementState.class) .addFieldClause(GroupResourcePlacementState.FIELD_NAME_RESOURCE_POOL_LINK, state.resourcePoolLink) .build(); QueryTask queryTask = QueryTask.Builder.createDirectTask() .setQuery(query) .addOption(QueryOption.EXPAND_CONTENT) .build(); List<GroupResourcePlacementState> placements = new ArrayList<>(); new ServiceDocumentQuery<>(getHost(), GroupResourcePlacementState.class).query( queryTask, (r) -> { if (r.hasException()) { failTask(String.format("Error quering placements for resource pool '%s'", state.resourcePoolLink), r.getException()); } else if (r.hasResult()) { placements.add(r.getResult()); } else { updatePlacements(state, placements); } }); }
/** * Triggers the capacity update task for the given resource pool. Makes sure no multiple tasks * are run in parallel for the same resource pool. */ public static void triggerForResourcePool(Service sender, String resourcePoolLink) { PlacementCapacityUpdateTaskState task = new PlacementCapacityUpdateTaskState(); task.resourcePoolLink = resourcePoolLink; task.documentSelfLink = extractRpId(task); Operation.createPost(sender.getHost(), PlacementCapacityUpdateTaskService.FACTORY_LINK) .addPragmaDirective(Operation.PRAGMA_DIRECTIVE_FORCE_INDEX_UPDATE) .setBody(task) .setCompletion((o, e) -> { if (o.getStatusCode() == Operation.STATUS_CODE_NOT_MODIFIED) { sender.getHost().log(Level.FINE, "Capacity update task already running for " + resourcePoolLink); return; } if (e != null) { sender.getHost().log(Level.WARNING, "Failed to start capacity update task for %s: %s", resourcePoolLink, e.getMessage()); return; } sender.getHost().log(Level.INFO, "Started capacity update task for " + resourcePoolLink); }).sendWith(sender); }