All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vmware.photon.controller.model.resources.ResourcePoolService Maven / Gradle / Ivy

/*
 * Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.  You may obtain a copy of
 * the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, without warranties or
 * conditions of any kind, EITHER EXPRESS OR IMPLIED.  See the License for the
 * specific language governing permissions and limitations under the License.
 */

package com.vmware.photon.controller.model.resources;

import java.util.EnumSet;

import com.vmware.photon.controller.model.UriPaths;
import com.vmware.photon.controller.model.resources.ComputeService.ComputeState;
import com.vmware.photon.controller.model.resources.ResourcePoolService.ResourcePoolState.ResourcePoolProperty;
import com.vmware.xenon.common.Operation;
import com.vmware.xenon.common.ServiceDocumentDescription.PropertyUsageOption;
import com.vmware.xenon.common.StatefulService;
import com.vmware.xenon.common.Utils;
import com.vmware.xenon.services.common.QueryTask.Query;

/**
 * Describes a resource pool. A resource pool is a grouping of {@link ComputeState}s that can be
 * used as a single unit for planning and allocation purposes.
 *
 * 

{@link ComputeState}s that contribute capacity to this resource pool are found by * executing the {@link ResourcePoolState#query} query. For non-elastic resource pools * the query is auto-generated by using the {@link ComputeState#resourcePoolLink}. For * elastic resource pools the query is provided by the resource pool creator. * *

Thus a resource may participate in at most one non-elastic resource pool and zero or more * elastic resource pools. */ public class ResourcePoolService extends StatefulService { public static final String FACTORY_LINK = UriPaths.RESOURCES + "/pools"; /** * This class represents the document state associated with a * {@link ResourcePoolService} task. */ public static class ResourcePoolState extends ResourceState { public static final String FIELD_NAME_PROPERTIES = "properties"; /** * Enumeration used to define properties of the resource pool. */ public enum ResourcePoolProperty { /** * An elastic resource pool uses a dynamic query to find the participating resources. * The {@link ComputeState#resourcePoolLink} field of the returned resources may not * match this resource pool instance. */ ELASTIC } /** * Project name of this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public String projectName; /** * Properties of this resource pool, if it is elastic, etc. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public EnumSet properties; /** * Minimum number of CPU Cores in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Long minCpuCount; /** * Minimum number of GPU Cores in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Long minGpuCount; /** * Minimum amount of memory (in bytes) in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Long minMemoryBytes; /** * Minimum disk capacity (in bytes) in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Long minDiskCapacityBytes; /** * Maximum number of CPU Cores in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Long maxCpuCount; /** * Maximum number of GPU Cores in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Long maxGpuCount; /** * Maximum amount of memory (in bytes) in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Long maxMemoryBytes; /** * Maximum disk capacity (in bytes) in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Long maxDiskCapacityBytes; /** * Maximum CPU Cost (per minute) in this resource pool. */ @Deprecated public Double maxCpuCostPerMinute; /** * Maximum Disk cost (per minute) in this resource pool. */ @Deprecated public Double maxDiskCostPerMinute; /** * Currency unit used for pricing. */ @Deprecated public String currencyUnit; /** * Query to use to retrieve resources in this resource pool. */ @UsageOption(option = PropertyUsageOption.AUTO_MERGE_IF_NOT_NULL) public Query query; } public ResourcePoolService() { super(ResourcePoolState.class); super.toggleOption(ServiceOption.PERSISTENCE, true); super.toggleOption(ServiceOption.REPLICATION, true); super.toggleOption(ServiceOption.OWNER_SELECTION, true); super.toggleOption(ServiceOption.IDEMPOTENT_POST, true); } @Override public void handleDelete(Operation delete) { logInfo("Deleting ResourcePool, Path: %s, Operation ID: %d, Referrer: %s", delete.getUri().getPath(), delete.getId(), delete.getRefererAsString()); super.handleDelete(delete); } @Override public void handleCreate(Operation createPost) { try { processInput(createPost); createPost.complete(); } catch (Throwable t) { createPost.fail(t); } } @Override public void handlePut(Operation put) { try { ResourcePoolState returnState = processInput(put); setState(put, returnState); put.complete(); } catch (Throwable t) { put.fail(t); } } private ResourcePoolState processInput(Operation op) { if (!op.hasBody()) { throw (new IllegalArgumentException("body is required")); } ResourcePoolState state = op.getBody(ResourcePoolState.class); validateState(state); if (!state.properties.contains(ResourcePoolProperty.ELASTIC)) { state.query = generateResourcePoolQuery(state); } return state; } @Override public void handlePatch(Operation patch) { ResourcePoolState currentState = getState(patch); if (!currentState.properties.contains(ResourcePoolProperty.ELASTIC)) { // clean auto-generated query to catch patches with unexpected query currentState.query = null; } // use standard resource merging with an additional custom handler for the query ResourceUtils.handlePatch(patch, currentState, getStateDescription(), ResourcePoolState.class, op -> { // check state and re-generate the query, if needed validateState(currentState); if (!currentState.properties.contains(ResourcePoolProperty.ELASTIC)) { currentState.query = generateResourcePoolQuery(currentState); } // don't report a state change, it is already reported if resource pool type has // changed return false; }); } public void validateState(ResourcePoolState state) { Utils.validateState(getStateDescription(), state); if (state.name == null) { throw new IllegalArgumentException("Resource pool name is required."); } if (state.properties == null) { state.properties = EnumSet .noneOf(ResourcePoolState.ResourcePoolProperty.class); } if (state.properties.contains(ResourcePoolProperty.ELASTIC)) { if (state.query == null) { throw new IllegalArgumentException("Query is required for elastic resource pools."); } } } /** * Generates a query that finds all computes which resource pool link points to this * resource pool. Applicable to non-elastic pools only. */ private Query generateResourcePoolQuery(ResourcePoolState initState) { Query query = Query.Builder.create() .addKindFieldClause(ComputeState.class) .addFieldClause(ComputeState.FIELD_NAME_RESOURCE_POOL_LINK, getSelfLink()) .build(); return query; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy