mirror of
https://github.com/kemko/nomad.git
synced 2026-01-02 00:15:43 +03:00
Allow users to configure a host volumes quota in MB. This will be enforced at the time of provisioning via create/register RPCs. This changeset is the CE version of ENT/2114. Ref: https://github.com/hashicorp/nomad-enterprise/pull/2114 Ref: https://hashicorp.atlassian.net/browse/NET-11549
221 lines
6.3 KiB
Go
221 lines
6.3 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
)
|
|
|
|
// Quotas is used to query the quotas endpoints.
|
|
type Quotas struct {
|
|
client *Client
|
|
}
|
|
|
|
// Quotas returns a new handle on the quotas.
|
|
func (c *Client) Quotas() *Quotas {
|
|
return &Quotas{client: c}
|
|
}
|
|
|
|
// List is used to dump all of the quota specs
|
|
func (q *Quotas) List(qo *QueryOptions) ([]*QuotaSpec, *QueryMeta, error) {
|
|
var resp []*QuotaSpec
|
|
qm, err := q.client.query("/v1/quotas", &resp, qo)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
sort.Sort(QuotaSpecIndexSort(resp))
|
|
return resp, qm, nil
|
|
}
|
|
|
|
// PrefixList is used to do a PrefixList search over quota specs
|
|
func (q *Quotas) PrefixList(prefix string, qo *QueryOptions) ([]*QuotaSpec, *QueryMeta, error) {
|
|
if qo == nil {
|
|
qo = &QueryOptions{Prefix: prefix}
|
|
} else {
|
|
qo.Prefix = prefix
|
|
}
|
|
|
|
return q.List(qo)
|
|
}
|
|
|
|
// ListUsage is used to dump all of the quota usages
|
|
func (q *Quotas) ListUsage(qo *QueryOptions) ([]*QuotaUsage, *QueryMeta, error) {
|
|
var resp []*QuotaUsage
|
|
qm, err := q.client.query("/v1/quota-usages", &resp, qo)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
sort.Sort(QuotaUsageIndexSort(resp))
|
|
return resp, qm, nil
|
|
}
|
|
|
|
// PrefixList is used to do a PrefixList search over quota usages
|
|
func (q *Quotas) PrefixListUsage(prefix string, qo *QueryOptions) ([]*QuotaUsage, *QueryMeta, error) {
|
|
if qo == nil {
|
|
qo = &QueryOptions{Prefix: prefix}
|
|
} else {
|
|
qo.Prefix = prefix
|
|
}
|
|
|
|
return q.ListUsage(qo)
|
|
}
|
|
|
|
// Info is used to query a single quota spec by its name.
|
|
func (q *Quotas) Info(name string, qo *QueryOptions) (*QuotaSpec, *QueryMeta, error) {
|
|
var resp QuotaSpec
|
|
qm, err := q.client.query("/v1/quota/"+name, &resp, qo)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return &resp, qm, nil
|
|
}
|
|
|
|
// Usage is used to query a single quota usage by its name.
|
|
func (q *Quotas) Usage(name string, qo *QueryOptions) (*QuotaUsage, *QueryMeta, error) {
|
|
var resp QuotaUsage
|
|
qm, err := q.client.query("/v1/quota/usage/"+name, &resp, qo)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return &resp, qm, nil
|
|
}
|
|
|
|
// Register is used to register a quota spec.
|
|
func (q *Quotas) Register(spec *QuotaSpec, qo *WriteOptions) (*WriteMeta, error) {
|
|
wm, err := q.client.put("/v1/quota", spec, nil, qo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return wm, nil
|
|
}
|
|
|
|
// Delete is used to delete a quota spec
|
|
func (q *Quotas) Delete(quota string, qo *WriteOptions) (*WriteMeta, error) {
|
|
wm, err := q.client.delete(fmt.Sprintf("/v1/quota/%s", quota), nil, nil, qo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return wm, nil
|
|
}
|
|
|
|
// QuotaSpec specifies the allowed resource usage across regions.
|
|
type QuotaSpec struct {
|
|
// Name is the name for the quota object
|
|
Name string
|
|
|
|
// Description is an optional description for the quota object
|
|
Description string
|
|
|
|
// Limits is the set of quota limits encapsulated by this quota object. Each
|
|
// limit applies quota in a particular region and in the future over a
|
|
// particular priority range and datacenter set.
|
|
Limits []*QuotaLimit
|
|
|
|
// Raft indexes to track creation and modification
|
|
CreateIndex uint64
|
|
ModifyIndex uint64
|
|
}
|
|
|
|
// QuotaLimit describes the resource limit in a particular region.
|
|
type QuotaLimit struct {
|
|
// Region is the region in which this limit has affect
|
|
Region string
|
|
|
|
// RegionLimit is the quota limit that applies to any allocation within a
|
|
// referencing namespace in the region. A value of zero is treated as
|
|
// unlimited and a negative value is treated as fully disallowed. This is
|
|
// useful for once we support GPUs
|
|
RegionLimit *QuotaResources
|
|
|
|
// VariablesLimit is the maximum total size of all variables
|
|
// Variable.EncryptedData. A value of zero is treated as unlimited and a
|
|
// negative value is treated as fully disallowed.
|
|
//
|
|
// DEPRECATED: use RegionLimit.Storage.VariablesMB instead. This field will
|
|
// be removed in Nomad 1.12.0.
|
|
VariablesLimit *int `mapstructure:"variables_limit" hcl:"variables_limit,optional"`
|
|
|
|
// Hash is the hash of the object and is used to make replication efficient.
|
|
Hash []byte
|
|
}
|
|
|
|
type QuotaResources struct {
|
|
CPU *int `hcl:"cpu,optional"`
|
|
Cores *int `hcl:"cores,optional"`
|
|
MemoryMB *int `mapstructure:"memory" hcl:"memory,optional"`
|
|
MemoryMaxMB *int `mapstructure:"memory_max" hcl:"memory_max,optional"`
|
|
Devices []*RequestedDevice `hcl:"device,block"`
|
|
NUMA *NUMAResource `hcl:"numa,block"`
|
|
SecretsMB *int `mapstructure:"secrets" hcl:"secrets,optional"`
|
|
Storage *QuotaStorageResources `mapstructure:"storage" hcl:"storage,block"`
|
|
}
|
|
|
|
type QuotaStorageResources struct {
|
|
// VariablesMB is the maximum total size of all variables
|
|
// Variable.EncryptedData, in megabytes (2^20 bytes). A value of zero is
|
|
// treated as unlimited and a negative value is treated as fully disallowed.
|
|
VariablesMB int `hcl:"variables"`
|
|
|
|
// HostVolumesMB is the maximum provisioned size of all dynamic host
|
|
// volumes, in megabytes (2^20 bytes). A value of zero is treated as
|
|
// unlimited and a negative value is treated as fully disallowed.
|
|
HostVolumesMB int `hcl:"host_volumes"`
|
|
}
|
|
|
|
// QuotaUsage is the resource usage of a Quota
|
|
type QuotaUsage struct {
|
|
Name string
|
|
Used map[string]*QuotaLimit
|
|
CreateIndex uint64
|
|
ModifyIndex uint64
|
|
}
|
|
|
|
// QuotaSpecIndexSort is a wrapper to sort QuotaSpecs by CreateIndex. We
|
|
// reverse the test so that we get the highest index first.
|
|
type QuotaSpecIndexSort []*QuotaSpec
|
|
|
|
func (q QuotaSpecIndexSort) Len() int {
|
|
return len(q)
|
|
}
|
|
|
|
func (q QuotaSpecIndexSort) Less(i, j int) bool {
|
|
return q[i].CreateIndex > q[j].CreateIndex
|
|
}
|
|
|
|
func (q QuotaSpecIndexSort) Swap(i, j int) {
|
|
q[i], q[j] = q[j], q[i]
|
|
}
|
|
|
|
// QuotaUsageIndexSort is a wrapper to sort QuotaUsages by CreateIndex. We
|
|
// reverse the test so that we get the highest index first.
|
|
type QuotaUsageIndexSort []*QuotaUsage
|
|
|
|
func (q QuotaUsageIndexSort) Len() int {
|
|
return len(q)
|
|
}
|
|
|
|
func (q QuotaUsageIndexSort) Less(i, j int) bool {
|
|
return q[i].CreateIndex > q[j].CreateIndex
|
|
}
|
|
|
|
func (q QuotaUsageIndexSort) Swap(i, j int) {
|
|
q[i], q[j] = q[j], q[i]
|
|
}
|
|
|
|
// QuotaLimitSort is a wrapper to sort QuotaLimits
|
|
type QuotaLimitSort []*QuotaLimit
|
|
|
|
func (q QuotaLimitSort) Len() int {
|
|
return len(q)
|
|
}
|
|
|
|
func (q QuotaLimitSort) Less(i, j int) bool {
|
|
return q[i].Region < q[j].Region
|
|
}
|
|
|
|
func (q QuotaLimitSort) Swap(i, j int) {
|
|
q[i], q[j] = q[j], q[i]
|
|
}
|