allocations

« Previous section Next section »

UCloud Developer Guide / Accounting and Project Management / Accounting / Accounting

Accounting

Tracks resource usage

Rationale

The goal of UCloud's accounting system is to:

  1. Allow or deny access to a provider's service catalog

  2. Track consumption of resources at the workspace level

  3. Generate visualizations and reports which track historical consumption data

Allocations: Granting access to a service catalog

UCloud achieves the first point by having the ability to grant resource allocations. A resource allocation is also known as a WalletAllocation. They grant a workspace the ability to use Products from a specific ProductCategory. Unless otherwise stated, a workspace must always hold an allocation to use a product. If a workspace does not hold an allocation, then the accounting system will deny access to them. An allocation sets several limits on how the workspace can use the products. This includes:

  • An allocation is only valid for the Products belonging to a single category. For example, if a workspace has an allocation for u1-standard then it does not grant access to u1-gpu.

  • An allocation has a start date and an end date. Outside of this period, the allocation is invalid.

  • Each allocation have an associated quota. If a workspace is using more than the quota allows, then the provider should deny access to the Product.


📝NOTE: It is the responsibility of the provider and not UCloud's accounting system to deny access to a resource when the quota is exceeded. UCloud assists in this process by telling providers when a workspace exceeds their quota. But the responsibility lies with the providers, as they usually have more information. UCloud will only check for the existence of a valid allocation before forwarding the request.


Resource allocations are hierarchical in UCloud. In practice, this means that all allocations can have either 0 or 1 parent allocation. Allocations which do not have a parent are root allocations. Only UCloud administrators/provider administrators can create root allocations. Administrators of a workspace can "sub-allocate" their own allocations. This will create a new allocation which has one of their existing allocations as the parent. UCloud allows for over-allocation when creating sub-allocations. UCloud avoids over-spending by making sure that the usage in a sub-tree doesn't exceed the quota specified in the root of the sub-tree. For example, consider the following sub-allocation created by a workspace administrator:

They can even create another which is even larger.

The sub-allocations themselves can continue to create new sub-allocations. These hierarchies can be as complex as they need to be.

In the above example neither "Research 1" or "Research 2" can have a usage above 10GB due to their parent. Similarly, if the combined usage goes above 10GB then UCloud will lock both of the allocations.

Summary

Important concepts:

  • WalletAllocation: Stores a resource allocation which grants a workspace access to a ProductCategory

  • Wallet: Combines multiple allocations, belonging to the same workspace for a specific category. The accounting system spreads out usages evenly across all allocations in a Wallet.

  • Allocations form a hierarchy. Over-allocation is allowed but the combined usage in a single allocation tree must not exceed the quota in the root.

Important calls:

Table of Contents

1. Remote Procedure Calls

2. Data Models

Remote Procedure Calls

browseSubAllocations

Browses the catalog of sub-allocations

This endpoint will find all WalletAllocations which are direct children of one of your accessible WalletAllocations.

browseWallets

Browses the catalog of accessible Wallets

searchSubAllocations

Searches the catalog of sub-allocations

This endpoint will find all WalletAllocations which are direct children of one of your accessible WalletAllocations.

browseProviderAllocations

Browses allocations relevant for a specific provider

This endpoint is only usable by providers. The endpoint will return a stable results.

browseWalletsInternal

Retrieves a list of up-to-date wallets

This endpoint will return a list of Wallets which are related to the active workspace. This is mainly for backend use. For frontend, use the browse call instead for a paginated response

findRelevantProviders

reportDelta

reportTotalUsage

retrieveAllocationsInternal

Retrieves a list of product specific up-to-date allocation from the in-memory DB

This endpoint will return a list of WalletAllocations which are related to the given product available to the user. This is mainly for backend use. For frontend, use the browse call instead for a paginated response

rootAllocate

subAllocate

updateAllocation

Data Models

AccountingFrequency

enum class AccountingFrequency {
    ONCE,
    PERIODIC_MINUTE,
    PERIODIC_HOUR,
    PERIODIC_DAY,
}
Properties


AccountingUnit

data class AccountingUnit(
    val name: String,
    val namePlural: String,
    val floatingPoint: Boolean,
    val displayFrequencySuffix: Boolean,
)
Properties


AccountingUnitConversion

data class AccountingUnitConversion(
    val factor: Double,
    val destinationUnit: AccountingUnit,
)
Properties


ChargeDescription

data class ChargeDescription(
    val description: String,
    val itemized: List<ItemizedCharge>,
)
Properties


ItemizedCharge

data class ItemizedCharge(
    val description: String,
    val usage: Long?,
    val productId: String?,
)
Properties


ProductCategory

data class ProductCategory(
    val name: String,
    val provider: String,
    val productType: ProductType,
    val accountingUnit: AccountingUnit,
    val accountingFrequency: AccountingFrequency,
    val conversionTable: List<AccountingUnitConversion>?,
    val freeToUse: Boolean?,
)
Properties


SubAllocationV2

A parent allocator's view of a WalletAllocation

data class SubAllocationV2(
    val id: String,
    val path: String,
    val startDate: Long,
    val endDate: Long?,
    val productCategory: ProductCategory,
    val workspaceId: String,
    val workspaceTitle: String,
    val workspaceIsProject: Boolean,
    val projectPI: String?,
    val usage: Long,
    val quota: Long,
    val grantedIn: Long?,
)
Properties


UsageReportItem

data class UsageReportItem(
    val owner: WalletOwner,
    val categoryIdV2: ProductCategoryIdV2,
    val usage: Long,
    val description: ChargeDescription,
)
Properties


WalletAllocationV2

data class WalletAllocationV2(
    val id: String,
    val allocationPath: List<String>,
    val localUsage: Long,
    val quota: Long,
    val treeUsage: Long?,
    val startDate: Long,
    val endDate: Long,
    val grantedIn: Long?,
    val deicAllocationId: String?,
    val canAllocate: Boolean?,
    val allowSubAllocationsToAllocate: Boolean?,
)
Properties


WalletV2

data class WalletV2(
    val owner: WalletOwner,
    val paysFor: ProductCategory,
    val allocations: List<WalletAllocationV2>,
)
Properties


AccountingV2.BrowseAllocationsInternal.Request

data class Request(
    val owner: WalletOwner,
    val categoryId: ProductCategoryIdV2,
)
Properties


AccountingV2.BrowseProviderAllocations.Request

The base type for requesting paginated content.

data class Request(
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
    val filterOwnerId: String?,
    val filterOwnerIsProject: Boolean?,
    val filterCategory: String?,
)

Paginated content can be requested with one of the following consistency guarantees, this greatly changes the semantics of the call:

ConsistencyDescription

PREFER

Consistency is preferred but not required. An inconsistent snapshot might be returned.

REQUIRE

Consistency is required. A request will fail if consistency is no longer guaranteed.

The consistency refers to if collecting all the results via the pagination API are consistent. We consider the results to be consistent if it contains a complete view at some point in time. In practice this means that the results must contain all the items, in the correct order and without duplicates.

If you use the PREFER consistency then you may receive in-complete results that might appear out-of-order and can contain duplicate items. UCloud will still attempt to serve a snapshot which appears mostly consistent. This is helpful for user-interfaces which do not strictly depend on consistency but would still prefer something which is mostly consistent.

The results might become inconsistent if the client either takes too long, or a service instance goes down while fetching the results. UCloud attempts to keep each next token alive for at least one minute before invalidating it. This does not mean that a client must collect all results within a minute but rather that they must fetch the next page within a minute of the last page. If this is not feasible and consistency is not required then PREFER should be used.


📝 NOTE: Services are allowed to ignore extra criteria of the request if the next token is supplied. This is needed in order to provide a consistent view of the results. Clients should provide the same criterion as they paginate through the results.


Properties


AccountingV2.BrowseSubAllocations.Request

data class Request(
    val filterType: ProductType?,
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
)
Properties


AccountingV2.BrowseWallets.Request

The base type for requesting paginated content.

data class Request(
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
    val filterType: ProductType?,
)

Paginated content can be requested with one of the following consistency guarantees, this greatly changes the semantics of the call:

ConsistencyDescription

PREFER

Consistency is preferred but not required. An inconsistent snapshot might be returned.

REQUIRE

Consistency is required. A request will fail if consistency is no longer guaranteed.

The consistency refers to if collecting all the results via the pagination API are consistent. We consider the results to be consistent if it contains a complete view at some point in time. In practice this means that the results must contain all the items, in the correct order and without duplicates.

If you use the PREFER consistency then you may receive in-complete results that might appear out-of-order and can contain duplicate items. UCloud will still attempt to serve a snapshot which appears mostly consistent. This is helpful for user-interfaces which do not strictly depend on consistency but would still prefer something which is mostly consistent.

The results might become inconsistent if the client either takes too long, or a service instance goes down while fetching the results. UCloud attempts to keep each next token alive for at least one minute before invalidating it. This does not mean that a client must collect all results within a minute but rather that they must fetch the next page within a minute of the last page. If this is not feasible and consistency is not required then PREFER should be used.


📝 NOTE: Services are allowed to ignore extra criteria of the request if the next token is supplied. This is needed in order to provide a consistent view of the results. Clients should provide the same criterion as they paginate through the results.


Properties


AccountingV2.BrowseWalletsInternal.Request

data class Request(
    val owner: WalletOwner,
)
Properties


AccountingV2.FindRelevantProviders.RequestItem

data class RequestItem(
    val username: String,
    val project: String?,
    val useProject: Boolean,
)
Properties


AccountingV2.RootAllocate.RequestItem

data class RequestItem(
    val owner: WalletOwner,
    val productCategory: ProductCategoryIdV2,
    val quota: Long,
    val start: Long,
    val end: Long,
    val deicAllocationId: String?,
    val forcedSync: Boolean?,
)
Properties


AccountingV2.SearchSubAllocations.Request

data class Request(
    val query: String,
    val filterType: ProductType?,
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
)
Properties


AccountingV2.SubAllocate.RequestItem

data class RequestItem(
    val parentAllocation: String,
    val owner: WalletOwner,
    val quota: Long,
    val start: Long,
    val end: Long?,
    val dry: Boolean?,
    val grantedIn: Long?,
    val deicAllocationId: String?,
)
Properties


AccountingV2.UpdateAllocation.RequestItem

data class RequestItem(
    val allocationId: String,
    val newQuota: Long?,
    val newStart: Long?,
    val newEnd: Long?,
    val reason: String,
)
Properties


AccountingV2.BrowseAllocationsInternal.Response

data class Response(
    val allocations: List<WalletAllocationV2>,
)
Properties


AccountingV2.BrowseProviderAllocations.ResponseItem

data class ResponseItem(
    val id: String,
    val owner: WalletOwner,
    val categoryId: ProductCategory,
    val notBefore: Long,
    val notAfter: Long?,
    val quota: Long,
)
Properties


AccountingV2.BrowseWalletsInternal.Response

data class Response(
    val wallets: List<WalletV2>,
)
Properties


AccountingV2.FindRelevantProviders.Response

data class Response(
    val providers: List<String>,
)
Properties


Last updated