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{}