421 lines
16 KiB
Go
421 lines
16 KiB
Go
![]() |
package volume
|
||
|
|
||
|
import (
|
||
|
"github.com/docker/docker/api/types/swarm"
|
||
|
)
|
||
|
|
||
|
// ClusterVolume contains options and information specific to, and only present
|
||
|
// on, Swarm CSI cluster volumes.
|
||
|
type ClusterVolume struct {
|
||
|
// ID is the Swarm ID of the volume. Because cluster volumes are Swarm
|
||
|
// objects, they have an ID, unlike non-cluster volumes, which only have a
|
||
|
// Name. This ID can be used to refer to the cluster volume.
|
||
|
ID string
|
||
|
|
||
|
// Meta is the swarm metadata about this volume.
|
||
|
swarm.Meta
|
||
|
|
||
|
// Spec is the cluster-specific options from which this volume is derived.
|
||
|
Spec ClusterVolumeSpec
|
||
|
|
||
|
// PublishStatus contains the status of the volume as it pertains to its
|
||
|
// publishing on Nodes.
|
||
|
PublishStatus []*PublishStatus `json:",omitempty"`
|
||
|
|
||
|
// Info is information about the global status of the volume.
|
||
|
Info *Info `json:",omitempty"`
|
||
|
}
|
||
|
|
||
|
// ClusterVolumeSpec contains the spec used to create this volume.
|
||
|
type ClusterVolumeSpec struct {
|
||
|
// Group defines the volume group of this volume. Volumes belonging to the
|
||
|
// same group can be referred to by group name when creating Services.
|
||
|
// Referring to a volume by group instructs swarm to treat volumes in that
|
||
|
// group interchangeably for the purpose of scheduling. Volumes with an
|
||
|
// empty string for a group technically all belong to the same, emptystring
|
||
|
// group.
|
||
|
Group string `json:",omitempty"`
|
||
|
|
||
|
// AccessMode defines how the volume is used by tasks.
|
||
|
AccessMode *AccessMode `json:",omitempty"`
|
||
|
|
||
|
// AccessibilityRequirements specifies where in the cluster a volume must
|
||
|
// be accessible from.
|
||
|
//
|
||
|
// This field must be empty if the plugin does not support
|
||
|
// VOLUME_ACCESSIBILITY_CONSTRAINTS capabilities. If it is present but the
|
||
|
// plugin does not support it, volume will not be created.
|
||
|
//
|
||
|
// If AccessibilityRequirements is empty, but the plugin does support
|
||
|
// VOLUME_ACCESSIBILITY_CONSTRAINTS, then Swarmkit will assume the entire
|
||
|
// cluster is a valid target for the volume.
|
||
|
AccessibilityRequirements *TopologyRequirement `json:",omitempty"`
|
||
|
|
||
|
// CapacityRange defines the desired capacity that the volume should be
|
||
|
// created with. If nil, the plugin will decide the capacity.
|
||
|
CapacityRange *CapacityRange `json:",omitempty"`
|
||
|
|
||
|
// Secrets defines Swarm Secrets that are passed to the CSI storage plugin
|
||
|
// when operating on this volume.
|
||
|
Secrets []Secret `json:",omitempty"`
|
||
|
|
||
|
// Availability is the Volume's desired availability. Analogous to Node
|
||
|
// Availability, this allows the user to take volumes offline in order to
|
||
|
// update or delete them.
|
||
|
Availability Availability `json:",omitempty"`
|
||
|
}
|
||
|
|
||
|
// Availability specifies the availability of the volume.
|
||
|
type Availability string
|
||
|
|
||
|
const (
|
||
|
// AvailabilityActive indicates that the volume is active and fully
|
||
|
// schedulable on the cluster.
|
||
|
AvailabilityActive Availability = "active"
|
||
|
|
||
|
// AvailabilityPause indicates that no new workloads should use the
|
||
|
// volume, but existing workloads can continue to use it.
|
||
|
AvailabilityPause Availability = "pause"
|
||
|
|
||
|
// AvailabilityDrain indicates that all workloads using this volume
|
||
|
// should be rescheduled, and the volume unpublished from all nodes.
|
||
|
AvailabilityDrain Availability = "drain"
|
||
|
)
|
||
|
|
||
|
// AccessMode defines the access mode of a volume.
|
||
|
type AccessMode struct {
|
||
|
// Scope defines the set of nodes this volume can be used on at one time.
|
||
|
Scope Scope `json:",omitempty"`
|
||
|
|
||
|
// Sharing defines the number and way that different tasks can use this
|
||
|
// volume at one time.
|
||
|
Sharing SharingMode `json:",omitempty"`
|
||
|
|
||
|
// MountVolume defines options for using this volume as a Mount-type
|
||
|
// volume.
|
||
|
//
|
||
|
// Either BlockVolume or MountVolume, but not both, must be present.
|
||
|
MountVolume *TypeMount `json:",omitempty"`
|
||
|
|
||
|
// BlockVolume defines options for using this volume as a Block-type
|
||
|
// volume.
|
||
|
//
|
||
|
// Either BlockVolume or MountVolume, but not both, must be present.
|
||
|
BlockVolume *TypeBlock `json:",omitempty"`
|
||
|
}
|
||
|
|
||
|
// Scope defines the Scope of a CSI Volume. This is how many nodes a
|
||
|
// Volume can be accessed simultaneously on.
|
||
|
type Scope string
|
||
|
|
||
|
const (
|
||
|
// ScopeSingleNode indicates the volume can be used on one node at a
|
||
|
// time.
|
||
|
ScopeSingleNode Scope = "single"
|
||
|
|
||
|
// ScopeMultiNode indicates the volume can be used on many nodes at
|
||
|
// the same time.
|
||
|
ScopeMultiNode Scope = "multi"
|
||
|
)
|
||
|
|
||
|
// SharingMode defines the Sharing of a CSI Volume. This is how Tasks using a
|
||
|
// Volume at the same time can use it.
|
||
|
type SharingMode string
|
||
|
|
||
|
const (
|
||
|
// SharingNone indicates that only one Task may use the Volume at a
|
||
|
// time.
|
||
|
SharingNone SharingMode = "none"
|
||
|
|
||
|
// SharingReadOnly indicates that the Volume may be shared by any
|
||
|
// number of Tasks, but they must be read-only.
|
||
|
SharingReadOnly SharingMode = "readonly"
|
||
|
|
||
|
// SharingOneWriter indicates that the Volume may be shared by any
|
||
|
// number of Tasks, but all after the first must be read-only.
|
||
|
SharingOneWriter SharingMode = "onewriter"
|
||
|
|
||
|
// SharingAll means that the Volume may be shared by any number of
|
||
|
// Tasks, as readers or writers.
|
||
|
SharingAll SharingMode = "all"
|
||
|
)
|
||
|
|
||
|
// TypeBlock defines options for using a volume as a block-type volume.
|
||
|
//
|
||
|
// Intentionally empty.
|
||
|
type TypeBlock struct{}
|
||
|
|
||
|
// TypeMount contains options for using a volume as a Mount-type
|
||
|
// volume.
|
||
|
type TypeMount struct {
|
||
|
// FsType specifies the filesystem type for the mount volume. Optional.
|
||
|
FsType string `json:",omitempty"`
|
||
|
|
||
|
// MountFlags defines flags to pass when mounting the volume. Optional.
|
||
|
MountFlags []string `json:",omitempty"`
|
||
|
}
|
||
|
|
||
|
// TopologyRequirement expresses the user's requirements for a volume's
|
||
|
// accessible topology.
|
||
|
type TopologyRequirement struct {
|
||
|
// Requisite specifies a list of Topologies, at least one of which the
|
||
|
// volume must be accessible from.
|
||
|
//
|
||
|
// Taken verbatim from the CSI Spec:
|
||
|
//
|
||
|
// Specifies the list of topologies the provisioned volume MUST be
|
||
|
// accessible from.
|
||
|
// This field is OPTIONAL. If TopologyRequirement is specified either
|
||
|
// requisite or preferred or both MUST be specified.
|
||
|
//
|
||
|
// If requisite is specified, the provisioned volume MUST be
|
||
|
// accessible from at least one of the requisite topologies.
|
||
|
//
|
||
|
// Given
|
||
|
// x = number of topologies provisioned volume is accessible from
|
||
|
// n = number of requisite topologies
|
||
|
// The CO MUST ensure n >= 1. The SP MUST ensure x >= 1
|
||
|
// If x==n, then the SP MUST make the provisioned volume available to
|
||
|
// all topologies from the list of requisite topologies. If it is
|
||
|
// unable to do so, the SP MUST fail the CreateVolume call.
|
||
|
// For example, if a volume should be accessible from a single zone,
|
||
|
// and requisite =
|
||
|
// {"region": "R1", "zone": "Z2"}
|
||
|
// then the provisioned volume MUST be accessible from the "region"
|
||
|
// "R1" and the "zone" "Z2".
|
||
|
// Similarly, if a volume should be accessible from two zones, and
|
||
|
// requisite =
|
||
|
// {"region": "R1", "zone": "Z2"},
|
||
|
// {"region": "R1", "zone": "Z3"}
|
||
|
// then the provisioned volume MUST be accessible from the "region"
|
||
|
// "R1" and both "zone" "Z2" and "zone" "Z3".
|
||
|
//
|
||
|
// If x<n, then the SP SHALL choose x unique topologies from the list
|
||
|
// of requisite topologies. If it is unable to do so, the SP MUST fail
|
||
|
// the CreateVolume call.
|
||
|
// For example, if a volume should be accessible from a single zone,
|
||
|
// and requisite =
|
||
|
// {"region": "R1", "zone": "Z2"},
|
||
|
// {"region": "R1", "zone": "Z3"}
|
||
|
// then the SP may choose to make the provisioned volume available in
|
||
|
// either the "zone" "Z2" or the "zone" "Z3" in the "region" "R1".
|
||
|
// Similarly, if a volume should be accessible from two zones, and
|
||
|
// requisite =
|
||
|
// {"region": "R1", "zone": "Z2"},
|
||
|
// {"region": "R1", "zone": "Z3"},
|
||
|
// {"region": "R1", "zone": "Z4"}
|
||
|
// then the provisioned volume MUST be accessible from any combination
|
||
|
// of two unique topologies: e.g. "R1/Z2" and "R1/Z3", or "R1/Z2" and
|
||
|
// "R1/Z4", or "R1/Z3" and "R1/Z4".
|
||
|
//
|
||
|
// If x>n, then the SP MUST make the provisioned volume available from
|
||
|
// all topologies from the list of requisite topologies and MAY choose
|
||
|
// the remaining x-n unique topologies from the list of all possible
|
||
|
// topologies. If it is unable to do so, the SP MUST fail the
|
||
|
// CreateVolume call.
|
||
|
// For example, if a volume should be accessible from two zones, and
|
||
|
// requisite =
|
||
|
// {"region": "R1", "zone": "Z2"}
|
||
|
// then the provisioned volume MUST be accessible from the "region"
|
||
|
// "R1" and the "zone" "Z2" and the SP may select the second zone
|
||
|
// independently, e.g. "R1/Z4".
|
||
|
Requisite []Topology `json:",omitempty"`
|
||
|
|
||
|
// Preferred is a list of Topologies that the volume should attempt to be
|
||
|
// provisioned in.
|
||
|
//
|
||
|
// Taken from the CSI spec:
|
||
|
//
|
||
|
// Specifies the list of topologies the CO would prefer the volume to
|
||
|
// be provisioned in.
|
||
|
//
|
||
|
// This field is OPTIONAL. If TopologyRequirement is specified either
|
||
|
// requisite or preferred or both MUST be specified.
|
||
|
//
|
||
|
// An SP MUST attempt to make the provisioned volume available using
|
||
|
// the preferred topologies in order from first to last.
|
||
|
//
|
||
|
// If requisite is specified, all topologies in preferred list MUST
|
||
|
// also be present in the list of requisite topologies.
|
||
|
//
|
||
|
// If the SP is unable to to make the provisioned volume available
|
||
|
// from any of the preferred topologies, the SP MAY choose a topology
|
||
|
// from the list of requisite topologies.
|
||
|
// If the list of requisite topologies is not specified, then the SP
|
||
|
// MAY choose from the list of all possible topologies.
|
||
|
// If the list of requisite topologies is specified and the SP is
|
||
|
// unable to to make the provisioned volume available from any of the
|
||
|
// requisite topologies it MUST fail the CreateVolume call.
|
||
|
//
|
||
|
// Example 1:
|
||
|
// Given a volume should be accessible from a single zone, and
|
||
|
// requisite =
|
||
|
// {"region": "R1", "zone": "Z2"},
|
||
|
// {"region": "R1", "zone": "Z3"}
|
||
|
// preferred =
|
||
|
// {"region": "R1", "zone": "Z3"}
|
||
|
// then the the SP SHOULD first attempt to make the provisioned volume
|
||
|
// available from "zone" "Z3" in the "region" "R1" and fall back to
|
||
|
// "zone" "Z2" in the "region" "R1" if that is not possible.
|
||
|
//
|
||
|
// Example 2:
|
||
|
// Given a volume should be accessible from a single zone, and
|
||
|
// requisite =
|
||
|
// {"region": "R1", "zone": "Z2"},
|
||
|
// {"region": "R1", "zone": "Z3"},
|
||
|
// {"region": "R1", "zone": "Z4"},
|
||
|
// {"region": "R1", "zone": "Z5"}
|
||
|
// preferred =
|
||
|
// {"region": "R1", "zone": "Z4"},
|
||
|
// {"region": "R1", "zone": "Z2"}
|
||
|
// then the the SP SHOULD first attempt to make the provisioned volume
|
||
|
// accessible from "zone" "Z4" in the "region" "R1" and fall back to
|
||
|
// "zone" "Z2" in the "region" "R1" if that is not possible. If that
|
||
|
// is not possible, the SP may choose between either the "zone"
|
||
|
// "Z3" or "Z5" in the "region" "R1".
|
||
|
//
|
||
|
// Example 3:
|
||
|
// Given a volume should be accessible from TWO zones (because an
|
||
|
// opaque parameter in CreateVolumeRequest, for example, specifies
|
||
|
// the volume is accessible from two zones, aka synchronously
|
||
|
// replicated), and
|
||
|
// requisite =
|
||
|
// {"region": "R1", "zone": "Z2"},
|
||
|
// {"region": "R1", "zone": "Z3"},
|
||
|
// {"region": "R1", "zone": "Z4"},
|
||
|
// {"region": "R1", "zone": "Z5"}
|
||
|
// preferred =
|
||
|
// {"region": "R1", "zone": "Z5"},
|
||
|
// {"region": "R1", "zone": "Z3"}
|
||
|
// then the the SP SHOULD first attempt to make the provisioned volume
|
||
|
// accessible from the combination of the two "zones" "Z5" and "Z3" in
|
||
|
// the "region" "R1". If that's not possible, it should fall back to
|
||
|
// a combination of "Z5" and other possibilities from the list of
|
||
|
// requisite. If that's not possible, it should fall back to a
|
||
|
// combination of "Z3" and other possibilities from the list of
|
||
|
// requisite. If that's not possible, it should fall back to a
|
||
|
// combination of other possibilities from the list of requisite.
|
||
|
Preferred []Topology `json:",omitempty"`
|
||
|
}
|
||
|
|
||
|
// Topology is a map of topological domains to topological segments.
|
||
|
//
|
||
|
// This description is taken verbatim from the CSI Spec:
|
||
|
//
|
||
|
// A topological domain is a sub-division of a cluster, like "region",
|
||
|
// "zone", "rack", etc.
|
||
|
// A topological segment is a specific instance of a topological domain,
|
||
|
// like "zone3", "rack3", etc.
|
||
|
// For example {"com.company/zone": "Z1", "com.company/rack": "R3"}
|
||
|
// Valid keys have two segments: an OPTIONAL prefix and name, separated
|
||
|
// by a slash (/), for example: "com.company.example/zone".
|
||
|
// The key name segment is REQUIRED. The prefix is OPTIONAL.
|
||
|
// The key name MUST be 63 characters or less, begin and end with an
|
||
|
// alphanumeric character ([a-z0-9A-Z]), and contain only dashes (-),
|
||
|
// underscores (_), dots (.), or alphanumerics in between, for example
|
||
|
// "zone".
|
||
|
// The key prefix MUST be 63 characters or less, begin and end with a
|
||
|
// lower-case alphanumeric character ([a-z0-9]), contain only
|
||
|
// dashes (-), dots (.), or lower-case alphanumerics in between, and
|
||
|
// follow domain name notation format
|
||
|
// (https://tools.ietf.org/html/rfc1035#section-2.3.1).
|
||
|
// The key prefix SHOULD include the plugin's host company name and/or
|
||
|
// the plugin name, to minimize the possibility of collisions with keys
|
||
|
// from other plugins.
|
||
|
// If a key prefix is specified, it MUST be identical across all
|
||
|
// topology keys returned by the SP (across all RPCs).
|
||
|
// Keys MUST be case-insensitive. Meaning the keys "Zone" and "zone"
|
||
|
// MUST not both exist.
|
||
|
// Each value (topological segment) MUST contain 1 or more strings.
|
||
|
// Each string MUST be 63 characters or less and begin and end with an
|
||
|
// alphanumeric character with '-', '_', '.', or alphanumerics in
|
||
|
// between.
|
||
|
type Topology struct {
|
||
|
Segments map[string]string `json:",omitempty"`
|
||
|
}
|
||
|
|
||
|
// CapacityRange describes the minimum and maximum capacity a volume should be
|
||
|
// created with
|
||
|
type CapacityRange struct {
|
||
|
// RequiredBytes specifies that a volume must be at least this big. The
|
||
|
// value of 0 indicates an unspecified minimum.
|
||
|
RequiredBytes int64
|
||
|
|
||
|
// LimitBytes specifies that a volume must not be bigger than this. The
|
||
|
// value of 0 indicates an unspecified maximum
|
||
|
LimitBytes int64
|
||
|
}
|
||
|
|
||
|
// Secret represents a Swarm Secret value that must be passed to the CSI
|
||
|
// storage plugin when operating on this Volume. It represents one key-value
|
||
|
// pair of possibly many.
|
||
|
type Secret struct {
|
||
|
// Key is the name of the key of the key-value pair passed to the plugin.
|
||
|
Key string
|
||
|
|
||
|
// Secret is the swarm Secret object from which to read data. This can be a
|
||
|
// Secret name or ID. The Secret data is retrieved by Swarm and used as the
|
||
|
// value of the key-value pair passed to the plugin.
|
||
|
Secret string
|
||
|
}
|
||
|
|
||
|
// PublishState represents the state of a Volume as it pertains to its
|
||
|
// use on a particular Node.
|
||
|
type PublishState string
|
||
|
|
||
|
const (
|
||
|
// StatePending indicates that the volume should be published on
|
||
|
// this node, but the call to ControllerPublishVolume has not been
|
||
|
// successfully completed yet and the result recorded by swarmkit.
|
||
|
StatePending PublishState = "pending-publish"
|
||
|
|
||
|
// StatePublished means the volume is published successfully to the node.
|
||
|
StatePublished PublishState = "published"
|
||
|
|
||
|
// StatePendingNodeUnpublish indicates that the Volume should be
|
||
|
// unpublished on the Node, and we're waiting for confirmation that it has
|
||
|
// done so. After the Node has confirmed that the Volume has been
|
||
|
// unpublished, the state will move to StatePendingUnpublish.
|
||
|
StatePendingNodeUnpublish PublishState = "pending-node-unpublish"
|
||
|
|
||
|
// StatePendingUnpublish means the volume is still published to the node
|
||
|
// by the controller, awaiting the operation to unpublish it.
|
||
|
StatePendingUnpublish PublishState = "pending-controller-unpublish"
|
||
|
)
|
||
|
|
||
|
// PublishStatus represents the status of the volume as published to an
|
||
|
// individual node
|
||
|
type PublishStatus struct {
|
||
|
// NodeID is the ID of the swarm node this Volume is published to.
|
||
|
NodeID string `json:",omitempty"`
|
||
|
|
||
|
// State is the publish state of the volume.
|
||
|
State PublishState `json:",omitempty"`
|
||
|
|
||
|
// PublishContext is the PublishContext returned by the CSI plugin when
|
||
|
// a volume is published.
|
||
|
PublishContext map[string]string `json:",omitempty"`
|
||
|
}
|
||
|
|
||
|
// Info contains information about the Volume as a whole as provided by
|
||
|
// the CSI storage plugin.
|
||
|
type Info struct {
|
||
|
// CapacityBytes is the capacity of the volume in bytes. A value of 0
|
||
|
// indicates that the capacity is unknown.
|
||
|
CapacityBytes int64 `json:",omitempty"`
|
||
|
|
||
|
// VolumeContext is the context originating from the CSI storage plugin
|
||
|
// when the Volume is created.
|
||
|
VolumeContext map[string]string `json:",omitempty"`
|
||
|
|
||
|
// VolumeID is the ID of the Volume as seen by the CSI storage plugin. This
|
||
|
// is distinct from the Volume's Swarm ID, which is the ID used by all of
|
||
|
// the Docker Engine to refer to the Volume. If this field is blank, then
|
||
|
// the Volume has not been successfully created yet.
|
||
|
VolumeID string `json:",omitempty"`
|
||
|
|
||
|
// AccessibleTopolgoy is the topology this volume is actually accessible
|
||
|
// from.
|
||
|
AccessibleTopology []Topology `json:",omitempty"`
|
||
|
}
|