mirror of
https://github.com/kemko/nomad.git
synced 2026-01-03 08:55:43 +03:00
249 lines
8.1 KiB
Go
249 lines
8.1 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package api
|
|
|
|
import "net/url"
|
|
|
|
// HostVolume represents a Dynamic Host Volume: a volume associated with a
|
|
// specific Nomad client agent but created via API.
|
|
type HostVolume struct {
|
|
// Namespace is the Nomad namespace for the host volume, which constrains
|
|
// which jobs can mount it.
|
|
Namespace string `mapstructure:"namespace" hcl:"namespace"`
|
|
|
|
// ID is a UUID-like string generated by the server.
|
|
ID string `mapstructure:"id" hcl:"id"`
|
|
|
|
// Name is the name that group.volume will use to identify the volume
|
|
// source. Not expected to be unique.
|
|
Name string `mapstructure:"name" hcl:"name"`
|
|
|
|
// PluginID is the name of the host volume plugin on the client that will be
|
|
// used for creating the volume. If omitted, the client will use its default
|
|
// built-in plugin.
|
|
PluginID string `mapstructure:"plugin_id" hcl:"plugin_id"`
|
|
|
|
// NodePool is the node pool of the node where the volume is placed. If the
|
|
// user doesn't provide a node ID, a node will be selected using the
|
|
// NodePool and Constraints. If the user provides both NodePool and NodeID,
|
|
// NodePool will be used to validate the request. If omitted, the server
|
|
// will populate this value in before writing the volume to Raft.
|
|
NodePool string `mapstructure:"node_pool" hcl:"node_pool"`
|
|
|
|
// NodeID is the node where the volume is placed. If the user doesn't
|
|
// provide a NodeID, one will be selected using the NodePool and
|
|
// Constraints. If omitted, this field will then be populated by the server
|
|
// before writing the volume to Raft.
|
|
NodeID string `mapstructure:"node_id" hcl:"node_id"`
|
|
|
|
// Constraints are optional. If the NodeID is not provided, the NodePool and
|
|
// Constraints are used to select a node. If the NodeID is provided,
|
|
// Constraints are used to validate that the node meets those constraints at
|
|
// the time of volume creation.
|
|
Constraints []*Constraint `json:",omitempty" hcl:"constraint"`
|
|
|
|
// Because storage may allow only specific intervals of size, we accept a
|
|
// min and max and return the actual capacity when the volume is created or
|
|
// updated on the client
|
|
RequestedCapacityMinBytes int64 `mapstructure:"capacity_min" hcl:"capacity_min"`
|
|
RequestedCapacityMaxBytes int64 `mapstructure:"capacity_max" hcl:"capacity_max"`
|
|
CapacityBytes int64
|
|
|
|
// RequestedCapabilities defines the options available to group.volume
|
|
// blocks. The scheduler checks against the listed capability blocks and
|
|
// selects a node for placement if *any* capability block works.
|
|
RequestedCapabilities []*HostVolumeCapability `hcl:"capability"`
|
|
|
|
// Parameters are an opaque map of parameters for the host volume plugin.
|
|
Parameters map[string]string `json:",omitempty"`
|
|
|
|
// HostPath is the path on disk where the volume's mount point was
|
|
// created. We record this to make debugging easier.
|
|
HostPath string `mapstructure:"host_path" hcl:"host_path"`
|
|
|
|
// State represents the overall state of the volume. One of pending, ready,
|
|
// deleted.
|
|
State HostVolumeState
|
|
|
|
CreateIndex uint64
|
|
CreateTime int64
|
|
|
|
ModifyIndex uint64
|
|
ModifyTime int64
|
|
|
|
// Allocations is the list of non-client-terminal allocations with claims on
|
|
// this host volume. They are denormalized on read and this field will be
|
|
// never written to Raft
|
|
Allocations []*AllocationListStub `json:",omitempty" mapstructure:"-" hcl:"-"`
|
|
}
|
|
|
|
// HostVolume state reports the current status of the host volume
|
|
type HostVolumeState string
|
|
|
|
const (
|
|
HostVolumeStatePending HostVolumeState = "pending"
|
|
HostVolumeStateReady HostVolumeState = "ready"
|
|
HostVolumeStateDeleted HostVolumeState = "deleted"
|
|
)
|
|
|
|
// HostVolumeCapability is the requested attachment and access mode for a volume
|
|
type HostVolumeCapability struct {
|
|
AttachmentMode HostVolumeAttachmentMode `mapstructure:"attachment_mode" hcl:"attachment_mode"`
|
|
AccessMode HostVolumeAccessMode `mapstructure:"access_mode" hcl:"access_mode"`
|
|
}
|
|
|
|
// HostVolumeAttachmentMode chooses the type of storage API that will be used to
|
|
// interact with the device.
|
|
type HostVolumeAttachmentMode string
|
|
|
|
const (
|
|
HostVolumeAttachmentModeUnknown HostVolumeAttachmentMode = ""
|
|
HostVolumeAttachmentModeBlockDevice HostVolumeAttachmentMode = "block-device"
|
|
HostVolumeAttachmentModeFilesystem HostVolumeAttachmentMode = "file-system"
|
|
)
|
|
|
|
// HostVolumeAccessMode indicates how Nomad should make the volume available to
|
|
// concurrent allocations.
|
|
type HostVolumeAccessMode string
|
|
|
|
const (
|
|
HostVolumeAccessModeUnknown HostVolumeAccessMode = ""
|
|
|
|
HostVolumeAccessModeSingleNodeReader HostVolumeAccessMode = "single-node-reader-only"
|
|
HostVolumeAccessModeSingleNodeWriter HostVolumeAccessMode = "single-node-writer"
|
|
|
|
HostVolumeAccessModeMultiNodeReader HostVolumeAccessMode = "multi-node-reader-only"
|
|
HostVolumeAccessModeMultiNodeSingleWriter HostVolumeAccessMode = "multi-node-single-writer"
|
|
HostVolumeAccessModeMultiNodeMultiWriter HostVolumeAccessMode = "multi-node-multi-writer"
|
|
)
|
|
|
|
// HostVolumeStub is used for responses for the List Volumes endpoint
|
|
type HostVolumeStub struct {
|
|
Namespace string
|
|
ID string
|
|
Name string
|
|
PluginID string
|
|
NodePool string
|
|
NodeID string
|
|
CapacityBytes int64
|
|
State HostVolumeState
|
|
|
|
CreateIndex uint64
|
|
CreateTime int64
|
|
|
|
ModifyIndex uint64
|
|
ModifyTime int64
|
|
}
|
|
|
|
// HostVolumes is used to access the host volumes API.
|
|
type HostVolumes struct {
|
|
client *Client
|
|
}
|
|
|
|
// HostVolumes returns a new handle on the host volumes API.
|
|
func (c *Client) HostVolumes() *HostVolumes {
|
|
return &HostVolumes{client: c}
|
|
}
|
|
|
|
type HostVolumeCreateRequest struct {
|
|
Volume *HostVolume
|
|
|
|
// PolicyOverride overrides Sentinel soft-mandatory policy enforcement
|
|
PolicyOverride bool
|
|
}
|
|
|
|
type HostVolumeRegisterRequest struct {
|
|
Volume *HostVolume
|
|
|
|
// PolicyOverride overrides Sentinel soft-mandatory policy enforcement
|
|
PolicyOverride bool
|
|
}
|
|
|
|
type HostVolumeCreateResponse struct {
|
|
Volume *HostVolume
|
|
Warnings string
|
|
}
|
|
|
|
type HostVolumeRegisterResponse struct {
|
|
Volume *HostVolume
|
|
Warnings string
|
|
}
|
|
|
|
type HostVolumeListRequest struct {
|
|
NodeID string
|
|
NodePool string
|
|
}
|
|
|
|
type HostVolumeDeleteRequest struct {
|
|
ID string
|
|
}
|
|
|
|
// Create forwards to client agents so a host volume can be created on those
|
|
// hosts, and registers the volume with Nomad servers.
|
|
func (hv *HostVolumes) Create(req *HostVolumeCreateRequest, opts *WriteOptions) (*HostVolumeCreateResponse, *WriteMeta, error) {
|
|
var out *HostVolumeCreateResponse
|
|
wm, err := hv.client.put("/v1/volume/host/create", req, &out, opts)
|
|
if err != nil {
|
|
return nil, wm, err
|
|
}
|
|
return out, wm, nil
|
|
}
|
|
|
|
// Register registers a host volume that was created out-of-band with the Nomad
|
|
// servers.
|
|
func (hv *HostVolumes) Register(req *HostVolumeRegisterRequest, opts *WriteOptions) (*HostVolumeRegisterResponse, *WriteMeta, error) {
|
|
var out *HostVolumeRegisterResponse
|
|
wm, err := hv.client.put("/v1/volume/host/register", req, &out, opts)
|
|
if err != nil {
|
|
return nil, wm, err
|
|
}
|
|
return out, wm, nil
|
|
}
|
|
|
|
// Get queries for a single host volume, by ID
|
|
func (hv *HostVolumes) Get(id string, opts *QueryOptions) (*HostVolume, *QueryMeta, error) {
|
|
var out *HostVolume
|
|
path, err := url.JoinPath("/v1/volume/host/", url.PathEscape(id))
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
qm, err := hv.client.query(path, &out, opts)
|
|
if err != nil {
|
|
return nil, qm, err
|
|
}
|
|
return out, qm, nil
|
|
}
|
|
|
|
// List queries for a set of host volumes, by namespace, node, node pool, or
|
|
// name prefix.
|
|
func (hv *HostVolumes) List(req *HostVolumeListRequest, opts *QueryOptions) ([]*HostVolumeStub, *QueryMeta, error) {
|
|
var out []*HostVolumeStub
|
|
qv := url.Values{}
|
|
qv.Set("type", "host")
|
|
if req != nil {
|
|
if req.NodeID != "" {
|
|
qv.Set("node_id", req.NodeID)
|
|
}
|
|
if req.NodePool != "" {
|
|
qv.Set("node_pool", req.NodePool)
|
|
}
|
|
}
|
|
|
|
qm, err := hv.client.query("/v1/volumes?"+qv.Encode(), &out, opts)
|
|
if err != nil {
|
|
return nil, qm, err
|
|
}
|
|
return out, qm, nil
|
|
}
|
|
|
|
// Delete deletes a host volume
|
|
func (hv *HostVolumes) Delete(req *HostVolumeDeleteRequest, opts *WriteOptions) (*WriteMeta, error) {
|
|
path, err := url.JoinPath("/v1/volume/host/", url.PathEscape(req.ID))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
wm, err := hv.client.delete(path, nil, nil, opts)
|
|
return wm, err
|
|
}
|