github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/storage/interface.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package storage
     5  
     6  import (
     7  	"github.com/juju/names/v5"
     8  
     9  	"github.com/juju/juju/core/instance"
    10  	"github.com/juju/juju/environs/context"
    11  )
    12  
    13  // ProviderType uniquely identifies a storage provider, such as "ebs" or "loop".
    14  type ProviderType string
    15  
    16  // Scope defines the scope of the storage that a provider manages.
    17  // Machine-scoped storage must be managed from within the machine,
    18  // whereas environment-level storage must be managed by an environment
    19  // storage provisioner.
    20  type Scope int
    21  
    22  const (
    23  	ScopeEnviron Scope = iota
    24  	ScopeMachine
    25  )
    26  
    27  // ProviderRegistry is an interface for obtaining storage providers.
    28  type ProviderRegistry interface {
    29  	// StorageProviderTypes returns the storage provider types
    30  	// contained within this registry.
    31  	//
    32  	// Determining the supported storage providers may be dynamic.
    33  	// Multiple calls for the same registry must return consistent
    34  	// results.
    35  	StorageProviderTypes() ([]ProviderType, error)
    36  
    37  	// StorageProvider returns the storage provider with the given
    38  	// provider type. StorageProvider must return an errors satisfying
    39  	// errors.IsNotFound if the registry does not contain the
    40  	// specified provider type.
    41  	StorageProvider(ProviderType) (Provider, error)
    42  }
    43  
    44  // Provider is an interface for obtaining storage sources.
    45  type Provider interface {
    46  	// VolumeSource returns a VolumeSource given the specified storage
    47  	// provider configurations, or an error if the provider does not
    48  	// support creating volumes or the configuration is invalid.
    49  	//
    50  	// If the storage provider does not support creating volumes as a
    51  	// first-class primitive, then VolumeSource must return an error
    52  	// satisfying errors.IsNotSupported.
    53  	VolumeSource(*Config) (VolumeSource, error)
    54  
    55  	// FilesystemSource returns a FilesystemSource given the specified
    56  	// storage provider configurations, or an error if the provider does
    57  	// not support creating filesystems or the configuration is invalid.
    58  	FilesystemSource(*Config) (FilesystemSource, error)
    59  
    60  	// Supports reports whether or not the storage provider supports
    61  	// the specified storage kind.
    62  	//
    63  	// A provider that supports volumes but not filesystems can still
    64  	// be used for creating filesystem storage; Juju will request a
    65  	// volume from the provider and then manage the filesystem itself.
    66  	Supports(kind StorageKind) bool
    67  
    68  	// Scope returns the scope of storage managed by this provider.
    69  	Scope() Scope
    70  
    71  	// Dynamic reports whether or not the storage provider is capable
    72  	// of dynamic storage provisioning. Non-dynamic storage must be
    73  	// created at the time a machine is provisioned.
    74  	Dynamic() bool
    75  
    76  	// Releasable reports whether or not the storage provider is capable
    77  	// of releasing dynamic storage, with either ReleaseVolumes or
    78  	// ReleaseFilesystems.
    79  	Releasable() bool
    80  
    81  	// DefaultPools returns the default storage pools for this provider,
    82  	// to register in each new model.
    83  	DefaultPools() []*Config
    84  
    85  	// ValidateConfig validates the provided storage provider config,
    86  	// returning an error if it is invalid.
    87  	ValidateConfig(*Config) error
    88  
    89  	// ValidateForK8s validates if a storage provider can be set for
    90  	// a given K8s configuration.
    91  	ValidateForK8s(map[string]any) error
    92  }
    93  
    94  // VolumeSource provides an interface for creating, destroying, describing,
    95  // attaching and detaching volumes in the environment. A VolumeSource is
    96  // configured in a particular way, and corresponds to a storage "pool".
    97  type VolumeSource interface {
    98  	// CreateVolumes creates volumes with the specified parameters. If the
    99  	// volumes are initially attached, then CreateVolumes returns
   100  	// information about those attachments too.
   101  	CreateVolumes(ctx context.ProviderCallContext, params []VolumeParams) ([]CreateVolumesResult, error)
   102  
   103  	// ListVolumes lists the provider volume IDs for every volume
   104  	// created by this volume source.
   105  	ListVolumes(ctx context.ProviderCallContext) ([]string, error)
   106  
   107  	// DescribeVolumes returns the properties of the volumes with the
   108  	// specified provider volume IDs.
   109  	DescribeVolumes(ctx context.ProviderCallContext, volIds []string) ([]DescribeVolumesResult, error)
   110  
   111  	// DestroyVolumes destroys the volumes with the specified provider
   112  	// volume IDs.
   113  	DestroyVolumes(ctx context.ProviderCallContext, volIds []string) ([]error, error)
   114  
   115  	// ReleaseVolumes releases the volumes with the specified provider
   116  	// volume IDs from the model/controller.
   117  	ReleaseVolumes(ctx context.ProviderCallContext, volIds []string) ([]error, error)
   118  
   119  	// ValidateVolumeParams validates the provided volume creation
   120  	// parameters, returning an error if they are invalid.
   121  	ValidateVolumeParams(params VolumeParams) error
   122  
   123  	// AttachVolumes attaches volumes to machines.
   124  	//
   125  	// AttachVolumes must be idempotent; it may be called even if the
   126  	// attachment already exists, to ensure that it exists, e.g. over
   127  	// machine restarts.
   128  	//
   129  	// TODO(axw) we need to validate attachment requests prior to
   130  	// recording in state. For example, the ec2 provider must reject
   131  	// an attempt to attach a volume to an instance if they are in
   132  	// different availability zones.
   133  	AttachVolumes(ctx context.ProviderCallContext, params []VolumeAttachmentParams) ([]AttachVolumesResult, error)
   134  
   135  	// DetachVolumes detaches the volumes with the specified provider
   136  	// volume IDs from the instances with the corresponding index.
   137  	//
   138  	// TODO(axw) we need to record in state whether or not volumes
   139  	// are detachable, and reject attempts to attach/detach on
   140  	// that basis.
   141  	DetachVolumes(ctx context.ProviderCallContext, params []VolumeAttachmentParams) ([]error, error)
   142  }
   143  
   144  // FilesystemSource provides an interface for creating, destroying and
   145  // describing filesystems in the environment. A FilesystemSource is
   146  // configured in a particular way, and corresponds to a storage "pool".
   147  type FilesystemSource interface {
   148  	// ValidateFilesystemParams validates the provided filesystem creation
   149  	// parameters, returning an error if they are invalid.
   150  	ValidateFilesystemParams(params FilesystemParams) error
   151  
   152  	// CreateFilesystems creates filesystems with the specified size, in MiB.
   153  	CreateFilesystems(ctx context.ProviderCallContext, params []FilesystemParams) ([]CreateFilesystemsResult, error)
   154  
   155  	// DestroyFilesystems destroys the filesystems with the specified
   156  	// providerd filesystem IDs.
   157  	DestroyFilesystems(ctx context.ProviderCallContext, fsIds []string) ([]error, error)
   158  
   159  	// ReleaseFilesystems releases the filesystems with the specified provider
   160  	// filesystem IDs from the model/controller.
   161  	ReleaseFilesystems(ctx context.ProviderCallContext, volIds []string) ([]error, error)
   162  
   163  	// AttachFilesystems attaches filesystems to machines.
   164  	//
   165  	// AttachFilesystems must be idempotent; it may be called even if
   166  	// the attachment already exists, to ensure that it exists, e.g. over
   167  	// machine restarts.
   168  	//
   169  	// TODO(axw) we need to validate attachment requests prior to
   170  	// recording in state. For example, the ec2 provider must reject
   171  	// an attempt to attach a volume to an instance if they are in
   172  	// different availability zones.
   173  	AttachFilesystems(ctx context.ProviderCallContext, params []FilesystemAttachmentParams) ([]AttachFilesystemsResult, error)
   174  
   175  	// DetachFilesystems detaches the filesystems with the specified
   176  	// provider filesystem IDs from the instances with the corresponding
   177  	// index.
   178  	DetachFilesystems(ctx context.ProviderCallContext, params []FilesystemAttachmentParams) ([]error, error)
   179  }
   180  
   181  // FilesystemImporter provides an interface for importing filesystems
   182  // into the controller/model.
   183  //
   184  // TODO(axw) make this part of FilesystemSource?
   185  type FilesystemImporter interface {
   186  	// ImportFilesystem updates the filesystem with the specified
   187  	// filesystem provider ID with the given resource tags, so that
   188  	// it is seen as being managed by this Juju controller/model.
   189  	// ImportFilesystem returns the filesystem information to store
   190  	// in the model.
   191  	//
   192  	// Implementations of ImportFilesystem should validate that the
   193  	// filesystem is not in use before allowing the import to proceed.
   194  	// Once it is imported, it is assumed to be in a detached state.
   195  	ImportFilesystem(
   196  		ctx context.ProviderCallContext,
   197  		filesystemId string,
   198  		resourceTags map[string]string,
   199  	) (FilesystemInfo, error)
   200  }
   201  
   202  // VolumeImporter provides an interface for importing volumes
   203  // into the controller/model.
   204  //
   205  // TODO(axw) make this part of VolumeSource?
   206  type VolumeImporter interface {
   207  	// ImportVolume updates the volume with the specified volume
   208  	// provider ID with the given resource tags, so that it is
   209  	// seen as being managed by this Juju controller/model.
   210  	// ImportVolume returns the volume information to store
   211  	// in the model.
   212  	//
   213  	// Implementations of ImportVolume should validate that the
   214  	// volume is not in use before allowing the import to proceed.
   215  	// Once it is imported, it is assumed to be in a detached state.
   216  	ImportVolume(
   217  		ctx context.ProviderCallContext,
   218  		volumeId string,
   219  		resourceTags map[string]string,
   220  	) (VolumeInfo, error)
   221  }
   222  
   223  // VolumeParams is a fully specified set of parameters for volume creation,
   224  // derived from one or more of user-specified storage constraints, a
   225  // storage pool definition, and charm storage metadata.
   226  type VolumeParams struct {
   227  	// Tag is a unique tag name assigned by Juju for the requested volume.
   228  	Tag names.VolumeTag
   229  
   230  	// Size is the minimum size of the volume in MiB.
   231  	Size uint64
   232  
   233  	// Provider is the name of the storage provider that is to be used to
   234  	// create the volume.
   235  	Provider ProviderType
   236  
   237  	// Attributes is the set of provider-specific attributes to pass to
   238  	// the storage provider when creating the volume. Attributes is derived
   239  	// from the storage pool configuration.
   240  	Attributes map[string]interface{}
   241  
   242  	// ResourceTags is a set of tags to set on the created volume, if the
   243  	// storage provider supports tags.
   244  	ResourceTags map[string]string
   245  
   246  	// Attachment identifies the machine that the volume should be attached
   247  	// to initially, or nil if the volume should not be attached to any
   248  	// machine. Some providers, such as MAAS, do not support dynamic
   249  	// attachment, and so provisioning time is the only opportunity to
   250  	// perform attachment.
   251  	//
   252  	// When machine instances are created, the instance provider will be
   253  	// presented with parameters for any due-to-be-attached volumes. If
   254  	// once the instance is created there are still unprovisioned volumes,
   255  	// the dynamic storage provisioner will take care of creating them.
   256  	Attachment *VolumeAttachmentParams
   257  }
   258  
   259  // VolumeAttachmentParams is a set of parameters for volume attachment or
   260  // detachment.
   261  type VolumeAttachmentParams struct {
   262  	AttachmentParams
   263  
   264  	// Volume is a unique tag assigned by Juju for the volume that
   265  	// should be attached/detached.
   266  	Volume names.VolumeTag
   267  
   268  	// VolumeId is the unique provider-supplied ID for the volume that
   269  	// should be attached/detached.
   270  	VolumeId string
   271  }
   272  
   273  // AttachmentParams describes the parameters for attaching a volume or
   274  // filesystem to a machine.
   275  type AttachmentParams struct {
   276  	// Provider is the name of the storage provider that is to be used to
   277  	// create the attachment.
   278  	Provider ProviderType
   279  
   280  	// Machine is the tag of the Juju machine that the storage should be
   281  	// attached to. Storage providers may use this to perform machine-
   282  	// specific operations, such as configuring access controls for the
   283  	// machine.
   284  	// This is a generic tag as it's also used to hold a unit for caas storage.
   285  	// TODO(caas)-rename to Host
   286  	Machine names.Tag
   287  
   288  	// InstanceId is the ID of the cloud instance that the storage should
   289  	// be attached to. This will only be of interest to storage providers
   290  	// that interact with the instances, such as EBS/EC2. The InstanceId
   291  	// field will be empty if the instance is not yet provisioned.
   292  	InstanceId instance.Id
   293  
   294  	// ReadOnly indicates that the storage should be attached as read-only.
   295  	ReadOnly bool
   296  }
   297  
   298  // FilesystemParams is a fully specified set of parameters for filesystem creation,
   299  // derived from one or more of user-specified storage constraints, a
   300  // storage pool definition, and charm storage metadata.
   301  type FilesystemParams struct {
   302  	// Tag is a unique tag assigned by Juju for the requested filesystem.
   303  	Tag names.FilesystemTag
   304  
   305  	// Volume is the tag of the volume that backs the filesystem, if any.
   306  	Volume names.VolumeTag
   307  
   308  	// Size is the minimum size of the filesystem in MiB.
   309  	Size uint64
   310  
   311  	// The provider type for this filesystem.
   312  	Provider ProviderType
   313  
   314  	// Attributes is a set of provider-specific options for storage creation,
   315  	// as defined in a storage pool.
   316  	Attributes map[string]interface{}
   317  
   318  	// ResourceTags is a set of tags to set on the created filesystem, if the
   319  	// storage provider supports tags.
   320  	ResourceTags map[string]string
   321  
   322  	// Attachment identifies the machine that the filesystem should be attached
   323  	// to initially, or nil if the filesystem should not be attached to any
   324  	// machine.
   325  	Attachment *FilesystemAttachmentParams
   326  }
   327  
   328  // FilesystemAttachmentParams is a set of parameters for filesystem attachment
   329  // or detachment.
   330  type FilesystemAttachmentParams struct {
   331  	AttachmentParams
   332  
   333  	// Filesystem is a unique tag assigned by Juju for the filesystem that
   334  	// should be attached/detached.
   335  	Filesystem names.FilesystemTag
   336  
   337  	// FilesystemId is the unique provider-supplied ID for the filesystem that
   338  	// should be attached/detached.
   339  	FilesystemId string
   340  
   341  	// Path is the path at which the filesystem is to be mounted on the machine that
   342  	// this attachment corresponds to.
   343  	Path string
   344  }
   345  
   346  // CreateVolumesResult contains the result of a VolumeSource.CreateVolumes call
   347  // for one volume. Volume and VolumeAttachment should only be used if Error is
   348  // nil.
   349  type CreateVolumesResult struct {
   350  	Volume           *Volume
   351  	VolumeAttachment *VolumeAttachment
   352  	Error            error
   353  }
   354  
   355  // DescribeVolumesResult contains the result of a VolumeSource.DescribeVolumes call
   356  // for one volume. Volume should only be used if Error is nil.
   357  type DescribeVolumesResult struct {
   358  	VolumeInfo *VolumeInfo
   359  	Error      error
   360  }
   361  
   362  // AttachVolumesResult contains the result of a VolumeSource.AttachVolumes call
   363  // for one volume. VolumeAttachment should only be used if Error is nil.
   364  type AttachVolumesResult struct {
   365  	VolumeAttachment *VolumeAttachment
   366  	Error            error
   367  }
   368  
   369  // CreateFilesystemsResult contains the result of a FilesystemSource.CreateFilesystems call
   370  // for one filesystem. Filesystem should only be used if Error is nil.
   371  type CreateFilesystemsResult struct {
   372  	Filesystem *Filesystem
   373  	Error      error
   374  }
   375  
   376  // AttachFilesystemsResult contains the result of a FilesystemSource.AttachFilesystems call
   377  // for one filesystem. FilesystemAttachment should only be used if Error is nil.
   378  type AttachFilesystemsResult struct {
   379  	FilesystemAttachment *FilesystemAttachment
   380  	Error                error
   381  }