github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/structs/csi.go (about) 1 package structs 2 3 import ( 4 "github.com/hashicorp/nomad/nomad/structs" 5 "github.com/hashicorp/nomad/plugins/csi" 6 ) 7 8 // CSIVolumeMountOptions contains the mount options that should be provided when 9 // attaching and mounting a volume with the CSIVolumeAttachmentModeFilesystem 10 // attachment mode. 11 type CSIVolumeMountOptions struct { 12 // Filesystem is the desired filesystem type that should be used by the volume 13 // (e.g ext4, aufs, zfs). This field is optional. 14 Filesystem string 15 16 // MountFlags contain the mount options that should be used for the volume. 17 // These may contain _sensitive_ data and should not be leaked to logs or 18 // returned in debugging data. 19 // The total size of this field must be under 4KiB. 20 MountFlags []string 21 } 22 23 func (c *CSIVolumeMountOptions) ToCSIMountOptions() *structs.CSIMountOptions { 24 if c == nil { 25 return nil 26 } 27 28 return &structs.CSIMountOptions{ 29 FSType: c.Filesystem, 30 MountFlags: c.MountFlags, 31 } 32 } 33 34 // CSIControllerRequest interface lets us set embedded CSIControllerQuery 35 // fields in the server 36 type CSIControllerRequest interface { 37 SetControllerNodeID(string) 38 } 39 40 // CSIControllerQuery is used to specify various flags for queries against CSI 41 // Controllers 42 type CSIControllerQuery struct { 43 // ControllerNodeID is the node that should be targeted by the request 44 ControllerNodeID string 45 46 // PluginID is the plugin that should be targeted on the given node. 47 PluginID string 48 } 49 50 func (c *CSIControllerQuery) SetControllerNodeID(nodeID string) { 51 c.ControllerNodeID = nodeID 52 } 53 54 type ClientCSIControllerValidateVolumeRequest struct { 55 VolumeID string // note: this is the external ID 56 57 VolumeCapabilities []*structs.CSIVolumeCapability 58 MountOptions *structs.CSIMountOptions 59 Secrets structs.CSISecrets 60 61 // COMPAT(1.1.1): the AttachmentMode and AccessMode fields are deprecated 62 // and replaced by the VolumeCapabilities field above 63 AttachmentMode structs.CSIVolumeAttachmentMode 64 AccessMode structs.CSIVolumeAccessMode 65 66 // Parameters as returned by storage provider in CreateVolumeResponse. 67 // This field is optional. 68 Parameters map[string]string 69 70 // Volume context as returned by storage provider in CreateVolumeResponse. 71 // This field is optional. 72 Context map[string]string 73 74 CSIControllerQuery 75 } 76 77 func (c *ClientCSIControllerValidateVolumeRequest) ToCSIRequest() (*csi.ControllerValidateVolumeRequest, error) { 78 if c == nil { 79 return &csi.ControllerValidateVolumeRequest{}, nil 80 } 81 82 creq := &csi.ControllerValidateVolumeRequest{ 83 ExternalID: c.VolumeID, 84 Secrets: c.Secrets, 85 Capabilities: []*csi.VolumeCapability{}, 86 Parameters: c.Parameters, 87 Context: c.Context, 88 } 89 90 for _, cap := range c.VolumeCapabilities { 91 ccap, err := csi.VolumeCapabilityFromStructs( 92 cap.AttachmentMode, cap.AccessMode, c.MountOptions) 93 if err != nil { 94 return nil, err 95 } 96 creq.Capabilities = append(creq.Capabilities, ccap) 97 } 98 return creq, nil 99 } 100 101 type ClientCSIControllerValidateVolumeResponse struct { 102 } 103 104 type ClientCSIControllerAttachVolumeRequest struct { 105 // The external ID of the volume to be used on a node. 106 // This field is REQUIRED. 107 VolumeID string 108 109 // The ID of the node. This field is REQUIRED. This must match the NodeID that 110 // is fingerprinted by the target node for this plugin name. 111 ClientCSINodeID string 112 113 // AttachmentMode indicates how the volume should be attached and mounted into 114 // a task. 115 AttachmentMode structs.CSIVolumeAttachmentMode 116 117 // AccessMode indicates the desired concurrent access model for the volume 118 AccessMode structs.CSIVolumeAccessMode 119 120 // MountOptions is an optional field that contains additional configuration 121 // when providing an AttachmentMode of CSIVolumeAttachmentModeFilesystem 122 MountOptions *CSIVolumeMountOptions 123 124 // ReadOnly indicates that the volume will be used in a readonly fashion. This 125 // only works when the Controller has the PublishReadonly capability. 126 ReadOnly bool 127 128 // Secrets required by plugin to complete the controller publish 129 // volume request. This field is OPTIONAL. 130 Secrets structs.CSISecrets 131 132 // Volume context as returned by storage provider in CreateVolumeResponse. 133 // This field is optional. 134 VolumeContext map[string]string 135 136 CSIControllerQuery 137 } 138 139 func (c *ClientCSIControllerAttachVolumeRequest) ToCSIRequest() (*csi.ControllerPublishVolumeRequest, error) { 140 if c == nil { 141 return &csi.ControllerPublishVolumeRequest{}, nil 142 } 143 144 var opts = c.MountOptions.ToCSIMountOptions() 145 caps, err := csi.VolumeCapabilityFromStructs(c.AttachmentMode, c.AccessMode, opts) 146 if err != nil { 147 return nil, err 148 } 149 150 return &csi.ControllerPublishVolumeRequest{ 151 ExternalID: c.VolumeID, 152 NodeID: c.ClientCSINodeID, 153 VolumeCapability: caps, 154 ReadOnly: c.ReadOnly, 155 Secrets: c.Secrets, 156 VolumeContext: c.VolumeContext, 157 }, nil 158 } 159 160 // ClientCSIControllerDetachVolumeRequest is the RPC made from the server to 161 // a Nomad client to tell a CSI controller plugin on that client to perform 162 // ControllerUnpublish for a volume on a specific client. 163 type ClientCSIControllerAttachVolumeResponse struct { 164 // Opaque static publish properties of the volume. SP MAY use this 165 // field to ensure subsequent `NodeStageVolume` or `NodePublishVolume` 166 // calls calls have contextual information. 167 // The contents of this field SHALL be opaque to nomad. 168 // The contents of this field SHALL NOT be mutable. 169 // The contents of this field SHALL be safe for the nomad to cache. 170 // The contents of this field SHOULD NOT contain sensitive 171 // information. 172 // The contents of this field SHOULD NOT be used for uniquely 173 // identifying a volume. The `volume_id` alone SHOULD be sufficient to 174 // identify the volume. 175 // This field is OPTIONAL and when present MUST be passed to 176 // subsequent `NodeStageVolume` or `NodePublishVolume` calls 177 PublishContext map[string]string 178 } 179 180 type ClientCSIControllerDetachVolumeRequest struct { 181 // The external ID of the volume to be unpublished for the node 182 // This field is REQUIRED. 183 VolumeID string 184 185 // The CSI Node ID for the Node that the volume should be detached from. 186 // This field is REQUIRED. This must match the NodeID that is fingerprinted 187 // by the target node for this plugin name. 188 ClientCSINodeID string 189 190 // Secrets required by plugin to complete the controller unpublish 191 // volume request. This field is OPTIONAL. 192 Secrets structs.CSISecrets 193 194 CSIControllerQuery 195 } 196 197 func (c *ClientCSIControllerDetachVolumeRequest) ToCSIRequest() *csi.ControllerUnpublishVolumeRequest { 198 if c == nil { 199 return &csi.ControllerUnpublishVolumeRequest{} 200 } 201 202 return &csi.ControllerUnpublishVolumeRequest{ 203 ExternalID: c.VolumeID, 204 NodeID: c.ClientCSINodeID, 205 } 206 } 207 208 type ClientCSIControllerDetachVolumeResponse struct{} 209 210 // ClientCSIControllerCreateVolumeRequest the RPC made from the server to a 211 // Nomad client to tell a CSI controller plugin on that client to perform 212 // CreateVolume 213 type ClientCSIControllerCreateVolumeRequest struct { 214 Name string 215 VolumeCapabilities []*structs.CSIVolumeCapability 216 MountOptions *structs.CSIMountOptions 217 Parameters map[string]string 218 Secrets structs.CSISecrets 219 CapacityMin int64 220 CapacityMax int64 221 SnapshotID string 222 CloneID string 223 RequestedTopologies *structs.CSITopologyRequest 224 225 CSIControllerQuery 226 } 227 228 func (req *ClientCSIControllerCreateVolumeRequest) ToCSIRequest() (*csi.ControllerCreateVolumeRequest, error) { 229 230 creq := &csi.ControllerCreateVolumeRequest{ 231 Name: req.Name, 232 VolumeCapabilities: []*csi.VolumeCapability{}, 233 Parameters: req.Parameters, 234 Secrets: req.Secrets, 235 ContentSource: &csi.VolumeContentSource{ 236 CloneID: req.CloneID, 237 SnapshotID: req.SnapshotID, 238 }, 239 AccessibilityRequirements: &csi.TopologyRequirement{ 240 Requisite: []*csi.Topology{}, 241 Preferred: []*csi.Topology{}, 242 }, 243 } 244 245 // The CSI spec requires that at least one of the fields in CapacityRange 246 // must be defined. Fields set to 0 are considered unspecified and the 247 // CreateVolumeRequest should not send an invalid value. 248 if req.CapacityMin != 0 || req.CapacityMax != 0 { 249 creq.CapacityRange = &csi.CapacityRange{ 250 RequiredBytes: req.CapacityMin, 251 LimitBytes: req.CapacityMax, 252 } 253 } 254 255 for _, cap := range req.VolumeCapabilities { 256 ccap, err := csi.VolumeCapabilityFromStructs(cap.AttachmentMode, cap.AccessMode, req.MountOptions) 257 if err != nil { 258 return nil, err 259 } 260 creq.VolumeCapabilities = append(creq.VolumeCapabilities, ccap) 261 } 262 263 if req.RequestedTopologies != nil { 264 for _, topo := range req.RequestedTopologies.Required { 265 creq.AccessibilityRequirements.Requisite = append( 266 creq.AccessibilityRequirements.Requisite, &csi.Topology{ 267 Segments: topo.Segments, 268 }) 269 } 270 for _, topo := range req.RequestedTopologies.Preferred { 271 creq.AccessibilityRequirements.Preferred = append( 272 creq.AccessibilityRequirements.Preferred, &csi.Topology{ 273 Segments: topo.Segments, 274 }) 275 } 276 } 277 return creq, nil 278 } 279 280 type ClientCSIControllerCreateVolumeResponse struct { 281 ExternalVolumeID string 282 CapacityBytes int64 283 VolumeContext map[string]string 284 Topologies []*structs.CSITopology 285 } 286 287 // ClientCSIControllerDeleteVolumeRequest the RPC made from the server to a 288 // Nomad client to tell a CSI controller plugin on that client to perform 289 // DeleteVolume 290 type ClientCSIControllerDeleteVolumeRequest struct { 291 ExternalVolumeID string 292 Secrets structs.CSISecrets 293 294 CSIControllerQuery 295 } 296 297 func (req *ClientCSIControllerDeleteVolumeRequest) ToCSIRequest() *csi.ControllerDeleteVolumeRequest { 298 return &csi.ControllerDeleteVolumeRequest{ 299 ExternalVolumeID: req.ExternalVolumeID, 300 Secrets: req.Secrets, 301 } 302 } 303 304 type ClientCSIControllerDeleteVolumeResponse struct{} 305 306 // ClientCSIControllerListVolumesVolumeRequest the RPC made from the server to 307 // a Nomad client to tell a CSI controller plugin on that client to perform 308 // ListVolumes 309 type ClientCSIControllerListVolumesRequest struct { 310 // these pagination fields match the pagination fields of the plugins and 311 // not Nomad's own fields, for clarity when mapping between the two RPCs 312 MaxEntries int32 313 StartingToken string 314 315 CSIControllerQuery 316 } 317 318 func (req *ClientCSIControllerListVolumesRequest) ToCSIRequest() *csi.ControllerListVolumesRequest { 319 return &csi.ControllerListVolumesRequest{ 320 MaxEntries: req.MaxEntries, 321 StartingToken: req.StartingToken, 322 } 323 } 324 325 type ClientCSIControllerListVolumesResponse struct { 326 Entries []*structs.CSIVolumeExternalStub 327 NextToken string 328 } 329 330 // ClientCSIControllerCreateSnapshotRequest the RPC made from the server to a 331 // Nomad client to tell a CSI controller plugin on that client to perform 332 // CreateSnapshot 333 type ClientCSIControllerCreateSnapshotRequest struct { 334 ExternalSourceVolumeID string 335 Name string 336 Secrets structs.CSISecrets 337 Parameters map[string]string 338 339 CSIControllerQuery 340 } 341 342 func (req *ClientCSIControllerCreateSnapshotRequest) ToCSIRequest() (*csi.ControllerCreateSnapshotRequest, error) { 343 return &csi.ControllerCreateSnapshotRequest{ 344 VolumeID: req.ExternalSourceVolumeID, 345 Name: req.Name, 346 Secrets: req.Secrets, 347 Parameters: req.Parameters, 348 }, nil 349 } 350 351 type ClientCSIControllerCreateSnapshotResponse struct { 352 ID string 353 ExternalSourceVolumeID string 354 SizeBytes int64 355 CreateTime int64 356 IsReady bool 357 } 358 359 // ClientCSIControllerDeleteSnapshotRequest the RPC made from the server to a 360 // Nomad client to tell a CSI controller plugin on that client to perform 361 // DeleteSnapshot 362 type ClientCSIControllerDeleteSnapshotRequest struct { 363 ID string 364 Secrets structs.CSISecrets 365 366 CSIControllerQuery 367 } 368 369 func (req *ClientCSIControllerDeleteSnapshotRequest) ToCSIRequest() *csi.ControllerDeleteSnapshotRequest { 370 return &csi.ControllerDeleteSnapshotRequest{ 371 SnapshotID: req.ID, 372 Secrets: req.Secrets, 373 } 374 } 375 376 type ClientCSIControllerDeleteSnapshotResponse struct{} 377 378 // ClientCSIControllerListSnapshotsRequest is the RPC made from the server to 379 // a Nomad client to tell a CSI controller plugin on that client to perform 380 // ListSnapshots 381 type ClientCSIControllerListSnapshotsRequest struct { 382 // these pagination fields match the pagination fields of the plugins and 383 // not Nomad's own fields, for clarity when mapping between the two RPCs 384 MaxEntries int32 385 StartingToken string 386 Secrets structs.CSISecrets 387 388 CSIControllerQuery 389 } 390 391 func (req *ClientCSIControllerListSnapshotsRequest) ToCSIRequest() *csi.ControllerListSnapshotsRequest { 392 return &csi.ControllerListSnapshotsRequest{ 393 MaxEntries: req.MaxEntries, 394 StartingToken: req.StartingToken, 395 Secrets: req.Secrets, 396 } 397 } 398 399 type ClientCSIControllerListSnapshotsResponse struct { 400 Entries []*structs.CSISnapshot 401 NextToken string 402 } 403 404 // ClientCSINodeDetachVolumeRequest is the RPC made from the server to 405 // a Nomad client to tell a CSI node plugin on that client to perform 406 // NodeUnpublish and NodeUnstage. 407 type ClientCSINodeDetachVolumeRequest struct { 408 PluginID string // ID of the plugin that manages the volume (required) 409 VolumeID string // ID of the volume to be unpublished (required) 410 AllocID string // ID of the allocation we're unpublishing for (required) 411 NodeID string // ID of the Nomad client targeted 412 ExternalID string // External ID of the volume to be unpublished (required) 413 414 // These fields should match the original volume request so that 415 // we can find the mount points on the client 416 AttachmentMode structs.CSIVolumeAttachmentMode 417 AccessMode structs.CSIVolumeAccessMode 418 ReadOnly bool 419 } 420 421 type ClientCSINodeDetachVolumeResponse struct{}