Documentation
¶
Overview ¶
Package driver defines the storage driver interface that the Rune VolumeController and node-side agent talk to. Built-in drivers live in subpackages (driver/local, driver/dovolume, ...) and register themselves with the registry from init().
Introduced in RUNE-069.
Package driver — registry for storage drivers.
Drivers register themselves in init() via Register(). The runed binary blank-imports each built-in driver package from cmd/runed/main.go; out-of-tree drivers are added by adding one more blank-import.
Index ¶
- Variables
- func Register(name string, factory Factory)
- func Registered() []string
- type Capabilities
- type DevicePath
- type Driver
- type Factory
- type MountOpts
- type MountTarget
- type NodeID
- type OpContext
- type ProvisionRequest
- type RestoreRequest
- type SnapshotHandle
- type SnapshotRequest
- type UsageReporter
- type VolumeHandle
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUnsupported is returned by drivers that lack the requested // capability (e.g. local-host calling Snapshot). ErrUnsupported = errors.New("storage driver: operation unsupported") // ErrNotFound is returned when a handle has no backing store. Delete // implementations SHOULD swallow this internally and return nil to // preserve idempotency. ErrNotFound = errors.New("storage driver: handle not found") // ErrInvalidConfig is returned for misconfigured StorageClass / // Volume parameters (bad fsType, missing required field, ...). ErrInvalidConfig = errors.New("storage driver: invalid configuration") // ErrOnlineExpandUnsupported is returned by Expand when the driver // requires the volume to be detached first. ErrOnlineExpandUnsupported = errors.New("storage driver: online expand unsupported") // ErrAccessModeUnsupported is returned by Provision when the requested // AccessMode is not in Capabilities.AccessModes. ErrAccessModeUnsupported = errors.New("storage driver: access mode unsupported") )
Sentinel errors. Drivers SHOULD wrap these with %w when returning richer context so callers can use errors.Is.
Functions ¶
func Register ¶
Register adds a driver factory under the given name. Panics if name is empty or already registered — driver registration happens at init() time in operator-controlled code, so a duplicate name is a programming bug that must not be papered over at runtime.
func Registered ¶
func Registered() []string
Registered returns the sorted list of currently-registered driver names. Useful for diagnostics and the API-server's StorageClass linter.
Types ¶
type Capabilities ¶
type Capabilities struct {
// AccessModes is the set of access modes the driver can satisfy.
AccessModes []types.AccessMode
// Snapshots indicates Snapshot/RestoreFromSnapshot are implemented.
Snapshots bool
// Expand indicates Expand is implemented (some drivers only support
// offline expand — see Driver.Expand docs).
Expand bool
// OnlineExpand is true if Expand may be called while the volume is
// Bound (without first detaching).
OnlineExpand bool
// BlockDevice is true if the driver exposes a raw block device the
// runner is expected to format/mount itself. Directory-style drivers
// (local, local-host, NFS) set this to false.
BlockDevice bool
// TopologyKeys are the well-known label keys this driver consumes from
// StorageClass.AllowedTopologies. Used by the API-server linter to
// reject unknown keys early.
TopologyKeys []string
}
Capabilities describes the optional features a driver supports.
type DevicePath ¶
type DevicePath string
DevicePath is a node-local block device path returned by Attach (e.g. "/dev/disk/by-id/scsi-0DO_Volume_flo-data"). Empty for directory drivers.
type Driver ¶
type Driver interface {
// Name returns the registered driver name (e.g. "local", "do-volume").
// Must match the registry key.
Name() string
// Capabilities describes what this driver supports. Returned values are
// expected to be stable for the lifetime of the process.
Capabilities() Capabilities
// Provision creates a new backing store for the volume and returns an
// opaque handle that subsequent calls (Attach, Snapshot, ...) re-parse.
// MUST be idempotent on Volume.ID — the controller retries on failure.
Provision(ctx context.Context, opctx OpContext, req ProvisionRequest) (VolumeHandle, error)
// Delete destroys the backing store identified by handle. Implementations
// MUST tolerate missing/already-deleted handles (return nil).
Delete(ctx context.Context, opctx OpContext, handle VolumeHandle) error
// Attach makes the volume available to the named node (e.g. attaches a
// cloud block device, opens an iSCSI session, no-ops for local
// directories). Returns the device path the node should Mount.
// For drivers that don't have a separate attach step, return an empty
// DevicePath and a nil error.
Attach(ctx context.Context, opctx OpContext, handle VolumeHandle, node NodeID) (DevicePath, error)
// Detach is the inverse of Attach. Idempotent.
Detach(ctx context.Context, opctx OpContext, handle VolumeHandle, node NodeID) error
// Mount makes the volume usable at MountTarget. For block-device drivers
// this typically formats (if needed) and mounts; for directory-style
// drivers it bind-mounts or returns the source path the runner should
// bind-mount itself. The returned MountTarget is what the runner uses —
// drivers may rewrite it (e.g. local-host returns the host path
// directly rather than the proposed Target).
Mount(ctx context.Context, opctx OpContext, opts MountOpts) (MountTarget, error)
// Unmount is the inverse of Mount. Idempotent.
Unmount(ctx context.Context, opctx OpContext, target MountTarget) error
// Snapshot creates a point-in-time snapshot of the volume. Drivers
// without snapshot support (Capabilities.Snapshots == false) MUST return
// ErrUnsupported.
Snapshot(ctx context.Context, opctx OpContext, req SnapshotRequest) (SnapshotHandle, error)
// RestoreFromSnapshot provisions a NEW volume from a snapshot. The
// returned handle replaces the volume's existing handle. OpContext
// here describes the TARGET volume + its class — the source snapshot
// is carried on RestoreRequest.
// Drivers without snapshot support MUST return ErrUnsupported.
RestoreFromSnapshot(ctx context.Context, opctx OpContext, req RestoreRequest) (VolumeHandle, error)
// DeleteSnapshot destroys the snapshot identified by handle. MUST be
// idempotent — implementations should swallow ErrNotFound and return
// nil so the controller can re-drive a Deleting snapshot safely.
// Drivers without snapshot support MUST return ErrUnsupported.
DeleteSnapshot(ctx context.Context, opctx OpContext, handle SnapshotHandle) error
// Expand grows the volume to NewSize. Online expansion vs offline is
// driver-dependent; drivers that only support offline expand (e.g.
// do-volume) MUST refuse if the volume is currently Bound and return
// ErrOnlineExpandUnsupported.
// Drivers without expand support (Capabilities.Expand == false) MUST
// return ErrUnsupported.
Expand(ctx context.Context, opctx OpContext, handle VolumeHandle, newSize string) error
}
Driver is the contract every storage backend implements. The interface is deliberately not CSI: it captures only what Rune needs in v1 and keeps the surface narrow enough for in-process Go drivers. A future CSI shim driver can wrap external CSI plugins behind this same interface.
The leader-side VolumeController calls Provision, Delete, Snapshot, RestoreFromSnapshot and Expand. Node-side agents call Attach, Detach, Mount and Unmount. Capabilities and Name are pure metadata.
Every operation method takes an OpContext as the second argument (after ctx). The controller / agent populates it with the resolved StorageClass, the Volume row, and the merged parameter map. Drivers consult OpContext for any per-class / per-volume configuration they need (region, fsType, auth references, …) — the v0.0.1-dev.46 fix routed Volume.Size into the driver layer the same way; this generalises the pattern to all driver methods so per-class config no longer has to live in the runefile only. See RUNE-200.
All methods MUST be context-aware and idempotent: the controller and agent retry on transient failures.
type Factory ¶
Factory constructs a Driver from operator-supplied config (parsed from the runefile [storage.<name>] section). Returning an error here is fatal — the controller will refuse to start with an unconfigurable driver.
config is the raw map for the runefile section; drivers decode it themselves to keep this package free of viper/koanf dependencies.
func Lookup ¶
Lookup returns the factory registered under name, or false if none. Used by the controller at boot to instantiate drivers referenced by StorageClass.Driver.
func MustLookup ¶
MustLookup is the panic-on-missing variant. Reserved for tests and init-time wiring where a missing driver is unambiguously a bug.
type MountOpts ¶
type MountOpts struct {
Handle VolumeHandle
Node NodeID
Device DevicePath // device returned by Attach (empty for directory drivers)
Target MountTarget // proposed mount target (may be rewritten by driver)
ReadOnly bool
// FsType is the filesystem to format with on first mount of a block
// device. Ignored by directory drivers. Sourced from StorageClass /
// Volume parameters.
FsType string
}
MountOpts is the input to Driver.Mount. The Volume lives on the accompanying OpContext.
type MountTarget ¶
type MountTarget string
MountTarget is a node-local filesystem path the runner consumes when it bind-mounts the volume into a container.
type NodeID ¶
type NodeID string
NodeID identifies a node in the Rune cluster (matches types.Node.ID).
type OpContext ¶
type OpContext struct {
// StorageClass that this operation is acting on. May be nil for
// orphan deletes (class removed before its volumes). Live operations
// always carry the resolved class.
StorageClass *types.StorageClass
// Volume is the row this operation pertains to. Always non-nil for
// volume-scoped operations (every method on the interface).
Volume *types.Volume
// Parameters is StorageClass.Parameters with Volume.Parameters
// overlaid on top, pre-merged by the caller. Drivers consult this
// map for per-class configuration (region, fsType, auth refs, etc.)
// rather than re-merging themselves.
Parameters map[string]string
// NodeHostname is the OS hostname (os.Hostname()) of the agent
// running this call, populated by the controller / agent at
// build time. Cloud-backed drivers use it to map Rune's node
// identity onto the cloud provider's instance identity — DO
// droplets, for example, are addressable by their hostname-derived
// name via /v2/droplets?name=... Empty when the caller has no
// hostname to report (controller-only operations like Provision /
// Delete that don't run on a specific node, or tests).
NodeHostname string
}
OpContext is the per-call context every Driver method receives as the second positional argument (after ctx). The controller / agent builds it before each call so drivers can consult per-class / per-volume configuration without holding it as instance state. Drivers MUST treat OpContext fields as read-only.
StorageClass MAY be nil — orphan deletes (the class was deleted before its volumes were reclaimed) carry only Volume + Parameters, where Parameters comes from Volume.Metadata.DriverParameters as a snapshot taken at Provision time (see RUNE-200 PR 2).
Parameters is always populated (may be empty). Drivers MUST consult Parameters rather than re-merging StorageClass.Parameters with Volume.Parameters themselves.
type ProvisionRequest ¶
type ProvisionRequest struct {
// SizeBytes is Volume.Size already parsed into bytes by the controller.
// Drivers that need the original string can read OpContext.Volume.Size.
SizeBytes int64
// Topology is the topology constraint the controller selected for this
// provision (the chosen TopologySelector after intersecting
// StorageClass.AllowedTopologies with node availability). Empty means
// no constraint.
Topology *types.TopologySelector
// Deadline is a soft deadline for the operation. Drivers should respect
// ctx.Done() but may use this for finer-grained internal timeouts.
Deadline time.Time
}
ProvisionRequest is the input to Driver.Provision. Volume, StorageClass and merged parameters live on the accompanying OpContext; this struct carries only fields specific to the provision operation itself.
type RestoreRequest ¶
type RestoreRequest struct {
// Source is the snapshot being restored.
Source *types.Snapshot
SourceHandle SnapshotHandle
// SizeBytes is the target Volume.Size already parsed into bytes.
SizeBytes int64
}
RestoreRequest is the input to Driver.RestoreFromSnapshot. The TARGET volume and its storage class live on the accompanying OpContext; this struct carries only the source snapshot reference.
type SnapshotHandle ¶
type SnapshotHandle string
SnapshotHandle is the opaque driver identifier for a snapshot.
type SnapshotRequest ¶
type SnapshotRequest struct {
Handle VolumeHandle
Snapshot *types.Snapshot
}
SnapshotRequest is the input to Driver.Snapshot. The Volume being snapshotted lives on the accompanying OpContext.
type UsageReporter ¶
type UsageReporter interface {
Usage(ctx context.Context, opctx OpContext, handle VolumeHandle) (usedBytes, capacityBytes uint64, err error)
}
UsageReporter is an OPTIONAL capability: drivers that can measure a volume's live on-disk usage implement it (the local directory drivers do, via a bounded directory walk). The API read path type-asserts for it and leaves usage at zero/unknown for drivers without it — cloud block drivers would need a node-local statfs, which requires agent support and is future work.
usedBytes is the measured usage. capacityBytes MAY be 0 when the driver cannot determine a real capacity (directory-backed volumes have no device boundary); callers should then fall back to the volume's spec size.
type VolumeHandle ¶
type VolumeHandle string
VolumeHandle is the opaque, driver-owned identifier returned by Provision and stored on Volume.Handle. The controller treats it as a black-box string; the owning driver re-parses it.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package awsebs implements the "aws-ebs" storage driver, backed by Amazon EBS (Elastic Block Store) volumes.
|
Package awsebs implements the "aws-ebs" storage driver, backed by Amazon EBS (Elastic Block Store) volumes. |
|
Package dovolume implements the "do-volume" storage driver — Rune's reference cloud driver, backed by DigitalOcean Block Storage.
|
Package dovolume implements the "do-volume" storage driver — Rune's reference cloud driver, backed by DigitalOcean Block Storage. |
|
Package gcepd implements the "gce-pd" storage driver, backed by Google Compute Engine Persistent Disks.
|
Package gcepd implements the "gce-pd" storage driver, backed by Google Compute Engine Persistent Disks. |
|
Package hcloudvolume implements the "hcloud-volume" storage driver — Rune's Hetzner Cloud Block Storage driver.
|
Package hcloudvolume implements the "hcloud-volume" storage driver — Rune's Hetzner Cloud Block Storage driver. |
|
Package local implements two storage Driver names that ship with the Rune binary:
|
Package local implements two storage Driver names that ship with the Rune binary: |