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 xn, 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"` }